mirror of
https://github.com/greenshot/greenshot
synced 2025-08-20 13:33:27 -07:00
Code quality changes
This commit is contained in:
parent
f07ed83722
commit
610f45d082
189 changed files with 4609 additions and 5203 deletions
|
@ -24,23 +24,19 @@ namespace Greenshot.IniFile {
|
|||
/// <summary>
|
||||
/// Attribute for telling that this class is linked to a section in the ini-configuration
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class IniSectionAttribute : Attribute {
|
||||
private string name;
|
||||
public IniSectionAttribute(string name) {
|
||||
this.name = name;
|
||||
Name = name;
|
||||
}
|
||||
public string Description;
|
||||
public string Name {
|
||||
get { return name; }
|
||||
set { name = value; }
|
||||
}
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute for telling that a field is linked to a property in the ini-configuration selection
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field|AttributeTargets.Property, AllowMultiple = false)]
|
||||
[AttributeUsage(AttributeTargets.Field|AttributeTargets.Property)]
|
||||
public class IniPropertyAttribute : Attribute {
|
||||
public IniPropertyAttribute() {
|
||||
Separator = ",";
|
||||
|
|
|
@ -28,55 +28,50 @@ using log4net;
|
|||
|
||||
namespace Greenshot.IniFile {
|
||||
public class IniConfig {
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(IniConfig));
|
||||
private const string INI_EXTENSION = ".ini";
|
||||
private const string DEFAULTS_POSTFIX = "-defaults";
|
||||
private const string FIXED_POSTFIX = "-fixed";
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(IniConfig));
|
||||
private const string IniExtension = ".ini";
|
||||
private const string DefaultsPostfix = "-defaults";
|
||||
private const string FixedPostfix = "-fixed";
|
||||
|
||||
/// <summary>
|
||||
/// A lock object for the ini file saving
|
||||
/// </summary>
|
||||
private static readonly object iniLock = new object();
|
||||
private static readonly object IniLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// As the ini implementation is kept someone generic, for reusing, this holds the name of the application
|
||||
/// </summary>
|
||||
private static string applicationName;
|
||||
private static string _applicationName;
|
||||
|
||||
/// <summary>
|
||||
/// As the ini implementation is kept someone generic, for reusing, this holds the name of the configuration
|
||||
/// </summary>
|
||||
private static string configName;
|
||||
private static string _configName;
|
||||
|
||||
/// <summary>
|
||||
/// A Dictionary with all the sections stored by section name
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, IniSection> sectionMap = new Dictionary<string, IniSection>();
|
||||
private static readonly Dictionary<string, IniSection> SectionMap = new Dictionary<string, IniSection>();
|
||||
|
||||
/// <summary>
|
||||
/// A Dictionary with the properties for a section stored by section name
|
||||
/// </summary>
|
||||
private static Dictionary<string, Dictionary<string, string>> sections = new Dictionary<string, Dictionary<string, string>>();
|
||||
private static Dictionary<string, Dictionary<string, string>> _sections = new Dictionary<string, Dictionary<string, string>>();
|
||||
|
||||
/// <summary>
|
||||
/// A Dictionary with the fixed-properties for a section stored by section name
|
||||
/// </summary>
|
||||
private static Dictionary<string, Dictionary<string, string>> fixedProperties;
|
||||
private static Dictionary<string, Dictionary<string, string>> _fixedProperties;
|
||||
|
||||
/// <summary>
|
||||
/// Stores if we checked for portable
|
||||
/// </summary>
|
||||
private static bool portableCheckMade;
|
||||
private static bool _portableCheckMade;
|
||||
|
||||
/// <summary>
|
||||
/// Is the configuration portable (meaning we don't store it in the AppData directory)
|
||||
/// </summary>
|
||||
private static bool portable;
|
||||
public static bool IsPortable {
|
||||
get {
|
||||
return portable;
|
||||
}
|
||||
}
|
||||
public static bool IsPortable { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Config directory when set from external
|
||||
|
@ -92,34 +87,34 @@ namespace Greenshot.IniFile {
|
|||
/// <param name="appName"></param>
|
||||
/// <param name="configName"></param>
|
||||
public static void Init(string appName, string configName) {
|
||||
applicationName = appName;
|
||||
IniConfig.configName = configName;
|
||||
_applicationName = appName;
|
||||
_configName = configName;
|
||||
Reload();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if we initialized the ini
|
||||
/// </summary>
|
||||
public static bool isInitialized {
|
||||
get {
|
||||
return applicationName != null && configName != null && sectionMap.Count > 0;
|
||||
}
|
||||
}
|
||||
public static bool IsInitialized => _applicationName != null && _configName != null && SectionMap.Count > 0;
|
||||
|
||||
/// <summary>
|
||||
/// This forces the ini to be stored in the startup path, used for portable applications
|
||||
/// </summary>
|
||||
public static void ForceIniInStartupPath() {
|
||||
if (portableCheckMade) {
|
||||
if (_portableCheckMade) {
|
||||
throw new Exception("ForceLocal should be called before any file is read");
|
||||
}
|
||||
portable = false;
|
||||
portableCheckMade = true;
|
||||
IsPortable = false;
|
||||
_portableCheckMade = true;
|
||||
string applicationStartupPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||
if (applicationName == null || configName == null) {
|
||||
if (_applicationName == null || _configName == null) {
|
||||
Init();
|
||||
}
|
||||
string forcedIni = Path.Combine(applicationStartupPath, applicationName + INI_EXTENSION);
|
||||
if (applicationStartupPath == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
string forcedIni = Path.Combine(applicationStartupPath, _applicationName + IniExtension);
|
||||
if (!File.Exists(forcedIni)) {
|
||||
using (File.Create(forcedIni)) {}
|
||||
}
|
||||
|
@ -130,9 +125,9 @@ namespace Greenshot.IniFile {
|
|||
/// </summary>
|
||||
public static void Init() {
|
||||
AssemblyProductAttribute[] assemblyProductAttributes = Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false) as AssemblyProductAttribute[];
|
||||
if (assemblyProductAttributes.Length > 0) {
|
||||
if (assemblyProductAttributes != null && assemblyProductAttributes.Length > 0) {
|
||||
string productName = assemblyProductAttributes[0].Product;
|
||||
LOG.InfoFormat("Using ProductName {0}", productName);
|
||||
Log.InfoFormat("Using ProductName {0}", productName);
|
||||
Init(productName, productName);
|
||||
} else {
|
||||
throw new InvalidOperationException("Assembly ProductName not set.");
|
||||
|
@ -144,8 +139,8 @@ namespace Greenshot.IniFile {
|
|||
/// </summary>
|
||||
public static string ConfigLocation {
|
||||
get {
|
||||
if (isInitialized) {
|
||||
return CreateIniLocation(configName + INI_EXTENSION, false);
|
||||
if (IsInitialized) {
|
||||
return CreateIniLocation(_configName + IniExtension, false);
|
||||
}
|
||||
throw new InvalidOperationException("Ini configuration was not initialized!");
|
||||
}
|
||||
|
@ -155,7 +150,7 @@ namespace Greenshot.IniFile {
|
|||
/// Create the location of the configuration file
|
||||
/// </summary>
|
||||
private static string CreateIniLocation(string configFilename, bool isReadOnly) {
|
||||
if (applicationName == null || configName == null) {
|
||||
if (_applicationName == null || _configName == null) {
|
||||
throw new InvalidOperationException("IniConfig.Init not called!");
|
||||
}
|
||||
string iniFilePath = null;
|
||||
|
@ -174,53 +169,60 @@ namespace Greenshot.IniFile {
|
|||
iniFilePath = null;
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
LOG.WarnFormat("The ini-directory {0} can't be used due to: {1}", IniDirectory, exception.Message);
|
||||
Log.WarnFormat("The ini-directory {0} can't be used due to: {1}", IniDirectory, exception.Message);
|
||||
}
|
||||
|
||||
string applicationStartupPath = "";
|
||||
string applicationStartupPath;
|
||||
try {
|
||||
applicationStartupPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||
} catch (Exception exception) {
|
||||
LOG.WarnFormat("Problem retrieving the AssemblyLocation: {0} (Designer mode?)", exception.Message);
|
||||
Log.WarnFormat("Problem retrieving the AssemblyLocation: {0} (Designer mode?)", exception.Message);
|
||||
applicationStartupPath = @".";
|
||||
}
|
||||
string pafPath = Path.Combine(applicationStartupPath, @"App\" + applicationName);
|
||||
if (applicationStartupPath != null)
|
||||
{
|
||||
string pafPath = Path.Combine(applicationStartupPath, @"App\" + _applicationName);
|
||||
|
||||
if (portable || !portableCheckMade) {
|
||||
if (!portable) {
|
||||
LOG.Info("Checking for portable mode.");
|
||||
portableCheckMade = true;
|
||||
if (Directory.Exists(pafPath)) {
|
||||
portable = true;
|
||||
LOG.Info("Portable mode active!");
|
||||
}
|
||||
}
|
||||
if (portable) {
|
||||
string pafConfigPath = Path.Combine(applicationStartupPath, @"Data\Settings");
|
||||
try {
|
||||
if (!Directory.Exists(pafConfigPath)) {
|
||||
Directory.CreateDirectory(pafConfigPath);
|
||||
if (IsPortable || !_portableCheckMade) {
|
||||
if (!IsPortable) {
|
||||
Log.Info("Checking for portable mode.");
|
||||
_portableCheckMade = true;
|
||||
if (Directory.Exists(pafPath)) {
|
||||
IsPortable = true;
|
||||
Log.Info("Portable mode active!");
|
||||
}
|
||||
}
|
||||
if (IsPortable) {
|
||||
string pafConfigPath = Path.Combine(applicationStartupPath, @"Data\Settings");
|
||||
try {
|
||||
if (!Directory.Exists(pafConfigPath)) {
|
||||
Directory.CreateDirectory(pafConfigPath);
|
||||
}
|
||||
iniFilePath = Path.Combine(pafConfigPath, configFilename);
|
||||
} catch(Exception e) {
|
||||
Log.InfoFormat("Portable mode NOT possible, couldn't create directory '{0}'! Reason: {1}", pafConfigPath, e.Message);
|
||||
}
|
||||
iniFilePath = Path.Combine(pafConfigPath, configFilename);
|
||||
} catch(Exception e) {
|
||||
LOG.InfoFormat("Portable mode NOT possible, couldn't create directory '{0}'! Reason: {1}", pafConfigPath, e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iniFilePath == null) {
|
||||
if (iniFilePath == null)
|
||||
{
|
||||
// check if file is in the same location as started from, if this is the case
|
||||
// we will use this file instead of the ApplicationData folder
|
||||
// Done for Feature Request #2741508
|
||||
iniFilePath = Path.Combine(applicationStartupPath, configFilename);
|
||||
if (applicationStartupPath != null)
|
||||
{
|
||||
iniFilePath = Path.Combine(applicationStartupPath, configFilename);
|
||||
}
|
||||
if (!File.Exists(iniFilePath)) {
|
||||
string iniDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), applicationName);
|
||||
string iniDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), _applicationName);
|
||||
if (!Directory.Exists(iniDirectory)) {
|
||||
Directory.CreateDirectory(iniDirectory);
|
||||
}
|
||||
iniFilePath = Path.Combine(iniDirectory, configFilename);
|
||||
}
|
||||
}
|
||||
LOG.InfoFormat("Using ini file {0}", iniFilePath);
|
||||
Log.InfoFormat("Using ini file {0}", iniFilePath);
|
||||
return iniFilePath;
|
||||
}
|
||||
|
||||
|
@ -229,25 +231,25 @@ namespace Greenshot.IniFile {
|
|||
/// </summary>
|
||||
public static void Reload() {
|
||||
// Clear the current properties
|
||||
sections = new Dictionary<string, Dictionary<string, string>>();
|
||||
_sections = new Dictionary<string, Dictionary<string, string>>();
|
||||
// Load the defaults
|
||||
Read(CreateIniLocation(configName + DEFAULTS_POSTFIX + INI_EXTENSION, true));
|
||||
Read(CreateIniLocation(_configName + DefaultsPostfix + IniExtension, true));
|
||||
// Load the normal
|
||||
Read(CreateIniLocation(configName + INI_EXTENSION, false));
|
||||
Read(CreateIniLocation(_configName + IniExtension, false));
|
||||
// Load the fixed settings
|
||||
fixedProperties = Read(CreateIniLocation(configName + FIXED_POSTFIX + INI_EXTENSION, true));
|
||||
_fixedProperties = Read(CreateIniLocation(_configName + FixedPostfix + IniExtension, true));
|
||||
|
||||
foreach (IniSection section in sectionMap.Values) {
|
||||
foreach (IniSection section in SectionMap.Values) {
|
||||
try {
|
||||
section.Fill(PropertiesForSection(section));
|
||||
FixProperties(section);
|
||||
} catch (Exception ex) {
|
||||
string sectionName = "unknown";
|
||||
if (section != null && section.IniSectionAttribute != null && section.IniSectionAttribute.Name != null) {
|
||||
if (section?.IniSectionAttribute?.Name != null) {
|
||||
sectionName = section.IniSectionAttribute.Name;
|
||||
}
|
||||
LOG.WarnFormat("Problem reading the ini section {0}", sectionName);
|
||||
LOG.Warn("Exception", ex);
|
||||
Log.WarnFormat("Problem reading the ini section {0}", sectionName);
|
||||
Log.Warn("Exception", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,14 +260,18 @@ namespace Greenshot.IniFile {
|
|||
/// <param name="section">IniSection</param>
|
||||
private static void FixProperties(IniSection section) {
|
||||
// Make properties unchangeable
|
||||
if (fixedProperties != null) {
|
||||
Dictionary<string, string> fixedPropertiesForSection = null;
|
||||
if (fixedProperties.TryGetValue(section.IniSectionAttribute.Name, out fixedPropertiesForSection)) {
|
||||
foreach (string fixedPropertyKey in fixedPropertiesForSection.Keys) {
|
||||
if (section.Values.ContainsKey(fixedPropertyKey)) {
|
||||
section.Values[fixedPropertyKey].IsFixed = true;
|
||||
}
|
||||
}
|
||||
if (_fixedProperties == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Dictionary<string, string> fixedPropertiesForSection;
|
||||
if (!_fixedProperties.TryGetValue(section.IniSectionAttribute.Name, out fixedPropertiesForSection))
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (string fixedPropertyKey in fixedPropertiesForSection.Keys) {
|
||||
if (section.Values.ContainsKey(fixedPropertyKey)) {
|
||||
section.Values[fixedPropertyKey].IsFixed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -276,21 +282,21 @@ namespace Greenshot.IniFile {
|
|||
/// <param name="iniLocation">Path & Filename of ini file</param>
|
||||
private static Dictionary<string, Dictionary<string, string>> Read(string iniLocation) {
|
||||
if (!File.Exists(iniLocation)) {
|
||||
LOG.Info("Can't find file: " + iniLocation);
|
||||
Log.Info("Can't find file: " + iniLocation);
|
||||
return null;
|
||||
}
|
||||
LOG.InfoFormat("Loading ini-file: {0}", iniLocation);
|
||||
Log.InfoFormat("Loading ini-file: {0}", iniLocation);
|
||||
//LOG.Info("Reading ini-properties from file: " + iniLocation);
|
||||
Dictionary<string, Dictionary<string, string>> newSections = IniReader.read(iniLocation, Encoding.UTF8);
|
||||
// Merge the newly loaded properties to the already available
|
||||
foreach(string section in newSections.Keys) {
|
||||
Dictionary<string, string> newProperties = newSections[section];
|
||||
if (!sections.ContainsKey(section)) {
|
||||
if (!_sections.ContainsKey(section)) {
|
||||
// This section is not yet loaded, simply add the complete section
|
||||
sections.Add(section, newProperties);
|
||||
_sections.Add(section, newProperties);
|
||||
} else {
|
||||
// Overwrite or add every property from the newly loaded section to the available one
|
||||
Dictionary<string, string> currentProperties = sections[section];
|
||||
Dictionary<string, string> currentProperties = _sections[section];
|
||||
foreach(string propertyName in newProperties.Keys) {
|
||||
string propertyValue = newProperties[propertyName];
|
||||
if (currentProperties.ContainsKey(propertyName)) {
|
||||
|
@ -308,7 +314,7 @@ namespace Greenshot.IniFile {
|
|||
|
||||
public static IEnumerable<string> IniSectionNames {
|
||||
get {
|
||||
foreach (string sectionName in sectionMap.Keys) {
|
||||
foreach (string sectionName in SectionMap.Keys) {
|
||||
yield return sectionName;
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +327,7 @@ namespace Greenshot.IniFile {
|
|||
/// <returns></returns>
|
||||
public static IniSection GetIniSection(string sectionName) {
|
||||
IniSection returnValue;
|
||||
sectionMap.TryGetValue(sectionName, out returnValue);
|
||||
SectionMap.TryGetValue(sectionName, out returnValue);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
@ -345,20 +351,20 @@ namespace Greenshot.IniFile {
|
|||
|
||||
Type iniSectionType = typeof(T);
|
||||
string sectionName = IniSection.GetIniSectionAttribute(iniSectionType).Name;
|
||||
if (sectionMap.ContainsKey(sectionName)) {
|
||||
if (SectionMap.ContainsKey(sectionName)) {
|
||||
//LOG.Debug("Returning pre-mapped section " + sectionName);
|
||||
section = (T)sectionMap[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);
|
||||
SectionMap.Add(sectionName, section);
|
||||
section.Fill(PropertiesForSection(section));
|
||||
FixProperties(section);
|
||||
}
|
||||
if (allowSave && section.IsDirty) {
|
||||
LOG.DebugFormat("Section {0} is marked dirty, saving!", sectionName);
|
||||
Log.DebugFormat("Section {0} is marked dirty, saving!", sectionName);
|
||||
Save();
|
||||
}
|
||||
return section;
|
||||
|
@ -373,11 +379,11 @@ namespace Greenshot.IniFile {
|
|||
string sectionName = section.IniSectionAttribute.Name;
|
||||
// Get the properties for the section
|
||||
IDictionary<string, string> properties;
|
||||
if (sections.ContainsKey(sectionName)) {
|
||||
properties = sections[sectionName];
|
||||
if (_sections.ContainsKey(sectionName)) {
|
||||
properties = _sections[sectionName];
|
||||
} else {
|
||||
sections.Add(sectionName, new Dictionary<string, string>());
|
||||
properties = sections[sectionName];
|
||||
_sections.Add(sectionName, new Dictionary<string, string>());
|
||||
properties = _sections[sectionName];
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
@ -388,23 +394,23 @@ namespace Greenshot.IniFile {
|
|||
public static void Save() {
|
||||
bool acquiredLock = false;
|
||||
try {
|
||||
acquiredLock = Monitor.TryEnter(iniLock, TimeSpan.FromMilliseconds(200));
|
||||
acquiredLock = Monitor.TryEnter(IniLock, TimeSpan.FromMilliseconds(200));
|
||||
if (acquiredLock) {
|
||||
// Code that accesses resources that are protected by the lock.
|
||||
string iniLocation = CreateIniLocation(configName + INI_EXTENSION, false);
|
||||
string iniLocation = CreateIniLocation(_configName + IniExtension, false);
|
||||
try {
|
||||
SaveInternally(iniLocation);
|
||||
} catch (Exception ex) {
|
||||
LOG.Error("A problem occured while writing the configuration file to: " + iniLocation);
|
||||
LOG.Error(ex);
|
||||
Log.Error("A problem occured while writing the configuration file to: " + iniLocation);
|
||||
Log.Error(ex);
|
||||
}
|
||||
} else {
|
||||
// Code to deal with the fact that the lock was not acquired.
|
||||
LOG.Warn("A second thread tried to save the ini-file, we blocked as the first took too long.");
|
||||
Log.Warn("A second thread tried to save the ini-file, we blocked as the first took too long.");
|
||||
}
|
||||
} finally {
|
||||
if (acquiredLock) {
|
||||
Monitor.Exit(iniLock);
|
||||
Monitor.Exit(IniLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -414,13 +420,15 @@ namespace Greenshot.IniFile {
|
|||
/// </summary>
|
||||
/// <param name="iniLocation"></param>
|
||||
private static void SaveInternally(string iniLocation) {
|
||||
LOG.Info("Saving configuration to: " + iniLocation);
|
||||
if (!Directory.Exists(Path.GetDirectoryName(iniLocation))) {
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(iniLocation));
|
||||
Log.Info("Saving configuration to: " + iniLocation);
|
||||
var iniPath = Path.GetDirectoryName(iniLocation);
|
||||
if (iniPath != null && !Directory.Exists(iniPath))
|
||||
{
|
||||
Directory.CreateDirectory(iniPath);
|
||||
}
|
||||
using (MemoryStream memoryStream = new MemoryStream()) {
|
||||
using (var memoryStream = new MemoryStream()) {
|
||||
using (TextWriter writer = new StreamWriter(memoryStream, Encoding.UTF8)) {
|
||||
foreach (IniSection section in sectionMap.Values) {
|
||||
foreach (var section in SectionMap.Values) {
|
||||
section.Write(writer, false);
|
||||
// Add empty line after section
|
||||
writer.WriteLine();
|
||||
|
@ -428,20 +436,22 @@ namespace Greenshot.IniFile {
|
|||
}
|
||||
writer.WriteLine();
|
||||
// Write left over properties
|
||||
foreach (string sectionName in sections.Keys) {
|
||||
foreach (string sectionName in _sections.Keys) {
|
||||
// Check if the section is one that is "registered", if so skip it!
|
||||
if (!sectionMap.ContainsKey(sectionName)) {
|
||||
writer.WriteLine("; The section {0} hasn't been 'claimed' since the last start of Greenshot, therefor it doesn't have additional information here!", sectionName);
|
||||
writer.WriteLine("; The reason could be that the section {0} just hasn't been used, a plugin has an error and can't claim it or maybe the whole section {0} is obsolete.", sectionName);
|
||||
// Write section name
|
||||
writer.WriteLine("[{0}]", sectionName);
|
||||
Dictionary<string, string> properties = sections[sectionName];
|
||||
// Loop and write properties
|
||||
foreach (string propertyName in properties.Keys) {
|
||||
writer.WriteLine("{0}={1}", propertyName, properties[propertyName]);
|
||||
}
|
||||
writer.WriteLine();
|
||||
if (SectionMap.ContainsKey(sectionName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
writer.WriteLine("; The section {0} hasn't been 'claimed' since the last start of Greenshot, therefor it doesn't have additional information here!", sectionName);
|
||||
writer.WriteLine("; The reason could be that the section {0} just hasn't been used, a plugin has an error and can't claim it or maybe the whole section {0} is obsolete.", sectionName);
|
||||
// Write section name
|
||||
writer.WriteLine("[{0}]", sectionName);
|
||||
Dictionary<string, string> properties = _sections[sectionName];
|
||||
// Loop and write properties
|
||||
foreach (string propertyName in properties.Keys) {
|
||||
writer.WriteLine("{0}={1}", propertyName, properties[propertyName]);
|
||||
}
|
||||
writer.WriteLine();
|
||||
}
|
||||
// Don't forget to flush the buffer
|
||||
writer.Flush();
|
||||
|
|
|
@ -31,22 +31,22 @@ namespace Greenshot.IniFile {
|
|||
/// A container to be able to pass the value from a IniSection around.
|
||||
/// </summary>
|
||||
public class IniValue {
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(IniValue));
|
||||
private readonly PropertyInfo propertyInfo;
|
||||
private readonly FieldInfo fieldInfo;
|
||||
private readonly IniSection containingIniSection;
|
||||
private readonly IniPropertyAttribute attributes;
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(IniValue));
|
||||
private readonly PropertyInfo _propertyInfo;
|
||||
private readonly FieldInfo _fieldInfo;
|
||||
private readonly IniSection _containingIniSection;
|
||||
private readonly IniPropertyAttribute _attributes;
|
||||
|
||||
public IniValue(IniSection containingIniSection, PropertyInfo propertyInfo, IniPropertyAttribute iniPropertyAttribute) {
|
||||
this.containingIniSection = containingIniSection;
|
||||
this.propertyInfo = propertyInfo;
|
||||
attributes = iniPropertyAttribute;
|
||||
_containingIniSection = containingIniSection;
|
||||
_propertyInfo = propertyInfo;
|
||||
_attributes = iniPropertyAttribute;
|
||||
}
|
||||
|
||||
public IniValue(IniSection containingIniSection, FieldInfo fieldInfo, IniPropertyAttribute iniPropertyAttribute) {
|
||||
this.containingIniSection = containingIniSection;
|
||||
this.fieldInfo = fieldInfo;
|
||||
attributes = iniPropertyAttribute;
|
||||
_containingIniSection = containingIniSection;
|
||||
_fieldInfo = fieldInfo;
|
||||
_attributes = iniPropertyAttribute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -54,14 +54,14 @@ namespace Greenshot.IniFile {
|
|||
/// </summary>
|
||||
public bool IsFixed {
|
||||
get {
|
||||
if (attributes != null) {
|
||||
return attributes.FixedValue;
|
||||
if (_attributes != null) {
|
||||
return _attributes.FixedValue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
set {
|
||||
if (attributes != null) {
|
||||
attributes.FixedValue = value;
|
||||
if (_attributes != null) {
|
||||
_attributes.FixedValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,14 +71,14 @@ namespace Greenshot.IniFile {
|
|||
/// </summary>
|
||||
public bool IsExpert {
|
||||
get {
|
||||
if (attributes != null) {
|
||||
return attributes.Expert;
|
||||
if (_attributes != null) {
|
||||
return _attributes.Expert;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
set {
|
||||
if (attributes != null) {
|
||||
attributes.Expert = value;
|
||||
if (_attributes != null) {
|
||||
_attributes.Expert = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,65 +87,49 @@ namespace Greenshot.IniFile {
|
|||
/// <summary>
|
||||
/// Return true when the value is can be changed by the GUI
|
||||
/// </summary>
|
||||
public bool IsEditable {
|
||||
get {
|
||||
return !IsFixed;
|
||||
}
|
||||
}
|
||||
public bool IsEditable => !IsFixed;
|
||||
|
||||
/// <summary>
|
||||
/// Return true when the value is visible in the GUI
|
||||
/// </summary>
|
||||
public bool IsVisible {
|
||||
get {
|
||||
return !IsExpert;
|
||||
}
|
||||
}
|
||||
public bool IsVisible => !IsExpert;
|
||||
|
||||
public MemberInfo MemberInfo {
|
||||
get {
|
||||
if (propertyInfo == null) {
|
||||
return fieldInfo;
|
||||
} else {
|
||||
return propertyInfo;
|
||||
get
|
||||
{
|
||||
if (_propertyInfo == null) {
|
||||
return _fieldInfo;
|
||||
}
|
||||
return _propertyInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the IniSection this value is contained in
|
||||
/// </summary>
|
||||
public IniSection ContainingIniSection {
|
||||
get {
|
||||
return containingIniSection;
|
||||
}
|
||||
}
|
||||
|
||||
public IniSection ContainingIniSection => _containingIniSection;
|
||||
|
||||
/// <summary>
|
||||
/// Get the in the ini file defined attributes
|
||||
/// </summary>
|
||||
public IniPropertyAttribute Attributes {
|
||||
get {
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
|
||||
public IniPropertyAttribute Attributes => _attributes;
|
||||
|
||||
/// <summary>
|
||||
/// Get the value for this IniValue
|
||||
/// </summary>
|
||||
public object Value {
|
||||
get {
|
||||
if (propertyInfo == null) {
|
||||
return fieldInfo.GetValue(containingIniSection);
|
||||
} else {
|
||||
return propertyInfo.GetValue(containingIniSection, null);
|
||||
get
|
||||
{
|
||||
if (_propertyInfo == null) {
|
||||
return _fieldInfo.GetValue(_containingIniSection);
|
||||
}
|
||||
return _propertyInfo.GetValue(_containingIniSection, null);
|
||||
}
|
||||
set {
|
||||
if (propertyInfo == null) {
|
||||
fieldInfo.SetValue(containingIniSection, value);
|
||||
if (_propertyInfo == null) {
|
||||
_fieldInfo.SetValue(_containingIniSection, value);
|
||||
} else {
|
||||
propertyInfo.SetValue(containingIniSection, value, null);
|
||||
_propertyInfo.SetValue(_containingIniSection, value, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,13 +139,9 @@ namespace Greenshot.IniFile {
|
|||
/// </summary>
|
||||
public Type ValueType {
|
||||
get {
|
||||
Type valueType = null;
|
||||
if (propertyInfo == null) {
|
||||
valueType = fieldInfo.FieldType;
|
||||
} else {
|
||||
valueType = propertyInfo.PropertyType;
|
||||
}
|
||||
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
|
||||
var valueType = _propertyInfo?.PropertyType ?? _fieldInfo.FieldType;
|
||||
var genericTypeDefinition = valueType.GetGenericTypeDefinition();
|
||||
if (genericTypeDefinition != null && (valueType.IsGenericType && genericTypeDefinition == typeof(Nullable<>))) {
|
||||
// We are dealing with a generic type that is nullable
|
||||
valueType = Nullable.GetUnderlyingType(valueType);
|
||||
}
|
||||
|
@ -178,29 +158,29 @@ namespace Greenshot.IniFile {
|
|||
object myValue = Value;
|
||||
Type valueType = ValueType;
|
||||
if (myValue == null) {
|
||||
if (attributes.ExcludeIfNull) {
|
||||
if (_attributes.ExcludeIfNull) {
|
||||
return;
|
||||
}
|
||||
if (attributes.DefaultValue != null) {
|
||||
myValue = attributes.DefaultValue;
|
||||
if (_attributes.DefaultValue != null) {
|
||||
myValue = _attributes.DefaultValue;
|
||||
valueType = typeof(string);
|
||||
} else {
|
||||
myValue = containingIniSection.GetDefault(attributes.Name);
|
||||
myValue = _containingIniSection.GetDefault(_attributes.Name);
|
||||
if (myValue != null) {
|
||||
valueType = myValue.GetType();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myValue == null) {
|
||||
if (attributes.ExcludeIfNull) {
|
||||
if (_attributes.ExcludeIfNull) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!onlyProperties) {
|
||||
writer.WriteLine("; {0}", attributes.Description);
|
||||
writer.WriteLine("; {0}", _attributes.Description);
|
||||
}
|
||||
if (myValue == null) {
|
||||
writer.WriteLine("{0}=", attributes.Name);
|
||||
writer.WriteLine("{0}=", _attributes.Name);
|
||||
return;
|
||||
}
|
||||
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
|
||||
|
@ -218,10 +198,10 @@ namespace Greenshot.IniFile {
|
|||
var key = current.Invoke(enumerator, null);
|
||||
var valueObject = item.GetValue(myValue, new[] { key });
|
||||
// Write to ini file!
|
||||
writer.WriteLine("{0}.{1}={2}", attributes.Name, ConvertValueToString(valueType1, key, attributes.Separator), ConvertValueToString(valueType2, valueObject, attributes.Separator));
|
||||
writer.WriteLine("{0}.{1}={2}", _attributes.Name, ConvertValueToString(valueType1, key, _attributes.Separator), ConvertValueToString(valueType2, valueObject, _attributes.Separator));
|
||||
}
|
||||
} else {
|
||||
writer.WriteLine("{0}={1}", attributes.Name, ConvertValueToString(valueType, myValue, attributes.Separator));
|
||||
writer.WriteLine("{0}={1}", _attributes.Name, ConvertValueToString(valueType, myValue, _attributes.Separator));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,10 +210,10 @@ namespace Greenshot.IniFile {
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void SetValueFromProperties(IDictionary<string, string> properties) {
|
||||
string propertyName = attributes.Name;
|
||||
string propertyName = _attributes.Name;
|
||||
string propertyValue = null;
|
||||
if (properties.ContainsKey(propertyName) && properties[propertyName] != null) {
|
||||
propertyValue = containingIniSection.PreCheckValue(propertyName, properties[propertyName]);
|
||||
propertyValue = _containingIniSection.PreCheckValue(propertyName, properties[propertyName]);
|
||||
}
|
||||
UseValueOrDefault(propertyValue);
|
||||
}
|
||||
|
@ -244,23 +224,23 @@ namespace Greenshot.IniFile {
|
|||
/// <param name="propertyValue"></param>
|
||||
public void UseValueOrDefault(string propertyValue) {
|
||||
Type valueType = ValueType;
|
||||
string propertyName = attributes.Name;
|
||||
string defaultValue = attributes.DefaultValue;
|
||||
string propertyName = _attributes.Name;
|
||||
string defaultValue = _attributes.DefaultValue;
|
||||
bool defaultUsed = false;
|
||||
object defaultValueFromConfig = containingIniSection.GetDefault(propertyName);
|
||||
object defaultValueFromConfig = _containingIniSection.GetDefault(propertyName);
|
||||
|
||||
if (string.IsNullOrEmpty(propertyValue)) {
|
||||
if (defaultValue != null && defaultValue.Trim().Length != 0) {
|
||||
propertyValue = defaultValue;
|
||||
defaultUsed = true;
|
||||
} else if (defaultValueFromConfig != null) {
|
||||
LOG.DebugFormat("Default for Property {0} implemented!", propertyName);
|
||||
Log.DebugFormat("Default for Property {0} implemented!", propertyName);
|
||||
} else {
|
||||
if (attributes.ExcludeIfNull) {
|
||||
if (_attributes.ExcludeIfNull) {
|
||||
Value = null;
|
||||
return;
|
||||
}
|
||||
LOG.DebugFormat("Property {0} has no value or default value!", propertyName);
|
||||
Log.DebugFormat("Property {0} has no value or default value!", propertyName);
|
||||
}
|
||||
}
|
||||
// Now set the value
|
||||
|
@ -272,7 +252,7 @@ namespace Greenshot.IniFile {
|
|||
object dictionary = Activator.CreateInstance(valueType);
|
||||
MethodInfo addMethodInfo = valueType.GetMethod("Add");
|
||||
bool addedElements = false;
|
||||
IDictionary<string, string> properties = IniConfig.PropertiesForSection(containingIniSection);
|
||||
IDictionary<string, string> properties = IniConfig.PropertiesForSection(_containingIniSection);
|
||||
foreach (string key in properties.Keys) {
|
||||
if (key != null && key.StartsWith(propertyName + ".")) {
|
||||
// What "key" do we need to store it under?
|
||||
|
@ -281,15 +261,15 @@ namespace Greenshot.IniFile {
|
|||
object newValue1 = null;
|
||||
object newValue2 = null;
|
||||
try {
|
||||
newValue1 = ConvertStringToValueType(type1, subPropertyName, attributes.Separator);
|
||||
newValue1 = ConvertStringToValueType(type1, subPropertyName, _attributes.Separator);
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
Log.Warn(ex);
|
||||
//LOG.Error("Problem converting " + subPropertyName + " to type " + type1.FullName, e);
|
||||
}
|
||||
try {
|
||||
newValue2 = ConvertStringToValueType(type2, stringValue, attributes.Separator);
|
||||
newValue2 = ConvertStringToValueType(type2, stringValue, _attributes.Separator);
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn(ex);
|
||||
Log.Warn(ex);
|
||||
//LOG.Error("Problem converting " + stringValue + " to type " + type2.FullName, e);
|
||||
}
|
||||
addMethodInfo.Invoke(dictionary, new[] { newValue1, newValue2 });
|
||||
|
@ -300,31 +280,33 @@ namespace Greenshot.IniFile {
|
|||
if (addedElements) {
|
||||
Value = dictionary;
|
||||
return;
|
||||
} else if (defaultValueFromConfig != null) {
|
||||
}
|
||||
if (defaultValueFromConfig != null) {
|
||||
Value = defaultValueFromConfig;
|
||||
return;
|
||||
}
|
||||
} else if (!string.IsNullOrEmpty(propertyValue)) {
|
||||
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
|
||||
var genericTypeDefinition = valueType.GetGenericTypeDefinition();
|
||||
if (genericTypeDefinition != null && (valueType.IsGenericType && genericTypeDefinition == typeof(Nullable<>))) {
|
||||
// We are dealing with a generic type that is nullable
|
||||
valueType = Nullable.GetUnderlyingType(valueType);
|
||||
}
|
||||
object newValue = null;
|
||||
object newValue;
|
||||
try {
|
||||
newValue = ConvertStringToValueType(valueType, propertyValue, attributes.Separator);
|
||||
newValue = ConvertStringToValueType(valueType, propertyValue, _attributes.Separator);
|
||||
} catch (Exception ex1) {
|
||||
newValue = null;
|
||||
if (!defaultUsed) {
|
||||
try {
|
||||
LOG.WarnFormat("Problem '{0}' while converting {1} to type {2} trying fallback...", ex1.Message, propertyValue, valueType.FullName);
|
||||
newValue = ConvertStringToValueType(valueType, defaultValue, attributes.Separator);
|
||||
Log.WarnFormat("Problem '{0}' while converting {1} to type {2} trying fallback...", ex1.Message, propertyValue, valueType.FullName);
|
||||
newValue = ConvertStringToValueType(valueType, defaultValue, _attributes.Separator);
|
||||
ContainingIniSection.IsDirty = true;
|
||||
LOG.InfoFormat("Used default value {0} for property {1}", defaultValue, propertyName);
|
||||
Log.InfoFormat("Used default value {0} for property {1}", defaultValue, propertyName);
|
||||
} catch (Exception ex2) {
|
||||
LOG.Warn("Problem converting fallback value " + defaultValue + " to type " + valueType.FullName, ex2);
|
||||
Log.Warn("Problem converting fallback value " + defaultValue + " to type " + valueType.FullName, ex2);
|
||||
}
|
||||
} else {
|
||||
LOG.Warn("Problem converting " + propertyValue + " to type " + valueType.FullName, ex1);
|
||||
Log.Warn("Problem converting " + propertyValue + " to type " + valueType.FullName, ex1);
|
||||
}
|
||||
}
|
||||
Value = newValue;
|
||||
|
@ -340,7 +322,7 @@ namespace Greenshot.IniFile {
|
|||
try {
|
||||
Value = Activator.CreateInstance(ValueType);
|
||||
} catch (Exception) {
|
||||
LOG.WarnFormat("Couldn't create instance of {0} for {1}, using default value.", ValueType.FullName, attributes.Name);
|
||||
Log.WarnFormat("Couldn't create instance of {0} for {1}, using default value.", ValueType.FullName, _attributes.Name);
|
||||
Value = default(ValueType);
|
||||
}
|
||||
} else {
|
||||
|
@ -371,18 +353,18 @@ namespace Greenshot.IniFile {
|
|||
object list = Activator.CreateInstance(valueType);
|
||||
// Logic for List<>
|
||||
string[] arrayValues = valueString.Split(new[] { arraySeparator }, StringSplitOptions.None);
|
||||
if (arrayValues == null || arrayValues.Length == 0) {
|
||||
if (arrayValues.Length == 0) {
|
||||
return list;
|
||||
}
|
||||
MethodInfo addMethodInfo = valueType.GetMethod("Add");
|
||||
|
||||
foreach (string arrayValue in arrayValues) {
|
||||
if (arrayValue != null && arrayValue.Length > 0) {
|
||||
if (!string.IsNullOrEmpty(arrayValue)) {
|
||||
object newValue = null;
|
||||
try {
|
||||
newValue = ConvertStringToValueType(valueType.GetGenericArguments()[0], arrayValue, separator);
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn("Problem converting " + arrayValue + " to type " + valueType.FullName, ex);
|
||||
Log.Warn("Problem converting " + arrayValue + " to type " + valueType.FullName, ex);
|
||||
}
|
||||
if (newValue != null) {
|
||||
addMethodInfo.Invoke(list, new[] { newValue });
|
||||
|
@ -394,7 +376,7 @@ namespace Greenshot.IniFile {
|
|||
//LOG.Debug("No convertor for " + fieldType.ToString());
|
||||
if (valueType == typeof(object) && valueString.Length > 0) {
|
||||
//LOG.Debug("Parsing: " + valueString);
|
||||
string[] values = valueString.Split(new[] { ':' });
|
||||
string[] values = valueString.Split(':');
|
||||
//LOG.Debug("Type: " + values[0]);
|
||||
//LOG.Debug("Value: " + values[1]);
|
||||
Type fieldTypeForValue = Type.GetType(values[0], true);
|
||||
|
@ -402,25 +384,7 @@ namespace Greenshot.IniFile {
|
|||
return ConvertStringToValueType(fieldTypeForValue, values[1], separator);
|
||||
}
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(valueType);
|
||||
if (converter != null) {
|
||||
return converter.ConvertFromInvariantString(valueString);
|
||||
} else if (valueType.IsEnum) {
|
||||
if (valueString.Length > 0) {
|
||||
try {
|
||||
return Enum.Parse(valueType, valueString);
|
||||
} catch (ArgumentException) {
|
||||
//LOG.InfoFormat("Couldn't match {0} to {1}, trying case-insentive match", valueString, fieldType);
|
||||
foreach (Enum enumValue in Enum.GetValues(valueType)) {
|
||||
if (enumValue.ToString().Equals(valueString, StringComparison.InvariantCultureIgnoreCase)) {
|
||||
//LOG.Info("Match found...");
|
||||
return enumValue;
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return converter.ConvertFromInvariantString(valueString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -428,7 +392,7 @@ namespace Greenshot.IniFile {
|
|||
/// </summary>
|
||||
/// <returns>string representation of this</returns>
|
||||
public override string ToString() {
|
||||
return ConvertValueToString(ValueType, Value, attributes.Separator);
|
||||
return ConvertValueToString(ValueType, Value, _attributes.Separator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -479,14 +443,10 @@ namespace Greenshot.IniFile {
|
|||
if (assemblyName.StartsWith("Green")) {
|
||||
assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(','));
|
||||
}
|
||||
return string.Format("{0},{1}:{2}", valueTypeName, assemblyName, ourValue);
|
||||
return $"{valueTypeName},{assemblyName}:{ourValue}";
|
||||
}
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(valueType);
|
||||
if (converter != null) {
|
||||
return converter.ConvertToInvariantString(valueObject);
|
||||
}
|
||||
// All other types
|
||||
return valueObject.ToString();
|
||||
return converter.ConvertToInvariantString(valueObject);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue