Skip to content

Commit d06e05d

Browse files
authored
Merge pull request #1030 from rwf-rr/refactor-user-settings-location
Refactor settings, in prep for settings exporter
2 parents f80cfb5 + d3ae4a2 commit d06e05d

File tree

11 files changed

+162
-20
lines changed

11 files changed

+162
-20
lines changed

Source/Orts.Common/SettingsBase.cs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
1717

1818
using System;
19+
using System.IO;
1920
using System.Collections.Generic;
2021
using System.Diagnostics;
2122
using System.Linq;
@@ -27,6 +28,52 @@ namespace ORTS.Common
2728
/// </summary>
2829
public abstract class SettingsBase
2930
{
31+
public const string DefaultRegistryKey = "SOFTWARE\\OpenRails\\ORTS";
32+
public const string DefaultSettingsFileName = "OpenRails.ini";
33+
34+
public static string RegistryKey { get; private set; } // ie @"SOFTWARE\OpenRails\ORTS"
35+
public static string SettingsFilePath { get; private set; } // ie @"C:\Program Files\Open Rails\OpenRails.ini"
36+
37+
static SettingsBase()
38+
{
39+
// Only one of these is allowed; if the INI file exists, we use that, otherwise we use the registry.
40+
RegistryKey = DefaultRegistryKey;
41+
SettingsFilePath = Path.Combine(ApplicationInfo.ProcessDirectory, DefaultSettingsFileName);
42+
if (File.Exists(SettingsFilePath))
43+
RegistryKey = null;
44+
else
45+
SettingsFilePath = null;
46+
}
47+
48+
/// <summary>
49+
/// Override the location for the settings. This only changes the static names.
50+
/// Only one must be specified (see SettingsBase static constructor).
51+
/// If settings objects already exist, they need to be changed using ChangeSettingsStore().
52+
/// </summary>
53+
/// <param name="filePath">The new ini file path, relative to the OpenRails base directory, or NULL.</param>
54+
/// <param name="registryKey">The new registry key, relative to the HKEY_CURRENT_USER, or NULL.</param>
55+
public static void OverrideSettingsLocations(string filePath, string registryKey)
56+
{
57+
if (!String.IsNullOrEmpty(filePath) && !String.IsNullOrEmpty(registryKey))
58+
{
59+
throw new ArgumentException("Only one of filePath and registryKey may be provided.");
60+
}
61+
else if (!String.IsNullOrEmpty(filePath))
62+
{
63+
SettingsFilePath = Path.Combine(ApplicationInfo.ProcessDirectory, filePath);
64+
RegistryKey = null;
65+
}
66+
else if (!String.IsNullOrEmpty(registryKey))
67+
{
68+
RegistryKey = registryKey;
69+
SettingsFilePath = null;
70+
}
71+
else
72+
{
73+
throw new ArgumentException("One of filePath and registryKey must be provided.");
74+
}
75+
}
76+
3077
/// <summary>
3178
/// Enumeration of the various sources for settings
3279
/// </summary>
@@ -42,6 +89,7 @@ protected enum Source
4289

4390
/// <summary>The store of the settings</summary>
4491
protected SettingsStore SettingStore { get; private set; }
92+
4593
/// <summary>Translates name of a setting to its source</summary>
4694
protected readonly Dictionary<string, Source> Sources = new Dictionary<string, Source>();
4795

@@ -100,6 +148,33 @@ protected SettingsBase(SettingsStore settings)
100148
/// </summary>
101149
public abstract void Reset();
102150

151+
public String GetSettingsStoreName()
152+
{
153+
string name = "none";
154+
if (SettingStore != null) { name = SettingStore.GetStoreName(); }
155+
return name;
156+
}
157+
158+
/// <summary>
159+
/// Change the settings store. Creates a new SettingsStore based on the provided parameters.
160+
/// Only one of filePath and registry key should be specified. If both are provided, filePath
161+
/// prevails. Does not change the static locations (as that would affect other objects).
162+
/// See also SettingsStore.GetSettingStore() and OverrideSettingsLocations().
163+
/// </summary>
164+
/// <param name="filePath">The path to the INI file, or NULL if using the registry.</param>
165+
/// <param name="registryKey">The registry key (name), or NULL if using an INI file. </param>
166+
/// <param name="section">Optional, the name of the section / subkey.</param>
167+
public virtual void ChangeSettingsStore(string filePath, string registryKey, string section)
168+
{
169+
if (SettingStore != null)
170+
{
171+
SettingStore.Discard();
172+
SettingStore = null;
173+
}
174+
var fullPath = String.IsNullOrEmpty(filePath) ? null : Path.Combine(ApplicationInfo.ProcessDirectory, filePath);
175+
SettingStore = SettingsStore.GetSettingStore(fullPath, registryKey, section);
176+
}
177+
103178
/// <summary>
104179
/// Load settings from the options
105180
/// </summary>

Source/Orts.Common/SettingsStore.cs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,21 @@ protected static void AssertGetUserValueType(Type expectedType)
138138
/// <param name="name">name of the setting</param>
139139
public abstract void DeleteUserValue(string name);
140140

141+
/// <summary>
142+
/// Discard the settings store.
143+
/// Performs actions (if any) to close the settings store so that a new one can be used.
144+
/// </summary>
145+
public virtual void Discard()
146+
{
147+
// default action is to do nothing. Concrete classes may override.
148+
}
149+
150+
/// <summary>
151+
/// Get the name of the settings store.
152+
/// </summary>
153+
public abstract String GetStoreName();
154+
155+
141156
/// <summary>
142157
/// Factory method to create a setting store (sub-class of SettingsStore)
143158
/// </summary>
@@ -308,6 +323,29 @@ public override void DeleteUserValue(string name)
308323
{
309324
Key.DeleteValue(name, false);
310325
}
326+
327+
/// <summary>
328+
/// Discard the settings store.
329+
/// Close the registry key.
330+
/// </summary>
331+
public override void Discard()
332+
{
333+
if (Key != null)
334+
{
335+
Key.Close();
336+
// cannot set to null, as Key (and string version) are readonly
337+
}
338+
}
339+
340+
/// <summary>
341+
/// Get the name of the settings store, in this case the registry key.
342+
/// </summary>
343+
public override String GetStoreName()
344+
{
345+
string name = "None (registry)";
346+
if (Key != null) { name = Key.Name; }
347+
return name;
348+
}
311349
}
312350

