This commit is contained in:
Paddy Xu
2017-08-06 15:06:55 +03:00
parent 768425ad0f
commit 3a20245304
41 changed files with 427 additions and 607 deletions

View File

@@ -20,6 +20,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Windows.Controls; using System.Windows.Controls;
using QuickLook.ExtensionMethods;
using SharpCompress.Archives; using SharpCompress.Archives;
using SharpCompress.Common; using SharpCompress.Common;
using SharpCompress.Readers; using SharpCompress.Readers;
@@ -88,8 +89,9 @@ namespace QuickLook.Plugin.ArchiveViewer
archiveCount.Content = archiveCount.Content =
$"{_type} archive{t}"; $"{_type} archive{t}";
archiveSizeC.Content = $"Compressed size {_totalZippedSize.ToPrettySize(2)}"; archiveSizeC.Content =
archiveSizeU.Content = $"Uncompressed size {sizeU.ToPrettySize(2)}"; $"Compressed size {((long) _totalZippedSize).ToPrettySize(2)}";
archiveSizeU.Content = $"Uncompressed size {((long) sizeU).ToPrettySize(2)}";
} }
private void LoadItemsFromArchive(string path) private void LoadItemsFromArchive(string path)
@@ -99,7 +101,7 @@ namespace QuickLook.Plugin.ArchiveViewer
// ReaderFactory is slow... so limit its usage // ReaderFactory is slow... so limit its usage
string[] useReader = {".tar.gz", ".tgz", ".tar.bz2", ".tar.lz", ".tar.xz"}; string[] useReader = {".tar.gz", ".tgz", ".tar.bz2", ".tar.lz", ".tar.xz"};
if (useReader.Any(i => path.EndsWith(i))) if (useReader.Any(path.ToLower().EndsWith))
{ {
var reader = ReaderFactory.Open(stream, new ChardetReaderOptions()); var reader = ReaderFactory.Open(stream, new ChardetReaderOptions());

View File

@@ -19,6 +19,7 @@ using System;
using System.Globalization; using System.Globalization;
using System.Windows; using System.Windows;
using System.Windows.Data; using System.Windows.Data;
using QuickLook.ExtensionMethods;
namespace QuickLook.Plugin.ArchiveViewer namespace QuickLook.Plugin.ArchiveViewer
{ {
@@ -77,7 +78,7 @@ namespace QuickLook.Plugin.ArchiveViewer
var size = (ulong) values[0]; var size = (ulong) values[0];
var isFolder = (bool) values[1]; var isFolder = (bool) values[1];
return isFolder ? "" : size.ToPrettySize(2); return isFolder ? "" : ((long) size).ToPrettySize(2);
} }
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)

View File

@@ -49,29 +49,5 @@ namespace QuickLook.Plugin.ArchiveViewer
} }
return foundElement; return foundElement;
} }
public static string ToPrettySize(this ulong value, int decimalPlaces = 0)
{
const long OneKb = 1024;
const long OneMb = OneKb * 1024;
const long OneGb = OneMb * 1024;
const long OneTb = OneGb * 1024;
var asTb = Math.Round((double) value / OneTb, decimalPlaces);
var asGb = Math.Round((double) value / OneGb, decimalPlaces);
var asMb = Math.Round((double) value / OneMb, decimalPlaces);
var asKb = Math.Round((double) value / OneKb, decimalPlaces);
var chosenValue = asTb > 1
? $"{asTb} TB"
: asGb > 1
? $"{asGb} GB"
: asMb > 1
? $"{asMb} MB"
: asKb > 1
? $"{asKb} KB"
: $"{Math.Round((double) value, decimalPlaces)} bytes";
return chosenValue;
}
} }
} }

View File

