Gearing up for release.

Added installer. Consolidated logic for scanner. Fixed some race conditions with file access. Changed icon.
This commit is contained in:
Jordan Wages 2021-02-12 01:30:36 -06:00
parent f230812765
commit 0c5cb4df3b
14 changed files with 546 additions and 317 deletions

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="MDFinder" Language="1033" Version="0.9.0.0" Manufacturer="Jordan Wages" UpgradeCode="bed4df95-335c-4e57-be16-4fb662f39921">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Feature Id="ProductFeature" Title="mdfinder.installer" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="mdfinder" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
<Component Id="mdfinder" Guid="6D7CD382-5E6D-44A8-953D-AF135FD2865E">
<File Source="$(var.mdfinder.TargetDir)" Id="csmic.dll" />
<File Source="$(var.mdfinder.TargetDir)" Id="mdfinder.exe.config" />
<File Source="$(var.mdfinder.TargetDir)" Id="Gu.Wpf.Media.dll" />
<File Source="$(var.mdfinder.TargetDir)" Id="LiteDB.dll" />
<File Source="$(var.mdfinder.TargetDir)" Id="Octokit.dll" />
<File Source="$(var.mdfinder.TargetDir)" Id="mdfinder.hashprovider.dll" />
<File Source="$(var.mdfinder.TargetPath)" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.10</ProductVersion>
<ProjectGuid>a8185834-0eea-4255-86df-fea9dfdf9752</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>mdfinder.installer</OutputName>
<OutputType>Package</OutputType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="Product.wxs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mdfinder.hashprovider\mdfinder.hashprovider.csproj">
<Name>mdfinder.hashprovider</Name>
<Project>{f383e2d1-f62e-44cf-9e58-63542dcbd06e}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\mdfinder\mdfinder.csproj">
<Name>mdfinder</Name>
<Project>{e0f831fa-fce1-471e-8767-d3fd7edc7ccf}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
</ItemGroup>
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
</Target>
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Wix.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -7,20 +7,38 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mdfinder", "mdfinder\mdfind
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mdfinder.hashprovider", "mdfinder.hashprovider\mdfinder.hashprovider.csproj", "{F383E2D1-F62E-44CF-9E58-63542DCBD06E}"
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "mdfinder.installer", "mdfinder.installer\mdfinder.installer.wixproj", "{A8185834-0EEA-4255-86DF-FEA9DFDF9752}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Debug|x86.ActiveCfg = Debug|Any CPU
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Debug|x86.Build.0 = Debug|Any CPU
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Release|Any CPU.Build.0 = Release|Any CPU
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Release|x86.ActiveCfg = Release|Any CPU
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Release|x86.Build.0 = Release|Any CPU
{F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Debug|x86.ActiveCfg = Debug|Any CPU
{F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Debug|x86.Build.0 = Debug|Any CPU
{F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Release|Any CPU.Build.0 = Release|Any CPU
{F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Release|x86.ActiveCfg = Release|Any CPU
{F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Release|x86.Build.0 = Release|Any CPU
{A8185834-0EEA-4255-86DF-FEA9DFDF9752}.Debug|Any CPU.ActiveCfg = Debug|x86
{A8185834-0EEA-4255-86DF-FEA9DFDF9752}.Debug|x86.ActiveCfg = Debug|x86
{A8185834-0EEA-4255-86DF-FEA9DFDF9752}.Debug|x86.Build.0 = Debug|x86
{A8185834-0EEA-4255-86DF-FEA9DFDF9752}.Release|Any CPU.ActiveCfg = Release|x86
{A8185834-0EEA-4255-86DF-FEA9DFDF9752}.Release|x86.ActiveCfg = Release|x86
{A8185834-0EEA-4255-86DF-FEA9DFDF9752}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,11 +1,7 @@
using LiteDB;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace mdfinder
{
@ -35,6 +31,16 @@ namespace mdfinder
}
}
/// <summary> Gets the database statistics string. </summary>
/// <value> The database statistics. </value>
public string DbStatistics
{
get
{
return string.Format("{0} Files In Database.", this.FileRecordCollection.Count());
}
}
#endregion Properties
#region Constructors
@ -42,7 +48,7 @@ namespace mdfinder
/// <summary> Default constructor. </summary>
public DBHelper()
{
this.Database = new LiteDatabase(DEFAULT_DB_FILE_NAME);
this.Database = new LiteDatabase(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DEFAULT_DB_FILE_NAME));
}
/// <summary> Constructor. </summary>
@ -65,6 +71,8 @@ namespace mdfinder
{
var fileRecord = new FileRecord(path, size, hash, hashProvider);
this.FileRecordCollection.Upsert(fileRecord);
this.OnPropertyChanged("DbStatistics");
}
/// <summary> Removes the file record described by its path. </summary>
@ -72,6 +80,8 @@ namespace mdfinder
public void RemoveFileRecord(string id)
{
this.FileRecordCollection.Delete(fr => fr.Id == id);
this.OnPropertyChanged("DbStatistics");
}
/// <summary> Gets the file records in this collection. </summary>
@ -97,6 +107,8 @@ namespace mdfinder
public void Clear()
{
this.FileRecordCollection.Delete(Query.All());
this.OnPropertyChanged("DbStatistics");
}
#endregion Methods

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 806 B

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
@ -9,37 +7,41 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
viewBox="0 0 64 64"
sodipodi:docname="icon.svg"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
width="128.0px"
height="128.0px"
viewBox="0 0 128.0 128.0"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="icon.svg">
id="SVGRoot">
<defs
id="defs815" />
id="defs833" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6568542"
inkscape:cx="-5.6227241"
inkscape:cy="50.292753"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:snap-global="true"
inkscape:window-maximized="1"
inkscape:grid-bbox="true"
inkscape:snap-bbox="true" />
inkscape:window-y="357"
inkscape:window-x="1072"
inkscape:window-height="1417"
inkscape:window-width="3440"
showgrid="true"
inkscape:document-rotation="0"
inkscape:current-layer="layer1"
inkscape:document-units="px"
inkscape:cy="89.76195"
inkscape:cx="48.534596"
inkscape:zoom="5.6568542"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base">
<inkscape:grid
type="xygrid"
id="grid1403" />
</sodipodi:namedview>
<metadata
id="metadata818">
id="metadata836">
<rdf:RDF>
<cc:Work
rdf:about="">
@ -51,102 +53,107 @@
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
id="layer1"
inkscape:groupmode="layer"
id="layer1">
inkscape:label="Layer 1">
<g
id="g1425"
transform="translate(4.125,0.75)">
<g
id="g1396">
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 18.875,6.0625 v 50.375"
id="path1377"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 36.875,6.0625 v 50.375"
id="path1377-6"
inkscape:connector-curvature="0" />
</g>
<g
transform="rotate(90,27.875,31.25)"
id="g1396-3">
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 18.875,6.0625 v 50.375"
id="path1377-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 36.875,6.0625 v 50.375"
id="path1377-6-2"
inkscape:connector-curvature="0" />
</g>
transform="translate(0.22489393,-25.677048)"
id="g1585">
<rect
style="fill:#c2092f;fill-opacity:1;stroke:#000000;stroke-width:2.00617;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1410"
width="52.96468"
height="15.501858"
x="3.1943736"
y="60.288105" />
<rect
y="81.926117"
x="3.1943736"
height="15.501858"
width="52.96468"
id="rect1410-5"
style="fill:#00732b;fill-opacity:1;stroke:#000000;stroke-width:2.00617;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
y="103.56413"
x="3.1943736"
height="15.501858"
width="52.96468"
id="rect1410-9"
style="fill:#b5732b;fill-opacity:1;stroke:#000000;stroke-width:2.00617;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
y="71.053925"
x="107.83192"
height="16.362434"
width="16.362461"
id="rect1410-4"
style="fill:#ffe718;fill-opacity:1;stroke:#000000;stroke-width:2.0062;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#0ba7d1;fill-opacity:1;stroke:#000000;stroke-width:2.0062;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1410-4-3"
width="16.362461"
height="16.362434"
x="107.99336"
y="92.69194" />
<path
id="path1477-5"
d="M 56.159055,90 H 70"
style="fill:none;stroke:#000000;stroke-width:1.09179px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path1477-4"
d="M 56.159055,110.66914 H 70"
style="fill:none;stroke:#000000;stroke-width:1.09179px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path1477-0"
d="m 93.99097,79.665428 h 13.84094"
style="fill:none;stroke:#000000;stroke-width:1.09179px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path1477-7"
d="m 94.9137,100.33457 h 13.84095"
style="fill:none;stroke:#000000;stroke-width:1.09179px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:none;stroke:#000000;stroke-width:1.09179px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="M 70,90 93.99097,79.665428"
id="path1512" />
<path
style="fill:none;stroke:#000000;stroke-width:1.09179px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="M 56.159055,68.039034 H 70"
id="path1525" />
<path
style="fill:none;stroke:#000000;stroke-width:1.09179px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="M 94.9137,100.33457 70,68.039034"
id="path1514" />
<path
style="fill:none;stroke:#000000;stroke-width:1.09179px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="M 70,110.66914 94.9137,100.33457"
id="path1520" />
</g>
<g
transform="translate(-4.5526783,-1.286792)"
id="g1593">
<circle
style="fill:#66c0c8;fill-opacity:0.16049381;stroke:#e9e9e9;stroke-width:4.92946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1555"
cx="51.918816"
cy="50.387043"
r="31.741579" />
<path
style="fill:none;stroke:#e9e9e9;stroke-width:11.2551;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 80,75 33.7653,33.7653"
id="path1557" />
<circle
d="m -34.979605,-52.489803 a 18.008158,18.008158 0 0 1 -18.008157,18.008157"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2.25102;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1565"
sodipodi:type="arc"
sodipodi:cx="-52.987762"
sodipodi:cy="-52.489803"
sodipodi:rx="18.008158"
sodipodi:ry="18.008158"
sodipodi:start="0"
sodipodi:end="1.5707963"
sodipodi:open="true"
sodipodi:arc-type="arc"
transform="scale(-1)" />
</g>
<rect
style="opacity:1;fill:#4aae59;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1427"
width="14.142136"
height="14.142136"
x="6.8125"
y="6.8125" />
<rect
style="opacity:1;fill:#ae4a4a;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1427-3"
width="14.142136"
height="14.142136"
x="24.928932"
y="24.928932" />
<rect
style="opacity:1;fill:#4a94ae;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1427-7"
width="14.142136"
height="14.142136"
x="24.928932"
y="6.8125" />
<rect
style="opacity:1;fill:#984aae;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1427-38"
width="14.142136"
height="14.142136"
x="43.045364"
y="6.8125" />
<rect
style="opacity:1;fill:#7c7c7c;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1427-2"
width="14.142136"
height="14.142136"
x="43.045364"
y="24.928932" />
<rect
style="opacity:1;fill:#aea74a;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1427-4"
width="14.142136"
height="14.142136"
x="6.8125"
y="24.928932" />
<rect
style="opacity:1;fill:#4a5cae;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1427-5"
width="14.142136"
height="14.142136"
x="6.8125"
y="43.045364" />
<rect
style="opacity:1;fill:#ae8a4a;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1427-8"
width="14.142136"
height="14.142136"
x="24.928932"
y="43.045364" />
<rect
style="opacity:1;fill:#d3dc1c;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1427-1"
width="14.142136"
height="14.142136"
x="43.045364"
y="43.045364" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -1,51 +1,75 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:mdfinder">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="MdfinderUIIcon">
<Viewbox>
<Canvas Width="64" Height="64">
<Canvas Width="128" Height="128">
<Canvas Name="layer1">
<Canvas Name="g1425">
<Canvas Name="g1585">
<Canvas.RenderTransform>
<TranslateTransform X="4.125" Y="0.75"/>
<TranslateTransform X="0.22489393" Y="-25.677048" />
</Canvas.RenderTransform>
<Canvas Name="g1396">
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path1377" StrokeThickness="1" Stroke="#FF000000" StrokeMiterLimit="4" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat">
<Path.Data>
<PathGeometry Figures="m 18.875 6.0625 v 50.375" FillRule="NonZero"/>
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path13776" StrokeThickness="1" Stroke="#FF000000" StrokeMiterLimit="4" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat">
<Path.Data>
<PathGeometry Figures="m 36.875 6.0625 v 50.375" FillRule="NonZero"/>
</Path.Data>
</Path>
</Canvas>
<Canvas Name="g13963">
<Canvas.RenderTransform>
<RotateTransform Angle="90" CenterX="27.875" CenterY="31.25"/>
</Canvas.RenderTransform>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path13778" StrokeThickness="1" Stroke="#FF000000" StrokeMiterLimit="4" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat">
<Path.Data>
<PathGeometry Figures="m 18.875 6.0625 v 50.375" FillRule="NonZero"/>
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path137762" StrokeThickness="1" Stroke="#FF000000" StrokeMiterLimit="4" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat">
<Path.Data>
<PathGeometry Figures="m 36.875 6.0625 v 50.375" FillRule="NonZero"/>
</Path.Data>
</Path>
</Canvas>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="3.1943736" Canvas.Top="60.288105" Width="52.96468" Height="15.501858" Name="rect1410" Fill="#FFC2092F" StrokeThickness="2.00617" Stroke="#FF000000" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" />
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="3.1943736" Canvas.Top="81.926117" Width="52.96468" Height="15.501858" Name="rect14105" Fill="#FF00732B" StrokeThickness="2.00617" Stroke="#FF000000" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" />
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="3.1943736" Canvas.Top="103.56413" Width="52.96468" Height="15.501858" Name="rect14109" Fill="#FFB5732B" StrokeThickness="2.00617" Stroke="#FF000000" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" />
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="107.83192" Canvas.Top="71.053925" Width="16.362461" Height="16.362434" Name="rect14104" Fill="#FFFFE718" StrokeThickness="2.0062" Stroke="#FF000000" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" />
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="107.99336" Canvas.Top="92.69194" Width="16.362461" Height="16.362434" Name="rect141043" Fill="#FF0BA7D1" StrokeThickness="2.0062" Stroke="#FF000000" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" />
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path14775" StrokeThickness="1.09179" Stroke="#FF000000" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat">
<Path.Data>
<PathGeometry Figures="M 56.159055 90 H 70" FillRule="NonZero" />
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path14774" StrokeThickness="1.09179" Stroke="#FF000000" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat">
<Path.Data>
<PathGeometry Figures="M 56.159055 110.66914 H 70" FillRule="NonZero" />
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path14770" StrokeThickness="1.09179" Stroke="#FF000000" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat">
<Path.Data>
<PathGeometry Figures="m 93.99097 79.665428 h 13.84094" FillRule="NonZero" />
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path14777" StrokeThickness="1.09179" Stroke="#FF000000" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat">
<Path.Data>
<PathGeometry Figures="m 94.9137 100.33457 h 13.84095" FillRule="NonZero" />
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path1512" StrokeThickness="1.09179" Stroke="#FF000000" StrokeLineJoin="Miter" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Path.Data>
<PathGeometry Figures="M 70 90 93.99097 79.665428" FillRule="NonZero" />
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path1525" StrokeThickness="1.09179" Stroke="#FF000000" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Path.Data>
<PathGeometry Figures="M 56.159055 68.039034 H 70" FillRule="NonZero" />
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path1514" StrokeThickness="1.09179" Stroke="#FF000000" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Path.Data>
<PathGeometry Figures="M 94.9137 100.33457 70 68.039034" FillRule="NonZero" />
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path1520" StrokeThickness="1.09179" Stroke="#FF000000" StrokeLineJoin="Miter" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Path.Data>
<PathGeometry Figures="M 70 110.66914 94.9137 100.33457" FillRule="NonZero" />
</Path.Data>
</Path>
</Canvas>
<Canvas Name="g1593">
<Canvas.RenderTransform>
<TranslateTransform X="-4.5526783" Y="-1.286792" />
</Canvas.RenderTransform>
<Ellipse xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="20.2" Canvas.Top="18.6" Width="63.5" Height="63.5" Name="path1555" Fill="#2966C0C8" StrokeThickness="4.92946" Stroke="#FFE9E9E9" StrokeMiterLimit="4" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round" />
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path1557" StrokeThickness="11.2551" Stroke="#FFE9E9E9" StrokeMiterLimit="4" StrokeLineJoin="Miter" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Path.Data>
<PathGeometry Figures="m 80 75 33.7653 33.7653" FillRule="NonZero" />
</Path.Data>
</Path>
<Ellipse xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path1565" StrokeThickness="2.25102" Stroke="#FFFFFFFF" StrokeMiterLimit="4" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Ellipse.RenderTransform>
<ScaleTransform ScaleX="-1" ScaleY="-1" />
</Ellipse.RenderTransform>
</Ellipse>
</Canvas>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="6.8125" Canvas.Top="6.8125" Width="14.142136" Height="14.142136" Name="rect1427" Fill="#FF4AAE59" StrokeThickness="1" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="24.928932" Canvas.Top="24.928932" Width="14.142136" Height="14.142136" Name="rect14273" Fill="#FFAE4A4A" StrokeThickness="1" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="24.928932" Canvas.Top="6.8125" Width="14.142136" Height="14.142136" Name="rect14277" Fill="#FF4A94AE" StrokeThickness="1" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="43.045364" Canvas.Top="6.8125" Width="14.142136" Height="14.142136" Name="rect142738" Fill="#FF984AAE" StrokeThickness="1" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="43.045364" Canvas.Top="24.928932" Width="14.142136" Height="14.142136" Name="rect14272" Fill="#FF7C7C7C" StrokeThickness="1" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="6.8125" Canvas.Top="24.928932" Width="14.142136" Height="14.142136" Name="rect14274" Fill="#FFAEA74A" StrokeThickness="1" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="6.8125" Canvas.Top="43.045364" Width="14.142136" Height="14.142136" Name="rect14275" Fill="#FF4A5CAE" StrokeThickness="1" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="24.928932" Canvas.Top="43.045364" Width="14.142136" Height="14.142136" Name="rect14278" Fill="#FFAE8A4A" StrokeThickness="1" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="43.045364" Canvas.Top="43.045364" Width="14.142136" Height="14.142136" Name="rect14271" Fill="#FFD3DC1C" StrokeThickness="1" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
</Canvas>
</Canvas>
</Viewbox>
@ -53,10 +77,10 @@
<ControlTemplate x:Key="InfoIcon">
<Viewbox>
<Canvas Width="24" Height="24">
<Ellipse Canvas.Left="1.4" Canvas.Top="1.4" Width="21.2" Height="21.2" Fill="#FF0F5777" StrokeThickness="4.02519703" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Ellipse Canvas.Left="1.4" Canvas.Top="1.4" Width="21.2" Height="21.2" Fill="#FF0F5777" StrokeThickness="4.02519703" StrokeMiterLimit="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1" />
<Path Fill="#FFFFFFFF">
<Path.Data>
<PathGeometry Figures="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-.001 5.75c.69 0 1.251.56 1.251 1.25s-.561 1.25-1.251 1.25-1.249-.56-1.249-1.25.559-1.25 1.249-1.25zm2.001 12.25h-4v-1c.484-.179 1-.201 1-.735v-4.467c0-.534-.516-.618-1-.797v-1h3v6.265c0 .535.517.558 1 .735v.999z" FillRule="Nonzero"/>
<PathGeometry Figures="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-.001 5.75c.69 0 1.251.56 1.251 1.25s-.561 1.25-1.251 1.25-1.249-.56-1.249-1.25.559-1.25 1.249-1.25zm2.001 12.25h-4v-1c.484-.179 1-.201 1-.735v-4.467c0-.534-.516-.618-1-.797v-1h3v6.265c0 .535.517.558 1 .735v.999z" FillRule="Nonzero" />
</Path.Data>
</Path>
</Canvas>
@ -66,7 +90,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z" FillRule="NonZero"/>
<PathGeometry Figures="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -75,7 +99,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm0 22c-5.514 0-10-4.486-10-10s4.486-10 10-10 10 4.486 10 10-4.486 10-10 10zm0-18.8c-4.853 0-8.8 3.947-8.8 8.8s3.947 8.8 8.8 8.8 8.8-3.947 8.8-8.8-3.947-8.8-8.8-8.8zm0 15.05c-.689 0-1.25-.56-1.25-1.25s.561-1.25 1.25-1.25c.691 0 1.25.56 1.25 1.25s-.559 1.25-1.25 1.25zm1.961-5.928c-.904.975-.947 1.514-.935 2.178h-2.005c-.007-1.475.02-2.125 1.432-3.468.572-.544 1.024-.975.962-1.821-.058-.805-.73-1.226-1.364-1.226-.709 0-1.538.527-1.538 2.013h-2.011c0-2.4 1.41-3.95 3.59-3.95 1.036 0 1.942.339 2.551.955.57.578.865 1.372.854 2.298-.018 1.383-.859 2.291-1.536 3.021z" FillRule="NonZero"/>
<PathGeometry Figures="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm0 22c-5.514 0-10-4.486-10-10s4.486-10 10-10 10 4.486 10 10-4.486 10-10 10zm0-18.8c-4.853 0-8.8 3.947-8.8 8.8s3.947 8.8 8.8 8.8 8.8-3.947 8.8-8.8-3.947-8.8-8.8-8.8zm0 15.05c-.689 0-1.25-.56-1.25-1.25s.561-1.25 1.25-1.25c.691 0 1.25.56 1.25 1.25s-.559 1.25-1.25 1.25zm1.961-5.928c-.904.975-.947 1.514-.935 2.178h-2.005c-.007-1.475.02-2.125 1.432-3.468.572-.544 1.024-.975.962-1.821-.058-.805-.73-1.226-1.364-1.226-.709 0-1.538.527-1.538 2.013h-2.011c0-2.4 1.41-3.95 3.59-3.95 1.036 0 1.942.339 2.551.955.57.578.865 1.372.854 2.298-.018 1.383-.859 2.291-1.536 3.021z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -84,7 +108,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M15.003 3h2.997v5h-2.997v-5zm8.997 1v20h-24v-24h20l4 4zm-19 5h14v-7h-14v7zm16 4h-18v9h18v-9z" FillRule="NonZero"/>
<PathGeometry Figures="M15.003 3h2.997v5h-2.997v-5zm8.997 1v20h-24v-24h20l4 4zm-19 5h14v-7h-14v7zm16 4h-18v9h18v-9z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -93,7 +117,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M9 2h6v1h-6v-1zm6-1v-1h-6v1h6zm-5.146 21l-1.854 2h8l-1.854-2h-4.292zm10.146-14h-5v-4h-6v4h-5l8 8 8-8zm-2 11h-12v-6.172l-2-2v10.172h16v-10.172l-2 2v6.172z" FillRule="NonZero"/>
<PathGeometry Figures="M9 2h6v1h-6v-1zm6-1v-1h-6v1h6zm-5.146 21l-1.854 2h8l-1.854-2h-4.292zm10.146-14h-5v-4h-6v4h-5l8 8 8-8zm-2 11h-12v-6.172l-2-2v10.172h16v-10.172l-2 2v6.172z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -102,7 +126,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M15.563 22.282l-3.563.718.72-3.562 2.843 2.844zm-2.137-3.552l2.845 2.845 7.729-7.73-2.845-2.845-7.729 7.73zm-3.062 2.27h-7.364v-7h12.327l6.673-6.688v-2.312l-4-4h-18v22h9.953l.411-2zm-5.364-18h12v7h-12v-7zm8.004 6h2.996v-5h-2.996v5z" FillRule="NonZero"/>
<PathGeometry Figures="M15.563 22.282l-3.563.718.72-3.562 2.843 2.844zm-2.137-3.552l2.845 2.845 7.729-7.73-2.845-2.845-7.729 7.73zm-3.062 2.27h-7.364v-7h12.327l6.673-6.688v-2.312l-4-4h-18v22h9.953l.411-2zm-5.364-18h12v7h-12v-7zm8.004 6h2.996v-5h-2.996v5z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -111,7 +135,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M11 5c-1.629 0-2.305-1.058-4-3h-7v20h24v-17h-13z" FillRule="NonZero"/>
<PathGeometry Figures="M11 5c-1.629 0-2.305-1.058-4-3h-7v20h24v-17h-13z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -120,7 +144,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M19 2h-14l-5 14v6h24v-6l-5-14zm-10.844 5.323l1.296 1.352c-.761.988-.544 2.088.178 2.84 1.039 1.084 2.923 1.267 4.221.42 1.372-.895 1.486-2.547.45-3.627-.443-.463-1.099-.821-1.957-.969l-.202 1.487-2.464-2.572 3.091-2.025-.197 1.493c1.339.188 2.47.805 3.263 1.633 1.783 1.859 1.448 4.464-.731 5.886-2.151 1.402-5.31 1.095-7.037-.706-1.411-1.469-1.538-3.62.089-5.212zm13.844 12.677h-20v-3h20v3zm-3-1.5c0-.276.224-.5.5-.5s.5.224.5.5-.224.5-.5.5-.5-.224-.5-.5z" FillRule="NonZero"/>
<PathGeometry Figures="M19 2h-14l-5 14v6h24v-6l-5-14zm-10.844 5.323l1.296 1.352c-.761.988-.544 2.088.178 2.84 1.039 1.084 2.923 1.267 4.221.42 1.372-.895 1.486-2.547.45-3.627-.443-.463-1.099-.821-1.957-.969l-.202 1.487-2.464-2.572 3.091-2.025-.197 1.493c1.339.188 2.47.805 3.263 1.633 1.783 1.859 1.448 4.464-.731 5.886-2.151 1.402-5.31 1.095-7.037-.706-1.411-1.469-1.538-3.62.089-5.212zm13.844 12.677h-20v-3h20v3zm-3-1.5c0-.276.224-.5.5-.5s.5.224.5.5-.224.5-.5.5-.5-.224-.5-.5z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -129,7 +153,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M18 6v-6h-18v18h6v6h18v-18h-6zm-12 10h-4v-14h14v4h-10v10zm16 6h-14v-14h14v14zm-3-8h-3v-3h-2v3h-3v2h3v3h2v-3h3v-2z" FillRule="NonZero"/>
<PathGeometry Figures="M18 6v-6h-18v18h6v6h18v-18h-6zm-12 10h-4v-14h14v4h-10v10zm16 6h-14v-14h14v14zm-3-8h-3v-3h-2v3h-3v2h3v3h2v-3h3v-2z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -138,7 +162,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M13 8h-8v-1h8v1zm0 2h-8v-1h8v1zm-3 2h-5v-1h5v1zm11.172 12l-7.387-7.387c-1.388.874-3.024 1.387-4.785 1.387-4.971 0-9-4.029-9-9s4.029-9 9-9 9 4.029 9 9c0 1.761-.514 3.398-1.387 4.785l7.387 7.387-2.828 2.828zm-12.172-8c3.859 0 7-3.14 7-7s-3.141-7-7-7-7 3.14-7 7 3.141 7 7 7z" FillRule="NonZero"/>
<PathGeometry Figures="M13 8h-8v-1h8v1zm0 2h-8v-1h8v1zm-3 2h-5v-1h5v1zm11.172 12l-7.387-7.387c-1.388.874-3.024 1.387-4.785 1.387-4.971 0-9-4.029-9-9s4.029-9 9-9 9 4.029 9 9c0 1.761-.514 3.398-1.387 4.785l7.387 7.387-2.828 2.828zm-12.172-8c3.859 0 7-3.14 7-7s-3.141-7-7-7-7 3.14-7 7 3.141 7 7 7z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -147,7 +171,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M18 15.422v.983c0 .771-1.862 1.396-4 1.396s-4-.625-4-1.396v-.983c.968.695 2.801.902 4 .902 1.202 0 3.035-.208 4-.902zm-4-1.363c-1.202 0-3.035-.209-4-.902v.973c0 .771 1.862 1.396 4 1.396s4-.625 4-1.396v-.973c-.968.695-2.801.902-4 .902zm0-5.86c-2.138 0-4 .625-4 1.396 0 .77 1.862 1.395 4 1.395s4-.625 4-1.395c0-.771-1.862-1.396-4-1.396zm0 3.591c-1.202 0-3.035-.209-4-.902v.977c0 .77 1.862 1.395 4 1.395s4-.625 4-1.395v-.977c-.968.695-2.801.902-4 .902zm-.5-9.79c-5.288 0-9.649 3.914-10.377 9h-3.123l4 5.917 4-5.917h-2.847c.711-3.972 4.174-7 8.347-7 4.687 0 8.5 3.813 8.5 8.5s-3.813 8.5-8.5 8.5c-3.015 0-5.662-1.583-7.171-3.957l-1.2 1.775c1.916 2.536 4.948 4.182 8.371 4.182 5.797 0 10.5-4.702 10.5-10.5s-4.703-10.5-10.5-10.5z" FillRule="NonZero"/>
<PathGeometry Figures="M18 15.422v.983c0 .771-1.862 1.396-4 1.396s-4-.625-4-1.396v-.983c.968.695 2.801.902 4 .902 1.202 0 3.035-.208 4-.902zm-4-1.363c-1.202 0-3.035-.209-4-.902v.973c0 .771 1.862 1.396 4 1.396s4-.625 4-1.396v-.973c-.968.695-2.801.902-4 .902zm0-5.86c-2.138 0-4 .625-4 1.396 0 .77 1.862 1.395 4 1.395s4-.625 4-1.395c0-.771-1.862-1.396-4-1.396zm0 3.591c-1.202 0-3.035-.209-4-.902v.977c0 .77 1.862 1.395 4 1.395s4-.625 4-1.395v-.977c-.968.695-2.801.902-4 .902zm-.5-9.79c-5.288 0-9.649 3.914-10.377 9h-3.123l4 5.917 4-5.917h-2.847c.711-3.972 4.174-7 8.347-7 4.687 0 8.5 3.813 8.5 8.5s-3.813 8.5-8.5 8.5c-3.015 0-5.662-1.583-7.171-3.957l-1.2 1.775c1.916 2.536 4.948 4.182 8.371 4.182 5.797 0 10.5-4.702 10.5-10.5s-4.703-10.5-10.5-10.5z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -156,7 +180,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M1 3.488c0-1.926 4.656-3.488 10-3.488 5.345 0 10 1.562 10 3.488s-4.655 3.487-10 3.487c-5.344 0-10-1.561-10-3.487zm10 14.823c.34 0 .678-.007 1.011-.019.045-1.407.537-2.7 1.342-3.745-.839.067-1.643.1-2.353.1-3.006 0-7.588-.523-10-2.256v2.434c0 1.925 4.656 3.486 10 3.486zm0-5.665c5.345 0 10-1.562 10-3.487v-2.44c-2.418 1.738-7.005 2.256-10 2.256-3.006 0-7.588-.523-10-2.256v2.44c0 1.926 4.656 3.487 10 3.487zm1.254 7.635c-.438.02-.861.03-1.254.03-2.995 0-7.582-.518-10-2.256v2.458c0 1.925 4.656 3.487 10 3.487 1.284 0 2.526-.092 3.676-.256-1.155-.844-2.02-2.055-2.422-3.463zm10.746-1.781c0 2.485-2.017 4.5-4.5 4.5s-4.5-2.015-4.5-4.5 2.017-4.5 4.5-4.5 4.5 2.015 4.5 4.5zm-2-.5h-5v1h5v-1z" FillRule="NonZero"/>
<PathGeometry Figures="M1 3.488c0-1.926 4.656-3.488 10-3.488 5.345 0 10 1.562 10 3.488s-4.655 3.487-10 3.487c-5.344 0-10-1.561-10-3.487zm10 14.823c.34 0 .678-.007 1.011-.019.045-1.407.537-2.7 1.342-3.745-.839.067-1.643.1-2.353.1-3.006 0-7.588-.523-10-2.256v2.434c0 1.925 4.656 3.486 10 3.486zm0-5.665c5.345 0 10-1.562 10-3.487v-2.44c-2.418 1.738-7.005 2.256-10 2.256-3.006 0-7.588-.523-10-2.256v2.44c0 1.926 4.656 3.487 10 3.487zm1.254 7.635c-.438.02-.861.03-1.254.03-2.995 0-7.582-.518-10-2.256v2.458c0 1.925 4.656 3.487 10 3.487 1.284 0 2.526-.092 3.676-.256-1.155-.844-2.02-2.055-2.422-3.463zm10.746-1.781c0 2.485-2.017 4.5-4.5 4.5s-4.5-2.015-4.5-4.5 2.017-4.5 4.5-4.5 4.5 2.015 4.5 4.5zm-2-.5h-5v1h5v-1z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -165,7 +189,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M19 0h-14c-2.762 0-5 2.239-5 5v14c0 2.761 2.238 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-4 4h2v3h-2v-3zm-8 0h2v8h-2v-8zm4 13h-2v3h-2v-3h-2v-3h6v3zm8-5h-2v8h-2v-8h-2v-3h6v3z" FillRule="NonZero"/>
<PathGeometry Figures="M19 0h-14c-2.762 0-5 2.239-5 5v14c0 2.761 2.238 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-4 4h2v3h-2v-3zm-8 0h2v8h-2v-8zm4 13h-2v3h-2v-3h-2v-3h6v3zm8-5h-2v8h-2v-8h-2v-3h6v3z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -174,7 +198,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M22 13v-13h-20v24h8.409c4.857 0 3.335-8 3.335-8 3.009.745 8.256.419 8.256-3zm-4-7h-12v-1h12v1zm0 3h-12v-1h12v1zm0 3h-12v-1h12v1zm-2.091 6.223c2.047.478 4.805-.279 6.091-1.179-1.494 1.998-5.23 5.708-7.432 6.881 1.156-1.168 1.563-4.234 1.341-5.702z" FillRule="NonZero"/>
<PathGeometry Figures="M22 13v-13h-20v24h8.409c4.857 0 3.335-8 3.335-8 3.009.745 8.256.419 8.256-3zm-4-7h-12v-1h12v1zm0 3h-12v-1h12v1zm0 3h-12v-1h12v1zm-2.091 6.223c2.047.478 4.805-.279 6.091-1.179-1.494 1.998-5.23 5.708-7.432 6.881 1.156-1.168 1.563-4.234 1.341-5.702z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -183,7 +207,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M4 22v-20h16v11.543c0 4.107-6 2.457-6 2.457s1.518 6-2.638 6h-7.362zm18-7.614v-14.386h-20v24h10.189c3.163 0 9.811-7.223 9.811-9.614zm-5-1.386h-10v-1h10v1zm0-4h-10v1h10v-1zm0-3h-10v1h10v-1z" FillRule="NonZero"/>
<PathGeometry Figures="M4 22v-20h16v11.543c0 4.107-6 2.457-6 2.457s1.518 6-2.638 6h-7.362zm18-7.614v-14.386h-20v24h10.189c3.163 0 9.811-7.223 9.811-9.614zm-5-1.386h-10v-1h10v1zm0-4h-10v1h10v-1zm0-3h-10v1h10v-1z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -192,7 +216,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M18.764 17.385l2.66 5.423-2.441 1.192-2.675-5.474-3.308 2.863v-12.389l10 7.675-4.236.71zm2.236-7.385h2v-4h-2v4zm0 2.619l2 1.535v-2.154h-2v.619zm-10 8.77v-1.389h-4v2h4v-.611zm-8-3.389h-2v4h4v-2h-2v-2zm-2-14h2v-2h2v-2h-4v4zm2 8h-2v4h2v-4zm8-12h-4v2h4v-2zm6 0h-4v2h4v-2zm4 4h2v-4h-4v2h2v2zm-18 2h-2v4h2v-4z" FillRule="NonZero"/>
<PathGeometry Figures="M18.764 17.385l2.66 5.423-2.441 1.192-2.675-5.474-3.308 2.863v-12.389l10 7.675-4.236.71zm2.236-7.385h2v-4h-2v4zm0 2.619l2 1.535v-2.154h-2v.619zm-10 8.77v-1.389h-4v2h4v-.611zm-8-3.389h-2v4h4v-2h-2v-2zm-2-14h2v-2h2v-2h-4v4zm2 8h-2v4h2v-4zm8-12h-4v2h4v-2zm6 0h-4v2h4v-2zm4 4h2v-4h-4v2h2v2zm-18 2h-2v4h2v-4z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -201,7 +225,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M6 17c2.269-9.881 11-11.667 11-11.667v-3.333l7 6.637-7 6.696v-3.333s-6.17-.171-11 5zm12 .145v2.855h-16v-12h6.598c.768-.787 1.561-1.449 2.339-2h-10.937v16h20v-6.769l-2 1.914z" FillRule="NonZero"/>
<PathGeometry Figures="M6 17c2.269-9.881 11-11.667 11-11.667v-3.333l7 6.637-7 6.696v-3.333s-6.17-.171-11 5zm12 .145v2.855h-16v-12h6.598c.768-.787 1.561-1.449 2.339-2h-10.937v16h20v-6.769l-2 1.914z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>
@ -210,7 +234,7 @@
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M19.604 2.562l-3.346 3.137c-1.27-.428-2.686-.699-4.243-.699-7.569 0-12.015 6.551-12.015 6.551s1.928 2.951 5.146 5.138l-2.911 2.909 1.414 1.414 17.37-17.035-1.415-1.415zm-6.016 5.779c-3.288-1.453-6.681 1.908-5.265 5.206l-1.726 1.707c-1.814-1.16-3.225-2.65-4.06-3.66 1.493-1.648 4.817-4.594 9.478-4.594.927 0 1.796.119 2.61.315l-1.037 1.026zm-2.883 7.431l5.09-4.993c1.017 3.111-2.003 6.067-5.09 4.993zm13.295-4.221s-4.252 7.449-11.985 7.449c-1.379 0-2.662-.291-3.851-.737l1.614-1.583c.715.193 1.458.32 2.237.32 4.791 0 8.104-3.527 9.504-5.364-.729-.822-1.956-1.99-3.587-2.952l1.489-1.46c2.982 1.9 4.579 4.327 4.579 4.327z" FillRule="NonZero"/>
<PathGeometry Figures="M19.604 2.562l-3.346 3.137c-1.27-.428-2.686-.699-4.243-.699-7.569 0-12.015 6.551-12.015 6.551s1.928 2.951 5.146 5.138l-2.911 2.909 1.414 1.414 17.37-17.035-1.415-1.415zm-6.016 5.779c-3.288-1.453-6.681 1.908-5.265 5.206l-1.726 1.707c-1.814-1.16-3.225-2.65-4.06-3.66 1.493-1.648 4.817-4.594 9.478-4.594.927 0 1.796.119 2.61.315l-1.037 1.026zm-2.883 7.431l5.09-4.993c1.017 3.111-2.003 6.067-5.09 4.993zm13.295-4.221s-4.252 7.449-11.985 7.449c-1.379 0-2.662-.291-3.851-.737l1.614-1.583c.715.193 1.458.32 2.237.32 4.791 0 8.104-3.527 9.504-5.364-.729-.822-1.956-1.99-3.587-2.952l1.489-1.46c2.982 1.9 4.579 4.327 4.579 4.327z" FillRule="NonZero" />
</Path.Data>
</Path>
</Viewbox>

View File

@ -132,6 +132,15 @@ namespace mdfinder.Localization {
}
}
/// <summary>
/// Looks up a localized string similar to Keep the largest item from each duplicate file group.
/// </summary>
public static string ActionLargestTooltip {
get {
return ResourceManager.GetString("ActionLargestTooltip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to KeepSelected.
/// </summary>
@ -141,6 +150,15 @@ namespace mdfinder.Localization {
}
}
/// <summary>
/// Looks up a localized string similar to Keep the selected items from each duplicate file group.
/// </summary>
public static string ActionSelectedTooltip {
get {
return ResourceManager.GetString("ActionSelectedTooltip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Keep Smallest.
/// </summary>
@ -150,6 +168,15 @@ namespace mdfinder.Localization {
}
}
/// <summary>
/// Looks up a localized string similar to Keep the smallest item from each duplicate file group.
/// </summary>
public static string ActionSmallestTooltip {
get {
return ResourceManager.GetString("ActionSmallestTooltip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Archive Folder.
/// </summary>
@ -204,6 +231,15 @@ namespace mdfinder.Localization {
}
}
/// <summary>
/// Looks up a localized string similar to Clear the file database completely.
/// </summary>
public static string ClearTooltip {
get {
return ResourceManager.GetString("ClearTooltip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Keep File.
/// </summary>
@ -384,6 +420,15 @@ namespace mdfinder.Localization {
}
}
/// <summary>
/// Looks up a localized string similar to Mark this set of files as unique.
/// </summary>
public static string NotDuplicateTooltip {
get {
return ResourceManager.GetString("NotDuplicateTooltip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to OK.
/// </summary>
@ -493,7 +538,7 @@ namespace mdfinder.Localization {
}
/// <summary>
/// Looks up a localized string similar to Scan Location.
/// Looks up a localized string similar to Scanning Actions.
/// </summary>
public static string ScanningLabel {
get {

View File

@ -244,7 +244,7 @@
<value>Location to Scan</value>
</data>
<data name="ScanningLabel" xml:space="preserve">
<value>Scan Location</value>
<value>Scanning Actions</value>
</data>
<data name="ScanTooltip" xml:space="preserve">
<value>Scan the selected path</value>
@ -285,4 +285,19 @@
<data name="NotDupliateLabel" xml:space="preserve">
<value>Not A Duplicate</value>
</data>
<data name="ActionLargestTooltip" xml:space="preserve">
<value>Keep the largest item from each duplicate file group</value>
</data>
<data name="ActionSelectedTooltip" xml:space="preserve">
<value>Keep the selected items from each duplicate file group</value>
</data>
<data name="ActionSmallestTooltip" xml:space="preserve">
<value>Keep the smallest item from each duplicate file group</value>
</data>
<data name="ClearTooltip" xml:space="preserve">
<value>Clear the file database completely</value>
</data>
<data name="NotDuplicateTooltip" xml:space="preserve">
<value>Mark this set of files as unique</value>
</data>
</root>

View File

@ -1,13 +1,14 @@
<Window x:Class="mdfinder.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:gu="https://github.com/JohanLarsson/Gu.Wpf.Media"
xmlns:mdfinder="clr-namespace:mdfinder"
xmlns:loc="clr-namespace:mdfinder.Localization"
xmlns:gu="https://github.com/JohanLarsson/Gu.Wpf.Media"
mc:Ignorable="d"
Title="{x:Static loc:Localization.Title}" Height="520.293" Width="1055.509">
Title="{x:Static loc:Localization.Title}" Height="520.293" Width="1055.509"
Icon="./Icon/icon.ico">
<Window.Resources>
<mdfinder:InverseBoolConverter x:Key="InverseBoolConverter" />
<mdfinder:BoolVisibilityConverter x:Key="BoolVisibilityConverter" />
@ -15,6 +16,9 @@
<mdfinder:URIConverter x:Key="URIConverter" />
<mdfinder:SizeConverter x:Key="SizeConverter" />
</Window.Resources>
<Window.TaskbarItemInfo>
<TaskbarItemInfo x:Name="taskBarInfo" Description="Taskbar progress"></TaskbarItemInfo>
</Window.TaskbarItemInfo>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="{x:Static loc:Localization.FileMenu}">
@ -66,6 +70,8 @@
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@ -78,35 +84,37 @@
<Label Content="{x:Static loc:Localization.ScanLabel}" />
</StackPanel>
</Button>
<Button Grid.Row="0" Grid.Column="1" Name="btnNotDuplicate" ToolTip="{x:Static loc:Localization.ScanTooltip}" IsEnabled="{Binding Scanner.IsScanning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Click="BtnNotDuplicate_Click">
<Button Grid.Row="0" Grid.Column="1" Name="btnNotDuplicate" ToolTip="{x:Static loc:Localization.NotDuplicateTooltip}" IsEnabled="{Binding Scanner.IsScanning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Click="BtnNotDuplicate_Click">
<StackPanel Orientation="Horizontal">
<ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource ClearIcon}" />
<Label Content="{x:Static loc:Localization.NotDupliateLabel}" />
</StackPanel>
</Button>
<Button Grid.Row="0" Grid.Column="2" Name="btnClear" ToolTip="{x:Static loc:Localization.ScanTooltip}" IsEnabled="{Binding Scanner.IsScanning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Click="BtnClear_Click">
<Button Grid.Row="0" Grid.Column="2" Name="btnClear" ToolTip="{x:Static loc:Localization.ClearTooltip}" IsEnabled="{Binding Scanner.IsScanning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Click="BtnClear_Click">
<StackPanel Orientation="Horizontal">
<ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource ClearIcon}" />
<Label Content="{x:Static loc:Localization.ClearLabel}" />
</StackPanel>
</Button>
<Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Name="txtDupeStats" Content="{Binding ScanResults.Statistics, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}}"></Label>
<Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" Name="txtDbStats" Content="{Binding Database.DbStatistics, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}}"></Label>
</Grid>
</GroupBox>
<GroupBox Name="SingleFileGroupDuplicateActions" Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="1" Header="{x:Static loc:Localization.ActionBarLabel}">
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="1">
<Button Grid.Row="0" Grid.Column="1" Name="btnKeepLargest" ToolTip="{x:Static loc:Localization.ScanTooltip}" IsEnabled="{Binding Scanner.IsScanning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Tag="largest" Click="PerformDuplicateAction_Click">
<Button Grid.Row="0" Grid.Column="1" Name="btnKeepLargest" ToolTip="{x:Static loc:Localization.ActionLargestTooltip}" IsEnabled="{Binding Scanner.IsScanning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Tag="largest" Click="PerformDuplicateAction_Click">
<StackPanel Orientation="Horizontal">
<ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource LargeFileIcon}" />
<Label Content="{x:Static loc:Localization.ActionLargestLabel}" />
</StackPanel>
</Button>
<Button Grid.Row="0" Grid.Column="1" Name="btnKeepSmallest" ToolTip="{x:Static loc:Localization.ScanTooltip}" IsEnabled="{Binding Scanner.IsScanning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Tag="smallest" Click="PerformDuplicateAction_Click">
<Button Grid.Row="0" Grid.Column="1" Name="btnKeepSmallest" ToolTip="{x:Static loc:Localization.ActionSmallestTooltip}" IsEnabled="{Binding Scanner.IsScanning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Tag="smallest" Click="PerformDuplicateAction_Click">
<StackPanel Orientation="Horizontal">
<ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource SmallFileIcon}" />
<Label Content="{x:Static loc:Localization.ActionSmallestLabel}" />
</StackPanel>
</Button>
<Button Grid.Row="0" Grid.Column="1" Name="btnKeepSelected" ToolTip="{x:Static loc:Localization.ScanTooltip}" IsEnabled="{Binding Scanner.IsScanning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Tag="selected" Click="PerformDuplicateAction_Click">
<Button Grid.Row="0" Grid.Column="1" Name="btnKeepSelected" ToolTip="{x:Static loc:Localization.ActionSelectedTooltip}" IsEnabled="{Binding Scanner.IsScanning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Tag="selected" Click="PerformDuplicateAction_Click">
<StackPanel Orientation="Horizontal">
<ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource SelectedFileIcon}" />
<Label Content="{x:Static loc:Localization.ActionSelectedLabel}" />

View File

@ -1,24 +1,17 @@
using System;
using mdfinder.hashprovider;
using System;
using System.Collections.Generic;
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 System.Windows.Forms;
using System.Threading;
using mdfinder.hashprovider;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Media.Imaging;
namespace mdfinder
{
@ -86,7 +79,18 @@ namespace mdfinder
Dispatcher.Invoke(() => txtProgressLabel.Content = file.FullName);
}
};
this.Scanner.ReportProgress += (sender, args) => Dispatcher.Invoke(() => { if(args.Processed > 0) { this.progressBar.Value = args.Percentage * 100; } });
this.Scanner.ReportProgress += (sender, args) => Dispatcher.Invoke(() =>
{
if(args.Processed > 0)
{
this.progressBar.Value = args.Percentage * 100;
this.taskBarInfo.ProgressValue = args.Percentage;
}
else
{
this.taskBarInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None;
}
});
InitializeComponent();
}
@ -149,6 +153,84 @@ namespace mdfinder
this.stackNoPreview.Visibility = Visibility.Visible;
}
private void ProcessDuplicateFileGroups(string tag, bool archive, params DuplicateFileGroup[] duplicateFileGroups)
{
new Thread(() =>
{
var actionableFiles = Enumerable.Empty<FileRecord>();
var archiveName = string.Format("archive-{0}.zip", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"));
this.Dispatcher.Invoke(() => this.IsEnabled = false);
if(duplicateFileGroups.Any())
{
foreach(var duplicateFileGroup in duplicateFileGroups)
{
if(duplicateFileGroup != null)
{
if(tag == "largest")
{
actionableFiles = duplicateFileGroup.FileRecords.OrderByDescending(fr => fr.Size).Skip(1);
}
else if(tag == "smallest")
{
actionableFiles = duplicateFileGroup.FileRecords.OrderBy(fr => fr.Size).Skip(1);
}
else
{
actionableFiles = duplicateFileGroup.FileRecords.Where(fr => !fr.Keep);
}
ZipArchive zipFile = null;
if(archive)
{
if(duplicateFileGroups.Count() == 1)
{
archiveName = string.Format("{0}.zip", duplicateFileGroup.Hash);
}
zipFile = ZipFile.Open(System.IO.Path.Combine(Properties.Settings.Default.ArchiveFolder, archiveName), ZipArchiveMode.Update);
}
if(archive && zipFile != null)
{
//Zip everything up.
foreach(var file in actionableFiles)
{
zipFile.CreateEntryFromFile(file.Path.LocalPath, System.IO.Path.GetFileName(file.Path.LocalPath));
}
zipFile.Dispose();
}
// Make sure the garbage collector has enough time to clear up all
// references to the files.
GC.Collect();
GC.WaitForPendingFinalizers();
foreach(var file in actionableFiles)
{
//Do the deletion
try
{
File.Delete(file.Path.LocalPath);
this.Database.RemoveFileRecord(file.Id);
}
catch(Exception ex)
{
var r = System.Windows.MessageBox.Show(ex.Message, string.Format("Error deleting {0}", file.Path));
}
}
SetDuplicateFileCollection(GetDuplicateFiles());
}
}
}
this.Dispatcher.Invoke(() => this.IsEnabled = true);
}).Start();
}
/// <summary> Event handler. Called by btnFilePicker for click events. </summary>
/// <param name="sender"> Source of the event. </param>
/// <param name="e"> Routed event information. </param>
@ -176,6 +258,8 @@ namespace mdfinder
this.Scanner.Scan(location);
this.Dispatcher.Invoke(() => txtProgressLabel.Content = string.Empty);
this.Dispatcher.Invoke(() => progressBar.Value = 0);
this.Dispatcher.Invoke(() => taskBarInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Normal);
this.Dispatcher.Invoke(() => taskBarInfo.ProgressValue = 0);
this.Dispatcher.Invoke(() => SetDuplicateFileCollection(GetDuplicateFiles()));
}).Start();
}
@ -327,112 +411,31 @@ namespace mdfinder
{
var tag = (sender as System.Windows.Controls.Button).Tag.ToString();
var duplicateFileGroup = this.listBoxDupes.SelectedItem as DuplicateFileGroup;
var actionableFiles = Enumerable.Empty<FileRecord>();
var archive = this.checkboxArchiveRemainingFiles.IsChecked ?? false;
this.ScanResults.SelectedDuplicateFileGroup = null;
ResetMediaPreview();
new Thread(() =>
{
if(duplicateFileGroup != null)
{
if(tag == "largest")
{
actionableFiles = duplicateFileGroup.FileRecords.OrderByDescending(fr => fr.Size).Skip(1);
}
else if(tag == "smallest")
{
actionableFiles = duplicateFileGroup.FileRecords.OrderBy(fr => fr.Size).Skip(1);
}
else
{
actionableFiles = duplicateFileGroup.FileRecords.Where(fr => !fr.Keep);
}
ZipArchive zipFile = null;
if(archive)
{
zipFile = ZipFile.Open(System.IO.Path.Combine(Properties.Settings.Default.ArchiveFolder, duplicateFileGroup.Hash + ".zip"), ZipArchiveMode.Update);
}
if(archive && zipFile != null)
{
//Zip everything up.
foreach(var file in actionableFiles)
{
zipFile.CreateEntryFromFile(file.Path.LocalPath, System.IO.Path.GetFileName(file.Path.LocalPath));
}
zipFile.Dispose();
}
foreach(var file in actionableFiles)
{
//Do the deletion
File.Delete(file.Path.LocalPath);
this.Database.RemoveFileRecord(file.Id);
}
SetDuplicateFileCollection(GetDuplicateFiles());
}
}).Start();
ProcessDuplicateFileGroups(tag, archive, duplicateFileGroup);
}
private void PerformDuplicateActionAll_Click(object sender, RoutedEventArgs e)
{
var tag = (sender as System.Windows.Controls.Button).Tag.ToString();
var duplicateFileGroups = new List<DuplicateFileGroup>();
var actionableFiles = new List<FileRecord>();
var archive = this.checkboxArchiveRemainingFiles.IsChecked ?? false;
foreach(var item in this.listBoxDupes.Items)
{
duplicateFileGroups.Add(item as DuplicateFileGroup);
}
this.ScanResults.SelectedDuplicateFileGroup = null;
ResetMediaPreview();
this.IsEnabled = false;
new Thread(() =>
{
foreach(var duplicateFileGroup in duplicateFileGroups)
{
if(tag == "largest")
{
actionableFiles.AddRange(duplicateFileGroup.FileRecords.Where(fr => !fr.Keep).OrderByDescending(fr => fr.Size).Skip(1));
}
else if(tag == "smallest")
{
actionableFiles.AddRange(duplicateFileGroup.FileRecords.Where(fr => !fr.Keep).OrderBy(fr => fr.Size).Skip(1));
}
}
var zipFile = ZipFile.Open(System.IO.Path.Combine(Properties.Settings.Default.ArchiveFolder, "archive.zip"), ZipArchiveMode.Update);
//Zip all the actionable files at once.
if(zipFile != null)
{
foreach(var file in actionableFiles)
{
zipFile.CreateEntryFromFile(file.Path.LocalPath, System.IO.Path.GetFileName(file.Path.LocalPath));
}
zipFile.Dispose();
foreach(var file in actionableFiles)
{
//Do the deletions
File.Delete(file.Path.LocalPath);
this.Database.RemoveFileRecord(file.Id);
}
}
SetDuplicateFileCollection(GetDuplicateFiles());
Dispatcher.Invoke(() => this.IsEnabled = true);
}).Start();
ProcessDuplicateFileGroups(tag, archive, duplicateFileGroups.ToArray());
}
/// <summary>

View File

@ -1,6 +1,4 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
@ -30,7 +28,6 @@ using System.Windows;
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
@ -40,7 +37,6 @@ using System.Windows;
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
@ -51,5 +47,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("0.9.0.0")]
[assembly: AssemblyFileVersion("0.9.0.0")]

View File

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace mdfinder
{
@ -13,10 +10,11 @@ namespace mdfinder
/// <summary> The duplicate files. </summary>
private IEnumerable<DuplicateFileGroup> duplicateFiles;
/// <summary> The selected duplicate file group. </summary>
private DuplicateFileGroup selectedDuplicateFileGroup;
#endregion
#endregion Members
#region Properties
@ -50,7 +48,17 @@ namespace mdfinder
}
}
#endregion
/// <summary> Gets the statistics string. </summary>
/// <value> The statistics string. </value>
public string Statistics
{
get
{
return string.Format("{0} Duplicates", this.duplicateFiles.Sum(df => df.Count - 1));
}
}
#endregion Properties
#region Constructors
@ -58,8 +66,10 @@ namespace mdfinder
{
this.duplicateFiles = Enumerable.Empty<DuplicateFileGroup>();
this.selectedDuplicateFileGroup = new DuplicateFileGroup(Enumerable.Empty<FileRecord>());
this.AddConstantCallProperty("Statistics");
}
#endregion
#endregion Constructors
}
}
}