using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Globalization; using System.Linq; using System.Reflection; using System.Text; using DTS.Storage; // ReSharper disable RedundantEmptyDefaultSwitchBranch // ReSharper disable once CheckNamespace namespace DTS.Slice.Users.UserSettings { /// /// user specific properties, stored in db /// /// these are all the user specific settings we are storing in the db currently as generic settings /// we have a few user specific settings like last used hardware that are stored in other places, that maybe /// should be stored here as well /// /// it's possible to retrieve all the settings at once (more efficient, only one db query), or retrieve settings individually /// one by one using the static accessors /// each setting has a default specified both in code and in the db. /// when retrieving a setting we fall back to the default if a user specific value is not found /// if the default setting in the db is not found, we can further fall back to the default specified in code /// /// in the db we have a table that lists all the settings with their fall back default value /// we have a separate table that stores the user specific values for any of those settings, which may or may not match the fall /// back default value /// /// the data should always be stored in invariant form in the db /// DisplayName, Description attributes translate so the properties can be displayed in a property grid /// public class UserSettings { #region properties [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultUploadEnabled)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultUploadEnabled)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultUploadEnabled)] [DefaultValue(false)] public bool UploadDefault { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultTestSampleRate)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultTestSampleRate)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultTestSampleRate)] [DefaultValue(10000D)] public double DefaultSampleRate { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultPostTriggerSeconds)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultPostTriggerSeconds)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultPostTriggerSeconds)] [DefaultValue(1D)] public double DefaultPostTriggerSeconds { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultPreTriggerSeconds)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultPreTriggerSeconds)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultPreTriggerSeconds)] [DefaultValue(1D)] public double DefaultPreTriggerSeconds { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultTriggerCheckStep)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultTriggerCheckStep)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultTriggerCheckStep)] [DefaultValue(true)] public bool DefaultTriggerCheckStep { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultRealtimeGraphCount)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRealtimeGraphCount)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRealtimeGraphCount)] [DefaultValue(6)] public int DefaultRealtimeGraphCount { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultROIStart)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultROIStart)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultROIStart)] [DefaultValue(-1D)] public double DefaultROIStart { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultROIEnd)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultROIEnd)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultROIEnd)] [DefaultValue(1D)] public double DefaultROIEnd { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultDownloadROI)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadROI)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadROI)] [DefaultValue(true)] public bool DefaultDownloadROI { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultViewROI)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultViewROI)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultViewROI)] [DefaultValue(true)] public bool DefaultViewROI { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultDownloadAll)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadAll)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadAll)] [DefaultValue(true)] public bool DefaultDownloadAll { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultViewAll)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultViewAll)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultViewAll)] [DefaultValue(false)] public bool DefaultViewAll { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics)] [DefaultValue(true)] public bool DefaultRequireAllUnitsPassDiagnostics { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors)] [DefaultValue(true)] public bool DefaultRequireUserConfirmationOnErrors { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultAllowMissingSensors)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultAllowMissingSensors)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultAllowMissingSensors)] [DefaultValue(false)] public bool DefaultAllowMissingSensors { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics)] [DefaultValue(false)] public bool DefaultRunPostTestDiagnostics { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultArmCheckListStep)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultArmCheckListStep)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultArmCheckListStep)] [DefaultValue(false)] public bool DefaultArmCheckListStep { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck)] [DefaultValue(true)] public bool DefaultCheckListInputVoltageCheck { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck)] [DefaultValue(true)] public bool DefaultCheckListBatteryVoltageCheck { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck)] [DefaultValue(true)] public bool DefaultCheckListSquibResistanceCheck { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck)] [DefaultValue(true)] public bool DefaultCheckListSensorIdCheck { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck)] [DefaultValue(true)] public bool DefaultCheckListTriggerStartCheck { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck)] [DefaultValue(true)] public bool DefaultCheckListTiltSensorCheck { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel)] [DefaultValue(true)] public bool DefaultAllowSensorIdToBlankChannel { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultCheckListMustPass)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListMustPass)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListMustPass)] [DefaultValue(false)] public bool DefaultChecklistMustPass { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [PropertyId(PropertyEnums.PropertyIds.DefaultViewRealtime)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultViewRealtime)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultViewRealtime)] [DefaultValue(true)] public bool DefaultViewRealtime { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultExport)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultExport)] [PropertyId(PropertyEnums.PropertyIds.DefaultExport)] [DefaultValue(false)] public bool DefaultExport { get; set; } [DefaultValue(0)] [CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultExportFormat)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultExportFormat)] [PropertyId(PropertyEnums.PropertyIds.DefaultExportFormat)] public int DefaultExportFormat { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.RealtimeSettings)] [PropertyId(PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds)] [DisplayAttributeEx(PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds)] [DefaultValue(2)] public double RealtimeChartWidthInSeconds { get; set; } [DefaultValue(true)] [CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics)] [PropertyId(PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics)] public bool DefaultTreeModeDiagnostics { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)] [PropertyId(PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM)] [DisplayAttributeEx(PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM)] [DefaultValue(true)] public bool ArmChecklistRequiredIfTOM { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)] [PropertyId(PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning)] [DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning)] [DefaultValue(true)] public bool DefaultSuppressMissingSensorsWarning { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)] [PropertyId(PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep)] [DisplayAttributeEx(PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep)] [DefaultValue(false)] public bool ArmTriggerDiagnosticsRunOnNextStep { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)] [PropertyId(PropertyEnums.PropertyIds.UsersCurrentTestSetup)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.UsersCurrentTestSetup)] [DisplayAttributeEx(PropertyEnums.PropertyIds.UsersCurrentTestSetup)] [DefaultValue("")] [ReadOnly(true)] public string UsersCurrentTestSetup { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)] [PropertyId(PropertyEnums.PropertyIds.LastRunTestSetup)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.LastRunTestSetup)] [DisplayAttributeEx(PropertyEnums.PropertyIds.LastRunTestSetup)] [DefaultValue("")] [ReadOnly(true)] public string LastRunTestSetup { get; set; } [CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)] [PropertyId(PropertyEnums.PropertyIds.LastUsedSampleRate)] [DescriptionAttributeEx(PropertyEnums.PropertyIds.LastUsedSampleRate)] [DisplayAttributeEx(PropertyEnums.PropertyIds.LastUsedSampleRate)] [DefaultValue(20000D)] [ReadOnly(true)] public double LastUsedSampleRate { get; set; } /* * Subcategory example */ //[Category("Category1")] //public SubCategory1 Subcategory1 { get; set; } //[Category("Category1")] //public SubCategory2 Subcategory2 { get; set; } #endregion properties #region Static Methods /// /// this function is designed to create any missing property settings if needed /// this might happen if the database table was just created for instance /// it will create defaults for all the settings in the db, and also settings for all users /// currently it's used by DataPRO.App /// public static void CreateAnyMissingUserSettingPropertyDefaults() { //get a list of all known properties var userSetting = new UserSettings(); var properties = userSetting.GetType().GetProperties(); var needToBeAdded = new Dictionary(); foreach (var property in properties) { var id = PropertyIdAttribute.GetPropertyId(property); needToBeAdded[id] = property; } //find if the property already exists in the db, if so, no need to add... using (var sql = DbOperations.GetCommand()) { sql.CommandText = "SELECT [PropertyId] from [DefaultProperties]"; using (var ds = DbOperations.Connection.QueryDataSet(sql)) { foreach (DataRow row in ds.Tables[0].Rows) { var id = Convert.ToInt32(row["PropertyId"]); if (needToBeAdded.ContainsKey(id)) { needToBeAdded.Remove(id); } } } } //if we have nothing to add, we are all done if (needToBeAdded.Values.Count <= 0) return; //otherwise add the defaults using (var sql = DbOperations.GetCommand()) { var sb = new StringBuilder(); sb.Append(DbOperations.BEGIN_STATEMENT); var needToBeAddedEnumerator = needToBeAdded.GetEnumerator(); int iIndex = 0; while (needToBeAddedEnumerator.MoveNext()) { var currentProperty = needToBeAddedEnumerator.Current.Value; sb.AppendFormat("INSERT INTO [DefaultProperties] ([PropertyId],[PropertyName],[DefaultValue]) VALUES (@1_{0}, @2_{0}, @3_{0});", iIndex); DbOperations.CreateParam(sql, string.Format("@1_{0}", iIndex), SqlDbType.Int, PropertyIdAttribute.GetPropertyId(currentProperty)); DbOperations.CreateParam(sql, string.Format("@2_{0}", iIndex), SqlDbType.NVarChar, PropertyIdAttribute.GetPropertyIdEnum(currentProperty).ToString()); DbOperations.CreateParam(sql, string.Format("@3_{0}", iIndex), SqlDbType.NVarChar, GetDefaultValueAsString(currentProperty)); iIndex++; } sb.Append(DbOperations.COMMIT_STATEMENT); sql.CommandText = sb.ToString(); DbOperations.Connection.ExecuteCommand(sql); } //finally add settings for any users we have currently CreateMissingUserSettingProperties(needToBeAdded.Values.ToArray()); } /// /// creates missing user settings (for all users) /// /// private static void CreateMissingUserSettingProperties(PropertyInfo[] needToBeAdded) { var userIds = new List(); using (var sql = DbOperations.GetCommand()) { sql.CommandText = "SELECT ID FROM [DataPROUsers]"; using (var ds = DbOperations.Connection.QueryDataSet(sql)) { foreach (DataRow row in ds.Tables[0].Rows) { var id = Convert.ToInt32(row["ID"]); if (!userIds.Contains(id)) { userIds.Add(id); } } } } foreach (var id in userIds) { CreateMissingUserSettingProperties(id, needToBeAdded); } } /// /// this funtion creates a list of settings for a specific user /// this may happen with a new database, it's called by the /// CreateAnyMissingUserSettingPropertyDefaults function above /// /// /// internal static void CreateMissingUserSettingProperties(int id, PropertyInfo[] needToBeAdded) { using (var sql = DbOperations.GetCommand()) { var index = 0; var sb = new StringBuilder(); sb.Append(DbOperations.BEGIN_STATEMENT); foreach (var property in needToBeAdded) { sb.AppendFormat( "INSERT INTO [UserProperties] ([UserId],[PropertyId], [PropertyValue]) VALUES (@1_{0},@2_{0},@3_{0});", index); DbOperations.CreateParam(sql, string.Format("@1_{0}", index), SqlDbType.Int, id); DbOperations.CreateParam(sql, string.Format("@2_{0}", index), SqlDbType.Int, PropertyIdAttribute.GetPropertyId(property)); DbOperations.CreateParam(sql, string.Format("@3_{0}", index), SqlDbType.NVarChar, GetDefaultValueAsString(property)); index++; } sb.Append(DbOperations.COMMIT_STATEMENT); sql.CommandText = sb.ToString(); DbOperations.Connection.ExecuteCommand(sql); } } /// /// get an invariant version of the value for db storage /// this is used when we create or insert a new default into the db /// /// /// private static string GetDefaultValueAsString(PropertyInfo property) { if (property == null) return ""; var attr = (DefaultValueAttribute)property.GetCustomAttribute(typeof(DefaultValueAttribute)); if (attr.Value is double) { return ((double) attr.Value).ToString(CultureInfo.InvariantCulture); } if (attr.Value is float) { return ((float) attr.Value).ToString(CultureInfo.InvariantCulture); } return attr.Value.ToString(); } /// /// gets a collection of all settings for a given user /// /// /// public static UserSettings GetUserSettings(int userId) { var settings = new UserSettings(); var properties = settings.GetType().GetProperties(); //first get all properties as filled out by code foreach (var property in properties) { var d = property.GetCustomAttribute(); if (d != null) { property.SetValue(settings, d.Value); } } //next make sure we get all the defaults from the db using (var sql = DbOperations.GetCommand()) { sql.CommandText = "SELECT [PropertyId], [DefaultValue] from [DefaultProperties]"; using (var ds = DbOperations.Connection.QueryDataSet(sql)) { foreach (DataRow row in ds.Tables[0].Rows) { var id = Convert.ToInt32(row["PropertyId"]); var dv = Convert.ToString(row["DefaultValue"]); settings.SetValue(id, dv); } } } //finally get the user specific values using (var sql = DbOperations.GetCommand()) { sql.CommandText = "SELECT [PropertyId], [PropertyValue] FROM [UserProperties] WHERE [UserId]=@1"; DbOperations.CreateParam(sql, "@1", SqlDbType.Int, userId); using (var ds = DbOperations.Connection.QueryDataSet(sql)) { foreach (DataRow row in ds.Tables[0].Rows) { var id = Convert.ToInt32(row["PropertyId"]); var value = Convert.ToString(row["PropertyValue"]); settings.SetValue(id, value); } } } return settings; } /// /// sets a specific user setting in the db /// function should handle the invariant nature of values /// /// /// /// public static void SetUserSetting(int userId, PropertyEnums.PropertyIds id, object value) { var sValue = value.ToString(); if (value is double) { sValue = ((double)value).ToString(CultureInfo.InvariantCulture); } else if (value is float) { sValue = ((float)value).ToString(CultureInfo.InvariantCulture); } using (var sql = DbOperations.GetCommand()) { sql.CommandText = "UPDATE [UserProperties] SET [PropertyValue]=@1 WHERE [UserId]=@2 AND [PropertyId]=@3"; DbOperations.CreateParam(sql, "@1", SqlDbType.NVarChar, sValue); DbOperations.CreateParam(sql, "@2", SqlDbType.Int, userId); DbOperations.CreateParam(sql, "@3", SqlDbType.Int, (int)id); DbOperations.Connection.ExecuteCommand(sql); } } /// /// gets a specific user setting as a bool /// /// /// /// public static bool GetUserSettingValueBool(int userId, PropertyEnums.PropertyIds property) { return Convert.ToBoolean(GetUserSettingValue(userId, property)); } /// /// gets a specific user setting as a double /// /// /// /// public static double GetUserSettingValueDouble(int userId, PropertyEnums.PropertyIds property) { return Convert.ToDouble(GetUserSettingValue(userId, property), CultureInfo.InvariantCulture); } /// /// gets a specific user setting as an integer /// /// /// /// public static int GetUserSettingValueInt(int userId, PropertyEnums.PropertyIds property) { return Convert.ToInt32(GetUserSettingValue(userId, property), CultureInfo.InvariantCulture); } /// /// Gets a specific user setting as a string /// /// /// /// public static string GetUserSettingValueString(int userid, PropertyEnums.PropertyIds property) { return GetUserSettingValue(userid, property); } /// /// gets a user setting out of the db, this is an internal function used by all the public /// single setting accessors. /// setting is determined by user settings table, default values table /// /// /// /// private static string GetUserSettingValue(int userid, PropertyEnums.PropertyIds property) { //if the user has a specific value set for this property, just return it directly using (var sql = DbOperations.GetCommand()) { sql.CommandText = "SELECT [PropertyValue] FROM [UserProperties] WHERE [UserId]=@1 AND [PropertyId]=@2"; DbOperations.CreateParam(sql, "@1", SqlDbType.Int, userid); DbOperations.CreateParam(sql, "@2", SqlDbType.Int, (int)property); using (var ds = DbOperations.Connection.QueryDataSet(sql)) { if (ds.Tables[0].Rows.Count > 0) { return Convert.ToString(ds.Tables[0].Rows[0]["PropertyValue"]); } } } //if there exists a specific default value set for this property, return that using (var sql = DbOperations.GetCommand()) { sql.CommandText = "SELECT [DefaultValue] FROM [DefaultProperties] WHERE [PropertyId] =@1"; DbOperations.CreateParam(sql, "@1", SqlDbType.Int, (int)property); using (var ds = DbOperations.Connection.QueryDataSet(sql)) { if (ds.Tables[0].Rows.Count > 0) { return Convert.ToString(ds.Tables[0].Rows[0]["DefaultValue"]); } } } //we could return the default value in code here, but we don't expect to get here, so //we can treat this as an exception for now throw new NullReferenceException(property.ToString()); } #endregion #region methods /// /// sets a specific value given a property id /// this is used when deserializing values out of the db /// /// /// /// protected void SetValue(int id, string dv) { var property = (PropertyEnums.PropertyIds)id; switch (property) { case PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM: ArmChecklistRequiredIfTOM = Convert.ToBoolean(dv); break; case PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep: ArmTriggerDiagnosticsRunOnNextStep = Convert.ToBoolean(dv); break; case PropertyEnums.PropertyIds.DefaultAllowMissingSensors: DefaultAllowMissingSensors = Convert.ToBoolean(dv); break; case PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel: DefaultAllowSensorIdToBlankChannel = Convert.ToBoolean(dv); break; case PropertyEnums.PropertyIds.DefaultArmCheckListStep: DefaultArmCheckListStep = Convert.ToBoolean(dv); break; case PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck: DefaultCheckListBatteryVoltageCheck = Convert.ToBoolean(dv); break; case PropertyEnums.PropertyIds.DefaultUploadEnabled: UploadDefault = Convert.ToBoolean(dv); break; case PropertyEnums.PropertyIds.DefaultTestSampleRate: DefaultSampleRate = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultPostTriggerSeconds: DefaultPostTriggerSeconds = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultPreTriggerSeconds: DefaultPreTriggerSeconds = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultTriggerCheckStep: DefaultTriggerCheckStep = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultRealtimeGraphCount: DefaultRealtimeGraphCount = Convert.ToInt32(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultROIStart: DefaultROIStart = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultROIEnd: DefaultROIEnd = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultDownloadROI: DefaultDownloadROI = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultViewROI: DefaultViewROI = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultDownloadAll: DefaultDownloadAll = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultViewAll: DefaultViewAll = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics: DefaultRequireAllUnitsPassDiagnostics = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors: DefaultRequireUserConfirmationOnErrors = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics: DefaultRunPostTestDiagnostics = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck: DefaultCheckListInputVoltageCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck: DefaultCheckListSquibResistanceCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck: DefaultCheckListSensorIdCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck: DefaultCheckListTriggerStartCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck: DefaultCheckListTiltSensorCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultCheckListMustPass: DefaultChecklistMustPass = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultViewRealtime: DefaultViewRealtime = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultExport: DefaultExport = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultExportFormat: DefaultExportFormat = Convert.ToInt32(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds: RealtimeChartWidthInSeconds = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics: DefaultTreeModeDiagnostics = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning: DefaultSuppressMissingSensorsWarning = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break; case PropertyEnums.PropertyIds.UsersCurrentTestSetup: UsersCurrentTestSetup = dv; break; case PropertyEnums.PropertyIds.LastRunTestSetup: LastRunTestSetup = dv; break; case PropertyEnums.PropertyIds.LastUsedSampleRate: LastUsedSampleRate = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break; default: break;//ignore unknown property, just just ignore it } } /// /// resets all the settings for a user in the db, using the default settings in the db /// /// public void ResetUserSettings(int userId) { //you can do this with one command with SQL, ie like //http://stackoverflow.com/questions/224732/sql-update-from-one-table-to-another-based-on-a-id-match //but since we haven't ditched SQlite yet, lets include support for both by separating it into two statements var properties = new List>(); using (var sql = DbOperations.GetCommand()) { sql.CommandText = "SELECT [PropertyId],[DefaultValue] from [DefaultProperties]"; using (var ds = DbOperations.Connection.QueryDataSet(sql)) { properties.AddRange(from DataRow row in ds.Tables[0].Rows let id = Convert.ToInt32(row["PropertyId"]) let value = Convert.ToString(row["DefaultValue"]) select new Tuple(id, value)); } } using (var sql = DbOperations.GetCommand()) { var sb = new StringBuilder(); sb.Append(DbOperations.BEGIN_STATEMENT); for (var i = 0; i < properties.Count; i ++) { sb.AppendFormat("UPDATE [UserProperties] SET [PropertyValue]=@1_{0} WHERE [PropertyId]=@2_{0} AND [UserId]=@3_{0};",i); DbOperations.CreateParam(sql, string.Format("@1_{0}", i), SqlDbType.NVarChar, properties[i].Item2); DbOperations.CreateParam(sql, string.Format("@2_{0}", i), SqlDbType.Int, properties[i].Item1); DbOperations.CreateParam(sql, string.Format("@3_{0}",i), SqlDbType.Int, userId); } sb.Append(DbOperations.COMMIT_STATEMENT); sql.CommandText = sb.ToString(); DbOperations.Connection.ExecuteCommand(sql); } } #endregion } /// /// Subcategory example /// http://stackoverflow.com/questions/9379353/category-hierarchy-in-winforms-propertygrid /// [TypeConverter(typeof(ExpandableObjectConverter))] public class SubCategory1 { public String Property1 { get; set; } public String Property2 { get; set; } public override string ToString() { return String.Empty; } } [TypeConverter(typeof(ExpandableObjectConverter))] public class SubCategory2 { public String Property3 { get; set; } public override string ToString() { return String.Empty; } } }