context: #region License
  
  // Copyright (c) 2013, ClearCanvas Inc.
  // All rights reserved.
  // http://www.clearcanvas.ca
  //
  // This file is part of the ClearCanvas RIS/PACS open source project.
  //
  // The ClearCanvas RIS/PACS open source project 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 3 of the
  // License, or (at your option) any later version.
  //
  // The ClearCanvas RIS/PACS open source project 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
  // the ClearCanvas RIS/PACS open source project.  If not, see
  // <http://www.gnu.org/licenses/>.
  
  #endregion
  
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using ClearCanvas.Common;
  using ClearCanvas.Common.Utilities;
  using ClearCanvas.Common.Configuration;
  using ClearCanvas.Desktop.Tables;
  using ClearCanvas.Desktop.Actions;
  
  namespace ClearCanvas.Desktop.Configuration
  {
  
  	/// <summary>
  	/// Extension point for views onto <see cref="SettingsManagementComponent"/>.
  	/// </summary>
  	[ExtensionPoint]
  	public sealed class SettingsManagementComponentViewExtensionPoint : ExtensionPoint<IApplicationComponentView>
  	{
  	}
  
  	/// <summary>
  	/// The <see cref="SettingsManagementComponent"/> allows editing of
  	/// the application and default user profile settings through a generic UI.
  	/// </summary>
  	[AssociateView(typeof(SettingsManagementComponentViewExtensionPoint))]
  	public partial class SettingsManagementComponent : ApplicationComponent
  	{
  		#region Group class
  
  		/// <summary>
  		/// Base class for entries in the settings group table.
  		/// </summary>
  		internal abstract class Group
  		{
  			private List<Property> _properties;
  
  			protected Group(SettingsGroupDescriptor descriptor)
  			{
  				Descriptor = descriptor;
  			}
  
  			public SettingsGroupDescriptor Descriptor { get; private set; }
  
  			public string Name
  			{
  				get { return Descriptor.Name; }
  			}
  
  			public Version Version
  			{
  				get { return Descriptor.Version; }
  			}
  
  			public string Description
  			{
  				get { return Descriptor.Description; }
  			}
  
  			public IList<Property> Properties
  			{
  				get { return _properties ?? (_properties = LoadProperties().ToList()); }
  			}
  
  			public void Save()
  			{
  				if (_properties == null)
  					return;
  
  				SaveProperties(_properties);
  
  				// mark all properties as clean again
  				foreach (var p in _properties)
  					p.MarkClean();
  			}
  
  			protected abstract IEnumerable<Property> LoadProperties();
  
  			protected abstract void SaveProperties(IList<Property> properties);
  		}
  
  		#endregion
  
  		#region SettingsStoreGroup class
  
  		/// <summary>
  		/// Represents a settings group that was retrieved from a settings store and 
  		/// may not exist in the locally installed plugins.
  		/// </summary>
  		internal class SettingsStoreGroup : Group
  		{
  			private readonly ISettingsStore _store;
  
  			internal SettingsStoreGroup(SettingsGroupDescriptor descriptor, ISettingsStore store)
  				: base(descriptor)
  			{
  				_store = store;
  			}
  
  			protected override IEnumerable<Property> LoadProperties()
  			{
  				var values = _store.GetSettingsValues(this.Descriptor, null, null);
  
  				return from pi in _store.ListSettingsProperties(this.Descriptor)
  					   select new Property(pi, values.ContainsKey(pi.Name) ? values[pi.Name] : pi.DefaultValue);
  			}
  
  			protected override void SaveProperties(IList<Property> properties)
  			{
  				// fill a dictionary with all dirty values
  				var values = properties.Where(p => p.Dirty).ToDictionary(p => p.Name, p => p.Value);
  
  				// save to the default profile
  				_store.PutSettingsValues(this.Descriptor, null, null, values);
  			}
  		}
  
  		#endregion
  
  		#region Property class
  
  		/// <summary>
  		/// Defines a settings property for presentation in properties table.
  		/// </summary>
  		internal class Property
  		{
  			private readonly SettingsPropertyDescriptor _descriptor;
  			private string _value;
  			private string _startingValue;
  
  			/// <summary>
  			/// Constructor.
  			/// </summary>
  			/// <param name="descriptor">The descriptor for the property.</param>
  			/// <param name="value">The current value of the property.</param>
  			public Property(SettingsPropertyDescriptor descriptor, string value)
  			{
  				_descriptor = descriptor;
  				_startingValue = _value = value;
  			}
  
  			/// <summary>
  			/// Gets the name of the settings property.
  			/// </summary>
  			public string Name
  			{
  				get { return _descriptor.Name; }
  			}
  
  			/// <summary>
  			/// Gets the type name of the settings property.
  			/// </summary>
  			public string TypeName
  			{
  				get { return _descriptor.TypeName; }
  			}
  
  			/// <summary>
  			/// Gets a description of the settings property.
  			/// </summary>
  			public string Description
  			{
  				get { return _descriptor.Description; }
  			}
  
  			/// <summary>
  			/// Gets an enum describing the scope of the settings property.
  			/// </summary>
  			public SettingScope Scope
  			{
  				get { return _descriptor.Scope; }
  			}
  
  			/// <summary>
  			/// Gets the default value of the settings property.
  			/// </summary>
  			public string DefaultValue
  			{
  
gt: 				get { return _descriptor.DefaultValue; }