@@ -17,12 +17,16 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Windows; using System.Windows;
namespace QuickLook.Plugin.ArchiveViewer namespace QuickLook.Plugin.ArchiveViewer
{ {
public class Plugin : IViewer public class Plugin : IViewer
{ {
private static readonly string[] Extensions =
{".rar", ".zip", ".tar", ".tgz", ".gz", ".bz2", ".lz", ".xz", ".7z"};
private ArchiveInfoPanel _panel; private ArchiveInfoPanel _panel;
public int Priority => 0; public int Priority => 0;
@@ -34,25 +38,7 @@ namespace QuickLook.Plugin.ArchiveViewer
public bool CanHandle(string path) public bool CanHandle(string path)
{ {
if (Directory.Exists(path)) return !Directory.Exists(path) && Extensions.Any(path.ToLower().EndsWith);
return false;
switch (Path.GetExtension(path).ToLower())
{
case ".rar":
case ".zip":
case ".tar":
case ".tgz":
case ".gz":
case ".bz2":
case ".lz":
case ".xz":
case ".7z":
return true;
default:
return false;
}
} }
public void Prepare(string path, ContextObject context) public void Prepare(string path, ContextObject context)

View File

@@ -34,10 +34,7 @@ namespace QuickLook.Plugin.CsvViewer
public bool CanHandle(string path) public bool CanHandle(string path)
{ {
if (Directory.Exists(path)) return !Directory.Exists(path) && path.ToLower().EndsWith(".csv");
return false;
return Path.GetExtension(path).ToLower() == ".csv";
} }
public void Prepare(string path, ContextObject context) public void Prepare(string path, ContextObject context)

View File

@@ -1,63 +0,0 @@
// Copyright © 2017 Paddy Xu
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace QuickLook.Plugin.HtmlViewer
{
internal static class DpiHelper
{
public enum DeviceCap
{
/// <summary>
/// Logical pixels inch in X
/// </summary>
LOGPIXELSX = 88,
/// <summary>
/// Logical pixels inch in Y
/// </summary>
LOGPIXELSY = 90
}
public const float DEFAULT_DPI = 96;
public static Dpi GetCurrentDpi()
{
var g = Graphics.FromHwnd(IntPtr.Zero);
var desktop = g.GetHdc();
var dpi = new Dpi
{
HorizontalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSX),
VerticalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSY)
};
return dpi;
}
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
}
internal class Dpi
{
public float HorizontalDpi { get; set; }
public float VerticalDpi { get; set; }
}
}

View File

@@ -17,6 +17,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Threading; using System.Windows.Threading;
@@ -24,6 +25,8 @@ namespace QuickLook.Plugin.HtmlViewer
{ {
public class Plugin : IViewer public class Plugin : IViewer
{ {
private static readonly string[] Extensions = {".mht", ".mhtml", ".htm", ".html"};
private WebpagePanel _panel; private WebpagePanel _panel;
public int Priority => int.MaxValue; public int Priority => int.MaxValue;
@@ -36,20 +39,7 @@ namespace QuickLook.Plugin.HtmlViewer
public bool CanHandle(string path) public bool CanHandle(string path)
{ {
if (Directory.Exists(path)) return !Directory.Exists(path) && Extensions.Any(path.ToLower().EndsWith);
return false;
switch (Path.GetExtension(path).ToLower())
{
case ".mht":
case ".mhtml":
case ".html":
case ".htm":
return true;
default:
return false;
}
} }
public void Prepare(string path, ContextObject context) public void Prepare(string path, ContextObject context)

View File

@@ -72,7 +72,6 @@
<Reference Include="PresentationFramework" /> <Reference Include="PresentationFramework" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="DpiHelpers.cs" />
<Compile Include="WpfBrowserWrapper.cs" /> <Compile Include="WpfBrowserWrapper.cs" />
<Page Include="WebpagePanel.xaml"> <Page Include="WebpagePanel.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>

View File

@@ -20,6 +20,7 @@ using System.IO;
using System.Text; using System.Text;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Threading; using System.Windows.Threading;
using QuickLook.Helpers;
namespace QuickLook.Plugin.HtmlViewer namespace QuickLook.Plugin.HtmlViewer
{ {
@@ -32,7 +33,7 @@ namespace QuickLook.Plugin.HtmlViewer
{ {
InitializeComponent(); InitializeComponent();
browser.Zoom = (int) (100 * DpiHelper.GetCurrentDpi().HorizontalDpi / DpiHelper.DEFAULT_DPI); browser.Zoom = (int) (100 * DpiHelper.GetCurrentScaleFactor().Vertical);
} }
public void Dispose() public void Dispose()

View File

@@ -17,12 +17,22 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Windows; using System.Windows;
namespace QuickLook.Plugin.IPreviewHandlers namespace QuickLook.Plugin.IPreviewHandlers
{ {
public class Plugin : IViewer public class Plugin : IViewer
{ {
private static readonly string[] Extensions =
{
".doc", ".docx", ".docm",
".xls", ".xlsx", ".xlsm", ".xlsb",
/*".vsd", ".vsdx",*/
".ppt", ".pptx",
".odt", ".ods", ".odp"
};
private PreviewPanel _panel; private PreviewPanel _panel;
public int Priority => int.MaxValue; public int Priority => int.MaxValue;
@@ -37,29 +47,8 @@ namespace QuickLook.Plugin.IPreviewHandlers
if (Directory.Exists(path)) if (Directory.Exists(path))
return false; return false;
switch (Path.GetExtension(path).ToLower()) if (Extensions.Any(path.ToLower().EndsWith))
{
// Word
case ".doc":
case ".docx":
case ".docm":
// Excel
case ".xls":
case ".xlsx":
case ".xlsm":
case ".xlsb":
// Visio Viewer will not quit after preview, which cause serious memory issue
//case ".vsd":
//case ".vsdx":
// PowerPoint
case ".ppt":
case ".pptx":
// OpenDocument
case ".odt":
case ".ods":
case ".odp":
return PreviewHandlerHost.GetPreviewHandlerGUID(path) != Guid.Empty; return PreviewHandlerHost.GetPreviewHandlerGUID(path) != Guid.Empty;
}
return false; return false;
} }

View File

@@ -25,7 +25,7 @@ namespace QuickLook.Plugin.ImageViewer
{ {
public class Plugin : IViewer public class Plugin : IViewer
{ {
private static readonly string[] _formats = private static readonly string[] Formats =
{ {
// camera raw // camera raw
".3fr", ".ari", ".arw", ".bay", ".crw", ".cr2", ".cap", ".data", ".dcs", ".dcr", ".dng", ".drf", ".eip", ".3fr", ".ari", ".arw", ".bay", ".crw", ".cr2", ".cap", ".data", ".dcs", ".dcr", ".dng", ".drf", ".eip",
@@ -51,10 +51,7 @@ namespace QuickLook.Plugin.ImageViewer
public bool CanHandle(string path) public bool CanHandle(string path)
{ {
if (Directory.Exists(path)) return !Directory.Exists(path) && Formats.Any(path.ToLower().EndsWith);
return false;
return _formats.Contains(Path.GetExtension(path).ToLower());
} }
public void Prepare(string path, ContextObject context) public void Prepare(string path, ContextObject context)

View File

@@ -17,6 +17,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Threading; using System.Windows.Threading;
using MsgReader; using MsgReader;
@@ -27,7 +28,7 @@ namespace QuickLook.Plugin.MailViewer
public class Plugin : IViewer public class Plugin : IViewer
{ {
private WebpagePanel _panel; private WebpagePanel _panel;
private string tmpDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); private string _tmpDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
public int Priority => int.MaxValue; public int Priority => int.MaxValue;
public bool AllowsTransparency => false; public bool AllowsTransparency => false;
@@ -38,18 +39,7 @@ namespace QuickLook.Plugin.MailViewer
public bool CanHandle(string path) public bool CanHandle(string path)
{ {
if (Directory.Exists(path)) return !Directory.Exists(path) && new[] {".eml", ".msg"}.Any(path.ToLower().EndsWith);
return false;
switch (Path.GetExtension(path).ToLower())
{
case ".eml":
case ".msg":
return true;
default:
return false;
}
} }
public void Prepare(string path, ContextObject context) public void Prepare(string path, ContextObject context)
@@ -74,18 +64,18 @@ namespace QuickLook.Plugin.MailViewer
_panel?.Dispose(); _panel?.Dispose();
_panel = null; _panel = null;
if (Directory.Exists(tmpDir)) if (Directory.Exists(_tmpDir))
Directory.Delete(tmpDir, true); Directory.Delete(_tmpDir, true);
} }
private string ExtractMailBody(string path) private string ExtractMailBody(string path)
{ {
tmpDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); _tmpDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tmpDir); Directory.CreateDirectory(_tmpDir);
var msg = new Reader(); var msg = new Reader();
var files = msg.ExtractToFolder(path, tmpDir, true); var files = msg.ExtractToFolder(path, _tmpDir, true);
if (files.Length > 0 && !string.IsNullOrEmpty(files[0])) if (files.Length > 0 && !string.IsNullOrEmpty(files[0]))
return files[0]; return files[0];

View File

@@ -17,6 +17,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Windows; using System.Windows;
using System.Windows.Threading; using System.Windows.Threading;
@@ -37,19 +38,7 @@ namespace QuickLook.Plugin.MarkdownViewer
public bool CanHandle(string path) public bool CanHandle(string path)
{ {
if (Directory.Exists(path)) return !Directory.Exists(path) && new[] {".md", ".rmd", ".maekdown"}.Any(path.ToLower().EndsWith);
return false;
switch (Path.GetExtension(path).ToLower())
{
case ".markdown":
case ".md":
case ".rmd":
return true;
default:
return false;
}
} }
public void Prepare(string path, ContextObject context) public void Prepare(string path, ContextObject context)

View File

@@ -1,63 +0,0 @@
// Copyright © 2017 Paddy Xu
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace QuickLook.Plugin.PDFViewer
{
internal static class DpiHelper
{
public enum DeviceCap
{
/// <summary>
/// Logical pixels inch in X
/// </summary>
LOGPIXELSX = 88,
/// <summary>
/// Logical pixels inch in Y
/// </summary>
LOGPIXELSY = 90
}
public const float DEFAULT_DPI = 96;
public static Dpi GetCurrentDpi()
{
var g = Graphics.FromHwnd(IntPtr.Zero);
var desktop = g.GetHdc();
var dpi = new Dpi
{
HorizontalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSX),
VerticalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSY)
};
return dpi;
}
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
}
internal class Dpi
{
public float HorizontalDpi { get; set; }
public float VerticalDpi { get; set; }
}
}

View File

@@ -1,80 +0,0 @@
// Copyright © 2017 Paddy Xu
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace QuickLook.Plugin.PDFViewer
{
public static class Extensions
{
public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach (var item in enumeration)
action(item);
}
public static T GetDescendantByType<T>(this Visual element) where T : class
{
if (element == null)
return default(T);
if (element.GetType() == typeof(T))
return element as T;
T foundElement = null;
(element as FrameworkElement)?.ApplyTemplate();
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
var visual = VisualTreeHelper.GetChild(element, i) as Visual;
foundElement = visual.GetDescendantByType<T>();
if (foundElement != null)
break;
}
return foundElement;
}
public static BitmapSource ToBitmapSource(this Bitmap source)
{
BitmapSource bs = null;
try
{
var data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, source.PixelFormat);
bs = BitmapSource.Create(source.Width, source.Height, source.HorizontalResolution,
source.VerticalResolution, PixelFormats.Bgr24, null,
data.Scan0, data.Stride * source.Height, data.Stride);
source.UnlockBits(data);
bs.Freeze();
}
catch
{
// ignored
}
return bs;
}
}
}

View File

@@ -19,6 +19,7 @@ using System;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using QuickLook.Helpers;
namespace QuickLook.Plugin.PDFViewer namespace QuickLook.Plugin.PDFViewer
{ {
@@ -37,9 +38,9 @@ namespace QuickLook.Plugin.PDFViewer
else else
NativeMethods.BoundPage_32(document, page, ref pageBound); NativeMethods.BoundPage_32(document, page, ref pageBound);
var currentDpi = DpiHelper.GetCurrentDpi(); var scale = DpiHelper.GetCurrentScaleFactor();
var zoomX = zoomFactor * (currentDpi.HorizontalDpi / DpiHelper.DEFAULT_DPI); var zoomX = zoomFactor * scale.Horizontal;
var zoomY = zoomFactor * (currentDpi.VerticalDpi / DpiHelper.DEFAULT_DPI); var zoomY = zoomFactor * scale.Vertical;
// gets the size of the page and multiplies it with zoom factors // gets the size of the page and multiplies it with zoom factors
var width = (int) (pageBound.Width * zoomX); var width = (int) (pageBound.Width * zoomX);
@@ -119,7 +120,7 @@ namespace QuickLook.Plugin.PDFViewer
else else
NativeMethods.DropPixmap_32(context, pix); NativeMethods.DropPixmap_32(context, pix);
bmp.SetResolution(currentDpi.HorizontalDpi, currentDpi.VerticalDpi); bmp.SetResolution(scale.Horizontal * DpiHelper.DefaultDpi, scale.Vertical * DpiHelper.DefaultDpi);
return bmp; return bmp;
} }

View File

@@ -18,6 +18,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Windows.Data; using System.Windows.Data;
using QuickLook.ExtensionMethods;
namespace QuickLook.Plugin.PDFViewer namespace QuickLook.Plugin.PDFViewer
{ {

View File

@@ -212,7 +212,7 @@ namespace QuickLook.Plugin.PDFViewer
// fill thumbnails list // fill thumbnails list
Enumerable.Range(0, PdfHandle.TotalPages).ForEach(PageIds.Add); Enumerable.Range(0, PdfHandle.TotalPages).ForEach(PageIds.Add);
OnPropertyChanged("PageIds"); OnPropertyChanged(nameof(PageIds));
CurrentPage = 0; CurrentPage = 0;
pagePanel.DoZoomToFit(); pagePanel.DoZoomToFit();

View File

@@ -24,6 +24,8 @@ namespace QuickLook.Plugin.PDFViewer
{ {
public class Plugin : IViewer public class Plugin : IViewer
{ {
private ContextObject _context;
private string _path;
private PdfViewerControl _pdfControl; private PdfViewerControl _pdfControl;
public int Priority => int.MaxValue; public int Priority => int.MaxValue;
@@ -50,6 +52,9 @@ namespace QuickLook.Plugin.PDFViewer
public void Prepare(string path, ContextObject context) public void Prepare(string path, ContextObject context)
{ {
_context = context;
_path = path;
var desiredSize = PdfViewerControl.GetDesiredControlSizeByFirstPage(path); var desiredSize = PdfViewerControl.GetDesiredControlSizeByFirstPage(path);
context.SetPreferredSizeFit(desiredSize, 0.8); context.SetPreferredSizeFit(desiredSize, 0.8);
@@ -69,8 +74,8 @@ namespace QuickLook.Plugin.PDFViewer
_pdfControl.LoadPdf(path); _pdfControl.LoadPdf(path);
context.Title = $"{Path.GetFileName(path)} (1 / {_pdfControl.TotalPages})"; context.Title = $"{Path.GetFileName(path)} (1 / {_pdfControl.TotalPages})";
_pdfControl.CurrentPageChanged += (sender2, e2) => context.Title =
$"{Path.GetFileName(path)} ({_pdfControl.CurrentPage + 1} / {_pdfControl.TotalPages})"; _pdfControl.CurrentPageChanged += UpdateVindowCaption;
context.IsBusy = false; context.IsBusy = false;
} }
catch (Exception e) catch (Exception e)
@@ -87,8 +92,16 @@ namespace QuickLook.Plugin.PDFViewer
{ {
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
_pdfControl.CurrentPageChanged -= UpdateVindowCaption;
_pdfControl?.Dispose(); _pdfControl?.Dispose();
_pdfControl = null; _pdfControl = null;
_context = null;
}
private void UpdateVindowCaption(object sender, EventArgs e2)
{
_context.Title = $"{Path.GetFileName(_path)} ({_pdfControl.CurrentPage + 1} / {_pdfControl.TotalPages})";
} }
~Plugin() ~Plugin()

View File

@@ -76,8 +76,6 @@
<DependentUpon>PdfViewerControl.xaml</DependentUpon> <DependentUpon>PdfViewerControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Plugin.cs" /> <Compile Include="Plugin.cs" />
<Compile Include="DpiHelpers.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="LibMuPdf.cs" /> <Compile Include="LibMuPdf.cs" />
<Compile Include="PageIdToImageConverter.cs" /> <Compile Include="PageIdToImageConverter.cs" />
<Compile Include="PdfFile.cs" /> <Compile Include="PdfFile.cs" />

View File

@@ -37,14 +37,14 @@ namespace QuickLook.Plugin.TextViewer
if (Directory.Exists(path)) if (Directory.Exists(path))
return false; return false;
const long MAX_SIZE = 20 * 1024 * 1024; const long maxSize = 20 * 1024 * 1024;
if (Path.GetExtension(path).ToLower() == ".txt") if (path.ToLower().EndsWith(".txt"))
return new FileInfo(path).Length <= MAX_SIZE; return new FileInfo(path).Length <= maxSize;
// if there is a matched highlighting scheme (by file extension), treat it as a plain text file // if there is a matched highlighting scheme (by file extension), treat it as a plain text file
if (HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(path)) != null) if (HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(path)) != null)
return new FileInfo(path).Length <= MAX_SIZE; return new FileInfo(path).Length <= maxSize;
// otherwise, read the first 512KB, check if we can get something. // otherwise, read the first 512KB, check if we can get something.
using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
@@ -53,7 +53,7 @@ namespace QuickLook.Plugin.TextViewer
var buffer = new byte[bufferLength]; var buffer = new byte[bufferLength];
var size = s.Read(buffer, 0, bufferLength); var size = s.Read(buffer, 0, bufferLength);
return IsText(buffer, size) && new FileInfo(path).Length <= MAX_SIZE; return IsText(buffer, size) && new FileInfo(path).Length <= maxSize;
} }
} }
@@ -64,7 +64,7 @@ namespace QuickLook.Plugin.TextViewer
public void View(string path, ContextObject context) public void View(string path, ContextObject context)
{ {
_tvp = new TextViewerPanel(path, context); _tvp = new TextViewerPanel(path);
context.ViewerContent = _tvp; context.ViewerContent = _tvp;
context.Title = $"{Path.GetFileName(path)}"; context.Title = $"{Path.GetFileName(path)}";

View File

@@ -21,6 +21,7 @@ using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using QuickLook.Helpers;
using UtfUnknown; using UtfUnknown;
namespace QuickLook.Plugin.TextViewer namespace QuickLook.Plugin.TextViewer
@@ -30,7 +31,7 @@ namespace QuickLook.Plugin.TextViewer
/// </summary> /// </summary>
public partial class TextViewerPanel : UserControl public partial class TextViewerPanel : UserControl
{ {
public TextViewerPanel(string path, ContextObject context) public TextViewerPanel(string path)
{ {
InitializeComponent(); InitializeComponent();
@@ -41,7 +42,7 @@ namespace QuickLook.Plugin.TextViewer
viewer.PreviewMouseWheel += Viewer_MouseWheel; viewer.PreviewMouseWheel += Viewer_MouseWheel;
viewer.FontFamily = viewer.FontFamily =
new FontFamily(context.GetString("Editor_FontFamily", failsafe: "Consolas")); new FontFamily(TranslationHelper.GetString("Editor_FontFamily"));
LoadFile(path); LoadFile(path);
} }

View File

@@ -28,6 +28,18 @@ namespace QuickLook.Plugin.VideoViewer
{ {
public class Plugin : IViewer public class Plugin : IViewer
{ {
private static readonly string[] Formats =
{
// video
".3g2", ".3gp", ".3gp2", ".3gpp", ".amv", ".asf", ".asf", ".avi", ".flv", ".m2ts", ".m4v", ".mkv",
".mov", ".mp4", ".mp4v", ".mpeg", ".mpg", ".ogv", ".qt", ".vob", ".webm", ".wmv",
// audio
".3gp", ".aa", ".aac", ".aax", ".act", ".aiff", ".amr", ".ape", ".au", ".awb", ".dct", ".dss", ".dvf",
".flac", ".gsm", ".iklax", ".ivs", ".m4a", ".m4b", ".m4p", ".mmf", ".mp3", ".mpc", ".msv", ".ogg",
".oga", ".mogg", ".opus", ".ra", ".rm", ".raw", ".tta", ".vox", ".wav", ".wma", ".wv", ".webm"
};
private ContextObject _context;
private Size _mediaSize = Size.Empty; private Size _mediaSize = Size.Empty;
private ViewerPanel _vp; private ViewerPanel _vp;
@@ -41,25 +53,13 @@ namespace QuickLook.Plugin.VideoViewer
public bool CanHandle(string path) public bool CanHandle(string path)
{ {
if (Directory.Exists(path)) return !Directory.Exists(path) && Formats.Contains(Path.GetExtension(path).ToLower());
return false;
var formats = new[]
{
// video
".3g2", ".3gp", ".3gp2", ".3gpp", ".amv", ".asf", ".asf", ".avi", ".flv", ".m2ts", ".m4v", ".mkv",
".mov", ".mp4", ".mp4v", ".mpeg", ".mpg", ".ogv", ".qt", ".vob", ".webm", ".wmv",
// audio
".3gp", ".aa", ".aac", ".aax", ".act", ".aiff", ".amr", ".ape", ".au", ".awb", ".dct", ".dss", ".dvf",
".flac", ".gsm", ".iklax", ".ivs", ".m4a", ".m4b", ".m4p", ".mmf", ".mp3", ".mpc", ".msv", ".ogg",
".oga", ".mogg", ".opus", ".ra", ".rm", ".raw", ".tta", ".vox", ".wav", ".wma", ".wv", ".webm"
};
return formats.Contains(Path.GetExtension(path).ToLower());
} }
public void Prepare(string path, ContextObject context) public void Prepare(string path, ContextObject context)
{ {
_context = context;
var def = new Size(450, 450); var def = new Size(450, 450);
_mediaSize = GetMediaSizeWithVlc(path); _mediaSize = GetMediaSizeWithVlc(path);
@@ -77,7 +77,8 @@ namespace QuickLook.Plugin.VideoViewer
context.ViewerContent = _vp; context.ViewerContent = _vp;
_vp.mediaElement.VlcMediaPlayer.Opening += (sender, e) => context.IsBusy = false;
_vp.mediaElement.VlcMediaPlayer.Opening += MarkReady;
_vp.LoadAndPlay(path); _vp.LoadAndPlay(path);
@@ -89,8 +90,16 @@ namespace QuickLook.Plugin.VideoViewer
public void Cleanup() public void Cleanup()
{ {
_vp.mediaElement.VlcMediaPlayer.Opening -= MarkReady;
_vp?.Dispose(); _vp?.Dispose();
_vp = null; _vp = null;
_context = null;
}
private void MarkReady(object sender, ObjectEventArgs<MediaState> e)
{
_context.IsBusy = false;
} }
private Size GetMediaSizeWithVlc(string path) private Size GetMediaSizeWithVlc(string path)

View File

@@ -266,7 +266,7 @@ namespace QuickLook.Plugin.VideoViewer
[DebuggerNonUserCode] [DebuggerNonUserCode]
private void ShowErrorNotification(object sender, EventArgs e) private void ShowErrorNotification(object sender, EventArgs e)
{ {
_context.ShowNotification("", "An error occurred while loading the video."); TrayIconManager.GetInstance().ShowNotification("", "An error occurred while loading the video.");
mediaElement?.Stop(); mediaElement?.Stop();
Dispose(); Dispose();

View File

@@ -20,15 +20,15 @@ using System.Drawing.Imaging;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
namespace QuickLook.Plugin.InfoPanel namespace QuickLook.ExtensionMethods
{ {
public static class Extensions public static class BitmapExtensions
{ {
public static BitmapSource ToBitmapSource(this Bitmap source) public static BitmapSource ToBitmapSource(this Bitmap old_source)
{ {
// BitmapSource.Create throws an exception when the image is scanned backward. // BitmapSource.Create throws an exception when the image is scanned backward.
// The Clone() will make it back scanning forward. // The Clone() will make it back scanning forward.
source = (Bitmap) source.Clone(); var source = (Bitmap) old_source.Clone();
BitmapSource bs = null; BitmapSource bs = null;
try try
@@ -48,6 +48,10 @@ namespace QuickLook.Plugin.InfoPanel
{ {
// ignored // ignored
} }
finally
{
source.Dispose();
}
return bs; return bs;
} }

View File

@@ -0,0 +1,31 @@
// Copyright © 2017 Paddy Xu
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
namespace QuickLook.ExtensionMethods
{
public static class EnumerableExtensions
{
public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach (var item in enumeration)
action(item);
}
}
}

View File

@@ -0,0 +1,48 @@
// Copyright © 2017 Paddy Xu
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
namespace QuickLook.ExtensionMethods
{
public static class FileExtensions
{
public static string ToPrettySize(this long value, int decimalPlaces = 0)
{
const long OneKb = 1024;
const long OneMb = OneKb * 1024;
const long OneGb = OneMb * 1024;
const long OneTb = OneGb * 1024;
var asTb = Math.Round((double) value / OneTb, decimalPlaces);
var asGb = Math.Round((double) value / OneGb, decimalPlaces);
var asMb = Math.Round((double) value / OneMb, decimalPlaces);
var asKb = Math.Round((double) value / OneKb, decimalPlaces);
var chosenValue = asTb > 1
? $"{asTb} TB"
: asGb > 1
? $"{asGb} GB"
: asMb > 1
? $"{asMb} MB"
: asKb > 1
? $"{asKb} KB"
: $"{Math.Round((double) value, decimalPlaces)} bytes";
return chosenValue;
}
}
}

View File

@@ -21,26 +21,23 @@ using System.Runtime.InteropServices;
namespace QuickLook.Helpers namespace QuickLook.Helpers
{ {
internal static class DpiHelper public static class DpiHelper
{ {
public const float DEFAULT_DPI = 96; public const float DefaultDpi = 96;
public static Dpi GetCurrentDpi() public static ScaleFactor GetCurrentScaleFactor()
{ {
var g = Graphics.FromHwnd(IntPtr.Zero); var g = Graphics.FromHwnd(IntPtr.Zero);
var desktop = g.GetHdc(); var desktop = g.GetHdc();
var dpi = new Dpi var horizontalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSX);
{ var verticalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSY);
HorizontalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSX),
VerticalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSY)
};
return dpi; return new ScaleFactor {Horizontal = horizontalDpi / DefaultDpi, Vertical = verticalDpi / DefaultDpi};
} }
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)] [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int GetDeviceCaps(IntPtr hDC, int nIndex); private static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
private enum DeviceCap private enum DeviceCap
{ {
@@ -54,10 +51,10 @@ namespace QuickLook.Helpers
LOGPIXELSY = 90 LOGPIXELSY = 90
} }
public struct Dpi public struct ScaleFactor
{ {
public float HorizontalDpi; public float Horizontal;
public float VerticalDpi; public float Vertical;
} }
} }
} }

View File

@@ -27,36 +27,37 @@ namespace QuickLook.Helpers
{ {
internal class FileHelper internal class FileHelper
{ {
public static bool? GetAssocApplication(string path, out string appFriendlyName) public static bool IsExecutable(string path, out string appFriendlyName)
{ {
appFriendlyName = string.Empty; appFriendlyName = string.Empty;
if (string.IsNullOrEmpty(path))
return null;
if (Directory.Exists(path))
return null;
if (!File.Exists(path))
return null;
var ext = Path.GetExtension(path).ToLower(); var ext = Path.GetExtension(path).ToLower();
var isExe = new[] {".cmd", ".bat", ".pif", ".scf", ".exe", ".com", ".scr"}.Contains(ext.ToLower()); var isExe = new[] {".cmd", ".bat", ".pif", ".scf", ".exe", ".com", ".scr"}.Contains(ext.ToLower());
// no assoc. app. found
if (!isExe) if (!isExe)
if (string.IsNullOrEmpty(GetAssocApplicationNative(ext, AssocStr.Command))) return false;
if (string.IsNullOrEmpty(GetAssocApplicationNative(ext, AssocStr.AppId))) // UWP
return null;
appFriendlyName = isExe
? FileVersionInfo.GetVersionInfo(path).FileDescription
: GetAssocApplicationNative(ext, AssocStr.FriendlyAppName);
appFriendlyName = FileVersionInfo.GetVersionInfo(path).FileDescription;
if (string.IsNullOrEmpty(appFriendlyName)) if (string.IsNullOrEmpty(appFriendlyName))
appFriendlyName = Path.GetFileName(path); appFriendlyName = Path.GetFileName(path);
return isExe; return true;
}
public static bool GetAssocApplication(string path, out string appFriendlyName)
{
appFriendlyName = string.Empty;
var ext = Path.GetExtension(path).ToLower();
// no assoc. app. found
if (string.IsNullOrEmpty(GetAssocApplicationNative(ext, AssocStr.Command)))
if (string.IsNullOrEmpty(GetAssocApplicationNative(ext, AssocStr.AppId))) // UWP
return false;
appFriendlyName = GetAssocApplicationNative(ext, AssocStr.FriendlyAppName);
if (string.IsNullOrEmpty(appFriendlyName))
appFriendlyName = Path.GetFileName(path);
return true;
} }
[DllImport("shlwapi.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("shlwapi.dll", CharSet = CharSet.Auto, SetLastError = true)]

View File

@@ -24,7 +24,7 @@ using System.Xml.XPath;
namespace QuickLook.Helpers namespace QuickLook.Helpers
{ {
internal class TranslationHelper public class TranslationHelper
{ {
private static readonly CultureInfo CurrentCultureInfo = CultureInfo.CurrentUICulture; private static readonly CultureInfo CurrentCultureInfo = CultureInfo.CurrentUICulture;
//private static readonly CultureInfo CurrentCultureInfo = CultureInfo.GetCultureInfo("zh-CN"); //private static readonly CultureInfo CurrentCultureInfo = CultureInfo.GetCultureInfo("zh-CN");

View File

@@ -25,17 +25,15 @@ using QuickLook.NativeMethods;
namespace QuickLook.Helpers namespace QuickLook.Helpers
{ {
internal static class WindowHelper public static class WindowHelper
{ {
public static Rect GetCurrentWindowRect() public static Rect GetCurrentWindowRect()
{ {
var screen = Screen.FromPoint(Cursor.Position).WorkingArea; var screen = Screen.FromPoint(Cursor.Position).WorkingArea;
var dpi = DpiHelper.GetCurrentDpi(); var scale = DpiHelper.GetCurrentScaleFactor();
var scaleX = dpi.HorizontalDpi / DpiHelper.DEFAULT_DPI;
var scaleY = dpi.VerticalDpi / DpiHelper.DEFAULT_DPI;
return new Rect( return new Rect(
new Point(screen.X / scaleX, screen.Y / scaleY), new Point(screen.X / scale.Horizontal, screen.Y / scale.Vertical),
new Size(screen.Width / scaleX, screen.Height / scaleY)); new Size(screen.Width / scale.Horizontal, screen.Height / scale.Vertical));
} }
public static void BringToFront(this Window window) public static void BringToFront(this Window window)

View File

@@ -30,9 +30,14 @@
</Window.Resources> </Window.Resources>
<WindowChrome.WindowChrome> <WindowChrome.WindowChrome>
<WindowChrome x:Name="chrome" <WindowChrome x:Name="chrome"
CaptionHeight="0"
ResizeBorderThickness="{Binding ContextObject.CanResize, Converter={StaticResource BooleanToResizeBorderThicknessConverter}, ElementName=mainWindow}" ResizeBorderThickness="{Binding ContextObject.CanResize, Converter={StaticResource BooleanToResizeBorderThicknessConverter}, ElementName=mainWindow}"
UseAeroCaptionButtons="False" /> UseAeroCaptionButtons="False" />
</WindowChrome.WindowChrome> </WindowChrome.WindowChrome>
<Window.ResizeMode>
<Binding ElementName="mainWindow" Path="ContextObject.CanResize"
Converter="{StaticResource BooleanToResizeModeConverter}" />
</Window.ResizeMode>
<Border> <Border>
<Border.Effect> <Border.Effect>
<DropShadowEffect BlurRadius="{StaticResource MainWindowShadowBlurRadius}" ShadowDepth="0" Opacity="0.6" <DropShadowEffect BlurRadius="{StaticResource MainWindowShadowBlurRadius}" ShadowDepth="0" Opacity="0.6"
@@ -49,13 +54,12 @@
<DoubleAnimation <DoubleAnimation
Storyboard.Target="{Binding Source={x:Reference windowCaptionContainer}}" Storyboard.Target="{Binding Source={x:Reference windowCaptionContainer}}"
Storyboard.TargetProperty="Opacity" To="0" BeginTime="0:0:3" Storyboard.TargetProperty="Opacity" To="0" BeginTime="0:0:3"
Duration="0:0:0.05" Completed="RemoveWindowChromeCaption" /> Duration="0:0:0.05" />
</Storyboard> </Storyboard>
<Storyboard x:Key="ShowTitlebarStoryboard"> <Storyboard x:Key="ShowTitlebarStoryboard">
<DoubleAnimation <DoubleAnimation
Storyboard.Target="{Binding Source={x:Reference windowCaptionContainer}}" Storyboard.Target="{Binding Source={x:Reference windowCaptionContainer}}"
Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.05" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.05" />
Completed="RestoreWindowChromeCaption" />
</Storyboard> </Storyboard>
</Grid.Resources> </Grid.Resources>
<Grid.Style> <Grid.Style>
@@ -82,12 +86,13 @@
</Grid.Style> </Grid.Style>
<glassLayer:GlassLayer BlurredElement="{Binding ElementName=containerPanel}" /> <glassLayer:GlassLayer BlurredElement="{Binding ElementName=containerPanel}" />
<DockPanel> <DockPanel>
<Border x:Name="buttonCloseWindow" Style="{StaticResource CaptionButtonStyle}" <Button x:Name="buttonCloseWindow" Style="{StaticResource CaptionCloseButtonStyle}"
DockPanel.Dock="Right"> DockPanel.Dock="Right">
<fa:ImageAwesome Icon="TimesCircle" <fa:ImageAwesome Icon="TimesCircle"
Foreground="{StaticResource CaptionButtonIconForeground}" /> Foreground="{StaticResource CaptionButtonIconForeground}" />
</Border> </Button>
<Border x:Name="buttonWindowStatus" Style="{StaticResource CaptionButtonStyle}" <Button x:Name="buttonWindowStatus" Style="{StaticResource CaptionButtonStyle}"
Visibility="{Binding ContextObject.CanResize, ElementName=mainWindow, Converter={StaticResource BooleanToVisibilityConverter}}"
DockPanel.Dock="Right"> DockPanel.Dock="Right">
<fa:ImageAwesome Foreground="{StaticResource CaptionButtonIconForeground}"> <fa:ImageAwesome Foreground="{StaticResource CaptionButtonIconForeground}">
<fa:ImageAwesome.Style> <fa:ImageAwesome.Style>
@@ -106,25 +111,21 @@
</Style> </Style>
</fa:ImageAwesome.Style> </fa:ImageAwesome.Style>
</fa:ImageAwesome> </fa:ImageAwesome>
</Border>
<Button x:Name="buttonOpenWith" DockPanel.Dock="Right" Content="Open with..." Height="20"
Margin="10,0,0,0" Padding="5,0"
MaxWidth="{Binding Width, ElementName=mainWindow, Converter={StaticResource ScaledValueConverter}, ConverterParameter='0.25'}"
Focusable="False" Cursor="Hand"
Background="#E5EEEEEE" BorderBrush="#E59A9A9A"
WindowChrome.IsHitTestVisibleInChrome="True" Foreground="#FF404040">
<Button.ContentTemplate>
<DataTemplate>
<TextBlock TextTrimming="CharacterEllipsis" Text="{Binding}" />
</DataTemplate>
</Button.ContentTemplate>
</Button> </Button>
<Border DockPanel.Dock="Left" x:Name="buttonPin" Style="{StaticResource CaptionButtonStyle}"> <Button x:Name="buttonOpenWith" DockPanel.Dock="Right"
Style="{StaticResource CaptionTextButtonStyle}">
<Button.Content>
<TextBlock x:Name="buttonOpenWithText" VerticalAlignment="Center">
Open with <Bold>AppName</Bold>
</TextBlock>
</Button.Content>
</Button>
<Button DockPanel.Dock="Left" x:Name="buttonPin" Style="{StaticResource CaptionButtonStyle}">
<fa:ImageAwesome Icon="ThumbTack" Foreground="{StaticResource CaptionButtonIconForeground}" /> <fa:ImageAwesome Icon="ThumbTack" Foreground="{StaticResource CaptionButtonIconForeground}" />
</Border> </Button>
<Border x:Name="buttonShare" Style="{StaticResource CaptionButtonStyle}" DockPanel.Dock="Left"> <Button x:Name="buttonShare" Style="{StaticResource CaptionButtonStyle}" DockPanel.Dock="Left">
<fa:ImageAwesome Icon="ShareAlt" Foreground="{StaticResource CaptionButtonIconForeground}" /> <fa:ImageAwesome Icon="ShareAlt" Foreground="{StaticResource CaptionButtonIconForeground}" />
</Border> </Button>
<Grid x:Name="titleArea" Background="Transparent"> <Grid x:Name="titleArea" Background="Transparent">
<TextBlock Text="{Binding ContextObject.Title, ElementName=mainWindow}" FontSize="12" <TextBlock Text="{Binding ContextObject.Title, ElementName=mainWindow}" FontSize="12"
HorizontalAlignment="Left" TextTrimming="CharacterEllipsis" HorizontalAlignment="Left" TextTrimming="CharacterEllipsis"

View File

@@ -19,9 +19,11 @@ using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices; using System.Runtime.ExceptionServices;
using System.Windows; using System.Windows;
using System.Windows.Documents;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
@@ -37,6 +39,7 @@ namespace QuickLook
public partial class MainWindowTransparent : Window, INotifyPropertyChanged public partial class MainWindowTransparent : Window, INotifyPropertyChanged
{ {
private bool _pinned; private bool _pinned;
private bool _restoreForDragMove;
internal MainWindowTransparent() internal MainWindowTransparent()
{ {
@@ -47,13 +50,11 @@ namespace QuickLook
FontFamily = new FontFamily(TranslationHelper.GetString("UI_FontFamily", failsafe: "Segoe UI")); FontFamily = new FontFamily(TranslationHelper.GetString("UI_FontFamily", failsafe: "Segoe UI"));
SourceInitialized += (sender, e) => windowCaptionContainer.MouseLeftButtonDown += WindowDragMoveStart;
{ windowCaptionContainer.MouseMove += WindowDragMoving;
//if (AllowsTransparency) windowCaptionContainer.MouseLeftButtonUp += WindowDragMoveEnd;
// BlurWindow.EnableWindowBlur(this);
};
buttonPin.MouseLeftButtonUp += (sender, e) => buttonPin.Click += (sender, e) =>
{ {
if (Pinned) if (Pinned)
{ {
@@ -68,7 +69,7 @@ namespace QuickLook
ViewWindowManager.GetInstance().ForgetCurrentWindow(); ViewWindowManager.GetInstance().ForgetCurrentWindow();
}; };
buttonCloseWindow.MouseLeftButtonUp += (sender, e) => buttonCloseWindow.Click += (sender, e) =>
{ {
if (Pinned) if (Pinned)
BeginClose(); BeginClose();
@@ -84,10 +85,10 @@ namespace QuickLook
ViewWindowManager.GetInstance().RunAndClosePreview(); ViewWindowManager.GetInstance().RunAndClosePreview();
}; };
buttonWindowStatus.MouseLeftButtonUp += (sender, e) => buttonWindowStatus.Click += (sender, e) =>
WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
buttonShare.MouseLeftButtonUp += buttonShare.Click +=
(sender, e) => RunWith("rundll32.exe", $"shell32.dll,OpenAs_RunDLL {Path}"); (sender, e) => RunWith("rundll32.exe", $"shell32.dll,OpenAs_RunDLL {Path}");
} }
@@ -108,6 +109,53 @@ namespace QuickLook
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
private void WindowDragMoveEnd(object sender, MouseButtonEventArgs e)
{
_restoreForDragMove = false;
}
private void WindowDragMoving(object sender, MouseEventArgs e)
{
if (!_restoreForDragMove)
return;
_restoreForDragMove = false;
var scale = DpiHelper.GetCurrentScaleFactor();
var point = PointToScreen(e.MouseDevice.GetPosition(this));
point.X /= scale.Horizontal;
point.Y /= scale.Vertical;
var monitor = WindowHelper.GetCurrentWindowRect();
var precentLeft = (point.X - monitor.Left) / monitor.Width;
var precentTop = (point.Y - monitor.Top) / monitor.Height;
Left = point.X - RestoreBounds.Width * precentLeft;
Top = point.Y - RestoreBounds.Height * precentTop;
WindowState = WindowState.Normal;
DragMove();
}
private void WindowDragMoveStart(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
if (ResizeMode != ResizeMode.CanResize &&
ResizeMode != ResizeMode.CanResizeWithGrip)
return;
WindowState = WindowState == WindowState.Maximized
? WindowState.Normal
: WindowState.Maximized;
}
else
{
_restoreForDragMove = WindowState == WindowState.Maximized;
DragMove();
}
}
internal void RunWith(string with, string arg) internal void RunWith(string with, string arg)
{ {
if (string.IsNullOrEmpty(Path)) if (string.IsNullOrEmpty(Path))
@@ -239,8 +287,6 @@ namespace QuickLook
ResizeAndCenter(new Size(newWidth, newHeight)); ResizeAndCenter(new Size(newWidth, newHeight));
chrome.CaptionHeight = ContextObject.FullWindowDragging ? Height : windowCaptionContainer.Height - 5;
if (Visibility != Visibility.Visible) if (Visibility != Visibility.Visible)
Show(); Show();
@@ -263,15 +309,43 @@ namespace QuickLook
private void SetOpenWithButtonAndPath() private void SetOpenWithButtonAndPath()
{ {
var isExe = FileHelper.GetAssocApplication(Path, out string appFriendlyName); buttonOpenWithText.Inlines.Clear();
buttonOpenWith.Content = isExe == null if (Directory.Exists(Path))
? Directory.Exists(Path) {
? string.Format(TranslationHelper.GetString("MW_BrowseFolder"), System.IO.Path.GetFileName(Path)) AddToInlines("MW_BrowseFolder", System.IO.Path.GetFileName(Path));
: string.Format(TranslationHelper.GetString("MW_Open"), System.IO.Path.GetFileName(Path)) return;
: isExe == true }
? string.Format(TranslationHelper.GetString("MW_Run"), appFriendlyName) var isExe = FileHelper.IsExecutable(Path, out string appFriendlyName);
: string.Format(TranslationHelper.GetString("MW_OpenWith"), appFriendlyName); if (isExe)
{
AddToInlines("MW_Run", appFriendlyName);
return;
}
// not an exe
var found = FileHelper.GetAssocApplication(Path, out appFriendlyName);
if (found)
{
AddToInlines("MW_OpenWith", appFriendlyName);
return;
}
// assoc not found
AddToInlines("MW_Open", System.IO.Path.GetFileName(Path));
void AddToInlines(string str, string replaceWith)
{
str = TranslationHelper.GetString(str);
var elements = str.Split(new[] {"{0}"}, StringSplitOptions.None).ToList();
while (elements.Count < 2)
elements.Add(string.Empty);
buttonOpenWithText.Inlines.Add(
new Run(elements[0]) {FontWeight = FontWeights.Normal}); // text beforehand
buttonOpenWithText.Inlines.Add(
new Run(replaceWith) {FontWeight = FontWeights.SemiBold}); // appFriendlyName
buttonOpenWithText.Inlines.Add(
new Run(elements[1]) {FontWeight = FontWeights.Normal}); // text afterward
}
} }
internal void BeginHide() internal void BeginHide()
@@ -301,15 +375,5 @@ namespace QuickLook
{ {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} }
private void RemoveWindowChromeCaption(object sender, EventArgs e)
{
chrome.CaptionHeight = 0;
}
private void RestoreWindowChromeCaption(object sender, EventArgs e)
{
chrome.CaptionHeight = ContextObject.FullWindowDragging ? Height : windowCaptionContainer.Height - 5;
}
} }
} }

View File

@@ -17,8 +17,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
using QuickLook.Annotations; using QuickLook.Annotations;
@@ -142,26 +140,6 @@ namespace QuickLook.Plugin
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Get a string from translation Xml document.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
public string GetString(string id, string file = null, CultureInfo locale = null, string failsafe = null)
{
return TranslationHelper.GetString(id, file, locale, failsafe, Assembly.GetCallingAssembly());
}
/// <summary>
/// Show a notification balloon.
/// </summary>
/// <param name="title">Title of the notification.</param>
/// <param name="content">The content.</param>
/// <param name="isError">Is this indicates a error?</param>
public void ShowNotification(string title, string content, bool isError = false)
{
TrayIconManager.GetInstance().ShowNotification(title, content, isError);
}
/// <summary> /// <summary>
/// Set the size of viewer window and shrink to fit (to screen resolution). /// Set the size of viewer window and shrink to fit (to screen resolution).
/// The window can take maximum (maxRatio*resolution) space. /// The window can take maximum (maxRatio*resolution) space.
@@ -173,7 +151,7 @@ namespace QuickLook.Plugin
if (maxRatio > 1) if (maxRatio > 1)
maxRatio = 1; maxRatio = 1;
var max = GetMaximumDisplayBound(); var max = WindowHelper.GetCurrentWindowRect();
var widthRatio = max.Width * maxRatio / size.Width; var widthRatio = max.Width * maxRatio / size.Width;
var heightRatio = max.Height * maxRatio / size.Height; var heightRatio = max.Height * maxRatio / size.Height;
@@ -186,14 +164,6 @@ namespace QuickLook.Plugin
return ratio; return ratio;
} }
/// <summary>
/// Get the device-independent resolution.
/// </summary>
public Rect GetMaximumDisplayBound()
{
return WindowHelper.GetCurrentWindowRect();
}
internal void Reset() internal void Reset()
{ {
ViewerWindow = null; ViewerWindow = null;

View File

@@ -1,63 +0,0 @@
// Copyright © 2017 Paddy Xu
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace QuickLook.Plugin.InfoPanel
{
internal static class DpiHelper
{
public enum DeviceCap
{
/// <summary>
/// Logical pixels inch in X
/// </summary>
LOGPIXELSX = 88,
/// <summary>
/// Logical pixels inch in Y
/// </summary>
LOGPIXELSY = 90
}
public const float DEFAULT_DPI = 96;
public static Dpi GetCurrentDpi()
{
var g = Graphics.FromHwnd(IntPtr.Zero);
var desktop = g.GetHdc();
var dpi = new Dpi
{
HorizontalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSX),
VerticalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSY)
};
return dpi;
}
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
}
internal class Dpi
{
public float HorizontalDpi { get; set; }
public float VerticalDpi { get; set; }
}
}

View File

@@ -73,29 +73,5 @@ namespace QuickLook.Plugin.InfoPanel
} }
} while (stack.Count != 0); } while (stack.Count != 0);
} }
public static string ToPrettySize(this long value, int decimalPlaces = 0)
{
const long OneKb = 1024;
const long OneMb = OneKb * 1024;
const long OneGb = OneMb * 1024;
const long OneTb = OneGb * 1024;
var asTb = Math.Round((double) value / OneTb, decimalPlaces);
var asGb = Math.Round((double) value / OneGb, decimalPlaces);
var asMb = Math.Round((double) value / OneMb, decimalPlaces);
var asKb = Math.Round((double) value / OneKb, decimalPlaces);
var chosenValue = asTb > 1
? $"{asTb} TB"
: asGb > 1
? $"{asGb} GB"
: asMb > 1
? $"{asMb} MB"
: asKb > 1
? $"{asKb} KB"
: $"{Math.Round((double) value, decimalPlaces)} bytes";
return chosenValue;
}
} }
} }

View File

@@ -20,6 +20,7 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Controls; using System.Windows.Controls;
using QuickLook.ExtensionMethods;
using QuickLook.Helpers; using QuickLook.Helpers;
namespace QuickLook.Plugin.InfoPanel namespace QuickLook.Plugin.InfoPanel
@@ -46,10 +47,12 @@ namespace QuickLook.Plugin.InfoPanel
{ {
Task.Run(() => Task.Run(() =>
{ {
var scale = DpiHelper.GetCurrentScaleFactor();
var icon = var icon =
WindowsThumbnailProvider.GetThumbnail(path, WindowsThumbnailProvider.GetThumbnail(path,
(int) (128 * DpiHelper.GetCurrentDpi().HorizontalDpi / DpiHelper.DEFAULT_DPI), (int) (128 * scale.Horizontal),
(int) (128 * DpiHelper.GetCurrentDpi().VerticalDpi / DpiHelper.DEFAULT_DPI), (int) (128 * scale.Vertical),
ThumbnailOptions.ScaleUp); ThumbnailOptions.ScaleUp);
var source = icon.ToBitmapSource(); var source = icon.ToBitmapSource();

View File

@@ -120,6 +120,9 @@
<Compile Include="Converters\BooleanToVisibilityConverter.cs" /> <Compile Include="Converters\BooleanToVisibilityConverter.cs" />
<Compile Include="Converters\BooleanToResizeBorderThicknessConverter.cs" /> <Compile Include="Converters\BooleanToResizeBorderThicknessConverter.cs" />
<Compile Include="Converters\ScaledValueConverter.cs" /> <Compile Include="Converters\ScaledValueConverter.cs" />
<Compile Include="ExtensionMethods\BitmapExtensions.cs" />
<Compile Include="ExtensionMethods\EnumerableExtensions.cs" />
<Compile Include="ExtensionMethods\FileExtensions.cs" />
<Compile Include="FocusMonitor.cs" /> <Compile Include="FocusMonitor.cs" />
<Compile Include="Helpers\AutoStartupHelper.cs" /> <Compile Include="Helpers\AutoStartupHelper.cs" />
<Compile Include="Controls\BusyDecorator\BackgroundVisualHost.cs" /> <Compile Include="Controls\BusyDecorator\BackgroundVisualHost.cs" />
@@ -150,8 +153,6 @@
<Compile Include="MainWindowNoTransparent.cs" /> <Compile Include="MainWindowNoTransparent.cs" />
<Compile Include="PipeServerManager.cs" /> <Compile Include="PipeServerManager.cs" />
<Compile Include="PluginManager.cs" /> <Compile Include="PluginManager.cs" />
<Compile Include="Plugin\InfoPanel\DpiHelpers.cs" />
<Compile Include="Plugin\InfoPanel\Extensions.cs" />
<Compile Include="Plugin\InfoPanel\FileHelper.cs" /> <Compile Include="Plugin\InfoPanel\FileHelper.cs" />
<Compile Include="Plugin\InfoPanel\InfoPanel.xaml.cs"> <Compile Include="Plugin\InfoPanel\InfoPanel.xaml.cs">
<DependentUpon>InfoPanel.xaml</DependentUpon> <DependentUpon>InfoPanel.xaml</DependentUpon>

View File

@@ -8,18 +8,73 @@
<SolidColorBrush x:Key="CaptionButtonIconForeground" Color="#E5868686" /> <SolidColorBrush x:Key="CaptionButtonIconForeground" Color="#E5868686" />
<SolidColorBrush x:Key="MainWindowBackground" Color="#FFF8F8FB" /> <SolidColorBrush x:Key="MainWindowBackground" Color="#FFF8F8FB" />
<Style x:Key="CaptionButtonStyle" TargetType="Border"> <Style x:Key="CaptionButtonBaseStyle" TargetType="Button">
<Setter Property="Width" Value="40" /> <Setter Property="Focusable" Value="False" />
<Setter Property="Height" Value="32" />
<Setter Property="Padding" Value="9,9,9,9" />
<Setter Property="Cursor" Value="Hand" /> <Setter Property="Cursor" Value="Hand" />
<Setter Property="Foreground" Value="#E50E0E0E" />
<Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Background" Value="Transparent" /> <Setter Property="Background" Value="Transparent" />
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" /> <Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" />
</Style>
<Style x:Key="CaptionTextButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonBaseStyle}">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="6,2,6,2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}" Padding="{TemplateBinding Padding}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers> <Style.Triggers>
<Trigger Property="IsMouseOver" Value="True"> <Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#22FFFFFF" /> <Setter Property="BorderBrush" Value="#FF3D3D3D" />
<Setter Property="Background" Value="#44FFFFFF" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#88FFFFFF" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="CaptionButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonBaseStyle}">
<Setter Property="Width" Value="40" />
<Setter Property="Height" Value="32" />
<Setter Property="Padding" Value="9,9,9,9" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderThickness="0"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#44FFFFFF" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#88FFFFFF" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="CaptionCloseButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyle}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#FFE81123" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#FFB5394B" />
</Trigger> </Trigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>

View File

@@ -5,10 +5,10 @@
<UI_FontFamily>Segoe UI</UI_FontFamily> <UI_FontFamily>Segoe UI</UI_FontFamily>
<APP_START>QuickLook is running in the background.</APP_START> <APP_START>QuickLook is running in the background.</APP_START>
<APP_SECOND>QuickLook is already running in the background.</APP_SECOND> <APP_SECOND>QuickLook is already running in the background.</APP_SECOND>
<MW_BrowseFolder>Browse {0}</MW_BrowseFolder> <MW_BrowseFolder>Browse {0}</MW_BrowseFolder>
<MW_Open>Open {0}</MW_Open> <MW_Open>Open {0}</MW_Open>
<MW_OpenWith>Open with {0}</MW_OpenWith> <MW_OpenWith>Open with {0}</MW_OpenWith>
<MW_Run>Run {0}</MW_Run> <MW_Run>Run {0}</MW_Run>
<Icon_RunAtStartup>Run at &amp;Startup</Icon_RunAtStartup> <Icon_RunAtStartup>Run at &amp;Startup</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Check for &amp;Updates...</Icon_CheckUpdate> <Icon_CheckUpdate>Check for &amp;Updates...</Icon_CheckUpdate>
@@ -28,10 +28,10 @@
<UI_FontFamily>Segoe UI,Microsoft Yahei UI,Microsoft Yahei,SimSun</UI_FontFamily> <UI_FontFamily>Segoe UI,Microsoft Yahei UI,Microsoft Yahei,SimSun</UI_FontFamily>
<APP_START>QuickLook 正在后台运行。</APP_START> <APP_START>QuickLook 正在后台运行。</APP_START>
<APP_SECOND>另一个 QuickLook 进程正在运行。</APP_SECOND> <APP_SECOND>另一个 QuickLook 进程正在运行。</APP_SECOND>
<MW_BrowseFolder>浏览 {0}</MW_BrowseFolder> <MW_BrowseFolder>浏览 {0}</MW_BrowseFolder>
<MW_Open>打开 {0}</MW_Open> <MW_Open>打开 {0}</MW_Open>
<MW_OpenWith>用 {0} 打开</MW_OpenWith> <MW_OpenWith>用 {0} 打开</MW_OpenWith>
<MW_Run>运行 {0}</MW_Run> <MW_Run>运行 {0}</MW_Run>
<Icon_RunAtStartup>启动时自动运行 (&amp;S)</Icon_RunAtStartup> <Icon_RunAtStartup>启动时自动运行 (&amp;S)</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>检查更新... (&amp;U)</Icon_CheckUpdate> <Icon_CheckUpdate>检查更新... (&amp;U)</Icon_CheckUpdate>
@@ -51,10 +51,10 @@
<UI_FontFamily>Segoe UI,Microsoft JhengHei UI,Microsoft JhengHei,SimSun</UI_FontFamily> <UI_FontFamily>Segoe UI,Microsoft JhengHei UI,Microsoft JhengHei,SimSun</UI_FontFamily>
<APP_START>QuickLook 正在背景執行。</APP_START> <APP_START>QuickLook 正在背景執行。</APP_START>
<APP_SECOND>另一個 QuickLook 處理程序正在執行。</APP_SECOND> <APP_SECOND>另一個 QuickLook 處理程序正在執行。</APP_SECOND>
<MW_BrowseFolder>瀏覽 {0}</MW_BrowseFolder> <MW_BrowseFolder>瀏覽 {0}</MW_BrowseFolder>
<MW_Open>開啟 {0}</MW_Open> <MW_Open>開啟 {0}</MW_Open>
<MW_OpenWith>用 {0} 開啟</MW_OpenWith> <MW_OpenWith>用 {0} 開啟</MW_OpenWith>
<MW_Run>執行 {0}</MW_Run> <MW_Run>執行 {0}</MW_Run>
<Icon_RunAtStartup>系統啟動時自動執行 (&amp;S)</Icon_RunAtStartup> <Icon_RunAtStartup>系統啟動時自動執行 (&amp;S)</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>檢查更新... (&amp;U)</Icon_CheckUpdate> <Icon_CheckUpdate>檢查更新... (&amp;U)</Icon_CheckUpdate>
@@ -74,10 +74,10 @@
<UI_FontFamily>Segoe UI</UI_FontFamily> <UI_FontFamily>Segoe UI</UI_FontFamily>
<APP_START>QuickLook está funcionando en segundo plano.</APP_START> <APP_START>QuickLook está funcionando en segundo plano.</APP_START>
<APP_SECOND>QuickLook ya está funcionando en segundo plano.</APP_SECOND> <APP_SECOND>QuickLook ya está funcionando en segundo plano.</APP_SECOND>
<MW_BrowseFolder>Explorar {0}</MW_BrowseFolder> <MW_BrowseFolder>Explorar {0}</MW_BrowseFolder>
<MW_Open>Abrir {0}</MW_Open> <MW_Open>Abrir {0}</MW_Open>
<MW_OpenWith>Abrir con {0}</MW_OpenWith> <MW_OpenWith>Abrir con {0}</MW_OpenWith>
<MW_Run>Iniciar {0}</MW_Run> <MW_Run>Iniciar {0}</MW_Run>
<Icon_RunAtStartup>Iniciar con el &amp;sistema</Icon_RunAtStartup> <Icon_RunAtStartup>Iniciar con el &amp;sistema</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Buscar &amp;actualizaciones...</Icon_CheckUpdate> <Icon_CheckUpdate>Buscar &amp;actualizaciones...</Icon_CheckUpdate>

View File

@@ -88,7 +88,7 @@ namespace QuickLook
} }
} }
internal static TrayIconManager GetInstance() public static TrayIconManager GetInstance()
{ {
return _instance ?? (_instance = new TrayIconManager()); return _instance ?? (_instance = new TrayIconManager());
} }