mirror of
				https://github.com/wagesj45/mdfinder.git
				synced 2025-09-09 03:20:38 -05:00 
			
		
		
		
	Ugly Safety Checkin
Everything works. Mostly. It is kinda of flimsy so it needs to be cleaned up.
This commit is contained in:
		
					parent
					
						
							
								be05120bdb
							
						
					
				
			
			
				commit
				
					
						1de70724b0
					
				
			
		
					 17 changed files with 885 additions and 145 deletions
				
			
		| 
						 | 
					@ -36,6 +36,9 @@
 | 
				
			||||||
      <setting name="Language" serializeAs="String">
 | 
					      <setting name="Language" serializeAs="String">
 | 
				
			||||||
        <value>en-US</value>
 | 
					        <value>en-US</value>
 | 
				
			||||||
      </setting>
 | 
					      </setting>
 | 
				
			||||||
 | 
					      <setting name="ArchiveFolder" serializeAs="String">
 | 
				
			||||||
 | 
					        <value />
 | 
				
			||||||
 | 
					      </setting>
 | 
				
			||||||
    </mdfinder.Properties.Settings>
 | 
					    </mdfinder.Properties.Settings>
 | 
				
			||||||
  </userSettings>
 | 
					  </userSettings>
 | 
				
			||||||
</configuration>
 | 
					</configuration>
 | 
				
			||||||
