├── logo.png
├── logo.xcf
├── screenshot.png
├── UserInterface
├── icon.ico
├── App.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Controls
│ ├── EnumDropDown.Designer.cs
│ ├── ProgressBarText.Designer.cs
│ ├── EnumFlagsDropDown.Designer.cs
│ ├── CheckBoxDropDown.Designer.cs
│ ├── FileBrowseControl.Designer.cs
│ ├── EnumDropDown.cs
│ ├── FileBrowseControl.cs
│ ├── EnumFlagsDropDown.cs
│ ├── ProgressBarText.cs
│ ├── FileBrowseControl.resx
│ ├── EnumDropDown.resx
│ ├── CheckBoxDropDown.resx
│ └── CheckBoxDropDown.cs
├── Program.cs
├── ExtensionMethods.cs
├── ParseArgs.cs
├── CLI.cs
├── UserInterface.csproj
└── Main.cs
├── MediaOrganizer
├── MediaOrganizer.ini
├── CopyItems.cs
├── MediaOrganizerException.cs
├── Properties
│ └── AssemblyInfo.cs
├── CopyItem.cs
├── MediaOrganizer.csproj
├── IniFile.cs
└── ExtensionMethods.cs
├── README.md
├── MetaParser
├── Parsers
│ ├── Parser.cs
│ ├── DirectoryParser.cs
│ ├── GenericMediaParser.cs
│ ├── FileParser.cs
│ ├── BmpParser.cs
│ ├── MP4Parser.cs
│ └── PNGParser.cs
├── MetaParseException.cs
├── Properties
│ └── AssemblyInfo.cs
├── ExtensionMethods.cs
├── MetaParser.csproj
├── MetaData.cs
└── MetaParser.cs
├── TODO
├── Common
├── CommonException.cs
├── Properties
│ └── AssemblyInfo.cs
├── Common.csproj
└── ExtensionMethods.cs
├── MediaQuerier
├── MediaQuerierException.cs
├── Properties
│ └── AssemblyInfo.cs
├── MediaQuerier.csproj
└── MediaQuerier.cs
├── ExifOrganizer.sln
└── .gitignore
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RiJo/ExifOrganizer/HEAD/logo.png
--------------------------------------------------------------------------------
/logo.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RiJo/ExifOrganizer/HEAD/logo.xcf
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RiJo/ExifOrganizer/HEAD/screenshot.png
--------------------------------------------------------------------------------
/UserInterface/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RiJo/ExifOrganizer/HEAD/UserInterface/icon.ico
--------------------------------------------------------------------------------
/UserInterface/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/UserInterface/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MediaOrganizer/MediaOrganizer.ini:
--------------------------------------------------------------------------------
1 | sourcePath: C:\temp
2 | destinationPath: C:\temp\backup
3 | recursive: 1
4 | locale: sv-SE
5 | patternImage: %y/%m %M/%t/%n.%e
6 | patternAudio: %y/%m %M/Audio/%a/%k %A - %T.%e
7 | patternVideo: %y/%m %M/Video/%t/%n.%e
8 | precondition: None
9 | comparator: FileSize, ChecksumMD5
10 | copyMode: KeepUnique
11 | exceptionHandling: Throw
12 | fileVerification: ChecksumMD5
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ExifOrganizer
2 | =============
3 |
4 | Organize image collections based on Exif data with customizable destination paths.
5 | ### Status
6 | Currently in development of first beta version.
7 |
8 | ## Description
9 | The idea is to select a source path to be organized, where media files (mainly images, but also videos and audio) are gathered from. Those files are then copied and structured into a destination path. How the media files are organized is configurable via a graphical user interface (GUI) or by command line interface (CLI) for scripting.
10 |
11 | ### Supported meta
12 | * Exif - .jpeg .jpg .tiff .tif
13 | * MP4 - .mp4 .m4a .mov .3gp .3g2
14 | * ID3 - .mp3
15 | * PNG - .png
16 |
17 | Most other media files are parsed in a generic way and lacks the detailed meta data.
18 |
19 | ### Screenshot
20 | 
21 |
22 | ## Environment
23 | Everything is written in C# 6.0 and .NET 4.5 using Visual Studio 2017. There are no external dependencies.
24 |
25 | ## License
26 | This project is licensed under GPLv3.
27 |
28 |
--------------------------------------------------------------------------------
/MetaParser/Parsers/Parser.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Parser.cs: Base class for meta data parser classes.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System.Collections.Generic;
20 | using System.IO;
21 | using System.Threading.Tasks;
22 |
23 | namespace ExifOrganizer.Meta.Parsers
24 | {
25 | internal abstract class Parser
26 | {
27 | internal abstract MetaData Parse(string path);
28 | internal abstract Task ParseAsync(string path);
29 | }
30 | }
--------------------------------------------------------------------------------
/UserInterface/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18444
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ExifOrganizer.UI.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/UserInterface/Controls/EnumDropDown.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ExifOrganizer.UI.Controls
2 | {
3 | partial class EnumDropDown
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.SuspendLayout();
32 | //
33 | // CheckBoxDropDown
34 | //
35 | this.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
36 | this.ResumeLayout(false);
37 |
38 | }
39 |
40 | #endregion
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/UserInterface/Controls/ProgressBarText.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ExifOrganizer.UI.Controls
2 | {
3 | partial class ProgressBarText
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | components = new System.ComponentModel.Container();
32 | }
33 |
34 | #endregion
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/UserInterface/Controls/EnumFlagsDropDown.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ExifOrganizer.UI.Controls
2 | {
3 | partial class EnumFlagsDropDown
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | components = new System.ComponentModel.Container();
32 | }
33 |
34 | #endregion
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | Features:
2 | 0.2 - Handle tags across years/months (e.g. "New year")
3 | - Comments in ini file using IniFile class
4 | - Multiple source/destination paths to be used
5 | - Favorites (stars) function for albums (e.g. "Pick out the best images from 2014")
6 | - Use database (SQLite?) to cache meta data etc
7 |
8 | Library:
9 | - Extract common functions (like extensions) to separate library
10 |
11 | GUI:
12 | 0.2 - separate settings/advanced form for improved usability
13 | - button to run prepare and prinotut information about copying
14 | - Separate progress of Parse() and Organize into 0.0-1.0 for each + message in event
15 | - Printout how many skipped files (grouped by extension/type)
16 |
17 | Bugs 0.1:
18 | - Printout elapsed time during progress as well as in completed message dialogue (separate times for image, audio and video files. Also separate parsing and organazation time elapsed)
19 | - Disable more controls during organization? Currently only submit-button
20 | - Add Abort-button to abort current progress
21 | - New option: merge source w/ destination files (also parse target path)
22 | - Checkboxes to skip image, audio, video files (merge w/ patterns?)
23 | - Property to set extensions of image, audio and video files
--------------------------------------------------------------------------------
/UserInterface/Controls/CheckBoxDropDown.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ExifOrganizer.UI.Controls
2 | {
3 | partial class CheckBoxDropDown
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.SuspendLayout();
32 | //
33 | // CheckBoxDropDown
34 | //
35 | this.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
36 | this.ResumeLayout(false);
37 |
38 | }
39 |
40 | #endregion
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/MediaOrganizer/CopyItems.cs:
--------------------------------------------------------------------------------
1 | //
2 | // CopyItems.cs: Data structure describing multiple items to be copied.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System;
20 | using System.Collections.Generic;
21 |
22 | namespace ExifOrganizer.Organizer
23 | {
24 | public class CopyItems : List
25 | {
26 | public string sourcePath;
27 | public string destinationPath;
28 |
29 | public override string ToString()
30 | {
31 | return $"Copy: [{sourcePath}] ---> [{destinationPath}]{Environment.NewLine}Items:{Environment.NewLine}{String.Join(Environment.NewLine, this)}";
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/Common/CommonException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // CommonException.cs: Custom exception class.
3 | //
4 | // Copyright (C) 2018 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System;
20 | using System.Runtime.Serialization;
21 |
22 | namespace ExifOrganizer.Common
23 | {
24 | [Serializable]
25 | public class CommonException : Exception
26 | {
27 | public CommonException(string message, params object[] args)
28 | : base(String.Format(message, args))
29 | {
30 | }
31 |
32 | public CommonException(string message, Exception innerException)
33 | : base(message, innerException)
34 | {
35 | }
36 |
37 | protected CommonException(SerializationInfo info, StreamingContext context)
38 | : base(info, context)
39 | {
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/MediaQuerier/MediaQuerierException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // MediaQuerierException.cs: Custom exception class.
3 | //
4 | // Copyright (C) 2016 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using ExifOrganizer.Common;
20 | using System;
21 | using System.Runtime.Serialization;
22 |
23 | namespace ExifOrganizer.Querier
24 | {
25 | [Serializable]
26 | public class MediaQuerierException : CommonException
27 | {
28 | public MediaQuerierException(string message, params object[] args)
29 | : base(message, args)
30 | {
31 | }
32 |
33 | public MediaQuerierException(string message, Exception innerException)
34 | : base(message, innerException)
35 | {
36 | }
37 |
38 | protected MediaQuerierException(SerializationInfo info, StreamingContext context)
39 | : base(info, context)
40 | {
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/MetaParser/MetaParseException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // MetaParseException.cs: Custom exception class.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using ExifOrganizer.Common;
20 | using System;
21 | using System.Runtime.Serialization;
22 |
23 | namespace ExifOrganizer.Meta
24 | {
25 | [Serializable]
26 | public class MetaParseException : CommonException
27 | {
28 | public MetaParseException(string message, params object[] args)
29 | : base(message, args)
30 | {
31 | }
32 |
33 | public MetaParseException(string message, Exception innerException)
34 | : base(message, innerException)
35 | {
36 | }
37 |
38 | protected MetaParseException(SerializationInfo info, StreamingContext context)
39 | : base(info, context)
40 | {
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/Common/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Common")]
9 | [assembly: AssemblyDescription("Library containing common shared implementation details.")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Common")]
13 | [assembly: AssemblyCopyright("Licensed under GPLv3")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("06a0bc9e-9100-4877-89a6-f5798bd3c7a3")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("0.1.0.*")]
36 | //[assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/MediaQuerier/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("MediaQuerier")]
9 | [assembly: AssemblyDescription("Library used to query media files based on its properties.")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("MediaQuerier")]
13 | [assembly: AssemblyCopyright("Licensed under GPLv3")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("7070940a-c83f-4d3d-bde4-55aee58a9385")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("0.1.1.*")]
36 | //[assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/MediaOrganizer/MediaOrganizerException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // MediaOrganizerException.cs: Custom exception class.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using ExifOrganizer.Common;
20 | using System;
21 | using System.Runtime.Serialization;
22 |
23 | namespace ExifOrganizer.Organizer
24 | {
25 | [Serializable]
26 | public class MediaOrganizerException : CommonException
27 | {
28 | public MediaOrganizerException(string message, params object[] args)
29 | : base(message, args)
30 | {
31 | }
32 |
33 | public MediaOrganizerException(string message, Exception innerException)
34 | : base(message, innerException)
35 | {
36 | }
37 |
38 | protected MediaOrganizerException(SerializationInfo info, StreamingContext context)
39 | : base(info, context)
40 | {
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/MetaParser/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ExifParser")]
9 | [assembly: AssemblyDescription("Library used to parse meta data from media files.")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ExifParser")]
13 | [assembly: AssemblyCopyright("Licensed under GPLv3")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("b29e9ab1-7c16-4eb9-8228-acc78be02702")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("0.2.0.*")]
36 | //[assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MediaOrganizer/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("MediaOrganizer")]
9 | [assembly: AssemblyDescription("Library used to organize media files based on its meta data.")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("MediaOrganizer")]
13 | [assembly: AssemblyCopyright("Licensed under GPLv3")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("d5e17db3-82df-4059-9fc4-b2014d354efc")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("0.2.0.*")]
36 | //[assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/UserInterface/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ExifOrganizer")]
9 | [assembly: AssemblyDescription("User interface (GUI and CLI) of ExifOrganizer application.")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ExifOrganizer")]
13 | [assembly: AssemblyCopyright("Licensed under GPLv3")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("f3f21b1e-f1cf-4d49-a14d-a66fd5b068b1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("0.3.0.*")]
36 | //[assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MetaParser/Parsers/DirectoryParser.cs:
--------------------------------------------------------------------------------
1 | //
2 | // DirectoryParser.cs: Directory meta data parser class.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System.IO;
20 | using System.Threading.Tasks;
21 |
22 | namespace ExifOrganizer.Meta.Parsers
23 | {
24 | internal class DirectoryParser : Parser
25 | {
26 | internal override MetaData Parse(string path)
27 | {
28 | Task task = ParseAsync(path);
29 | task.ConfigureAwait(false); // Prevent deadlock of caller
30 | return task.Result;
31 | }
32 |
33 | internal override Task ParseAsync(string path)
34 | {
35 | return Task.FromResult(ParseThread(path));
36 | }
37 |
38 | private MetaData ParseThread(string path)
39 | {
40 | if (!Directory.Exists(path))
41 | throw new MetaParseException("Directory not found: {0}", path);
42 |
43 | MetaData meta = new MetaData();
44 | meta.Type = MetaType.Directory;
45 | meta.Path = path;
46 | return meta;
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/MetaParser/Parsers/GenericMediaParser.cs:
--------------------------------------------------------------------------------
1 | //
2 | // GenericFileParser.cs: Generic meta data parser class.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System.Collections.Generic;
20 | using System.IO;
21 | using System.Threading.Tasks;
22 | using System.Linq;
23 |
24 | namespace ExifOrganizer.Meta.Parsers
25 | {
26 | internal class GenericMediaParser : FileParser
27 | {
28 | internal override IEnumerable GetSupportedFileExtensions()
29 | {
30 | return new string[] { ".gif", "wav", ".flac", ".aac", ".mpg", ".mpeg" };
31 | }
32 |
33 | internal override MetaType? GetMetaTypeByFileExtension(string extension)
34 | {
35 | switch (extension)
36 | {
37 | case ".gif":
38 | case ".bmp":
39 | return MetaType.Image;
40 | case ".wav":
41 | case ".flac":
42 | case ".aac":
43 | return MetaType.Audio;
44 | case ".mpg":
45 | case ".mpeg":
46 | return MetaType.Video;
47 | default:
48 | return base.GetMetaTypeByFileExtension(extension);
49 | }
50 | }
51 |
52 | protected override MetaData ParseFile(Stream stream, MetaData meta)
53 | {
54 | return meta;
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/MetaParser/ExtensionMethods.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ExtensionMethods.cs: Static extension methods used within the project.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Diagnostics;
22 | using System.IO;
23 | using System.Linq;
24 |
25 | namespace ExifOrganizer.Meta
26 | {
27 | public static class ExtensionMethods
28 | {
29 | public static MetaData Merge(this MetaData meta, MetaData other)
30 | {
31 | if (meta.Path != other.Path)
32 | throw new MetaParseException("Cannot merge meta data: path differ");
33 | //#if DEBUG
34 | // if (meta.Origin != other.Origin)
35 | // throw new MetaParseException("Cannot merge meta data: origin differ");
36 | //#endif
37 | if (meta.Type != other.Type)
38 | throw new MetaParseException("Cannot merge meta data: type differ");
39 |
40 | foreach (var kvp in other.Data)
41 | {
42 | if (meta.Data.ContainsKey(kvp.Key))
43 | {
44 | if (kvp.Value != meta.Data[kvp.Key])
45 | Trace.WriteLine($"[MetaData] merge ignore duplicate key: \"{kvp.Key}\"");
46 | continue;
47 | }
48 |
49 | meta.Data[kvp.Key] = kvp.Value;
50 | }
51 |
52 | return meta;
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/UserInterface/Program.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Program.cs: Program main function entry point.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System;
20 | using System.Runtime.InteropServices;
21 | using System.Windows.Forms;
22 |
23 | namespace ExifOrganizer.UI
24 | {
25 | internal static class Program
26 | {
27 | [DllImport("kernel32.dll")]
28 | private static extern bool AttachConsole(int dwProcessId);
29 |
30 | private const int ATTACH_PARENT_PROCESS = -1;
31 |
32 | ///
33 | /// The main entry point for the application.
34 | ///
35 | [STAThread]
36 | private static int Main(string[] args)
37 | {
38 | if (args.Length == 0)
39 | {
40 | return GUI(args);
41 | }
42 | else
43 | {
44 | return CLI(args);
45 | }
46 | }
47 |
48 | private static int GUI(string[] args)
49 | {
50 | // Graphical interface
51 | Application.EnableVisualStyles();
52 | Application.SetCompatibleTextRenderingDefault(false);
53 | Application.Run(new Main());
54 | return 0;
55 | }
56 |
57 | private static int CLI(string[] args)
58 | {
59 | // Make Console.Write() work
60 | AttachConsole(ATTACH_PARENT_PROCESS);
61 |
62 | // Command line interface
63 | CLI cli = new CLI();
64 | return cli.Run(args);
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/MediaOrganizer/CopyItem.cs:
--------------------------------------------------------------------------------
1 | //
2 | // CopyItem.cs: Data structure describing single item to be copied.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using ExifOrganizer.Common;
20 | using ExifOrganizer.Meta;
21 | using System;
22 | using System.Collections.Generic;
23 | using System.IO;
24 |
25 | namespace ExifOrganizer.Organizer
26 | {
27 | public class CopyItem
28 | {
29 | public string sourcePath;
30 | public string destinationPath;
31 | public FileInfo sourceInfo;
32 | public Dictionary meta;
33 |
34 | private Dictionary checksums = new Dictionary();
35 |
36 | public CopyItem()
37 | {
38 | }
39 |
40 | public string GetChecksumMD5()
41 | {
42 | if (!checksums.ContainsKey("md5"))
43 | checksums["md5"] = sourceInfo.GetMD5Sum();
44 | return checksums["md5"];
45 | }
46 |
47 | public string GetChecksumSHA1()
48 | {
49 | if (!checksums.ContainsKey("sha1"))
50 | checksums["sha1"] = sourceInfo.GetSHA1Sum();
51 | return checksums["sha1"];
52 | }
53 |
54 | public string GetChecksumSHA256()
55 | {
56 | if (!checksums.ContainsKey("sha256"))
57 | checksums["sha256"] = sourceInfo.GetSHA256Sum();
58 | return checksums["sha256"];
59 | }
60 |
61 | public override string ToString()
62 | {
63 | return $"[{sourcePath}] ---> [{destinationPath}]";
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/Common/Common.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {06A0BC9E-9100-4877-89A6-F5798BD3C7A3}
8 | Library
9 | Properties
10 | ExifOrganizer.Common
11 | ExifOrganizer.Common
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/MetaParser/Parsers/FileParser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using ExifOrganizer.Common;
8 |
9 | namespace ExifOrganizer.Meta.Parsers
10 | {
11 | internal abstract class FileParser : Parser
12 | {
13 | internal abstract IEnumerable GetSupportedFileExtensions();
14 | internal virtual MetaType? GetMetaTypeByFileExtension(string extension) { return null; }
15 |
16 | internal override MetaData Parse(string filename)
17 | {
18 | Task task = ParseAsync(filename);
19 | task.ConfigureAwait(false); // Prevent deadlock of caller
20 | return task.Result;
21 | }
22 |
23 | internal override Task ParseAsync(string filename)
24 | {
25 | MetaData meta = GetBaseMetaFileData(filename);
26 | return Task.Run(() => { using (FileStream stream = File.OpenRead(filename)) return ParseFile(stream, meta); });
27 | }
28 |
29 | protected abstract MetaData ParseFile(Stream stream, MetaData meta);
30 |
31 | private MetaData GetBaseMetaFileData(string filename)
32 | {
33 | if (!File.Exists(filename))
34 | throw new MetaParseException("File not found: {0}", filename);
35 |
36 | string extension = Path.GetExtension(filename).ToLower();
37 | MetaType? type = GetMetaTypeByFileExtension(extension);
38 | if (!type.HasValue)
39 | throw new MetaParseException($"Target file extension not handled by parser: {extension}");
40 |
41 | MetaData meta = new MetaData();
42 | meta.Path = filename;
43 | meta.Type = type.Value;
44 | meta.Data = new Dictionary();
45 | meta.Data[MetaKey.FileName] = Path.GetFileName(filename);
46 | meta.Data[MetaKey.OriginalName] = meta.Data[MetaKey.FileName];
47 | meta.Data[MetaKey.Size] = GetFileSize(filename);
48 | meta.Data[MetaKey.DateCreated] = File.GetCreationTime(filename);
49 | meta.Data[MetaKey.DateModified] = File.GetLastWriteTime(filename);
50 | meta.Data[MetaKey.Timestamp] = meta.Data[MetaKey.DateModified];
51 | meta.Data[MetaKey.Tags] = new string[0];
52 |
53 | return meta;
54 | }
55 |
56 | private static long GetFileSize(string filename)
57 | {
58 | return new FileInfo(filename).Length;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/UserInterface/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18444
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ExifOrganizer.UI.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ExifOrganizer.UI.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/UserInterface/Controls/FileBrowseControl.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ExifOrganizer.UI.Controls
2 | {
3 | partial class FileBrowseControl
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.browse = new System.Windows.Forms.Button();
32 | this.path = new System.Windows.Forms.TextBox();
33 | this.SuspendLayout();
34 | //
35 | // browse
36 | //
37 | this.browse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
38 | this.browse.Location = new System.Drawing.Point(271, 0);
39 | this.browse.Name = "browse";
40 | this.browse.Size = new System.Drawing.Size(25, 23);
41 | this.browse.TabIndex = 1;
42 | this.browse.Text = "...";
43 | this.browse.UseVisualStyleBackColor = true;
44 | this.browse.Click += new System.EventHandler(this.browse_Click);
45 | //
46 | // path
47 | //
48 | this.path.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
49 | | System.Windows.Forms.AnchorStyles.Right)));
50 | this.path.Location = new System.Drawing.Point(0, 2);
51 | this.path.Name = "path";
52 | this.path.Size = new System.Drawing.Size(265, 20);
53 | this.path.TabIndex = 0;
54 | //
55 | // FileBrowseControl
56 | //
57 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
58 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
59 | this.Controls.Add(this.path);
60 | this.Controls.Add(this.browse);
61 | this.Name = "FileBrowseControl";
62 | this.Size = new System.Drawing.Size(296, 23);
63 | this.ResumeLayout(false);
64 | this.PerformLayout();
65 |
66 | }
67 |
68 | #endregion
69 |
70 | private System.Windows.Forms.Button browse;
71 | private System.Windows.Forms.TextBox path;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/ExifOrganizer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27428.2015
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserInterface", "UserInterface\UserInterface.csproj", "{8F6FD0D9-E15F-4701-961E-3075BFB1CDA5}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetaParser", "MetaParser\MetaParser.csproj", "{19204B12-E95E-405F-9604-52DE1411C8B1}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaOrganizer", "MediaOrganizer\MediaOrganizer.csproj", "{626F29DA-4334-4E7E-8D9A-B2353BB37FC1}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaQuerier", "MediaQuerier\MediaQuerier.csproj", "{7070940A-C83F-4D3D-BDE4-55AEE58A9385}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{06A0BC9E-9100-4877-89A6-F5798BD3C7A3}"
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Release|Any CPU = Release|Any CPU
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {8F6FD0D9-E15F-4701-961E-3075BFB1CDA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {8F6FD0D9-E15F-4701-961E-3075BFB1CDA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {8F6FD0D9-E15F-4701-961E-3075BFB1CDA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {8F6FD0D9-E15F-4701-961E-3075BFB1CDA5}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {19204B12-E95E-405F-9604-52DE1411C8B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {19204B12-E95E-405F-9604-52DE1411C8B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {19204B12-E95E-405F-9604-52DE1411C8B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {19204B12-E95E-405F-9604-52DE1411C8B1}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {626F29DA-4334-4E7E-8D9A-B2353BB37FC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {626F29DA-4334-4E7E-8D9A-B2353BB37FC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {626F29DA-4334-4E7E-8D9A-B2353BB37FC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {626F29DA-4334-4E7E-8D9A-B2353BB37FC1}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {7070940A-C83F-4D3D-BDE4-55AEE58A9385}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {7070940A-C83F-4D3D-BDE4-55AEE58A9385}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {7070940A-C83F-4D3D-BDE4-55AEE58A9385}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {7070940A-C83F-4D3D-BDE4-55AEE58A9385}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {06A0BC9E-9100-4877-89A6-F5798BD3C7A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {06A0BC9E-9100-4877-89A6-F5798BD3C7A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {06A0BC9E-9100-4877-89A6-F5798BD3C7A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {06A0BC9E-9100-4877-89A6-F5798BD3C7A3}.Release|Any CPU.Build.0 = Release|Any CPU
42 | EndGlobalSection
43 | GlobalSection(SolutionProperties) = preSolution
44 | HideSolutionNode = FALSE
45 | EndGlobalSection
46 | GlobalSection(ExtensibilityGlobals) = postSolution
47 | SolutionGuid = {53403212-6FFE-46A1-A7D6-262A8003B79E}
48 | EndGlobalSection
49 | EndGlobal
50 |
--------------------------------------------------------------------------------
/MediaQuerier/MediaQuerier.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {7070940A-C83F-4D3D-BDE4-55AEE58A9385}
8 | Library
9 | Properties
10 | ExifOrganizer.Querier
11 | ExifOrganizer.Querier
12 | v4.5
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | true
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 | true
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | {06a0bc9e-9100-4877-89a6-f5798bd3c7a3}
53 | Common
54 |
55 |
56 | {19204b12-e95e-405f-9604-52de1411c8b1}
57 | MetaParser
58 |
59 |
60 |
61 |
68 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | bld/
16 | [Bb]in/
17 | [Oo]bj/
18 |
19 | # MSTest test Results
20 | [Tt]est[Rr]esult*/
21 | [Bb]uild[Ll]og.*
22 |
23 | #NUNIT
24 | *.VisualState.xml
25 | TestResult.xml
26 |
27 | # Build Results of an ATL Project
28 | [Dd]ebugPS/
29 | [Rr]eleasePS/
30 | dlldata.c
31 |
32 | *_i.c
33 | *_p.c
34 | *_i.h
35 | *.ilk
36 | *.meta
37 | *.obj
38 | *.pch
39 | *.pdb
40 | *.pgc
41 | *.pgd
42 | *.rsp
43 | *.sbr
44 | *.tlb
45 | *.tli
46 | *.tlh
47 | *.tmp
48 | *.tmp_proj
49 | *.log
50 | *.vspscc
51 | *.vssscc
52 | .builds
53 | *.pidb
54 | *.svclog
55 | *.scc
56 |
57 | # Chutzpah Test files
58 | _Chutzpah*
59 |
60 | # Visual C++ cache files
61 | ipch/
62 | *.aps
63 | *.ncb
64 | *.opensdf
65 | *.sdf
66 | *.cachefile
67 |
68 | # Visual Studio profiler
69 | *.psess
70 | *.vsp
71 | *.vspx
72 |
73 | # TFS 2012 Local Workspace
74 | $tf/
75 |
76 | # Guidance Automation Toolkit
77 | *.gpState
78 |
79 | # ReSharper is a .NET coding add-in
80 | _ReSharper*/
81 | *.[Rr]e[Ss]harper
82 | *.DotSettings.user
83 |
84 | # JustCode is a .NET coding addin-in
85 | .JustCode
86 |
87 | # TeamCity is a build add-in
88 | _TeamCity*
89 |
90 | # DotCover is a Code Coverage Tool
91 | *.dotCover
92 |
93 | # NCrunch
94 | *.ncrunch*
95 | _NCrunch_*
96 | .*crunch*.local.xml
97 |
98 | # MightyMoose
99 | *.mm.*
100 | AutoTest.Net/
101 |
102 | # Web workbench (sass)
103 | .sass-cache/
104 |
105 | # Installshield output folder
106 | [Ee]xpress/
107 |
108 | # DocProject is a documentation generator add-in
109 | DocProject/buildhelp/
110 | DocProject/Help/*.HxT
111 | DocProject/Help/*.HxC
112 | DocProject/Help/*.hhc
113 | DocProject/Help/*.hhk
114 | DocProject/Help/*.hhp
115 | DocProject/Help/Html2
116 | DocProject/Help/html
117 |
118 | # Click-Once directory
119 | publish/
120 |
121 | # Publish Web Output
122 | *.[Pp]ublish.xml
123 | *.azurePubxml
124 |
125 | # NuGet Packages Directory
126 | packages/
127 | ## TODO: If the tool you use requires repositories.config uncomment the next line
128 | #!packages/repositories.config
129 |
130 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
131 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)
132 | !packages/build/
133 |
134 | # Windows Azure Build Output
135 | csx/
136 | *.build.csdef
137 |
138 | # Windows Store app package directory
139 | AppPackages/
140 |
141 | # Others
142 | sql/
143 | *.Cache
144 | ClientBin/
145 | [Ss]tyle[Cc]op.*
146 | ~$*
147 | *~
148 | *.dbmdl
149 | *.dbproj.schemaview
150 | *.pfx
151 | *.publishsettings
152 | node_modules/
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | *.mdf
166 | *.ldf
167 |
168 | # Business Intelligence projects
169 | *.rdl.data
170 | *.bim.layout
171 | *.bim_*.settings
172 |
173 | # Microsoft Fakes
174 | FakesAssemblies/
175 |
--------------------------------------------------------------------------------
/MediaOrganizer/MediaOrganizer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {626F29DA-4334-4E7E-8D9A-B2353BB37FC1}
8 | Library
9 | Properties
10 | ExifOrganizer.Organizer
11 | ExifOrganizer.Organizer
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 | true
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 | true
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | {06a0bc9e-9100-4877-89a6-f5798bd3c7a3}
56 | Common
57 |
58 |
59 | {19204b12-e95e-405f-9604-52de1411c8b1}
60 | MetaParser
61 |
62 |
63 |
64 |
65 | Always
66 |
67 |
68 |
69 |
76 |
--------------------------------------------------------------------------------
/MetaParser/MetaParser.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {19204B12-E95E-405F-9604-52DE1411C8B1}
8 | Library
9 | Properties
10 | ExifOrganizer.Meta
11 | ExifOrganizer.Meta
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 | true
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 | true
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | {06a0bc9e-9100-4877-89a6-f5798bd3c7a3}
64 | Common
65 |
66 |
67 |
68 |
75 |
--------------------------------------------------------------------------------
/MetaParser/MetaData.cs:
--------------------------------------------------------------------------------
1 | //
2 | // MetaData.cs: Data structure for parsed meta data.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System.Collections.Generic;
20 |
21 | namespace ExifOrganizer.Meta
22 | {
23 | public enum MetaType
24 | {
25 | Directory,
26 | File,
27 |
28 | Image,
29 | Video,
30 | Audio
31 | }
32 |
33 | public enum MetaKey
34 | {
35 | // Common
36 | MetaType,
37 | OriginalName,
38 | FileName,
39 | Size,
40 | Timestamp,
41 | DateCreated,
42 | DateModified,
43 | Comment,
44 |
45 | // Image
46 | Resolution,
47 | Width,
48 | Height,
49 | Camera,
50 | Tags,
51 |
52 | // Music
53 | Title,
54 | Artist,
55 | Album,
56 | Year,
57 | Track,
58 | Genre
59 | }
60 |
61 | public enum MetaMediaType
62 | {
63 | Image,
64 | Audio,
65 | Video
66 | }
67 |
68 | public class MetaData
69 | {
70 | public MetaType Type;
71 | public string Path;
72 | public Dictionary Data;
73 | #if DEBUG
74 | public object Origin;
75 | #endif
76 | }
77 |
78 | public static class MetaDataExtensions
79 | {
80 | public static IEnumerable GetByMedia(this MetaMediaType media)
81 | {
82 | HashSet keys = new HashSet();
83 | keys.Add(MetaKey.MetaType);
84 | keys.Add(MetaKey.OriginalName);
85 | keys.Add(MetaKey.FileName);
86 | keys.Add(MetaKey.Size);
87 | keys.Add(MetaKey.Timestamp);
88 | keys.Add(MetaKey.DateCreated);
89 | keys.Add(MetaKey.DateModified);
90 | keys.Add(MetaKey.Comment);
91 |
92 | switch (media)
93 | {
94 | case MetaMediaType.Image:
95 | keys.Add(MetaKey.Resolution);
96 | keys.Add(MetaKey.Width);
97 | keys.Add(MetaKey.Height);
98 | keys.Add(MetaKey.Camera);
99 | keys.Add(MetaKey.Tags);
100 | break;
101 |
102 | case MetaMediaType.Audio:
103 | keys.Add(MetaKey.Title);
104 | keys.Add(MetaKey.Artist);
105 | keys.Add(MetaKey.Album);
106 | keys.Add(MetaKey.Year);
107 | keys.Add(MetaKey.Track);
108 | keys.Add(MetaKey.Genre);
109 | break;
110 |
111 | case MetaMediaType.Video:
112 | break;
113 |
114 | default:
115 | break;
116 | }
117 | return keys;
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/MediaOrganizer/IniFile.cs:
--------------------------------------------------------------------------------
1 | //
2 | // IniFile.cs: Data structure used to save/load an ini file.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System;
20 | using System.Collections.Generic;
21 | using System.IO;
22 |
23 | namespace ExifOrganizer.Organizer
24 | {
25 | public class IniFile : Dictionary
26 | {
27 | private const char CommentSymbol = ';';
28 | private const char KeyValueSeparator = ':';
29 |
30 | public IniFile()
31 | : base()
32 | {
33 | }
34 |
35 | public IniFile(string filename)
36 | : base()
37 | {
38 | TryLoad(filename);
39 | }
40 |
41 | public bool TryLoad(string filename)
42 | {
43 | try
44 | {
45 | Load(filename);
46 | return true;
47 | }
48 | catch (Exception)
49 | {
50 | return false;
51 | }
52 | }
53 |
54 | public void Load(string filename)
55 | {
56 | if (String.IsNullOrEmpty(filename))
57 | throw new ArgumentNullException(nameof(filename));
58 | if (!File.Exists(filename))
59 | throw new FileNotFoundException(filename);
60 |
61 | Clear();
62 |
63 | foreach (string line in File.ReadAllLines(filename))
64 | {
65 | if (line.Trim().Length == 0)
66 | continue; // Empty line
67 | if (line.Trim().StartsWith(CommentSymbol.ToString()))
68 | continue; // Comment
69 |
70 | string[] keyValue = line.Split(new char[] { KeyValueSeparator }, 2);
71 | if (keyValue.Length != 2)
72 | continue; // Invalid row
73 |
74 | string key = keyValue[0].Trim();
75 | string value = keyValue[1].Trim();
76 | Add(key, value);
77 | }
78 | }
79 |
80 | public bool TrySave(string filename)
81 | {
82 | try
83 | {
84 | Save(filename);
85 | return true;
86 | }
87 | catch (Exception)
88 | {
89 | return false;
90 | }
91 | }
92 |
93 | public void Save(string filename)
94 | {
95 | if (String.IsNullOrEmpty(filename))
96 | throw new ArgumentNullException(nameof(filename));
97 |
98 | List lines = new List();
99 | foreach (KeyValuePair kvp in this)
100 | {
101 | string line = $"{kvp.Key}{KeyValueSeparator} {kvp.Value}";
102 | lines.Add(line);
103 | }
104 |
105 | File.WriteAllLines(filename, lines);
106 | }
107 | }
108 | }
--------------------------------------------------------------------------------
/UserInterface/Controls/EnumDropDown.cs:
--------------------------------------------------------------------------------
1 | //
2 | // EnumDropDown.cs: User control to render enum values in a drop-down list.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Drawing;
22 | using System.Linq;
23 | using System.Windows.Forms;
24 |
25 | namespace ExifOrganizer.UI.Controls
26 | {
27 | public partial class EnumDropDown : ComboBox
28 | {
29 | private Type enumType;
30 | private Enum enumValue;
31 |
32 | protected class ComboboxItem
33 | {
34 | public string Text { get; set; }
35 | public Enum Value { get; set; }
36 |
37 | public override string ToString()
38 | {
39 | return Text;
40 | }
41 | }
42 |
43 | public EnumDropDown()
44 | : base()
45 | {
46 | InitializeComponent();
47 |
48 | DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
49 | SelectedIndexChanged += (sender, e) => { enumValue = ((ComboboxItem)SelectedItem).Value; };
50 | }
51 |
52 | public Func EnumText
53 | {
54 | get;
55 | set;
56 | }
57 |
58 | public Type EnumType
59 | {
60 | get { return enumType; }
61 | set
62 | {
63 | if (value == null)
64 | {
65 | enumType = null;
66 | Items.Clear();
67 | return;
68 | }
69 |
70 | if (!value.IsEnum)
71 | throw new ArgumentException($"Type must be Enum: {value}", nameof(value));
72 |
73 | if (value == enumType)
74 | return;
75 |
76 | enumType = value;
77 | enumValue = null;
78 |
79 | Items.Clear();
80 | foreach (Enum item in Enum.GetValues(value))
81 | Items.Add(new ComboboxItem() { Value = item, Text = (EnumText != null) ? EnumText(item) : item.ToString() });
82 | }
83 | }
84 |
85 | public Enum EnumValue
86 | {
87 | get { return enumValue; }
88 | set
89 | {
90 | if (value == null)
91 | return;
92 | if (enumType == null)
93 | throw new ArgumentException("Enum type not yet defined", nameof(enumType));
94 | if (value.GetType() != enumType)
95 | throw new ArgumentException($"Value must be of predefined Enum type: {enumType}", nameof(value));
96 |
97 | if (value == enumValue)
98 | return;
99 |
100 | long numeric = value.GetInt64();
101 | foreach (ComboboxItem item in Items)
102 | {
103 | if (item.Value.GetInt64() != numeric)
104 | continue;
105 |
106 | SelectedItem = item;
107 | break;
108 | }
109 | }
110 | }
111 | }
112 | }
--------------------------------------------------------------------------------
/UserInterface/Controls/FileBrowseControl.cs:
--------------------------------------------------------------------------------
1 | //
2 | // FileBrowseControl.cs: User control for browsing files or directories.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using System;
20 | using System.IO;
21 | using System.Windows.Forms;
22 |
23 | namespace ExifOrganizer.UI.Controls
24 | {
25 | public enum FileBrowseType
26 | {
27 | File,
28 | Directory
29 | }
30 |
31 | public partial class FileBrowseControl : UserControl
32 | {
33 | public FileBrowseControl()
34 | : base()
35 | {
36 | InitializeComponent();
37 | }
38 |
39 | #region Properties
40 |
41 | public FileBrowseType BrowseType
42 | {
43 | get;
44 | set;
45 | }
46 |
47 | public bool ReadOnly
48 | {
49 | get { return path.ReadOnly; }
50 | set { path.ReadOnly = value; }
51 | }
52 |
53 | public override string Text
54 | {
55 | get { return path.Text; }
56 | set { path.Text = value; }
57 | }
58 |
59 | public string SelectedPath
60 | {
61 | get { return path.Text; }
62 | set { path.Text = value; }
63 | }
64 |
65 | public string DialogTitle
66 | {
67 | get;
68 | set;
69 | }
70 |
71 | #endregion Properties
72 |
73 | private void browse_Click(object sender, EventArgs e)
74 | {
75 | if (BrowseType == FileBrowseType.File)
76 | {
77 | OpenFileDialog dialog = new OpenFileDialog();
78 | dialog.Title = DialogTitle;
79 | dialog.Multiselect = false;
80 | dialog.InitialDirectory = Path.GetDirectoryName(path.Text);
81 | dialog.FileName = Path.GetFileName(path.Text);
82 | if (dialog.ShowDialog(FindForm(), FormStartPosition.CenterParent) == DialogResult.OK)
83 | path.Text = dialog.FileName;
84 | }
85 | else
86 | {
87 | FolderBrowserDialog dialog = new FolderBrowserDialog();
88 | dialog.Description = DialogTitle;
89 | dialog.SelectedPath = path.Text;
90 | if (dialog.ShowDialog(FindForm(), FormStartPosition.CenterParent) == DialogResult.OK)
91 | path.Text = dialog.SelectedPath;
92 | }
93 | }
94 | }
95 |
96 | public static class CommonDialogExtensions
97 | {
98 | public static DialogResult ShowDialog(this CommonDialog dialog, IWin32Window owner, FormStartPosition position)
99 | {
100 | if (owner == null)
101 | return dialog.ShowDialog();
102 | if (position != FormStartPosition.CenterParent && position != FormStartPosition.CenterScreen)
103 | return dialog.ShowDialog(owner);
104 |
105 | // TODO: implement
106 | //using (Form form = new Form())
107 | //{
108 | // form.Owner = owner as Form;
109 | // form.StartPosition = position;
110 | // return dialog.ShowDialog(form);
111 | //}
112 | return dialog.ShowDialog(owner);
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/MediaOrganizer/ExtensionMethods.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ExtensionMethods.cs: Static extension methods used within the project.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using ExifOrganizer.Common;
20 | using System;
21 | using System.IO;
22 | using System.Security.Cryptography;
23 |
24 | namespace ExifOrganizer.Organizer
25 | {
26 | public static class ExtensionMethods
27 | {
28 | public static bool FileExistsInDirectory(this FileInfo fileInfo, DirectoryInfo directory, FileComparator comparator)
29 | {
30 | foreach (FileInfo tempFile in directory.GetFiles())
31 | {
32 | if (tempFile.AreFilesIdentical(fileInfo, comparator))
33 | return true;
34 | }
35 | return false;
36 | }
37 |
38 | public static bool AreFilesIdentical(this FileInfo fileInfo, FileInfo otherFile, FileComparator comparator)
39 | {
40 | if (fileInfo == null)
41 | throw new ArgumentNullException(nameof(fileInfo));
42 | if (otherFile == null)
43 | throw new ArgumentNullException(nameof(otherFile));
44 | if (!fileInfo.Exists)
45 | return false;
46 | if (!otherFile.Exists)
47 | return false;
48 |
49 | bool identical = true;
50 | if (identical && comparator.HasFlag(FileComparator.FileSize))
51 | identical &= (fileInfo.Length == otherFile.Length);
52 | if (identical && comparator.HasFlag(FileComparator.ChecksumMD5))
53 | identical &= fileInfo.GetMD5Sum() == otherFile.GetMD5Sum();
54 | if (identical && comparator.HasFlag(FileComparator.ChecksumSHA1))
55 | identical &= fileInfo.GetSHA1Sum() == otherFile.GetSHA1Sum();
56 | if (identical && comparator.HasFlag(FileComparator.ChecksumSHA256))
57 | identical &= fileInfo.GetSHA256Sum() == otherFile.GetSHA256Sum();
58 | if (identical && comparator.HasFlag(FileComparator.Created))
59 | identical &= (fileInfo.CreationTimeUtc == otherFile.CreationTimeUtc);
60 | if (identical && comparator.HasFlag(FileComparator.Modified))
61 | identical &= (fileInfo.LastWriteTimeUtc == otherFile.LastWriteTimeUtc);
62 | return identical;
63 | }
64 |
65 | public static string GetGroupTypeText(this GroupType groupType)
66 | {
67 | switch (groupType)
68 | {
69 | case GroupType.Index: return "Unique index";
70 | case GroupType.MonthName: return "Name of month";
71 | case GroupType.MonthNumber: return "Month numeric value";
72 | case GroupType.DayName: return "Name of day";
73 | case GroupType.DayNumber: return "Day numeric value";
74 | case GroupType.OriginalName: return "Original file name";
75 | case GroupType.FileName: return "File name";
76 | case GroupType.FileExtension: return "File extension";
77 | case GroupType.FileNameWithExtension: return "File name with extension";
78 | case GroupType.WidthPx: return "Width in pixels";
79 | case GroupType.HeightPx: return "Height in pixels";
80 | //case GroupType.HorizontalDpi: return "Horizontal DPI";
81 | //case GroupType.VerticalDpi: return "Vertical DPI";
82 | default: return groupType.ToString();
83 | }
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/UserInterface/ExtensionMethods.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ExtensionMethods.cs: Static extension methods used within the project.
3 | //
4 | // Copyright (C) 2014 Rikard Johansson
5 | //
6 | // This program is free software: you can redistribute it and/or modify it
7 | // under the terms of the GNU General Public License as published by the Free
8 | // Software Foundation, either version 3 of the License, or (at your option) any
9 | // later version.
10 | //
11 | // This program is distributed in the hope that it will be useful, but WITHOUT
12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along with
16 | // this program. If not, see http://www.gnu.org/licenses/.
17 | //
18 |
19 | using ExifOrganizer.Organizer;
20 | using System;
21 | using System.Windows.Forms;
22 |
23 | namespace ExifOrganizer.UI
24 | {
25 | public static class ExtensionMethods
26 | {
27 | #region Generic
28 |
29 | public static int GetInt32(this Enum value)
30 | {
31 | if (value == null)
32 | return 0;
33 | return Convert.ToInt32(value);
34 | }
35 |
36 | public static long GetInt64(this Enum value)
37 | {
38 | if (value == null)
39 | return 0;
40 | return Convert.ToInt64(value);
41 | }
42 |
43 | public static bool Flags(this Enum value)
44 | {
45 | if (value == null)
46 | return false;
47 |
48 | Type type = value.GetType();
49 | return type.HasAttributesFlags();
50 | }
51 |
52 | public static bool HasAttributesFlags(this Type type)
53 | {
54 | if (type == null)
55 | throw new ArgumentNullException(nameof(type));
56 |
57 | object[] attributes = type.GetCustomAttributes(true);
58 | foreach (object attribute in attributes)
59 | {
60 | if (attribute is FlagsAttribute)
61 | return true;
62 | }
63 | return false;
64 | }
65 |
66 | public static bool OneBitSet(this Enum value)
67 | {
68 | long x = value.GetInt64();
69 | return (x != 0) && (x & (x - 1)) == 0;
70 | }
71 |
72 | public static double Clamp(this double value, double min, double max)
73 | {
74 | if (value < min)
75 | return min;
76 | if (value > max)
77 | return max;
78 | return value;
79 | }
80 |
81 | public static Exception GetInnerMost(this Exception exception)
82 | {
83 | if (exception == null)
84 | return null;
85 | if (exception.InnerException == null)
86 | return exception;
87 |
88 | return exception.InnerException.GetInnerMost();
89 | }
90 |
91 | public static string Get(this Version version)
92 | {
93 | return $"{version.Major}.{version.Minor}.{version.Build} build {version.Revision}";
94 | }
95 |
96 | #endregion Generic
97 |
98 | #region WinForms
99 |
100 | public static void Invoke(this Control control, Action action, params object[] args)
101 | {
102 | control.Invoke((Delegate)action, args);
103 | }
104 |
105 | public static object Invoke(this Control control, Func