313351
/// <summary>
@@ -530,7 +568,17 @@ public override void DeleteUserValue(string name)
530568
{
531569
NativeMethods.WritePrivateProfileString(Section, name, null, FilePath);
532570
}
533-
}
571+
572+
/// <summary>
573+
/// Get the name of the settings store, in this case the INI file path.
574+
/// </summary>
575+
public override String GetStoreName()
576+
{
577+
string name = "None (file)";
578+
if (!String.IsNullOrEmpty(FilePath)) { name = FilePath; }
579+
return name;
580+
}
581+
}
534582

535583
// TODO: This class and its methods should be internal visibility.
536584
/// <summary>

Source/Orts.Settings/ContentSettings.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ namespace ORTS.Settings
2424
{
2525
public class ContentSettings : SettingsBase
2626
{
27+
public static readonly string SectionName = "ContentRoutes";
28+
2729
#region User Settings
2830
public ContentRouteSettings ContentRouteSettings;
2931
#endregion
3032

3133
public ContentSettings(IEnumerable<string> options)
32-
: base(SettingsStore.GetSettingStore(UserSettings.SettingsFilePath, UserSettings.RegistryKey, "ContentRoutes"))
34+
: base(SettingsStore.GetSettingStore(SettingsBase.SettingsFilePath, SettingsBase.RegistryKey, SectionName))
3335
{
3436
ContentRouteSettings = new ContentRouteSettings();
3537
Load(options);

Source/Orts.Settings/FolderSettings.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ namespace ORTS.Settings
2626
{
2727
public class FolderSettings : SettingsBase
2828
{
29+
public static readonly string SectionName = "Folders";
30+
2931
public readonly Dictionary<string, string> Folders;
3032

3133
public FolderSettings(IEnumerable<string> options)
32-
: base(SettingsStore.GetSettingStore(UserSettings.SettingsFilePath, UserSettings.RegistryKey, "Folders"))
34+
: base(SettingsStore.GetSettingStore(SettingsBase.SettingsFilePath, SettingsBase.RegistryKey, SectionName))
3335
{
3436
Folders = new Dictionary<string, string>();
3537
Load(options);

Source/Orts.Settings/InputSettings.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ public enum KeyModifiers
6262
/// </remarks>
6363
public class InputSettings : SettingsBase
6464
{
65+
public static readonly string SectionName = "Keys";
66+
6567
static GettextResourceManager commonCatalog = new GettextResourceManager("ORTS.Common");
6668
static GettextResourceManager settingsCatalog = new GettextResourceManager("ORTS.Settings");
6769

@@ -79,7 +81,7 @@ static InputSettings()
7981
/// </summary>
8082
/// <param name="options">The list of one-time options to override persisted settings, if any.</param>
8183
public InputSettings(IEnumerable<string> options)
82-
: base(SettingsStore.GetSettingStore(UserSettings.SettingsFilePath, UserSettings.RegistryKey, "Keys"))
84+
: base(SettingsStore.GetSettingStore(SettingsBase.SettingsFilePath, SettingsBase.RegistryKey, SectionName))
8385
{
8486
InitializeCommands(Commands);
8587
Load(options);

Source/Orts.Settings/RailDriverSettings.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ public enum RailDriverCalibrationSetting
4444

4545
public class RailDriverSettings : SettingsBase
4646
{
47+
public static readonly string SectionName = "RailDriver";
48+
4749
static readonly GettextResourceManager catalog = new GettextResourceManager("ORTS.Settings");
4850
private static readonly byte[] DefaultCalibrationSettings;
4951
private static readonly Dictionary<UserCommand, byte> DefaultUserCommands;
@@ -119,7 +121,7 @@ static RailDriverSettings()
119121
/// </summary>
120122
/// <param name="options">The list of one-time options to override persisted settings, if any.</param>
121123
public RailDriverSettings(IEnumerable<string> options)
122-
: base(SettingsStore.GetSettingStore(UserSettings.SettingsFilePath, UserSettings.RegistryKey, "RailDriver"))
124+
: base(SettingsStore.GetSettingStore(SettingsBase.SettingsFilePath, SettingsBase.RegistryKey, SectionName))
123125
{
124126
CalibrationSettings = new byte[DefaultCalibrationSettings.Length];
125127

Source/Orts.Settings/TelemetrySettings.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@ namespace ORTS.Settings
2222
{
2323
public class TelemetrySettings : PropertySettingsBase
2424
{
25+
public static readonly string SectionName = "Telemetry";
26+
2527
[Default(0)]
2628
public int RandomNumber1000 { get; set; }
2729
[Default("https://telemetry.openrails.org")]
2830
public string ServerURL { get; set; }
2931
public DateTime StateSystem { get; set; }
3032

3133
public TelemetrySettings()
32-
: base(SettingsStore.GetSettingStore(UserSettings.SettingsFilePath, UserSettings.RegistryKey, "Telemetry"))
34+
: base(SettingsStore.GetSettingStore(UserSettings.SettingsFilePath, UserSettings.RegistryKey, SectionName))
3335
{
3436
Load(new string[0]);
3537
}

Source/Orts.Settings/UpdateSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace ORTS.Settings
2626
{
2727
public class UpdateSettings : SettingsBase
2828
{
29-
public static readonly string SettingsFilePath = Path.Combine(ApplicationInfo.ProcessDirectory, "Updater.ini");
29+
public static new readonly string SettingsFilePath = Path.Combine(ApplicationInfo.ProcessDirectory, "Updater.ini");
3030

3131
#region User Settings
3232

Source/Orts.Settings/UpdateState.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ namespace ORTS.Settings
2626
{
2727
public class UpdateState : SettingsBase
2828
{
29+
public static readonly string SectionName = "UpdateState";
30+
2931
#region User Settings
3032

3133
// Please put all update settings in here as auto-properties. Public properties
@@ -41,7 +43,7 @@ public class UpdateState : SettingsBase
4143
#endregion
4244

4345
public UpdateState()
44-
: base(SettingsStore.GetSettingStore(UserSettings.SettingsFilePath, UserSettings.RegistryKey, "UpdateState"))
46+
: base(SettingsStore.GetSettingStore(SettingsBase.SettingsFilePath, SettingsBase.RegistryKey, SectionName))
4547
{
4648
Load(new string[0]);
4749
}

Source/Orts.Settings/UserSettings.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,12 @@ namespace ORTS.Settings
2727
{
2828
public class UserSettings : PropertySettingsBase
2929
{
30-
public static readonly string RegistryKey; // ie @"SOFTWARE\OpenRails\ORTS"
31-
public static readonly string SettingsFilePath; // ie @"C:\Program Files\Open Rails\OpenRails.ini"
3230
public static readonly string UserDataFolder; // ie @"C:\Users\Wayne\AppData\Roaming\Open Rails"
3331
public static readonly string DeletedSaveFolder; // ie @"C:\Users\Wayne\AppData\Roaming\Open Rails\Deleted Saves"
3432
public static readonly string SavePackFolder; // ie @"C:\Users\Wayne\AppData\Roaming\Open Rails\Save Packs"
3533

3634
static UserSettings()
3735
{
38-
// Only one of these is allowed; if the INI file exists, we use that, otherwise we use the registry.
39-
RegistryKey = "SOFTWARE\\OpenRails\\ORTS";
40-
SettingsFilePath = Path.Combine(ApplicationInfo.ProcessDirectory, "OpenRails.ini");
41-
if (File.Exists(SettingsFilePath))
42-
RegistryKey = null;
43-
else
44-
SettingsFilePath = null;
45-
4636
UserDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ApplicationInfo.ProductName);
4737
// TODO: If using INI file, move these to application directory as well.
4838
if (!Directory.Exists(UserDataFolder)) Directory.CreateDirectory(UserDataFolder);
@@ -476,7 +466,7 @@ public string DirectXFeatureLevel
476466
public TelemetrySettings Telemetry { get; private set; }
477467

478468
public UserSettings(IEnumerable<string> options)
479-
: base(SettingsStore.GetSettingStore(SettingsFilePath, RegistryKey, null))
469+
: base(SettingsStore.GetSettingStore(SettingsBase.SettingsFilePath, SettingsBase.RegistryKey, null))
480470
{
481471
CustomDefaultValues["LoggingPath"] = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
482472
CustomDefaultValues["ScreenshotPath"] = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), ApplicationInfo.ProductName);
@@ -520,5 +510,22 @@ public override void Save()
520510
Content.Save();
521511
Telemetry.Save();
522512
}
513+
514+
/// <summary>
515+
/// Change the settings store for the user settings and its sub-settings.
516+
/// Creates a new SettingsStore based on the provided parameters.
517+
/// </summary>
518+
/// <param name="filePath">The path to the INI file, or NULL if using the registry.</param>
519+
/// <param name="registryKey">The registry key (name), or NULL if using an INI file. </param>
520+
/// <param name="section">Optional, the name of the section / subkey.</param>
521+
public override void ChangeSettingsStore(string filePath, string registryKey, string section)
522+
{
523+
base.ChangeSettingsStore(filePath, registryKey, section); // section is defined in SettingsStoreLocalIni
524+
Folders.ChangeSettingsStore(filePath, registryKey, FolderSettings.SectionName);
525+
Input.ChangeSettingsStore(filePath, registryKey, InputSettings.SectionName);
526+
RailDriver.ChangeSettingsStore(filePath, registryKey, RailDriverSettings.SectionName);
527+
Content.ChangeSettingsStore(filePath, registryKey, ContentSettings.SectionName);
528+
Telemetry.ChangeSettingsStore(filePath, registryKey, TelemetrySettings.SectionName);
529+
}
523530
}
524531
}

0 commit comments

Comments
 (0)