| 
						 | 
					@ -63,8 +63,15 @@ namespace mdfinder
 | 
				
			||||||
        /// <param name="hashProvider"> The hash provider. </param>
 | 
					        /// <param name="hashProvider"> The hash provider. </param>
 | 
				
			||||||
        public void InsertFileRecord(string path, long size, string hash, string hashProvider)
 | 
					        public void InsertFileRecord(string path, long size, string hash, string hashProvider)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var fileRecord = new FileRecord() { Path = new Uri(path), Size = size, Hash = hash, HashProvider = hashProvider };
 | 
					            var fileRecord = new FileRecord(path, size, hash, hashProvider);
 | 
				
			||||||
            this.FileRecordCollection.Insert(fileRecord);
 | 
					            this.FileRecordCollection.Upsert(fileRecord);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Removes the file record described by ID. </summary>
 | 
				
			||||||
 | 
					        /// <param name="id"> The identifier. </param>
 | 
				
			||||||
 | 
					        public void RemoveFileRecord(string path)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.FileRecordCollection.Delete(fr => fr.Id == path);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary> Gets the file records in this collection. </summary>
 | 
					        /// <summary> Gets the file records in this collection. </summary>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										77
									
								
								mdfinder/DuplicateFileGroup.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								mdfinder/DuplicateFileGroup.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,77 @@
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace mdfinder
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class DuplicateFileGroup : PropertyChangedAlerter
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        #region Properties
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Gets the hash. </summary>
 | 
				
			||||||
 | 
					        /// <value> The hash. </value>
 | 
				
			||||||
 | 
					        public string Hash { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Gets the number of.  </summary>
 | 
				
			||||||
 | 
					        /// <value> The count. </value>
 | 
				
			||||||
 | 
					        public int Count { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Gets the total size of the file group. </summary>
 | 
				
			||||||
 | 
					        /// <value> The total number of size. </value>
 | 
				
			||||||
 | 
					        public long TotalSize { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Gets the potential size saving. </summary>
 | 
				
			||||||
 | 
					        /// <value> The potential size saving. </value>
 | 
				
			||||||
 | 
					        public long PotentialSizeSaving { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Gets or sets the file records. </summary>
 | 
				
			||||||
 | 
					        /// <value> The file records. </value>
 | 
				
			||||||
 | 
					        public List<FileRecord> FileRecords { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Constructor. </summary>
 | 
				
			||||||
 | 
					        /// <param name="fileRecords"> The file records. </param>
 | 
				
			||||||
 | 
					        /// <param name="savingsType"> (Optional) Type of the size savings to calculate. </param>
 | 
				
			||||||
 | 
					        public DuplicateFileGroup(IEnumerable<FileRecord> fileRecords, SavingsType savingsType = SavingsType.SaveBiggest)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.FileRecords = new List<FileRecord>(fileRecords);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //Precalculate stats.
 | 
				
			||||||
 | 
					            this.Hash = this.FileRecords.Select(fr => fr.Hash).FirstOrDefault();
 | 
				
			||||||
 | 
					            this.Count = this.FileRecords.Count();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.TotalSize = this.FileRecords.Sum(fr => fr.Size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            switch (savingsType)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case SavingsType.SaveBiggest:
 | 
				
			||||||
 | 
					                    this.PotentialSizeSaving = this.FileRecords.OrderByDescending(fr => fr.Size).Skip(1).Sum(fr => fr.Size); 
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case SavingsType.SaveSmallest:
 | 
				
			||||||
 | 
					                    this.PotentialSizeSaving = this.FileRecords.OrderBy(fr => fr.Size).Skip(1).Sum(fr => fr.Size);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case SavingsType.SaveMedian:
 | 
				
			||||||
 | 
					                    //This is kind of hacky, but good enough for our purposes here. CLOSE ENOUGH
 | 
				
			||||||
 | 
					                    var medianFileRecord = this.FileRecords.OrderBy(fr => fr.Size).ElementAt(this.Count / 2);
 | 
				
			||||||
 | 
					                    this.PotentialSizeSaving = this.FileRecords.Except(new[] { medianFileRecord }).Sum(fr => fr.Size);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Values that represent the ways of saving space. </summary>
 | 
				
			||||||
 | 
					        public enum SavingsType
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /// <summary> Saves the biggest, and presumably highest quality, file. </summary>
 | 
				
			||||||
 | 
					            SaveBiggest,
 | 
				
			||||||
 | 
					            /// <summary> Saves the smallest file. </summary>
 | 
				
			||||||
 | 
					            SaveSmallest,
 | 
				
			||||||
 | 
					            /// <summary> . </summary>
 | 
				
			||||||
 | 
					            SaveMedian
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -6,29 +6,149 @@ using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace mdfinder
 | 
					namespace mdfinder
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public class FileRecord
 | 
					    public class FileRecord : PropertyChangedAlerter
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        #region Members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> The identifier. </summary>
 | 
				
			||||||
 | 
					        private string id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Full pathname of the file. </summary>
 | 
				
			||||||
 | 
					        private Uri path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> The size. </summary>
 | 
				
			||||||
 | 
					        private long size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> The hash. </summary>
 | 
				
			||||||
 | 
					        private string hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> The hash provider. </summary>
 | 
				
			||||||
 | 
					        private string hashProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> True to keep. </summary>
 | 
				
			||||||
 | 
					        private bool keep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #region Properties
 | 
					        #region Properties
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary> Gets or sets the identifier. </summary>
 | 
					        /// <summary> Gets or sets the identifier. </summary>
 | 
				
			||||||
        /// <value> The identifier. </value>
 | 
					        /// <value> The identifier. </value>
 | 
				
			||||||
        public Int64 Id { get; set; }
 | 
					        public string Id
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return this.id;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.id = value;
 | 
				
			||||||
 | 
					                OnPropertyChanged();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary> Gets or sets the full pathname of the file. </summary>
 | 
					        /// <summary> Gets or sets the full pathname of the file. </summary>
 | 
				
			||||||
        /// <value> The full pathname of the file. </value>
 | 
					        /// <value> The full pathname of the file. </value>
 | 
				
			||||||
        public Uri Path { get; set; }
 | 
					        public Uri Path
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return this.path;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.path = value;
 | 
				
			||||||
 | 
					                OnPropertyChanged();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary> Gets or sets the size. </summary>
 | 
					        /// <summary> Gets or sets the size. </summary>
 | 
				
			||||||
        /// <value> The size. </value>
 | 
					        /// <value> The size. </value>
 | 
				
			||||||
        public long Size { get; set; }
 | 
					        public long Size
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return this.size;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.size = value;
 | 
				
			||||||
 | 
					                OnPropertyChanged();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary> Gets or sets the hash. </summary>
 | 
					        /// <summary> Gets or sets the hash. </summary>
 | 
				
			||||||
        /// <value> The hash. </value>
 | 
					        /// <value> The hash. </value>
 | 
				
			||||||
        public string Hash { get; set; }
 | 
					        public string Hash
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return this.hash;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.hash = value;
 | 
				
			||||||
 | 
					                OnPropertyChanged();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary> Gets or sets the hash provider. </summary>
 | 
					        /// <summary> Gets or sets the hash provider. </summary>
 | 
				
			||||||
        /// <value> The hash provider. </value>
 | 
					        /// <value> The hash provider. </value>
 | 
				
			||||||
        public string HashProvider { get; set; }
 | 
					        public string HashProvider
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return this.hashProvider;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.hashProvider = value;
 | 
				
			||||||
 | 
					                OnPropertyChanged();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Gets or sets a value indicating whether to keep the file when processing duplicates. </summary>
 | 
				
			||||||
 | 
					        /// <value> True if keep, false if not. </value>
 | 
				
			||||||
 | 
					        public bool Keep
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return this.keep;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.keep = value;
 | 
				
			||||||
 | 
					                OnPropertyChanged();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Constructors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public FileRecord()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Id = string.Empty;
 | 
				
			||||||
 | 
					            this.Path = default(Uri);
 | 
				
			||||||
 | 
					            this.Size = 0;
 | 
				
			||||||
 | 
					            this.Hash = string.Empty;
 | 
				
			||||||
 | 
					            this.HashProvider = string.Empty;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Constructor. </summary>
 | 
				
			||||||
 | 
					        /// <param name="path">         Full pathname of the file. </param>
 | 
				
			||||||
 | 
					        /// <param name="size">         The size. </param>
 | 
				
			||||||
 | 
					        /// <param name="hash">         The hash. </param>
 | 
				
			||||||
 | 
					        /// <param name="hashProvider"> The hash provider. </param>
 | 
				
			||||||
 | 
					        public FileRecord(string path, long size, string hash, string hashProvider)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Id = path;
 | 
				
			||||||
 | 
					            this.Path = new Uri(path);
 | 
				
			||||||
 | 
					            this.Size = size;
 | 
				
			||||||
 | 
					            this.Hash = hash;
 | 
				
			||||||
 | 
					            this.HashProvider = hashProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -170,4 +170,49 @@
 | 
				
			||||||
            </Path>
 | 
					            </Path>
 | 
				
			||||||
        </Viewbox>
 | 
					        </Viewbox>
 | 
				
			||||||
    </ControlTemplate>
 | 
					    </ControlTemplate>
 | 
				
			||||||
 | 
					    <ControlTemplate x:Key="LargeFileIcon">
 | 
				
			||||||
 | 
					        <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"/>
 | 
				
			||||||
 | 
					                </Path.Data>
 | 
				
			||||||
 | 
					            </Path>
 | 
				
			||||||
 | 
					        </Viewbox>
 | 
				
			||||||
 | 
					    </ControlTemplate>
 | 
				
			||||||
 | 
					    <ControlTemplate x:Key="SmallFileIcon">
 | 
				
			||||||
 | 
					        <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"/>
 | 
				
			||||||
 | 
					                </Path.Data>
 | 
				
			||||||
 | 
					            </Path>
 | 
				
			||||||
 | 
					        </Viewbox>
 | 
				
			||||||
 | 
					    </ControlTemplate>
 | 
				
			||||||
 | 
					    <ControlTemplate x:Key="SelectedFileIcon">
 | 
				
			||||||
 | 
					        <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"/>
 | 
				
			||||||
 | 
					                </Path.Data>
 | 
				
			||||||
 | 
					            </Path>
 | 
				
			||||||
 | 
					        </Viewbox>
 | 
				
			||||||
 | 
					    </ControlTemplate>
 | 
				
			||||||
 | 
					    <ControlTemplate x:Key="OpenFileIcon">
 | 
				
			||||||
 | 
					        <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"/>
 | 
				
			||||||
 | 
					                </Path.Data>
 | 
				
			||||||
 | 
					            </Path>
 | 
				
			||||||
 | 
					        </Viewbox>
 | 
				
			||||||
 | 
					    </ControlTemplate>
 | 
				
			||||||
 | 
					    <ControlTemplate x:Key="NoPreviewIcon">
 | 
				
			||||||
 | 
					        <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"/>
 | 
				
			||||||
 | 
					                </Path.Data>
 | 
				
			||||||
 | 
					            </Path>
 | 
				
			||||||
 | 
					        </Viewbox>
 | 
				
			||||||
 | 
					    </ControlTemplate>
 | 
				
			||||||
</ResourceDictionary>
 | 
					</ResourceDictionary>
 | 
				
			||||||
							
								
								
									
										125
									
								
								mdfinder/Localization/Localization.Designer.cs
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										125
									
								
								mdfinder/Localization/Localization.Designer.cs
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -106,7 +106,16 @@ namespace mdfinder.Localization {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to Actions.
 | 
					        ///   Looks up a localized string similar to Archive Remaining Files.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string ActionArchiveLabel {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("ActionArchiveLabel", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Duplicate Actions.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public static string ActionBarLabel {
 | 
					        public static string ActionBarLabel {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
| 
						 | 
					@ -114,6 +123,42 @@ namespace mdfinder.Localization {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Keep Largest.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string ActionLargestLabel {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("ActionLargestLabel", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to KeepSelected.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string ActionSelectedLabel {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("ActionSelectedLabel", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Keep Smallest.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string ActionSmallestLabel {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("ActionSmallestLabel", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Archive Folder.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string ArchiveFolderLabel {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("ArchiveFolderLabel", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to Would you like to visit mdfinder to update to the latest version?.
 | 
					        ///   Looks up a localized string similar to Would you like to visit mdfinder to update to the latest version?.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
| 
						 | 
					@ -159,6 +204,15 @@ namespace mdfinder.Localization {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Keep File.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string ColumnHeaderKeep {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("ColumnHeaderKeep", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to Hash.
 | 
					        ///   Looks up a localized string similar to Hash.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
| 
						 | 
					@ -268,29 +322,11 @@ namespace mdfinder.Localization {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to Filters.
 | 
					        ///   Looks up a localized string similar to Files.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public static string FilterBarLabel {
 | 
					        public static string FilesLabel {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                return ResourceManager.GetString("FilterBarLabel", resourceCulture);
 | 
					                return ResourceManager.GetString("FilesLabel", resourceCulture);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        ///   Looks up a localized string similar to Duplicates.
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        public static string FilterDuplicatesLabel {
 | 
					 | 
				
			||||||
            get {
 | 
					 | 
				
			||||||
                return ResourceManager.GetString("FilterDuplicatesLabel", resourceCulture);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        ///   Looks up a localized string similar to Show All.
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        public static string FilterShowAllLabel {
 | 
					 | 
				
			||||||
            get {
 | 
					 | 
				
			||||||
                return ResourceManager.GetString("FilterShowAllLabel", resourceCulture);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
| 
						 | 
					@ -330,6 +366,15 @@ namespace mdfinder.Localization {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to No Preview Available.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string NoPreviewLabel {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("NoPreviewLabel", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to OK.
 | 
					        ///   Looks up a localized string similar to OK.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
| 
						 | 
					@ -384,6 +429,15 @@ namespace mdfinder.Localization {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Potential Space Savings.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string PotentialSpaceSavingsLabel {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("PotentialSpaceSavingsLabel", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to Provider Location.
 | 
					        ///   Looks up a localized string similar to Provider Location.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
| 
						 | 
					@ -429,6 +483,15 @@ namespace mdfinder.Localization {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Scan Location.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string ScanningLabel {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("ScanningLabel", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to Scan the selected path.
 | 
					        ///   Looks up a localized string similar to Scan the selected path.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
| 
						 | 
					@ -438,6 +501,24 @@ namespace mdfinder.Localization {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Size:.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string SizeLabel {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("SizeLabel", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Size On Disk:.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string SizeOnDiskLabel {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("SizeOnDiskLabel", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to Skip Empty Files.
 | 
					        ///   Looks up a localized string similar to Skip Empty Files.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,8 +132,17 @@
 | 
				
			||||||
  <data name="AboutWindowTitle" xml:space="preserve">
 | 
					  <data name="AboutWindowTitle" xml:space="preserve">
 | 
				
			||||||
    <value>About mdfinder</value>
 | 
					    <value>About mdfinder</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="ActionArchiveLabel" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Archive Remaining Files</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
  <data name="ActionBarLabel" xml:space="preserve">
 | 
					  <data name="ActionBarLabel" xml:space="preserve">
 | 
				
			||||||
    <value>Actions</value>
 | 
					    <value>Duplicate Actions</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="ActionLargestLabel" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Keep Largest</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="ActionSmallestLabel" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Keep Smallest</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="BehindVersionQuestion" xml:space="preserve">
 | 
					  <data name="BehindVersionQuestion" xml:space="preserve">
 | 
				
			||||||
    <value>Would you like to visit mdfinder to update to the latest version?</value>
 | 
					    <value>Would you like to visit mdfinder to update to the latest version?</value>
 | 
				
			||||||
| 
						 | 
					@ -186,14 +195,8 @@
 | 
				
			||||||
  <data name="FileMenu" xml:space="preserve">
 | 
					  <data name="FileMenu" xml:space="preserve">
 | 
				
			||||||
    <value>File</value>
 | 
					    <value>File</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="FilterBarLabel" xml:space="preserve">
 | 
					  <data name="FilesLabel" xml:space="preserve">
 | 
				
			||||||
    <value>Filters</value>
 | 
					    <value>Files</value>
 | 
				
			||||||
  </data>
 | 
					 | 
				
			||||||
  <data name="FilterDuplicatesLabel" xml:space="preserve">
 | 
					 | 
				
			||||||
    <value>Duplicates</value>
 | 
					 | 
				
			||||||
  </data>
 | 
					 | 
				
			||||||
  <data name="FilterShowAllLabel" xml:space="preserve">
 | 
					 | 
				
			||||||
    <value>Show All</value>
 | 
					 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="HelpMenu" xml:space="preserve">
 | 
					  <data name="HelpMenu" xml:space="preserve">
 | 
				
			||||||
    <value>Help</value>
 | 
					    <value>Help</value>
 | 
				
			||||||
| 
						 | 
					@ -240,9 +243,15 @@
 | 
				
			||||||
  <data name="ScanLocationLabel" xml:space="preserve">
 | 
					  <data name="ScanLocationLabel" xml:space="preserve">
 | 
				
			||||||
    <value>Location to Scan</value>
 | 
					    <value>Location to Scan</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="ScanningLabel" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Scan Location</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
  <data name="ScanTooltip" xml:space="preserve">
 | 
					  <data name="ScanTooltip" xml:space="preserve">
 | 
				
			||||||
    <value>Scan the selected path</value>
 | 
					    <value>Scan the selected path</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="SizeLabel" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Size:</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
  <data name="SkipEmptyFilesLabel" xml:space="preserve">
 | 
					  <data name="SkipEmptyFilesLabel" xml:space="preserve">
 | 
				
			||||||
    <value>Skip Empty Files</value>
 | 
					    <value>Skip Empty Files</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
| 
						 | 
					@ -255,4 +264,22 @@
 | 
				
			||||||
  <data name="VersionLabel" xml:space="preserve">
 | 
					  <data name="VersionLabel" xml:space="preserve">
 | 
				
			||||||
    <value>Version</value>
 | 
					    <value>Version</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="ActionSelectedLabel" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>KeepSelected</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="ArchiveFolderLabel" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Archive Folder</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="ColumnHeaderKeep" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Keep File</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="NoPreviewLabel" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>No Preview Available</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="PotentialSpaceSavingsLabel" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Potential Space Savings</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="SizeOnDiskLabel" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Size On Disk:</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
</root>
 | 
					</root>
 | 
				
			||||||
| 
						 | 
					@ -3,10 +3,11 @@
 | 
				
			||||||
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 | 
					        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 | 
				
			||||||
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 | 
					        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 | 
				
			||||||
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 | 
					        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 | 
				
			||||||
 | 
					        xmlns:gu="https://github.com/JohanLarsson/Gu.Wpf.Media"
 | 
				
			||||||
        xmlns:mdfinder="clr-namespace:mdfinder"
 | 
					        xmlns:mdfinder="clr-namespace:mdfinder"
 | 
				
			||||||
        xmlns:loc="clr-namespace:mdfinder.Localization"
 | 
					        xmlns:loc="clr-namespace:mdfinder.Localization"
 | 
				
			||||||
        mc:Ignorable="d"
 | 
					        mc:Ignorable="d"
 | 
				
			||||||
        Title="{x:Static loc:Localization.Title}" Height="450" Width="800">
 | 
					        Title="{x:Static loc:Localization.Title}" Height="520.293" Width="814.505">
 | 
				
			||||||
    <Window.Resources>
 | 
					    <Window.Resources>
 | 
				
			||||||
        <mdfinder:InverseBoolConverter x:Key="InverseBoolConverter" />
 | 
					        <mdfinder:InverseBoolConverter x:Key="InverseBoolConverter" />
 | 
				
			||||||
        <mdfinder:BoolVisibilityConverter x:Key="BoolVisibilityConverter" />
 | 
					        <mdfinder:BoolVisibilityConverter x:Key="BoolVisibilityConverter" />
 | 
				
			||||||
| 
						 | 
					@ -62,7 +63,7 @@
 | 
				
			||||||
                    <Button Grid.Column="2" MinWidth="25" Name="btnFilePicker" Click="btnFilePicker_Click">...</Button>
 | 
					                    <Button Grid.Column="2" MinWidth="25" Name="btnFilePicker" Click="btnFilePicker_Click">...</Button>
 | 
				
			||||||
                </Grid>
 | 
					                </Grid>
 | 
				
			||||||
            </GroupBox>
 | 
					            </GroupBox>
 | 
				
			||||||
            <GroupBox Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="1" Header="{x:Static loc:Localization.ActionBarLabel}">
 | 
					            <GroupBox Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="1" Header="{x:Static loc:Localization.ScanningLabel}">
 | 
				
			||||||
                <Grid>
 | 
					                <Grid>
 | 
				
			||||||
                    <Grid.RowDefinitions>
 | 
					                    <Grid.RowDefinitions>
 | 
				
			||||||
                        <RowDefinition Height="32" />
 | 
					                        <RowDefinition Height="32" />
 | 
				
			||||||
| 
						 | 
					@ -85,80 +86,168 @@
 | 
				
			||||||
                    </Button>
 | 
					                    </Button>
 | 
				
			||||||
                </Grid>
 | 
					                </Grid>
 | 
				
			||||||
            </GroupBox>
 | 
					            </GroupBox>
 | 
				
			||||||
            <GroupBox Grid.Column="1"  Grid.ColumnSpan="3" Grid.Row="1" Header="{x:Static loc:Localization.FilterBarLabel}">
 | 
					            <GroupBox Grid.Column="1"  Grid.ColumnSpan="3" Grid.Row="1" Header="{x:Static loc:Localization.ActionBarLabel}">
 | 
				
			||||||
                <Grid>
 | 
					                <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="1">
 | 
				
			||||||
                    <Grid.RowDefinitions>
 | 
					                    <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">
 | 
				
			||||||
                        <RowDefinition Height="32" />
 | 
					 | 
				
			||||||
                    </Grid.RowDefinitions>
 | 
					 | 
				
			||||||
                    <Grid.ColumnDefinitions>
 | 
					 | 
				
			||||||
                        <ColumnDefinition Width="Auto" />
 | 
					 | 
				
			||||||
                        <ColumnDefinition Width="Auto" />
 | 
					 | 
				
			||||||
                    </Grid.ColumnDefinitions>
 | 
					 | 
				
			||||||
                    <Button Grid.Row="0" Grid.Column="0" Name="btnFilterShowAll" 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="BtnFilterShowAll_Click" >
 | 
					 | 
				
			||||||
                        <StackPanel Orientation="Horizontal">
 | 
					                        <StackPanel Orientation="Horizontal">
 | 
				
			||||||
                            <ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource ShowAllIcon}" />
 | 
					                            <ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource LargeFileIcon}" />
 | 
				
			||||||
                            <Label Content="{x:Static loc:Localization.FilterShowAllLabel}" />
 | 
					                            <Label Content="{x:Static loc:Localization.ActionLargestLabel}" />
 | 
				
			||||||
                        </StackPanel>
 | 
					                        </StackPanel>
 | 
				
			||||||
                    </Button>
 | 
					                    </Button>
 | 
				
			||||||
                    <Button Grid.Row="0" Grid.Column="1" Name="btnFilterDuplicates" 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="BtnFilterDuplicates_Click" >
 | 
					                    <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">
 | 
				
			||||||
                        <StackPanel Orientation="Horizontal">
 | 
					                        <StackPanel Orientation="Horizontal">
 | 
				
			||||||
                            <ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource DuplicateIcon}" />
 | 
					                            <ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource SmallFileIcon}" />
 | 
				
			||||||
                            <Label Content="{x:Static loc:Localization.FilterDuplicatesLabel}" />
 | 
					                            <Label Content="{x:Static loc:Localization.ActionSmallestLabel}" />
 | 
				
			||||||
                        </StackPanel>
 | 
					                        </StackPanel>
 | 
				
			||||||
                    </Button>
 | 
					                    </Button>
 | 
				
			||||||
                </Grid>
 | 
					                    <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">
 | 
				
			||||||
 | 
					                        <StackPanel Orientation="Horizontal">
 | 
				
			||||||
 | 
					                            <ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource SelectedFileIcon}" />
 | 
				
			||||||
 | 
					                            <Label Content="{x:Static loc:Localization.ActionSelectedLabel}" />
 | 
				
			||||||
 | 
					                        </StackPanel>
 | 
				
			||||||
 | 
					                    </Button>
 | 
				
			||||||
 | 
					                    <CheckBox Name="checkboxArchiveRemainingFiles" VerticalAlignment="Center" IsChecked="True" Content="{x:Static loc:Localization.ActionArchiveLabel}" />
 | 
				
			||||||
 | 
					                </StackPanel>
 | 
				
			||||||
            </GroupBox>
 | 
					            </GroupBox>
 | 
				
			||||||
            <DataGrid x:Name="datagridFileRecords" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Initialized="DatagridFileRecords_Initialized" IsReadOnly="True" AutoGenerateColumns="False">
 | 
					            <ListBox x:Name="listBoxDupes" Grid.Row="2" Grid.Column="0" Initialized="ListBoxDupes_Initialized" ItemsSource="{Binding ScanResults.DuplicateFiles, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}}" SelectionChanged="ListBoxDupes_SelectionChanged">
 | 
				
			||||||
                <DataGrid.Resources>
 | 
					                <ListBox.ItemTemplate>
 | 
				
			||||||
                    <Style TargetType="Hyperlink">
 | 
					                    <DataTemplate>
 | 
				
			||||||
                        <EventSetter Event="Click" Handler="Hyperlink_Click"/>
 | 
					                        <StackPanel Orientation="Horizontal">
 | 
				
			||||||
                    </Style>
 | 
					                            <Label Content="{Binding Count}" />
 | 
				
			||||||
                    <Style TargetType="{x:Type DataGridCell}">
 | 
					                            <Label Content="{x:Static loc:Localization.FilesLabel}" />
 | 
				
			||||||
                        <Style.Triggers>
 | 
					                            <Label Content="|" />
 | 
				
			||||||
                            <Trigger Property="DataGridCell.IsSelected" Value="True">
 | 
					                            <Label Content="{x:Static loc:Localization.SizeLabel}" />
 | 
				
			||||||
                                <Setter Property="Background" Value="Black" />
 | 
					                            <Label Content="{Binding TotalSize, Converter={StaticResource SizeConverter}}" />
 | 
				
			||||||
                            </Trigger>
 | 
					                        </StackPanel>
 | 
				
			||||||
                        </Style.Triggers>
 | 
					                    </DataTemplate>
 | 
				
			||||||
                    </Style>
 | 
					                </ListBox.ItemTemplate>
 | 
				
			||||||
                </DataGrid.Resources>
 | 
					            </ListBox>
 | 
				
			||||||
                <DataGrid.Columns>
 | 
					            <Grid x:Name="gridDuplicates" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" DataContext="{Binding SelectedItem, ElementName=listBoxDupe}">
 | 
				
			||||||
                    <DataGridHyperlinkColumn Header="{x:Static loc:Localization.ColumnHeadingPath}" Binding="{Binding Path}" ContentBinding="{Binding Path, Converter={StaticResource URIConverter}}" Width="Auto" IsReadOnly="True" />
 | 
					                <Grid.RowDefinitions>
 | 
				
			||||||
                    <DataGridTextColumn Header="{x:Static loc:Localization.ColumnHeadingSize}" Binding="{Binding Size, Converter={StaticResource SizeConverter}}" />
 | 
					                    <RowDefinition Height="Auto" />
 | 
				
			||||||
                    <DataGridTextColumn Header="{x:Static loc:Localization.ColumnHeadingHash}" Binding="{Binding Hash}" />
 | 
					                    <RowDefinition Height="*" />
 | 
				
			||||||
                    <DataGridTextColumn Header="{x:Static loc:Localization.ColumnHeadingHashProvider}" Binding="{Binding HashProvider}" />
 | 
					                </Grid.RowDefinitions>
 | 
				
			||||||
                </DataGrid.Columns>
 | 
					                <Grid.ColumnDefinitions>
 | 
				
			||||||
                <DataGrid.GroupStyle>
 | 
					                    <ColumnDefinition Width="*"/>
 | 
				
			||||||
                    <GroupStyle>
 | 
					                    <ColumnDefinition Width="*"/>
 | 
				
			||||||
                        <GroupStyle.HeaderTemplate>
 | 
					                </Grid.ColumnDefinitions>
 | 
				
			||||||
                            <DataTemplate>
 | 
					                <StackPanel Orientation="Vertical">
 | 
				
			||||||
                                <StackPanel>
 | 
					                    <StackPanel Orientation="Horizontal">
 | 
				
			||||||
                                    <TextBlock Text="{Binding Path=Hash}" />
 | 
					                        <Label Content="{x:Static loc:Localization.SizeOnDiskLabel}" />
 | 
				
			||||||
                                </StackPanel>
 | 
					                        <Label Content="{Binding ScanResults.SelectedDuplicateFileGroup.TotalSize, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, Converter={StaticResource SizeConverter}}" />
 | 
				
			||||||
                            </DataTemplate>
 | 
					                    </StackPanel>
 | 
				
			||||||
                        </GroupStyle.HeaderTemplate>
 | 
					                    <StackPanel Orientation="Horizontal">
 | 
				
			||||||
                        <GroupStyle.ContainerStyle>
 | 
					                        <Label Content="{x:Static loc:Localization.PotentialSpaceSavingsLabel}" />
 | 
				
			||||||
                            <Style TargetType="{x:Type GroupItem}">
 | 
					                        <Label Content="{Binding ScanResults.SelectedDuplicateFileGroup.PotentialSizeSaving, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}, Converter={StaticResource SizeConverter}}" />
 | 
				
			||||||
                                <Setter Property="Template">
 | 
					                    </StackPanel>
 | 
				
			||||||
                                    <Setter.Value>
 | 
					                </StackPanel>
 | 
				
			||||||
                                        <ControlTemplate TargetType="{x:Type GroupItem}">
 | 
					                <DataGrid Name="datagridFileList" Grid.Row="1" Grid.Column="0" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" ItemsSource="{Binding ScanResults.SelectedDuplicateFileGroup.FileRecords, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mdfinder:MainWindow}}}" SelectionChanged="DatagridFileList_SelectionChanged">
 | 
				
			||||||
                                            <Expander IsExpanded="True">
 | 
					                    <DataGrid.Resources>
 | 
				
			||||||
                                                <Expander.Header>
 | 
					                        <Style TargetType="Hyperlink">
 | 
				
			||||||
                                                    <StackPanel Orientation="Horizontal">
 | 
					                            <EventSetter Event="Click" Handler="Hyperlink_Click"/>
 | 
				
			||||||
                                                        <TextBlock Text="{Binding Path=Name}" />
 | 
					                            <Setter Property="Foreground" Value="DarkGreen"></Setter>
 | 
				
			||||||
                                                        <TextBlock Text="{Binding Path=ItemCount}"/>
 | 
					                            <Style.Triggers>
 | 
				
			||||||
                                                        <TextBlock Text="{x:Static loc:Localization.ItemsLabel}"/>
 | 
					                                <DataTrigger Binding="{Binding IsSelected, RelativeSource= {RelativeSource AncestorType={x:Type DataGridRow}}}" Value="True">
 | 
				
			||||||
                                                    </StackPanel>
 | 
					                                    <Setter Property="Foreground" Value="White" />
 | 
				
			||||||
                                                </Expander.Header>
 | 
					                                </DataTrigger>
 | 
				
			||||||
                                                <ItemsPresenter />
 | 
					                            </Style.Triggers>
 | 
				
			||||||
                                            </Expander>
 | 
					                        </Style>
 | 
				
			||||||
                                        </ControlTemplate>
 | 
					                    </DataGrid.Resources>
 | 
				
			||||||
                                    </Setter.Value>
 | 
					                    <DataGrid.Columns>
 | 
				
			||||||
                                </Setter>
 | 
					                        <DataGridTemplateColumn>
 | 
				
			||||||
                            </Style>
 | 
					                            <DataGridTemplateColumn.CellTemplate>
 | 
				
			||||||
                        </GroupStyle.ContainerStyle>
 | 
					                                <DataTemplate>
 | 
				
			||||||
                    </GroupStyle>
 | 
					                                    <TextBlock>
 | 
				
			||||||
                </DataGrid.GroupStyle>
 | 
					                                        <Hyperlink Click="Hyperlink_Click" NavigateUri="{Binding Path}">
 | 
				
			||||||
            </DataGrid>
 | 
					                                            <ContentControl Grid.Column="0" Template="{StaticResource OpenFileIcon}" Width="16" Margin="0,0,4,0" />
 | 
				
			||||||
 | 
					                                        </Hyperlink>
 | 
				
			||||||
 | 
					                                    </TextBlock>
 | 
				
			||||||
 | 
					                                </DataTemplate>
 | 
				
			||||||
 | 
					                            </DataGridTemplateColumn.CellTemplate>
 | 
				
			||||||
 | 
					                        </DataGridTemplateColumn>
 | 
				
			||||||
 | 
					                        <DataGridTextColumn IsReadOnly="True" Header="{x:Static loc:Localization.ColumnHeadingPath}" Binding="{Binding Path, Converter={StaticResource URIConverter}}" />
 | 
				
			||||||
 | 
					                        <DataGridTextColumn IsReadOnly="True" Header="{x:Static loc:Localization.ColumnHeadingSize}" Binding="{Binding Size, Converter={StaticResource SizeConverter}}"/>
 | 
				
			||||||
 | 
					                        <DataGridTemplateColumn Header="{x:Static loc:Localization.ColumnHeaderKeep}">
 | 
				
			||||||
 | 
					                            <DataGridTemplateColumn.CellTemplate>
 | 
				
			||||||
 | 
					                                <DataTemplate>
 | 
				
			||||||
 | 
					                                    <CheckBox IsChecked="{Binding Keep, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
 | 
				
			||||||
 | 
					                                </DataTemplate>
 | 
				
			||||||
 | 
					                            </DataGridTemplateColumn.CellTemplate>
 | 
				
			||||||
 | 
					                        </DataGridTemplateColumn>
 | 
				
			||||||
 | 
					                    </DataGrid.Columns>
 | 
				
			||||||
 | 
					                </DataGrid>
 | 
				
			||||||
 | 
					                <Grid Name="gridPreview" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2">
 | 
				
			||||||
 | 
					                    <Grid Name="mediaPreviewContainer" Visibility="Hidden">
 | 
				
			||||||
 | 
					                        <Grid.RowDefinitions>
 | 
				
			||||||
 | 
					                            <RowDefinition Height="*" />
 | 
				
			||||||
 | 
					                            <RowDefinition Height="Auto" />
 | 
				
			||||||
 | 
					                        </Grid.RowDefinitions>
 | 
				
			||||||
 | 
					                        <gu:MediaElementWrapper Name="mediaPreview" Grid.Row="0" Stretch="Uniform" />
 | 
				
			||||||
 | 
					                        <Grid Name="mediaBarPreview" Grid.Row="1" VerticalAlignment="Bottom" Background="#66666666">
 | 
				
			||||||
 | 
					                            <Grid.RowDefinitions>
 | 
				
			||||||
 | 
					                                <RowDefinition Height="Auto" />
 | 
				
			||||||
 | 
					                                <RowDefinition Height="Auto" />
 | 
				
			||||||
 | 
					                            </Grid.RowDefinitions>
 | 
				
			||||||
 | 
					                            <Slider x:Name="ProgressSlider" Grid.Row="0" gu:Drag.PauseWhileDragging="{Binding ElementName=mediaPreview}" Maximum="{Binding ElementName=mediaPreview, Path=Length, Converter={x:Static gu:NullableTimeSpanToSecondsConverter.Default}}" Minimum="0" Style="{StaticResource {x:Static gu:Styles.ProgressSliderStyleKey}}" Value="{Binding ElementName=mediaPreview, Path=Position, Converter={x:Static gu:NullableTimeSpanToSecondsConverter.Default}}" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            <Grid Grid.Row="1">
 | 
				
			||||||
 | 
					                                <Grid.Resources>
 | 
				
			||||||
 | 
					                                    <Style BasedOn="{StaticResource {x:Static gu:Styles.PlayerButtonBaseStyleKey}}" TargetType="{x:Type Button}" />
 | 
				
			||||||
 | 
					                                </Grid.Resources>
 | 
				
			||||||
 | 
					                                <Grid.ColumnDefinitions>
 | 
				
			||||||
 | 
					                                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
 | 
					                                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
 | 
					                                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
 | 
					                                    <ColumnDefinition />
 | 
				
			||||||
 | 
					                                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
 | 
					                                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
 | 
					                                </Grid.ColumnDefinitions>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                <ToggleButton x:Name="PlayPauseButton" Grid.Column="0" IsChecked="{Binding ElementName=mediaPreview, Path=IsPlaying}" IsEnabled="{Binding ElementName=mediaPreview, Path=HasMedia}">
 | 
				
			||||||
 | 
					                                    <ToggleButton.Style>
 | 
				
			||||||
 | 
					                                        <Style BasedOn="{StaticResource {x:Static gu:Styles.PlayerButtonBaseStyleKey}}" TargetType="{x:Type ToggleButton}">
 | 
				
			||||||
 | 
					                                            <Setter Property="gu:Icon.Geometry" Value="{StaticResource {x:Static gu:Geometries.PauseGeometryKey}}" />
 | 
				
			||||||
 | 
					                                            <Style.Triggers>
 | 
				
			||||||
 | 
					                                                <Trigger Property="IsChecked" Value="False">
 | 
				
			||||||
 | 
					                                                    <Setter Property="gu:Icon.Geometry" Value="{StaticResource {x:Static gu:Geometries.PlayGeometryKey}}" />
 | 
				
			||||||
 | 
					                                                </Trigger>
 | 
				
			||||||
 | 
					                                            </Style.Triggers>
 | 
				
			||||||
 | 
					                                        </Style>
 | 
				
			||||||
 | 
					                                    </ToggleButton.Style>
 | 
				
			||||||
 | 
					                                </ToggleButton>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                <ToggleButton x:Name="ToggleMutedButton" Grid.Column="1" IsChecked="{Binding ElementName=mediaPreview, Path=IsMuted}" IsEnabled="{Binding ElementName=mediaPreview, Path=HasMedia}">
 | 
				
			||||||
 | 
					                                    <ToggleButton.Style>
 | 
				
			||||||
 | 
					                                        <Style BasedOn="{StaticResource {x:Static gu:Styles.PlayerButtonBaseStyleKey}}" TargetType="{x:Type ToggleButton}">
 | 
				
			||||||
 | 
					                                            <Setter Property="gu:Icon.Geometry" Value="{StaticResource {x:Static gu:Geometries.UnMuteGeometryKey}}" />
 | 
				
			||||||
 | 
					                                            <Style.Triggers>
 | 
				
			||||||
 | 
					                                                <Trigger Property="IsChecked" Value="False">
 | 
				
			||||||
 | 
					                                                    <Setter Property="gu:Icon.Geometry" Value="{StaticResource {x:Static gu:Geometries.MuteGeometryKey}}" />
 | 
				
			||||||
 | 
					                                                </Trigger>
 | 
				
			||||||
 | 
					                                            </Style.Triggers>
 | 
				
			||||||
 | 
					                                        </Style>
 | 
				
			||||||
 | 
					                                    </ToggleButton.Style>
 | 
				
			||||||
 | 
					                                </ToggleButton>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                <TextBlock x:Name="ProgressTextBlock" Grid.Column="2" VerticalAlignment="Center" Foreground="{Binding ElementName=ToggleMutedButton, Path=Foreground}" Opacity="{Binding ElementName=ToggleMutedButton, Path=Opacity}">
 | 
				
			||||||
 | 
					                                    <TextBlock.Text>
 | 
				
			||||||
 | 
					                                        <MultiBinding StringFormat="{}{0} / {1}">
 | 
				
			||||||
 | 
					                                            <Binding Converter="{x:Static gu:TimeSpanToStringConverter.Default}" ElementName="MediaElement" Path="Position" />
 | 
				
			||||||
 | 
					                                            <Binding Converter="{x:Static gu:TimeSpanToStringConverter.Default}" ElementName="MediaElement" Path="Length" />
 | 
				
			||||||
 | 
					                                        </MultiBinding>
 | 
				
			||||||
 | 
					                                    </TextBlock.Text>
 | 
				
			||||||
 | 
					                                </TextBlock>
 | 
				
			||||||
 | 
					                            </Grid>
 | 
				
			||||||
 | 
					                        </Grid>
 | 
				
			||||||
 | 
					                    </Grid>
 | 
				
			||||||
 | 
					                    <Image Name="imagePreview" Visibility="Hidden" />
 | 
				
			||||||
 | 
					                    <TextBlock Name="textPreview" Visibility="Hidden" />
 | 
				
			||||||
 | 
					                    <StackPanel Name="stackNoPreview" Orientation="Vertical" VerticalAlignment="Center">
 | 
				
			||||||
 | 
					                        <ContentControl Grid.Column="0" Template="{StaticResource NoPreviewIcon}" Width="64" Margin="0,0,4,0" />
 | 
				
			||||||
 | 
					                        <Label HorizontalAlignment="Center" Content="{x:Static loc:Localization.NoPreviewLabel}" />
 | 
				
			||||||
 | 
					                    </StackPanel>
 | 
				
			||||||
 | 
					                </Grid>
 | 
				
			||||||
 | 
					            </Grid>
 | 
				
			||||||
            <Label x:Name="txtProgressLabel" Grid.Row="3" Grid.ColumnSpan="4" Panel.ZIndex="1"  />
 | 
					            <Label x:Name="txtProgressLabel" Grid.Row="3" Grid.ColumnSpan="4" Panel.ZIndex="1"  />
 | 
				
			||||||
            <ProgressBar Grid.Row="3" Grid.ColumnSpan="4" Name="progressBar" Minimum="0" Height="16"/>
 | 
					            <ProgressBar Grid.Row="3" Grid.ColumnSpan="4" Name="progressBar" Minimum="0" Height="16"/>
 | 
				
			||||||
        </Grid>
 | 
					        </Grid>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ using mdfinder.hashprovider;
 | 
				
			||||||
using System.Diagnostics;
 | 
					using System.Diagnostics;
 | 
				
			||||||
using System.Reflection;
 | 
					using System.Reflection;
 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.IO.Compression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace mdfinder
 | 
					namespace mdfinder
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -26,6 +27,16 @@ namespace mdfinder
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public partial class MainWindow : Window
 | 
					    public partial class MainWindow : Window
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        /// <summary> The media extentions. </summary>
 | 
				
			||||||
 | 
					        private static readonly string[] MEDIA_EXTENTIONS = new[] { ".AVI", ".MPG", ".MPEG", ".MP3", ".MP4", ".MKV", ".WAV" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> The image extentions. </summary>
 | 
				
			||||||
 | 
					        private static readonly string[] IMAGE_EXTENTIONS = new[] { ".JPG", ".JPEG", ".PNG", ".BMP", ".TIF", ".TIFF", ".ICO", "GIF" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> The text extentions. </summary>
 | 
				
			||||||
 | 
					        private static readonly string[] TEXT_EXTENTIONS = new[] { ".TXT", ".XML", ".HTM", ".HTML", ".JS", ".CSS" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #region Properties
 | 
					        #region Properties
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary> Gets or sets the database. </summary>
 | 
					        /// <summary> Gets or sets the database. </summary>
 | 
				
			||||||
| 
						 | 
					@ -44,6 +55,10 @@ namespace mdfinder
 | 
				
			||||||
        /// <value> The default provider. </value>
 | 
					        /// <value> The default provider. </value>
 | 
				
			||||||
        public IHashProvider DefaultProvider { get; set; }
 | 
					        public IHashProvider DefaultProvider { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Gets or sets the scan results. </summary>
 | 
				
			||||||
 | 
					        /// <value> The scan results. </value>
 | 
				
			||||||
 | 
					        public ScanResults ScanResults { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #region Constructors
 | 
					        #region Constructors
 | 
				
			||||||
| 
						 | 
					@ -55,6 +70,7 @@ namespace mdfinder
 | 
				
			||||||
            this.Scanner = new Scanner();
 | 
					            this.Scanner = new Scanner();
 | 
				
			||||||
            this.DefaultProvider = new MD5HashProvider();
 | 
					            this.DefaultProvider = new MD5HashProvider();
 | 
				
			||||||
            this.HashProviders = GetProviderPlugins();
 | 
					            this.HashProviders = GetProviderPlugins();
 | 
				
			||||||
 | 
					            this.ScanResults = new ScanResults();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.Scanner.DirectoryFound += (sender, args) => Dispatcher.Invoke(() => txtProgressLabel.Content = args.Directory.Name);
 | 
					            this.Scanner.DirectoryFound += (sender, args) => Dispatcher.Invoke(() => txtProgressLabel.Content = args.Directory.Name);
 | 
				
			||||||
            this.Scanner.FilesFound += (sender, args) =>
 | 
					            this.Scanner.FilesFound += (sender, args) =>
 | 
				
			||||||
| 
						 | 
					@ -87,17 +103,52 @@ namespace mdfinder
 | 
				
			||||||
        /// </returns>
 | 
					        /// </returns>
 | 
				
			||||||
        private IEnumerable<IHashProvider> GetProviderPlugins()
 | 
					        private IEnumerable<IHashProvider> GetProviderPlugins()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var directory = new DirectoryInfo(Properties.Settings.Default.ProviderFolder);
 | 
					            if (!string.IsNullOrWhiteSpace(Properties.Settings.Default.ProviderFolder) && Directory.Exists(Properties.Settings.Default.ProviderFolder))
 | 
				
			||||||
            foreach (var pluginFile in directory.GetFiles("*.dll"))
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var assembly = Assembly.LoadFrom(pluginFile.FullName);
 | 
					                var directory = new DirectoryInfo(Properties.Settings.Default.ProviderFolder);
 | 
				
			||||||
                foreach (var type in assembly.GetTypes().Where(t => t.GetInterface("IHashProvider") != null))
 | 
					                foreach (var pluginFile in directory.GetFiles("*.dll"))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    yield return Activator.CreateInstance(type) as IHashProvider;
 | 
					                    var assembly = Assembly.LoadFrom(pluginFile.FullName);
 | 
				
			||||||
 | 
					                    foreach (var type in assembly.GetTypes().Where(t => t.GetInterface("IHashProvider") != null))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        yield return Activator.CreateInstance(type) as IHashProvider;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Sets duplicate file collection. </summary>
 | 
				
			||||||
 | 
					        /// <param name="duplicates"> The duplicates. </param>
 | 
				
			||||||
 | 
					        private void SetDuplicateFileCollection(IEnumerable<DuplicateFileGroup> duplicates)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.ScanResults.DuplicateFiles = duplicates;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Gets the duplicate files in this collection. </summary>
 | 
				
			||||||
 | 
					        /// <returns>
 | 
				
			||||||
 | 
					        /// An enumerator that allows foreach to be used to process the duplicate files in this
 | 
				
			||||||
 | 
					        /// collection.
 | 
				
			||||||
 | 
					        /// </returns>
 | 
				
			||||||
 | 
					        private IEnumerable<DuplicateFileGroup> GetDuplicateFiles()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return this.Database.GetFileRecords().GroupBy(fr => fr.Hash).Where(g => g.Count() > 1).Select(g => new DuplicateFileGroup(g)).ToArray();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Resets the media preview. </summary>
 | 
				
			||||||
 | 
					        private void ResetMediaPreview()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.mediaPreview.Stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.mediaPreview.Source = null;
 | 
				
			||||||
 | 
					            this.imagePreview.Source = null;
 | 
				
			||||||
 | 
					            this.textPreview.Text = string.Empty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.mediaPreviewContainer.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					            this.imagePreview.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					            this.textPreview.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					            this.stackNoPreview.Visibility = Visibility.Visible;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary> Event handler. Called by btnFilePicker for click events. </summary>
 | 
					        /// <summary> Event handler. Called by btnFilePicker for click events. </summary>
 | 
				
			||||||
        /// <param name="sender"> Source of the event. </param>
 | 
					        /// <param name="sender"> Source of the event. </param>
 | 
				
			||||||
        /// <param name="e">      Routed event information. </param>
 | 
					        /// <param name="e">      Routed event information. </param>
 | 
				
			||||||
| 
						 | 
					@ -117,49 +168,27 @@ namespace mdfinder
 | 
				
			||||||
        private void btnScan_Click(object sender, RoutedEventArgs e)
 | 
					        private void btnScan_Click(object sender, RoutedEventArgs e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var location = txtScanLocation.Text;
 | 
					            var location = txtScanLocation.Text;
 | 
				
			||||||
 | 
					            ResetMediaPreview();
 | 
				
			||||||
            if (!this.Scanner.IsScanning)
 | 
					            if (!this.Scanner.IsScanning)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                new Thread(() =>
 | 
					                new Thread(() =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    this.Scanner.Scan(location);
 | 
					                    this.Scanner.Scan(location);
 | 
				
			||||||
                    this.Dispatcher.Invoke(() => txtProgressLabel.Content = string.Empty);
 | 
					                    this.Dispatcher.Invoke(() => txtProgressLabel.Content = string.Empty);
 | 
				
			||||||
                    this.Dispatcher.Invoke(() => datagridFileRecords.ItemsSource = this.Database.GetFileRecords());
 | 
					                    this.Dispatcher.Invoke(() => progressBar.Value = 0);
 | 
				
			||||||
 | 
					                    this.Dispatcher.Invoke(() => SetDuplicateFileCollection(GetDuplicateFiles()));
 | 
				
			||||||
                }).Start();
 | 
					                }).Start();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary> Event handler. Called by DatagridFileRecords for initialized events. </summary>
 | 
					 | 
				
			||||||
        /// <param name="sender"> Source of the event. </param>
 | 
					 | 
				
			||||||
        /// <param name="e">      Event information. </param>
 | 
					 | 
				
			||||||
        private void DatagridFileRecords_Initialized(object sender, EventArgs e)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            this.datagridFileRecords.ItemsSource = this.Database.GetFileRecords();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary> Event handler. Called by BtnFilterDuplicates for click events. </summary>
 | 
					 | 
				
			||||||
        /// <param name="sender"> Source of the event. </param>
 | 
					 | 
				
			||||||
        /// <param name="e">      Routed event information. </param>
 | 
					 | 
				
			||||||
        private void BtnFilterDuplicates_Click(object sender, RoutedEventArgs e)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            this.datagridFileRecords.ItemsSource = new ListCollectionView(this.Database.GetFileRecords().GroupBy(fr => fr.Hash).Where(g => g.Count() > 1).SelectMany(g => g).ToList());
 | 
					 | 
				
			||||||
            ((ListCollectionView)this.datagridFileRecords.ItemsSource).GroupDescriptions.Add(new PropertyGroupDescription("Hash"));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary> Event handler. Called by BtnFilterShowAll for click events. </summary>
 | 
					 | 
				
			||||||
        /// <param name="sender"> Source of the event. </param>
 | 
					 | 
				
			||||||
        /// <param name="e">      Routed event information. </param>
 | 
					 | 
				
			||||||
        private void BtnFilterShowAll_Click(object sender, RoutedEventArgs e)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            this.datagridFileRecords.ItemsSource = this.Database.GetFileRecords();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary> Event handler. Called by BtnClear for click events. </summary>
 | 
					        /// <summary> Event handler. Called by BtnClear for click events. </summary>
 | 
				
			||||||
        /// <param name="sender"> Source of the event. </param>
 | 
					        /// <param name="sender"> Source of the event. </param>
 | 
				
			||||||
        /// <param name="e">      Routed event information. </param>
 | 
					        /// <param name="e">      Routed event information. </param>
 | 
				
			||||||
        private void BtnClear_Click(object sender, RoutedEventArgs e)
 | 
					        private void BtnClear_Click(object sender, RoutedEventArgs e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this.Database.Clear();
 | 
					            this.Database.Clear();
 | 
				
			||||||
            this.datagridFileRecords.ItemsSource = Enumerable.Empty<FileRecord>();
 | 
					            ResetMediaPreview();
 | 
				
			||||||
 | 
					            SetDuplicateFileCollection(Enumerable.Empty<DuplicateFileGroup>());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary> Event handler. Called by Hyperlink for click events. </summary>
 | 
					        /// <summary> Event handler. Called by Hyperlink for click events. </summary>
 | 
				
			||||||
| 
						 | 
					@ -183,14 +212,153 @@ namespace mdfinder
 | 
				
			||||||
            this.HashProviders = GetProviderPlugins();
 | 
					            this.HashProviders = GetProviderPlugins();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Event handler. Called by MenuAbout for click events. </summary>
 | 
				
			||||||
 | 
					        /// <param name="sender"> Source of the event. </param>
 | 
				
			||||||
 | 
					        /// <param name="e">      Routed event information. </param>
 | 
				
			||||||
        private void MenuAbout_Click(object sender, RoutedEventArgs e)
 | 
					        private void MenuAbout_Click(object sender, RoutedEventArgs e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var aboutWindow = new AboutWindow();
 | 
					            var aboutWindow = new AboutWindow();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            aboutWindow.Show();
 | 
					            aboutWindow.Show();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        #endregion
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Event handler. Called by ListBoxDupes for initialized events. </summary>
 | 
				
			||||||
 | 
					        /// <param name="sender"> Source of the event. </param>
 | 
				
			||||||
 | 
					        /// <param name="e">      Event information. </param>
 | 
				
			||||||
 | 
					        private void ListBoxDupes_Initialized(object sender, EventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            new Thread(() =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.Dispatcher.Invoke(() => SetDuplicateFileCollection(GetDuplicateFiles()));
 | 
				
			||||||
 | 
					            }).Start();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Event handler. Called by ListBoxDupes for selection changed events. </summary>
 | 
				
			||||||
 | 
					        /// <param name="sender"> Source of the event. </param>
 | 
				
			||||||
 | 
					        /// <param name="e">      Selection changed event information. </param>
 | 
				
			||||||
 | 
					        private void ListBoxDupes_SelectionChanged(object sender, SelectionChangedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (e.AddedItems.Count > 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.ScanResults.SelectedDuplicateFileGroup = e.AddedItems[0] as DuplicateFileGroup;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.ScanResults.SelectedDuplicateFileGroup = null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Event handler. Called by PerformDuplicateAction for click events. </summary>
 | 
				
			||||||
 | 
					        /// <param name="sender"> Source of the event. </param>
 | 
				
			||||||
 | 
					        /// <param name="e">      Routed event information. </param>
 | 
				
			||||||
 | 
					        private void PerformDuplicateAction_Click(object sender, RoutedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ResetMediaPreview();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            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);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                foreach (var file in actionableFiles)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if(archive && zipFile != null)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        zipFile.CreateEntryFromFile(file.Path.LocalPath, System.IO.Path.GetFileName(file.Path.LocalPath));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    File.Delete(file.Path.LocalPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    this.Database.RemoveFileRecord(file.Id);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(zipFile != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    zipFile.Dispose();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                SetDuplicateFileCollection(GetDuplicateFiles());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Event handler. Called by DatagridFileList for selection changed events.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="sender"> Source of the event. </param>
 | 
				
			||||||
 | 
					        /// <param name="e">      Selection changed event information. </param>
 | 
				
			||||||
 | 
					        private void DatagridFileList_SelectionChanged(object sender, SelectionChangedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (e.AddedItems.Count == 1)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var fileRecord = e.AddedItems[0] as FileRecord;
 | 
				
			||||||
 | 
					                if (fileRecord != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    var extension = System.IO.Path.GetExtension(fileRecord.Path.LocalPath).ToUpper();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (MEDIA_EXTENTIONS.Contains(extension))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        this.mediaPreview.Source = fileRecord.Path;
 | 
				
			||||||
 | 
					                        this.imagePreview.Source = null;
 | 
				
			||||||
 | 
					                        this.textPreview.Text = string.Empty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        this.mediaPreviewContainer.Visibility = Visibility.Visible;
 | 
				
			||||||
 | 
					                        this.imagePreview.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					                        this.textPreview.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					                        this.stackNoPreview.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else if (IMAGE_EXTENTIONS.Contains(extension))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        this.mediaPreview.Source = null;
 | 
				
			||||||
 | 
					                        this.imagePreview.Source = new BitmapImage(fileRecord.Path);
 | 
				
			||||||
 | 
					                        this.textPreview.Text = string.Empty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        this.mediaPreviewContainer.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					                        this.imagePreview.Visibility = Visibility.Visible;
 | 
				
			||||||
 | 
					                        this.textPreview.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					                        this.stackNoPreview.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else if (TEXT_EXTENTIONS.Contains(extension))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        this.mediaPreview.Source = null;
 | 
				
			||||||
 | 
					                        this.imagePreview.Source = null;
 | 
				
			||||||
 | 
					                        this.textPreview.Text = File.ReadAllText(fileRecord.Path.LocalPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        this.mediaPreviewContainer.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					                        this.imagePreview.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					                        this.textPreview.Visibility = Visibility.Visible;
 | 
				
			||||||
 | 
					                        this.stackNoPreview.Visibility = Visibility.Hidden;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else //Can't preivew.
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        ResetMediaPreview();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,16 +26,29 @@
 | 
				
			||||||
            <Grid>
 | 
					            <Grid>
 | 
				
			||||||
                <Grid.ColumnDefinitions>
 | 
					                <Grid.ColumnDefinitions>
 | 
				
			||||||
                    <ColumnDefinition Width="Auto" />
 | 
					                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
                    <ColumnDefinition Width="77.126" />
 | 
					                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
                    <ColumnDefinition Width="25.874"/>
 | 
					                    <ColumnDefinition Width="Auto"/>
 | 
				
			||||||
                    <ColumnDefinition Width="*" />
 | 
					                    <ColumnDefinition Width="*" />
 | 
				
			||||||
                    <ColumnDefinition Width="Auto" />
 | 
					                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
                </Grid.ColumnDefinitions>
 | 
					                </Grid.ColumnDefinitions>
 | 
				
			||||||
                <ContentControl Grid.Column="0" Template="{StaticResource FolderIcon}" Width="16" Margin="0,0,4,0" />
 | 
					                <ContentControl Grid.Column="0" Template="{StaticResource FolderIcon}" Width="16" Margin="0,0,4,0" />
 | 
				
			||||||
                <Label Grid.Column="1" Content="{x:Static loc:Localization.ProviderFolderLabel}" Grid.ColumnSpan="2" />
 | 
					                <Label Grid.Column="1" Content="{x:Static loc:Localization.ProviderFolderLabel}" Grid.ColumnSpan="2" />
 | 
				
			||||||
                <TextBox x:Name="txtProviderLocation" Grid.Column="3" VerticalAlignment="Center" Text="{Binding Source={x:Static settings:Settings.Default}, Path=ProviderFolder, Mode=TwoWay}" Margin="0,4"  />
 | 
					                <TextBox x:Name="txtProviderLocation" Grid.Column="3" VerticalAlignment="Center" Text="{Binding Source={x:Static settings:Settings.Default}, Path=ProviderFolder, Mode=OneWay}" Margin="0,4"  />
 | 
				
			||||||
                <Button x:Name="btnProviderLocationDirectory" Grid.Column="4" MinWidth="25" Content="..." Click="BtnProviderLocationDirectory_Click" />
 | 
					                <Button x:Name="btnProviderLocationDirectory" Grid.Column="4" MinWidth="25" Content="..." Click="BtnProviderLocationDirectory_Click" />
 | 
				
			||||||
            </Grid>
 | 
					            </Grid>
 | 
				
			||||||
 | 
					            <Grid>
 | 
				
			||||||
 | 
					                <Grid.ColumnDefinitions>
 | 
				
			||||||
 | 
					                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
 | 
					                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
 | 
					                    <ColumnDefinition Width="Auto"/>
 | 
				
			||||||
 | 
					                    <ColumnDefinition Width="*" />
 | 
				
			||||||
 | 
					                    <ColumnDefinition Width="Auto" />
 | 
				
			||||||
 | 
					                </Grid.ColumnDefinitions>
 | 
				
			||||||
 | 
					                <ContentControl Grid.Column="0" Template="{StaticResource FolderIcon}" Width="16" Margin="0,0,4,0" />
 | 
				
			||||||
 | 
					                <Label Grid.Column="1" Content="{x:Static loc:Localization.ArchiveFolderLabel}" Grid.ColumnSpan="2" />
 | 
				
			||||||
 | 
					                <TextBox x:Name="txtArchiveLocation" Grid.Column="3" VerticalAlignment="Center" Text="{Binding Source={x:Static settings:Settings.Default}, Path=ArchiveFolder, Mode=OneWay}" Margin="0,4"  />
 | 
				
			||||||
 | 
					                <Button x:Name="btnArchiveLocationDirectory" Grid.Column="4" MinWidth="25" Content="..." Click="BtnArchiveLocationDirectory_Click" />
 | 
				
			||||||
 | 
					            </Grid>
 | 
				
			||||||
            <Separator Margin="0,10" />
 | 
					            <Separator Margin="0,10" />
 | 
				
			||||||
            <Button Name="btnSave" MaxWidth="45" Content="{x:Static loc:Localization.SaveLabel}" Click="BtnSave_Click" />
 | 
					            <Button Name="btnSave" MaxWidth="45" Content="{x:Static loc:Localization.SaveLabel}" Click="BtnSave_Click" />
 | 
				
			||||||
        </StackPanel>
 | 
					        </StackPanel>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,5 +63,18 @@ namespace mdfinder
 | 
				
			||||||
                Properties.Settings.Default.ProviderFolder = fbd.SelectedPath;
 | 
					                Properties.Settings.Default.ProviderFolder = fbd.SelectedPath;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Event handler. Called by BtnArchiveLocationDirectory for click events. </summary>
 | 
				
			||||||
 | 
					        /// <param name="sender"> Source of the event. </param>
 | 
				
			||||||
 | 
					        /// <param name="e">      Routed event information. </param>
 | 
				
			||||||
 | 
					        private void BtnArchiveLocationDirectory_Click(object sender, RoutedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var fbd = new FolderBrowserDialog();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Properties.Settings.Default.ArchiveFolder = fbd.SelectedPath;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								mdfinder/Properties/Settings.Designer.cs
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										12
									
								
								mdfinder/Properties/Settings.Designer.cs
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -70,5 +70,17 @@ namespace mdfinder.Properties {
 | 
				
			||||||
                this["Language"] = value;
 | 
					                this["Language"] = value;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        [global::System.Configuration.UserScopedSettingAttribute()]
 | 
				
			||||||
 | 
					        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
 | 
				
			||||||
 | 
					        [global::System.Configuration.DefaultSettingValueAttribute("")]
 | 
				
			||||||
 | 
					        public string ArchiveFolder {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ((string)(this["ArchiveFolder"]));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set {
 | 
				
			||||||
 | 
					                this["ArchiveFolder"] = value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,5 +14,8 @@
 | 
				
			||||||
    <Setting Name="Language" Type="System.Globalization.CultureInfo" Scope="User">
 | 
					    <Setting Name="Language" Type="System.Globalization.CultureInfo" Scope="User">
 | 
				
			||||||
      <Value Profile="(Default)">en-US</Value>
 | 
					      <Value Profile="(Default)">en-US</Value>
 | 
				
			||||||
    </Setting>
 | 
					    </Setting>
 | 
				
			||||||
 | 
					    <Setting Name="ArchiveFolder" Type="System.String" Scope="User">
 | 
				
			||||||
 | 
					      <Value Profile="(Default)" />
 | 
				
			||||||
 | 
					    </Setting>
 | 
				
			||||||
  </Settings>
 | 
					  </Settings>
 | 
				
			||||||
</SettingsFile>
 | 
					</SettingsFile>
 | 
				
			||||||
							
								
								
									
										65
									
								
								mdfinder/ScanResults.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								mdfinder/ScanResults.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,65 @@
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace mdfinder
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary> A scan results model providing bindable properties. </summary>
 | 
				
			||||||
 | 
					    public class ScanResults : PropertyChangedAlerter
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        #region Members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> The duplicate files. </summary>
 | 
				
			||||||
 | 
					        private IEnumerable<DuplicateFileGroup> duplicateFiles;
 | 
				
			||||||
 | 
					        /// <summary> The selected duplicate file group. </summary>
 | 
				
			||||||
 | 
					        private DuplicateFileGroup selectedDuplicateFileGroup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Properties
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Gets or sets the duplicate files. </summary>
 | 
				
			||||||
 | 
					        /// <value> The duplicate files. </value>
 | 
				
			||||||
 | 
					        public IEnumerable<DuplicateFileGroup> DuplicateFiles
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return this.duplicateFiles;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.duplicateFiles = value;
 | 
				
			||||||
 | 
					                OnPropertyChanged();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary> Gets or sets the selected duplicate file group. </summary>
 | 
				
			||||||
 | 
					        /// <value> The selected duplicate file group. </value>
 | 
				
			||||||
 | 
					        public DuplicateFileGroup SelectedDuplicateFileGroup
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return this.selectedDuplicateFileGroup;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.selectedDuplicateFileGroup = value;
 | 
				
			||||||
 | 
					                OnPropertyChanged();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Constructors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ScanResults()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.duplicateFiles = Enumerable.Empty<DuplicateFileGroup>();
 | 
				
			||||||
 | 
					            this.selectedDuplicateFileGroup = new DuplicateFileGroup(Enumerable.Empty<FileRecord>());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -76,8 +76,15 @@ namespace mdfinder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void Scan(string path)
 | 
					        public void Scan(string path)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            if(string.IsNullOrWhiteSpace(path))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.IsScanning = false;
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.Processed = 0;
 | 
					            this.Processed = 0;
 | 
				
			||||||
            this.Total = 0;
 | 
					            this.Total = 0;
 | 
				
			||||||
 | 
					            this.IsScanning = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var scanPath = new DirectoryInfo(path);
 | 
					            var scanPath = new DirectoryInfo(path);
 | 
				
			||||||
            if (scanPath.Exists)
 | 
					            if (scanPath.Exists)
 | 
				
			||||||
| 
						 | 
					@ -85,6 +92,8 @@ namespace mdfinder
 | 
				
			||||||
                Discover(scanPath);
 | 
					                Discover(scanPath);
 | 
				
			||||||
                Scan(scanPath);
 | 
					                Scan(scanPath);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.IsScanning = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void Discover(DirectoryInfo directory)
 | 
					        private void Discover(DirectoryInfo directory)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,6 +40,9 @@
 | 
				
			||||||
    <Reference Include="csmic, Version=1.1.4.0, Culture=neutral, processorArchitecture=MSIL">
 | 
					    <Reference Include="csmic, Version=1.1.4.0, Culture=neutral, processorArchitecture=MSIL">
 | 
				
			||||||
      <HintPath>..\packages\csmic.1.1.4\lib\net40\csmic.dll</HintPath>
 | 
					      <HintPath>..\packages\csmic.1.1.4\lib\net40\csmic.dll</HintPath>
 | 
				
			||||||
    </Reference>
 | 
					    </Reference>
 | 
				
			||||||
 | 
					    <Reference Include="Gu.Wpf.Media, Version=0.5.0.2, Culture=neutral, processorArchitecture=MSIL">
 | 
				
			||||||
 | 
					      <HintPath>..\packages\Gu.Wpf.Media.0.5.0.2\lib\net45\Gu.Wpf.Media.dll</HintPath>
 | 
				
			||||||
 | 
					    </Reference>
 | 
				
			||||||
    <Reference Include="LiteDB, Version=4.1.4.0, Culture=neutral, PublicKeyToken=4ee40123013c9f27, processorArchitecture=MSIL">
 | 
					    <Reference Include="LiteDB, Version=4.1.4.0, Culture=neutral, PublicKeyToken=4ee40123013c9f27, processorArchitecture=MSIL">
 | 
				
			||||||
      <HintPath>..\packages\LiteDB.4.1.4\lib\net40\LiteDB.dll</HintPath>
 | 
					      <HintPath>..\packages\LiteDB.4.1.4\lib\net40\LiteDB.dll</HintPath>
 | 
				
			||||||
    </Reference>
 | 
					    </Reference>
 | 
				
			||||||
| 
						 | 
					@ -49,6 +52,8 @@
 | 
				
			||||||
    <Reference Include="System" />
 | 
					    <Reference Include="System" />
 | 
				
			||||||
    <Reference Include="System.ComponentModel.DataAnnotations" />
 | 
					    <Reference Include="System.ComponentModel.DataAnnotations" />
 | 
				
			||||||
    <Reference Include="System.Data" />
 | 
					    <Reference Include="System.Data" />
 | 
				
			||||||
 | 
					    <Reference Include="System.IO.Compression" />
 | 
				
			||||||
 | 
					    <Reference Include="System.IO.Compression.FileSystem" />
 | 
				
			||||||
    <Reference Include="System.Runtime.Serialization" />
 | 
					    <Reference Include="System.Runtime.Serialization" />
 | 
				
			||||||
    <Reference Include="System.Security" />
 | 
					    <Reference Include="System.Security" />
 | 
				
			||||||
    <Reference Include="System.Windows.Forms" />
 | 
					    <Reference Include="System.Windows.Forms" />
 | 
				
			||||||
| 
						 | 
					@ -73,9 +78,11 @@
 | 
				
			||||||
    <Compile Include="AboutWindow.xaml.cs">
 | 
					    <Compile Include="AboutWindow.xaml.cs">
 | 
				
			||||||
      <DependentUpon>AboutWindow.xaml</DependentUpon>
 | 
					      <DependentUpon>AboutWindow.xaml</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
 | 
					    <Compile Include="DuplicateFileGroup.cs" />
 | 
				
			||||||
    <Compile Include="OptionsWindow.xaml.cs">
 | 
					    <Compile Include="OptionsWindow.xaml.cs">
 | 
				
			||||||
      <DependentUpon>OptionsWindow.xaml</DependentUpon>
 | 
					      <DependentUpon>OptionsWindow.xaml</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
 | 
					    <Compile Include="ScanResults.cs" />
 | 
				
			||||||
    <Compile Include="SizeConverter.cs" />
 | 
					    <Compile Include="SizeConverter.cs" />
 | 
				
			||||||
    <Compile Include="URIConverter.cs" />
 | 
					    <Compile Include="URIConverter.cs" />
 | 
				
			||||||
    <Page Include="AboutWindow.xaml">
 | 
					    <Page Include="AboutWindow.xaml">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
<?xml version="1.0" encoding="utf-8"?>
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
<packages>
 | 
					<packages>
 | 
				
			||||||
  <package id="csmic" version="1.1.4" targetFramework="net461" />
 | 
					  <package id="csmic" version="1.1.4" targetFramework="net461" />
 | 
				
			||||||
 | 
					  <package id="Gu.Wpf.Media" version="0.5.0.2" targetFramework="net461" />
 | 
				
			||||||
  <package id="LiteDB" version="4.1.4" targetFramework="net461" />
 | 
					  <package id="LiteDB" version="4.1.4" targetFramework="net461" />
 | 
				
			||||||
  <package id="Octokit" version="0.32.0" targetFramework="net461" />
 | 
					  <package id="Octokit" version="0.32.0" targetFramework="net461" />
 | 
				
			||||||
</packages>
 | 
					</packages>
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue