pcsx2/tools/GSDumpGUI/Forms/SettingsProvider/PortableXmlSettingsProvider.cs

217 lines
8.1 KiB
C#

/*
* Copyright (C) 2009-2019 PCSX2 Dev Team
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Xml;
using System.Xml.Linq;
namespace GSDumpGUI.Forms.SettingsProvider
{
public sealed class PortableXmlSettingsProvider : System.Configuration.SettingsProvider, IApplicationSettingsProvider
{
private const string RootNode = "configuration";
private static string SettingsDirectory => AppDomain.CurrentDomain.BaseDirectory;
public override string Name => nameof(PortableXmlSettingsProvider);
private static string ApplicationSettingsFile => Path.Combine(SettingsDirectory, "portable.config");
public static void ApplyProvider(params ApplicationSettingsBase[] settingsList)
=> ApplyProvider(new PortableXmlSettingsProvider(), settingsList);
public override string ApplicationName
{
get
{
return nameof(GSDumpGUI);
}
set { }
}
private static XDocument GetOrCreateXmlDocument()
{
if (!File.Exists(ApplicationSettingsFile))
return CreateNewDocument();
try
{
return XDocument.Load(ApplicationSettingsFile);
}
catch
{
return CreateNewDocument();
}
}
private static void ApplyProvider(PortableXmlSettingsProvider provider, params ApplicationSettingsBase[] settingsList)
{
foreach (ApplicationSettingsBase settings in settingsList)
{
settings.Providers.Clear();
settings.Providers.Add(provider);
foreach (SettingsProperty property in settings.Properties)
property.Provider = provider;
settings.Reload();
}
}
public override void Initialize(string name, NameValueCollection config)
{
if (String.IsNullOrEmpty(name))
name = Name;
base.Initialize(name, config);
}
public SettingsPropertyValue GetPreviousVersion(SettingsContext context, SettingsProperty property)
{
throw new NotImplementedException();
}
public void Reset(SettingsContext context)
{
if (!File.Exists(ApplicationSettingsFile))
return;
File.Delete(ApplicationSettingsFile);
}
public void Upgrade(SettingsContext context, SettingsPropertyCollection properties) { }
private static XDocument CreateNewDocument()
{
return new XDocument(new XElement(RootNode));
}
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
{
var xmlDoc = GetOrCreateXmlDocument();
var propertyValueCollection = new SettingsPropertyValueCollection();
foreach (SettingsProperty settingsProperty in collection)
{
propertyValueCollection.Add(new SettingsPropertyValue(settingsProperty)
{
IsDirty = false,
SerializedValue = GetValue(xmlDoc, settingsProperty)
});
}
return propertyValueCollection;
}
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
{
var xmlDoc = GetOrCreateXmlDocument();
foreach (SettingsPropertyValue settingsPropertyValue in collection)
SetValue(xmlDoc, settingsPropertyValue);
try
{
using (var writer = CreateWellFormattedXmlWriter(ApplicationSettingsFile))
{
xmlDoc.Save(writer);
}
}
catch { }
}
private static XmlWriter CreateWellFormattedXmlWriter(string outputFileName)
{
var settings = new XmlWriterSettings
{
NewLineHandling = NewLineHandling.Entitize,
Indent = true
};
return XmlWriter.Create(outputFileName, settings);
}
private static object GetValue(XContainer xmlDoc, SettingsProperty prop)
{
if (xmlDoc == null)
return prop.DefaultValue;
var rootNode = xmlDoc.Element(RootNode);
if (rootNode == null)
return prop.DefaultValue;
var settingNode = rootNode.Element(prop.Name);
if (settingNode == null)
return prop.DefaultValue;
return DeserializeSettingValueFromXmlNode(settingNode, prop);
}
private static void SetValue(XContainer xmlDoc, SettingsPropertyValue value)
{
if (xmlDoc == null)
throw new ArgumentNullException(nameof(xmlDoc));
var rootNode = xmlDoc.Element(RootNode);
if (rootNode == null)
throw new ArgumentNullException(nameof(rootNode));
var settingNode = rootNode.Element(value.Name);
var settingValueNode = SerializeSettingValueToXmlNode(value);
if (settingNode == null)
rootNode.Add(new XElement(value.Name, settingValueNode));
else
settingNode.ReplaceAll(settingValueNode);
}
private static XNode SerializeSettingValueToXmlNode(SettingsPropertyValue value)
{
if (value.SerializedValue == null)
return new XText("");
switch (value.Property.SerializeAs)
{
case SettingsSerializeAs.String:
return new XText((string) value.SerializedValue);
case SettingsSerializeAs.Xml:
case SettingsSerializeAs.Binary:
case SettingsSerializeAs.ProviderSpecific:
throw new NotImplementedException($"I don't know how to handle serialization of settings that should be serialized as {value.Property.SerializeAs}");
default:
throw new ArgumentOutOfRangeException();
}
}
private static object DeserializeSettingValueFromXmlNode(XNode node, SettingsProperty prop)
{
using (var reader = node.CreateReader())
{
reader.MoveToContent();
switch (prop.SerializeAs)
{
case SettingsSerializeAs.Xml:
case SettingsSerializeAs.Binary:
case SettingsSerializeAs.ProviderSpecific:
throw new NotImplementedException($"I don't know how to handle deserialization of settings that should be deserialized as {prop.SerializeAs}");
case SettingsSerializeAs.String:
return reader.ReadElementContentAsString();
default:
throw new ArgumentOutOfRangeException();
}
}
}
}
}