diff --git a/GreenshotCore/Configuration/CoreConfiguration.cs b/GreenshotCore/Configuration/CoreConfiguration.cs new file mode 100644 index 000000000..f4163ce55 --- /dev/null +++ b/GreenshotCore/Configuration/CoreConfiguration.cs @@ -0,0 +1,36 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2010 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +using System; + +namespace GreenshotCore.Configuration { + /// + /// Description of CoreConfiguration. + /// + [IniSection("Core", Description="Greenshot core configuration")] + public class CoreConfiguration : IniSection { + [IniProperty("Language", Description="The language in IETF format (e.g. en-EN)", DefaultValue="en-EN")] + public string Language; + [IniProperty("RegisterHotkeys", Description="Register the hotkeys?", DefaultValue="true")] + public bool RegisterHotkeys; + [IniProperty("IsFirstLaunch", Description="Is this the first time launch?", DefaultValue="true")] + public bool IsFirstLaunch; + } +} diff --git a/GreenshotCore/Core/ConfigHelper.cs b/GreenshotCore/Core/ConfigHelper.cs new file mode 100644 index 000000000..4dd2176ce --- /dev/null +++ b/GreenshotCore/Core/ConfigHelper.cs @@ -0,0 +1,391 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2010 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Windows.Forms; + +namespace GreenshotCore.Configuration { + + /// + /// Attribute for telling that this class is linked to a section in the ini-configuration + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=false)] + public class IniSectionAttribute : Attribute { + private string name; + public IniSectionAttribute(string name) { + this.name = name; + } + public string Description; + public string Name { + get {return name;} + set {name = value;} + } + } + + /// + /// Attribute for telling that a field is linked to a property in the ini-configuration selection + /// + [AttributeUsage(AttributeTargets.Field, AllowMultiple=false)] + public class IniPropertyAttribute : Attribute { + private string name; + public IniPropertyAttribute(string name) { + this.name = name; + } + public string Description; + public string DefaultValue; + public string Name { + get {return name;} + set {name = value;} + } + } + + // Interface for + public interface IniSection { + } + + public class IniConfig { + private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IniConfig)); + private const string CONFIG_FILE_NAME = "greenshot.ini"; + private const string DEFAULTS_CONFIG_FILE_NAME = "greenshot-defaults.ini"; + + private static IniConfig instance = null; + + private string iniLocation = null; + private Dictionary sectionMap = new Dictionary(); + private Dictionary> iniProperties = new Dictionary>(); + + /// + /// get an instance of IniConfig + /// + /// + public static IniConfig GetInstance() { + if (instance == null) { + instance = new IniConfig(); + } + return instance; + } + + /// + /// Create the location of the configuration file + /// + private static string CreateIniLocation(string configFilename) { + // check if file is in the same location as started from, if this is the case + // we will use this file instead of the Applicationdate folder + // Done for Feature Request #2741508 + if (File.Exists(Path.Combine(Application.StartupPath, configFilename))) { + return Path.Combine(Application.StartupPath, configFilename); + } + return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),@"Greenshot\" + configFilename); + } + + /// + /// Private Constuctor, + /// + /// + private IniConfig() { + this.iniLocation = CreateIniLocation(CONFIG_FILE_NAME); + Read(CreateIniLocation(DEFAULTS_CONFIG_FILE_NAME)); + Read(CreateIniLocation(iniLocation)); + } + + /// + /// Read the ini file into the Dictionary + /// + /// Path & Filename of ini file + private void Read(string iniLocation) { + if (!File.Exists(iniLocation)) { + LOG.Info("Can't find file: " + iniLocation); + return; + } + LOG.Info("Reading ini-properties from file: " + iniLocation); + + String currentSection = null; + foreach (string line in File.ReadAllLines(iniLocation)) { + if (line == null) { + continue; + } + string currentLine = line.TrimStart(); + if (currentLine.StartsWith("[")) { + currentSection = currentLine.Substring(1, currentLine.IndexOf(']')-1); + LOG.Debug("Found section: " + currentSection); + } else if (!currentLine.StartsWith(";") && currentLine.IndexOf('=') > 0) { + string [] split = currentLine.Split(new Char[] {'='}, 2); + if (split != null && split.Length == 2) { + string name = split[0]; + if (name == null || name.Length < 1) { + continue; + } + name = name.Trim(); + String value = split[1]; + if (!HasProperty(currentSection, name)) { + SetProperty(currentSection, name, value); + } else { + ChangeProperty(currentSection, name, value); + } + } + } + } + } + + /// + /// A generic method which returns an instance of the supplied type, filled with it's configuration + /// + /// Filled instance of IniSection type which was supplied + public T GetSection() where T : IniSection { + T section; + Type iniSectionType = typeof(T); + string sectionName = getSectionName(iniSectionType); + if (sectionMap.ContainsKey(sectionName)) { + section = (T)sectionMap[sectionName]; + } else { + // Create instance of this type + section = (T)Activator.CreateInstance(iniSectionType); + + // Store for later save & retrieval + sectionMap.Add(sectionName, section); + + // Get the properties for the section + Dictionary properties = null; + if (iniProperties.ContainsKey(sectionName)) { + properties = iniProperties[sectionName]; + } + + // Iterate over the fields and fill them + FieldInfo[] fields = iniSectionType.GetFields(); + foreach(FieldInfo field in fields) { + if (Attribute.IsDefined(field, typeof(IniPropertyAttribute))) { + IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)field.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0]; + string propertyName = iniPropertyAttribute.Name; + string propertyValue = null; + // Get the value from the ini file, if there is none take the default + if (properties != null && properties.ContainsKey(propertyName)) { + propertyValue = properties[propertyName]; + } else { + propertyValue = iniPropertyAttribute.DefaultValue; + } + + // Get the type, or the underlying type for nullables + Type fieldType = field.FieldType; + if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { + // We are dealing with a generic type that is nullable + fieldType = Nullable.GetUnderlyingType(fieldType); + } + + // Now set the value + if (fieldType == typeof(string)) { + field.SetValue(section, propertyValue); + } else if (fieldType == typeof(bool) || fieldType == typeof(bool?)) { + field.SetValue(section, bool.Parse(propertyValue)); + } else if (fieldType == typeof(int) || fieldType == typeof(int?)) { + field.SetValue(section, int.Parse(propertyValue)); + } else if (fieldType.IsEnum) { + field.SetValue(section, Enum.Parse(fieldType, propertyValue)); + } + } + } + } + return section; + } + + public IniSection GetSection(Type iniSectionType) { + IniSection section = null; + string sectionName = getSectionName(iniSectionType); + if (sectionMap.ContainsKey(sectionName)) { + section = sectionMap[sectionName]; + } else { + // Create instance of this type + section = (IniSection)Activator.CreateInstance(iniSectionType); + + // Get the properties for the section + Dictionary properties = null; + if (iniProperties.ContainsKey(sectionName)) { + properties = iniProperties[sectionName]; + } + + // Iterate over the fields and fill them + FieldInfo[] fields = iniSectionType.GetFields(); + foreach(FieldInfo field in fields) { + if (Attribute.IsDefined(field, typeof(IniPropertyAttribute))) { + IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)field.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0]; + string propertyName = iniPropertyAttribute.Name; + string propertyValue = null; + // Get the value from the ini file, if there is none take the default + if (properties != null && properties.ContainsKey(propertyName)) { + propertyValue = properties[propertyName]; + } else { + propertyValue = iniPropertyAttribute.DefaultValue; + } + + // Get the type, or the underlying type for nullables + Type fieldType = field.FieldType; + if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { + // We are dealing with a generic type that is nullable + fieldType = Nullable.GetUnderlyingType(fieldType); + } + + // Now set the value + if (fieldType == typeof(string)) { + field.SetValue(section, propertyValue); + } else if (fieldType == typeof(bool) || fieldType == typeof(bool?)) { + field.SetValue(section, bool.Parse(propertyValue)); + } else if (fieldType == typeof(int) || fieldType == typeof(int?)) { + field.SetValue(section, int.Parse(propertyValue)); + } else if (fieldType.IsEnum) { + field.SetValue(section, Enum.Parse(fieldType, propertyValue)); + } + } + } + } + return section; + } + + private string getSectionName(Type iniSectionType) { + Attribute[] classAttributes = Attribute.GetCustomAttributes(iniSectionType); + foreach(Attribute attribute in classAttributes) { + if (attribute is IniSectionAttribute) { + IniSectionAttribute iniSectionAttribute = (IniSectionAttribute)attribute; + return iniSectionAttribute.Name; + } + } + return null; + } + + private Dictionary getProperties(string section) { + if (iniProperties.ContainsKey(section)) { + return iniProperties[section]; + } + return null; + } + + public void ChangeProperty(string section, string name, string value) { + if (section != null) { + Dictionary properties = iniProperties[section]; + properties[name] = value; + LOG.Debug(String.Format("Changed property {0} to section: {0}.", name, section)); + } else { + LOG.Debug("Property without section: " + name); + } + } + + public void SetProperty(string section, string name, string value) { + if (section != null) { + Dictionary properties = null; + if (!iniProperties.ContainsKey(section)) { + properties = new Dictionary(); + iniProperties.Add(section, properties); + } else { + properties = iniProperties[section]; + } + properties.Add(name, value); + LOG.Debug(String.Format("Added property {0} to section: {0}.", name, section)); + } else { + LOG.Debug("Property without section: " + name); + } + } + + + public bool HasProperty(string section, string name) { + Dictionary properties = getProperties(section); + if (properties != null && properties.ContainsKey(name)) { + return true; + } + return false; + } + + public string GetProperty(string section, string name) { + Dictionary properties = getProperties(section); + if (properties != null && properties.ContainsKey(name)) { + return properties[name]; + } + return null; + } + + /// + /// Split property with ',' and return the splitted string as a string[] + /// + public string[] GetPropertyAsArray(string section, string key) { + Dictionary properties = getProperties(section); + string value = GetProperty(section, key); + if (value != null) { + return value.Split(new Char[] {','}); + } + return null; + } + + public bool GetBoolProperty(string section, string key) { + Dictionary properties = getProperties(section); + string value = GetProperty(section, key); + return bool.Parse(value); + } + + public int GetIntProperty(string section, string key) { + Dictionary properties = getProperties(section); + string value = GetProperty(section, key); + return int.Parse(value); + } + + public void Save() { + LOG.Info("Saving configuration to: " + iniLocation); + TextWriter writer = new StreamWriter(iniLocation); + foreach(IniSection section in sectionMap.Values) { + Type classType = section.GetType(); + Attribute[] classAttributes = Attribute.GetCustomAttributes(classType); + foreach(Attribute attribute in classAttributes) { + if (attribute is IniSectionAttribute) { + IniSectionAttribute iniSectionAttribute = (IniSectionAttribute)attribute; + writer.WriteLine("; {0}", iniSectionAttribute.Description); + writer.WriteLine("[{0}]", iniSectionAttribute.Name); + FieldInfo[] fields = classType.GetFields(); + foreach(FieldInfo field in fields) { + if (Attribute.IsDefined(field, typeof(IniPropertyAttribute))) { + IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)field.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0]; + writer.WriteLine("; {0}", iniPropertyAttribute.Description); + object value = field.GetValue(section); + if (value == null) { + value = iniPropertyAttribute.DefaultValue; + } + writer.WriteLine("{0}={1}", iniPropertyAttribute.Name, value); + } + } + } + } + writer.WriteLine(); + } + + // Write left over properties + foreach(string sectionName in iniProperties.Keys) { + // Check if the section is one that is "registered", if so skip it! + if (!sectionMap.ContainsKey(sectionName)) { + // Write section name + writer.WriteLine("[{0}]", sectionName); + Dictionary properties = iniProperties[sectionName]; + // Loop and write properties + foreach(string propertyName in properties.Keys) { + writer.WriteLine("{0}={1}", propertyName, properties[propertyName]); + } + } + } + writer.Close(); + } + } +} diff --git a/GreenshotCore/GreenshotCore.csproj b/GreenshotCore/GreenshotCore.csproj index 5368d4af0..51b00f8ac 100644 --- a/GreenshotCore/GreenshotCore.csproj +++ b/GreenshotCore/GreenshotCore.csproj @@ -62,9 +62,11 @@ + +