--- source_files: - DataPRO/Users/UserSettings/OptimizationSettings.cs - DataPRO/Users/UserSettings/CategoryAttributeEx.cs - DataPRO/Users/UserSettings/DisplayAttributeEx.cs - DataPRO/Users/UserSettings/DescriptionAttributeEx.cs - DataPRO/Users/UserSettings/PropertyIdAttribute.cs - DataPRO/Users/UserSettings/SampleRateConverter.cs - DataPRO/Users/UserSettings/UserHistory.cs - DataPRO/Users/UserSettings/PropertyEnums.cs generated_at: "2026-04-16T04:03:26.586662+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "1eb9bffd7fe29c43" --- # Documentation: User Settings Module ## 1. Purpose This module provides infrastructure for managing user-specific settings in the DataPRO system, including persistence to a database, localization via string resources, and UI integration for property grids. It defines core data structures (`OptimizationSettings`, `UserHistory`), attribute classes for metadata annotation (`CategoryAttributeEx`, `DisplayAttributeEx`, `DescriptionAttributeEx`, `PropertyIdAttribute`), and supporting utilities (`SampleRateConverter`). The module enables centralized storage and retrieval of user preferences (e.g., last used sample rate, export options, hardware assignments) with fallback to defaults defined in code or the database, while supporting localized display names and descriptions for UI rendering. ## 2. Public Interface ### `OptimizationSettings` class (`Users.UserSettings` namespace) - **`OptimizationSettings()`** Default constructor; initializes an empty `Settings` list. - **`OptimizationSettings(string xmlOptimizationSettings)`** Constructor that deserializes XML-formatted optimization settings into the `Settings` list using `XmlToObject.FromXml`. - **`Settings` property (`List`)** Collection of hardware-specific optimization settings. - **`Setting` nested class** - `HardwareType` (`HardwareTypes`): Specifies the hardware type (e.g., SLICE, TDAS). - `TransferSpeedSampleRateSettings` (`List`): List of sample rate configurations for transfer speed ranges. - **`TransferSpeedSampleRate` nested class** - `MaxTransferSpeed` (`float`): Upper bound of transfer speed (bytes/sec? units unspecified). - `MinTransferSpeed` (`float`): Lower bound of transfer speed. - `SampleRate` (`double`): Sample rate (Hz) to use within the speed range. ### `CategoryAttributeEx` class (`DTS.Slice.Users.UserSettings` namespace) - **`CategoryAttributeEx(PropertyEnums.PropertyCategories category)`** Constructor that initializes the attribute with a category enum value and stores it internally. - **`GetCategory()` method** Returns the stored `PropertyCategories` enum value. - **`GetLocalizedString(string value)` override** Looks up `value` in `StringResources.ResourceManager`; returns `"##ResourceNotFound##" + value` if not found. ### `DisplayAttributeEx` class (`DTS.Slice.Users.UserSettings` namespace) - **`DisplayAttributeEx(PropertyEnums.PropertyIds propertyId)`** Constructor for enum-based property ID lookup. - **`DisplayAttributeEx(string propertyId)`** Constructor for string-based property ID lookup. - **`DisplayName` override** Constructs resource key as `"{propertyId}_DisplayName"` (using enum or string), looks up in `StringResources.ResourceManager`; returns `"##DisplayNameNotFound##" + propertyId` if not found. ### `DescriptionAttributeEx` class (`DTS.Slice.Users.UserSettings` namespace) - **`DescriptionAttributeEx(PropertyEnums.PropertyIds propertyId)`** Constructor for enum-based property ID lookup. - **`DescriptionAttributeEx(string propertyId)`** Constructor for string-based property ID lookup. - **`Description` override** Constructs resource key as `"{propertyId}_Description"` (using enum or string), looks up in `StringResources.ResourceManager`; returns `"##DescriptionNotFound##" + propertyId` if not found. ### `PropertyIdAttribute` class (`DTS.Slice.Users.UserSettings` namespace) - **`PropertyIdAttribute(PropertyEnums.PropertyIds propertyId)`** Constructor that stores the property ID enum. - **`GetPropertyId(PropertyInfo o)` static method** Retrieves the integer property ID from a `PropertyInfo`'s `PropertyIdAttribute`. Throws `NullReferenceException` if property or attribute is missing. - **`GetPropertyIdEnum(PropertyInfo o)` static method** Retrieves the `PropertyIds` enum value from a `PropertyInfo`'s `PropertyIdAttribute`. Throws `NullReferenceException` if property or attribute is missing. ### `SampleRateConverter` class (`DTS.Slice.Users.UserSettings` namespace) - **`SampleRateConverter()`** Default constructor. - **`GetStandardValuesSupported(ITypeDescriptorContext context)` override** Returns `true`, indicating a standard list of values is available. - **`GetStandardValues(ITypeDescriptorContext context)` override** Returns a sorted list of valid sample rates (as `double[]`) by: 1. Reading `SPSINDEX_COUNT` (default 56) from `SettingsDB`. 2. Iterating `i = 0` to `SPSINDEX_COUNT-1`, fetching `SPSINDEX_{i}` from `SettingsDB` (defaulting to `AvailableSampleRatesDefault[i]` if `i < 27`). 3. Filtering out duplicates and non-positive values. Returns values as `StandardValuesCollection`. - **`AvailableSampleRatesDefault` static field (`int[]`)** Hardcoded default sample rates (Hz): `[5, 50, 100, ..., 1000000]` (27 values). ### `UserHistory` class (`DTS.Slice.Users.UserSettings` namespace) - **Static `CreateAnyMissingUserHistory()` method** Ensures all properties defined in `UserHistory` exist in the `DefaultProperties` database table and creates user-specific entries. Uses reflection to inspect properties, checks `DefaultProperties` table for existing entries, and inserts missing defaults via `DbOperations`. - **Instance Properties** (all annotated with `[CategoryAttributeEx]`, `[PropertyId]`, `[DescriptionAttributeEx]`, `[DisplayAttributeEx]`, `[DefaultValue]`, `[ReadOnly(true)]`): - `UsersCurrentTestSetup` (`string`, default `""`, ID `401`) - `LastRunTestSetup` (`string`, default `""`, ID `402`) - `LastUsedSampleRate` (`double`, default `20000.0`, ID `403`) - `ApplySensorDataToBlankChannels` (`bool`, default `true`, ID `404`) - `ApplyHardwareAssignmentInHardwareDisco` (`bool`, default `true`, ID `434`, `[Browsable(false)]`) - `ShowOptionsWhenApplyingSensorToBlankChannel` (`bool`, default `true`, ID `405`) ### `PropertyEnums` class (`DTS.Slice.Users.UserSettings` namespace) - **`PropertyCategories` enum** Categories for grouping settings in UI (e.g., `UserHistory`, `ExportOptions`, `RealtimeOptions`). Used by `CategoryAttributeEx`. - **`PropertyOrders` enum** Ordered list of property names (used for ordering within categories in UI). *Not directly used in the provided source files*. - **`PropertyIds` enum** Integer-based IDs for properties (e.g., `UsersCurrentTestSetup = 401`, `DefaultSampleRate = 103`). Used by `PropertyIdAttribute`, `DisplayAttributeEx`, and `DescriptionAttributeEx`. ## 3. Invariants - **Database storage format**: All settings are stored in invariant (culture-agnostic) form in the database (e.g., numeric sample rates, English string keys). - **Fallback chain**: When retrieving a setting, the system falls back in this order: user-specific value → default value in DB → default value in code (via `[DefaultValue]` or `TestSetupDefaults.GetDefaultValueAsString`). - **Resource key format**: Display names and descriptions use keys of the form `"{PropertyId}_DisplayName"` and `"{PropertyId}_Description"` (where `PropertyId` is the enum or string value). - **Property ID uniqueness**: Each `PropertyIds` enum value maps to a unique integer ID used as the primary key in `DefaultProperties` table. - **Sample rate list construction**: `SampleRateConverter.GetStandardValues()` always returns a sorted list of *unique*, *positive* sample rates derived from `SettingsDB` and `AvailableSampleRatesDefault`. - **Attribute consistency**: Properties in `UserHistory` must have exactly one `PropertyIdAttribute`, and its value must match the enum value used in `PropertyIdAttribute`/`DisplayAttributeEx`/`DescriptionAttributeEx`. ## 4. Dependencies ### Module depends on: - `DTS.Common.Enums.Hardware.HardwareTypes` (for `OptimizationSettings.Setting.HardwareType`) - `DTS.Common.Utilities.Xml.XmlToObject` (for XML deserialization in `OptimizationSettings`) - `DTS.Common.Settings.SettingsDB` (for `SampleRateConverter` to read global settings like `SPSINDEX_COUNT`) - `DTS.Common.Storage.DbOperations` (for database operations in `UserHistory.CreateAnyMissingUserHistory`) - `System.ComponentModel` (for `CategoryAttribute`, `DisplayNameAttribute`, `DescriptionAttribute`, `TypeConverter`) - `System.Resources.ResourceManager` (via `StringResources.ResourceManager` for localization) - `TestSetupDefaults.GetDefaultValueAsString` (for default value retrieval in `CreateAnyMissingUserHistory`) - `TestSetupDefaults.CreateMissingUserSettingProperties` (for user-specific setting creation) ### Module is depended on by: - UI components (e.g., property grids) that use `UserHistory` properties and attributes for display. - Settings persistence layer (e.g., `DbOperations`, `SettingsDB`) for reading/writing settings. - Code that consumes `OptimizationSettings` (e.g., hardware-specific optimization logic). - Localization infrastructure (via `StringResources`). ## 5. Gotchas - **Resource key mismatch**: If a property ID is passed as a string to `DisplayAttributeEx`/`DescriptionAttributeEx`, the resource key is `"{string}_DisplayName"` (e.g., `"MyProp_DisplayName"`), *not* the enum name. Ensure string-based keys match this pattern. - **Missing enum entries**: `PropertyOrders` enum is defined but *not used* in the provided source files; its purpose is unclear without additional context. - **Hardcoded defaults**: `SampleRateConverter` uses a hardcoded `AvailableSampleRatesDefault` array (27 values) as fallback, but `SPSINDEX_COUNT` defaults to 56. This may cause out-of-bounds access if `SPSINDEX_COUNT > 27` and missing DB entries exist. - **Case sensitivity**: Resource lookups are case-sensitive (via `ResourceManager.GetString`), but enum-to-string conversion uses `ToString()` (case-sensitive per C# conventions). - **No validation in `OptimizationSettings`**: The `Setting` and `TransferSpeedSampleRate` classes have no validation (e.g., `MinTransferSpeed ≤ MaxTransferSpeed`, `SampleRate > 0`). Invalid data may be deserialized silently. - **`ApplyHardwareAssignmentInHardwareDisco` is `[Browsable(false)]`**: Though public, this property will not appear in standard property grids. - **`SampleRateConverter` mutates state**: `GetStandardValues` clears and repopulates `_validSampleRateList` on each call. Not thread-safe if used concurrently. - **`PropertyIdAttribute.GetPropertyId` throws on null/missing**: No graceful handling; callers must ensure attributes exist before calling.