init
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/AddEditHardware/AddEditHardwareModule.cs
|
||||
generated_at: "2026-04-16T04:36:26.348285+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "05d78156d7f176cf"
|
||||
---
|
||||
|
||||
# AddEditHardware
|
||||
|
||||
### 1. **Purpose**
|
||||
The `AddEditHardwareModule` is a Prism-based modular component responsible for registering the view and view model for the hardware add/edit functionality within the application’s UI. It integrates with the Unity dependency injection container to expose `IAddEditHardwareView` and `IAddEditHardwareViewModel` as singleton services, enabling consistent instantiation and composition via Prism’s module loading infrastructure. Additionally, it defines assembly-level metadata attributes (`AddEditHardwareModuleNameAttribute` and `AddEditHardwareModuleImageAttribute`) that supply identifying information (name, image, group, region) for UI presentation—specifically for listing and rendering the module on the main screen.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
#### **Class: `AddEditHardwareModule`**
|
||||
- **`public AddEditHardwareModule(IUnityContainer unityContainer)`**
|
||||
Constructor. Accepts and stores a Unity container reference via dependency injection for later type registration.
|
||||
|
||||
- **`public void Initialize()`**
|
||||
Registers the view and view model types as singletons in the Unity container:
|
||||
- `IAddEditHardwareView → AddEditHardwareView`
|
||||
- `IAddEditHardwareViewModel → AddEditHardwareViewModel`
|
||||
|
||||
- **`public void OnInitialized(IContainerProvider containerProvider)`**
|
||||
Empty implementation. No logic executed during Prism’s `OnInitialized` phase.
|
||||
|
||||
- **`public void RegisterTypes(IContainerRegistry containerRegistry)`**
|
||||
Delegates to `Initialize()` to perform type registration. (Note: Uses `IContainerRegistry` from Prism but internally invokes the legacy `Initialize()` method that operates on `IUnityContainer`.)
|
||||
|
||||
#### **Attribute: `AddEditHardwareModuleNameAttribute`**
|
||||
- **Inherits from `TextAttribute`**
|
||||
- **`public override string AssemblyName { get; }`**
|
||||
Returns `"AddEditHardware"` (via `AssemblyNames.AddEditHardware.ToString()`).
|
||||
- **`public override string GetAssemblyName()`**
|
||||
Returns the same `AssemblyName` value.
|
||||
- **`public override Type GetAttributeType()`**
|
||||
Returns `typeof(TextAttribute)`.
|
||||
|
||||
#### **Attribute: `AddEditHardwareModuleImageAttribute`**
|
||||
- **Inherits from `ImageAttribute`**
|
||||
- **`public override BitmapImage AssemblyImage { get; }`**
|
||||
Loads and returns a `BitmapImage` by calling `AssemblyInfo.GetImage("AddEditHardware")`.
|
||||
- **`public override BitmapImage GetAssemblyImage()`**
|
||||
Returns `AssemblyImage`.
|
||||
- **`public override string AssemblyName { get; }`**
|
||||
Returns `"AddEditHardware"`.
|
||||
- **`public override string GetAssemblyName()`**
|
||||
Returns `AssemblyName`.
|
||||
- **`public override string AssemblyGroup { get; }`**
|
||||
Returns `"Prepare"` (via `eAssemblyGroups.Prepare.ToString()`).
|
||||
- **`public override string GetAssemblyGroup()`**
|
||||
Returns `AssemblyGroup`.
|
||||
- **`public override eAssemblyRegion AssemblyRegion { get; }`**
|
||||
Returns `eAssemblyRegion.AddEditHardwareRegion`.
|
||||
- **`public override eAssemblyRegion GetAssemblyRegion()`**
|
||||
Returns `AssemblyRegion`.
|
||||
- **`public override Type GetAttributeType()`**
|
||||
Returns `typeof(ImageAttribute)`.
|
||||
|
||||
> **Note**: The attributes are applied at the assembly level via `[assembly: ...]` directives and are not tied to instance-based usage.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
- The module *must* be loaded by Prism after the Unity container is available (via `RegisterTypes`), and *before* views requiring `IAddEditHardwareView` or `IAddEditHardwareViewModel` are resolved.
|
||||
- `AssemblyNames.AddEditHardware` and `eAssemblyGroups.Prepare` and `eAssemblyRegion.AddEditHardwareRegion` must be defined elsewhere (in `DTS.Common` or `DTS.Common.Interface`) and be non-null/valid at runtime for attribute initialization to succeed.
|
||||
- `AssemblyInfo.GetImage(...)` must return a non-null `BitmapImage` for `"AddEditHardware"`; otherwise, `AssemblyImage` may be `null`.
|
||||
- Type registrations in `Initialize()` are *idempotent* only if Unity allows re-registration of the same mapping (behavior depends on Unity configuration, but no explicit safeguards are present here).
|
||||
- The `OnInitialized` method is intentionally empty; no side effects occur during Prism’s `OnInitialized` phase.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
#### **Module Dependencies**
|
||||
- **`DTS.Common`** and **`DTS.Common.Interface`**
|
||||
Provide core types: `AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion`, `AssemblyInfo`, `TextAttribute`, `ImageAttribute`, and the interfaces `IAddEditHardwareView`, `IAddEditHardwareViewModel`.
|
||||
- **`Prism.Modularity`** and **`Prism.Ioc`**
|
||||
Required for `IModule`, `IContainerRegistry`, and `IContainerProvider`.
|
||||
- **`Unity`** (`Microsoft.Practices.Unity`)
|
||||
Required for `IUnityContainer`.
|
||||
- **`System.Windows.Media.Imaging`**
|
||||
Used for `BitmapImage`.
|
||||
|
||||
#### **Dependents (Inferred)**
|
||||
- The main shell/UI layer likely consumes `AddEditHardwareModuleImageAttribute` metadata to render module cards/tiles on the main screen.
|
||||
- Other modules or views may depend on `IAddEditHardwareView` or `IAddEditHardwareViewModel` being registered and available via the container.
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
- **Redundant `Initialize()` call**: `RegisterTypes` calls `Initialize()`, but `Initialize()` uses `_unityContainer` directly instead of the `IContainerRegistry containerRegistry` parameter passed to `RegisterTypes`. This suggests legacy or transitional code (e.g., migration from Unity-specific `IUnityContainer` to Prism’s `IContainerRegistry`), and may cause issues if `RegisterTypes` is invoked *before* `_unityContainer` is injected (though Prism guarantees `RegisterTypes` runs first).
|
||||
- **No null-safety in attribute constructors**: `AssemblyInfo.GetImage(...)` is called in both the parameterless and string-constructor overloads of `AddEditHardwareModuleImageAttribute`. If `"AddEditHardware"` is not a valid image key, `_img` may be `null`, and `AssemblyImage` will return `null` silently.
|
||||
- **Assembly-level attributes**: The attributes are applied at the assembly level and *not* tied to any runtime instance. Their properties are computed once at attribute instantiation time (i.e., during assembly load), not lazily.
|
||||
- **Unused `string s` parameter**: Both attribute constructors accept a `string s` parameter that is ignored—likely a remnant of base class expectations.
|
||||
- **No validation of view/viewmodel types**: `RegisterType` calls assume `AddEditHardwareView` and `AddEditHardwareViewModel` exist and implement `IAddEditHardwareView`/`IAddEditHardwareViewModel`. A mismatch would only surface at resolution time.
|
||||
|
||||
> **None identified from source alone** beyond the above—no obvious logic errors, but the design hints at technical debt in the `RegisterTypes`/`Initialize` interaction.
|
||||
@@ -0,0 +1,141 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/AddEditHardware/Model/DASModule.cs
|
||||
generated_at: "2026-04-16T04:37:06.260294+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "05acdd30203849a0"
|
||||
---
|
||||
|
||||
# Model
|
||||
|
||||
## Documentation: `DASModule.cs`
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
|
||||
The `DASModule` class models a hardware module in a Data Acquisition System (DAS) for use in a WPF-based UI for adding or editing hardware configurations. It encapsulates module-specific metadata—including type, bridge configuration (for SLICE modules), serial number, and associated visual representation—and exposes this data through a property-changed-aware model suitable for data binding. It serves as a view-model-like abstraction for hardware modules in the `AddEditHardware` workflow, implementing `IAddEditHardwareDASModule` and inheriting from `BasePropertyChanged` to support UI updates via `INotifyPropertyChanged`.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
#### `public bool Disabled { get; set; } = false;`
|
||||
- Indicates whether this module instance is disabled (e.g., not in use). Default is `false`.
|
||||
|
||||
#### `public SLICEBridgeTypes SLICEBridgeType { get; set; }`
|
||||
- Gets or sets the bridge type for SLICE modules (e.g., `Bridge`, `IEPE`, `ARS`, `ACC`).
|
||||
- **Behavior**: On change, triggers `SetProperty`, then calls `SetImage()` to update the image based on the new type.
|
||||
|
||||
#### `public HardwareTypes ModuleType { get; set; }`
|
||||
- Gets or sets the high-level hardware type (e.g., `SLICE_Bridge`, `TOM`, `SIM`, `DIM`, `UNDEFINED`).
|
||||
- **Behavior**: On change, triggers `SetProperty`, then calls `SetImage()`.
|
||||
|
||||
#### `public string SerialNumber { get; set; }`
|
||||
- Gets or sets the module’s serial number (empty string by default). No validation or prefix enforcement is performed in this property.
|
||||
|
||||
#### `public ImageSource DASImage { get; set; }`
|
||||
- Gets or sets the `ImageSource` used to display the module’s image in the UI.
|
||||
- **Behavior**: Set via `SetImage()` based on `ModuleType` and (for `SLICE_Bridge`) `SLICEBridgeType`. May be `null` if image loading fails or no matching asset is found.
|
||||
|
||||
#### `public SLICEBridgeTypes[] AvailableNanoBridges { get; }`
|
||||
- Returns a read-only array of valid `SLICEBridgeTypes` for *nano*-form-factor SLICE modules:
|
||||
`SLICEBridgeTypes.Bridge`, `SLICEBridgeTypes.IEPE`.
|
||||
|
||||
#### `public SLICEBridgeTypes[] AvailableMicroBridges { get; }`
|
||||
- Returns a read-only array of valid `SLICEBridgeTypes` for *micro*-form-factor SLICE modules:
|
||||
`SLICEBridgeTypes.Bridge`, `SLICEBridgeTypes.IEPE`, `SLICEBridgeTypes.ARS`, `SLICEBridgeTypes.ACC`.
|
||||
|
||||
#### `public HardwareTypes[] AvailableRACKModules { get; }`
|
||||
- Returns a read-only array of valid hardware types for rack-mounted modules:
|
||||
`HardwareTypes.UNDEFINED`, `HardwareTypes.SIM`, `HardwareTypes.TOM`, `HardwareTypes.DIM`.
|
||||
|
||||
#### `public IAddEditHardwareHardware OwningHardware { get; set; }`
|
||||
- Reference to the parent hardware object (e.g., chassis or device) that owns this module. Used for contextual navigation or validation.
|
||||
|
||||
#### `public string GetSerialNumberPrefix()`
|
||||
- Returns a short string prefix used for generating or validating serial numbers based on module type:
|
||||
- `"DIM"` for `HardwareTypes.DIM`
|
||||
- `"SIM"` for `HardwareTypes.SIM`
|
||||
- `"TOM"` for `HardwareTypes.TOM`
|
||||
- For `HardwareTypes.SLICE_Bridge`, returns a 2-letter prefix based on `SLICEBridgeType`:
|
||||
- `"AC"` for `ACC`
|
||||
- `"AR"` for `ARS`
|
||||
- `"BR"` for `Bridge`
|
||||
- `"IEPE"` for `IEPE`
|
||||
- Returns `string.Empty` for `UNDEFINED` or unrecognized types.
|
||||
|
||||
#### `public DASModule()`
|
||||
- Default constructor. Initializes `Disabled = false`, `_sliceBridgeType = Bridge`, `_moduleType = UNDEFINED`.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- **Image Consistency**: `DASImage` is always derived from `ModuleType` and (if applicable) `SLICEBridgeType`. Changing either triggers `SetImage()` and updates `DASImage`.
|
||||
- **Image Source URI**: All image paths are relative to the pack URI `pack://application:,,,/ResourceFile.xaml`.
|
||||
- **Image Loading Failure Handling**: If image loading fails (e.g., missing file), `DASImage` is set to `null`, and an error is logged via `APILogger`.
|
||||
- **Image Freezing**: Loaded `BitmapImage` instances are frozen for thread-safety and performance.
|
||||
- **Module Type Constraints**:
|
||||
- `SLICEBridgeType` is only meaningful when `ModuleType == HardwareTypes.SLICE_Bridge`.
|
||||
- `AvailableNanoBridges` and `AvailableMicroBridges` are static and immutable; they define allowed values but are not enforced by property setters.
|
||||
- **Serial Number Prefix**:
|
||||
- `GetSerialNumberPrefix()` returns `string.Empty` for unrecognized or `UNDEFINED` module types.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
#### **Imports/Usings**
|
||||
- `System`, `System.Windows`, `System.Windows.Input`, `System.Windows.Media`, `System.Windows.Media.Imaging`
|
||||
- `DTS.Common.Base` → `BasePropertyChanged`
|
||||
- `DTS.Common.Enums.Hardware` → `SLICEBridgeTypes`, `HardwareTypes`
|
||||
- `DTS.Common.Interface.Hardware.AddEditHardware` → `IAddEditHardwareDASModule`, `IAddEditHardwareHardware`
|
||||
- `DTS.Common.Utilities.Logging` → `APILogger`
|
||||
|
||||
#### **External Dependencies**
|
||||
- **WPF**: Uses `ImageSource`, `BitmapImage`, `Uri`, `pack://` URIs.
|
||||
- **Common Libraries**:
|
||||
- `DTS.Common.Base` for `BasePropertyChanged` (likely implements `INotifyPropertyChanged`).
|
||||
- `DTS.Common.Enums.Hardware` for type definitions.
|
||||
- `DTS.Common.Interface.Hardware.AddEditHardware` for interface contracts.
|
||||
- `DTS.Common.Utilities.Logging` for error logging.
|
||||
|
||||
#### **Consumers**
|
||||
- UI components bound to `DASModule` (e.g., `DataGrid`, `UserControl`) for editing hardware configurations.
|
||||
- Any class implementing or consuming `IAddEditHardwareDASModule`.
|
||||
- Likely instantiated and managed by a parent `IAddEditHardwareHardware` (via `OwningHardware`).
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **No Validation on `ModuleType`/`SLICEBridgeType` Combinations**:
|
||||
The class allows setting `ModuleType = SLICE_Bridge` and `SLICEBridgeType = ACC`, but also allows `ModuleType = TOM` with `SLICEBridgeType = IEPE`, which is semantically invalid. Validation (if any) must occur elsewhere (e.g., in UI or service layer).
|
||||
|
||||
- **`Disabled` Property Has No Side Effects**:
|
||||
Setting `Disabled = true` does not affect image loading, serial number generation, or any other logic in this class.
|
||||
|
||||
- **Image Paths Are Hardcoded and Fragile**:
|
||||
`SetImage()` uses hardcoded relative paths (e.g., `@"Assets/Hardware/SLICEIEPE_Side.png"`). If assets are renamed or moved, image loading silently fails (logs error, sets `DASImage = null`).
|
||||
|
||||
- **`GetSerialNumberPrefix()` Returns `"IEPE"` (4 chars) While Others Are 2–3 chars**:
|
||||
Inconsistent prefix length may cause downstream parsing issues if consumers assume fixed-width prefixes.
|
||||
|
||||
- **No Null/Empty Handling for `SerialNumber`**:
|
||||
The property accepts any string, including `null` or whitespace. No validation or trimming is applied.
|
||||
|
||||
- **`OwningHardware` Is Not Initialized**:
|
||||
The property is nullable and must be set externally; no constructor overloads or defaults are provided.
|
||||
|
||||
- **`_baseUri` Is Static and Fixed**:
|
||||
Assumes all images are in the same resource file (`ResourceFile.xaml`). Not configurable at runtime.
|
||||
|
||||
- **Exception Handling in `SetImage()` Is Broad**:
|
||||
Catches all exceptions during image loading but logs only the message (no stack trace or context), making debugging harder.
|
||||
|
||||
- **No Explicit Interface Implementation**:
|
||||
The class implements `IAddEditHardwareDASModule` implicitly; if the interface defines additional members, they are not visible in this file.
|
||||
|
||||
- **None identified from source alone.** *(Note: The above are inferred from observed behavior, not documented quirks.)*
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/AddEditHardware/Properties/Settings.Designer.cs
|
||||
- DataPRO/Modules/Hardware/AddEditHardware/Properties/AssemblyInfo.cs
|
||||
generated_at: "2026-04-16T04:36:44.098121+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "2868c6abccf6511a"
|
||||
---
|
||||
|
||||
# Properties
|
||||
|
||||
## Documentation: `AddEditHardware.Properties.Settings`
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
This module defines the strongly-typed application settings class `AddEditHardware.Properties.Settings`, which inherits from `System.Configuration.ApplicationSettingsBase`. It serves as the programmatic interface for accessing user- or application-scoped configuration values for the `AddEditHardware` module. The class is auto-generated by Visual Studio’s settings designer and provides a singleton-style static accessor (`Default`) for retrieving settings at runtime. It does not contain any custom settings properties in the provided source—only the infrastructure to host them.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
- **`Settings Default`** *(static property)*
|
||||
- **Signature**: `internal static Settings Default { get; }`
|
||||
- **Behavior**: Returns the singleton instance of the `Settings` class, synchronized for thread safety via `ApplicationSettingsBase.Synchronized()`. This is the sole public member exposed in the current source. No custom settings properties are defined here—any actual settings (e.g., `HardwareId`, `LastUsedTemplate`) would appear in the designer-generated body but are absent in the provided snippet.
|
||||
|
||||
> **Note**: The class is `internal sealed partial`, and the `Settings` type itself is `internal`. No public constructors or instance members are present.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- The `defaultInstance` field is initialized once and reused for all accesses to `Default`.
|
||||
- Thread safety is ensured by wrapping the initial `Settings` instance with `ApplicationSettingsBase.Synchronized()`, which enforces that all access to the settings instance is synchronized on a shared lock.
|
||||
- The class is sealed and non-extensible in this file (though `partial` allows extension in other generated files, not shown here).
|
||||
- No validation or custom logic is present in the provided source—behavior relies entirely on `ApplicationSettingsBase`.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
- **Depends on**:
|
||||
- `System.Configuration` (specifically `ApplicationSettingsBase`)
|
||||
- `System.Runtime.CompilerServices.CompilerGeneratedAttribute`
|
||||
- `System.CodeDom.Compiler.GeneratedCodeAttribute`
|
||||
|
||||
- **Depended on by**:
|
||||
- Other modules in the `AddEditHardware` assembly (e.g., UI forms or services in `DataPRO/Modules/Hardware/AddEditHardware`) that consume settings via `Settings.Default`.
|
||||
- The Visual Studio Settings Designer (at design time), which regenerates this file when settings are modified in the `.settings` designer file (not included here).
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **Auto-generated file**: This file is auto-generated by Visual Studio. Manual edits will be overwritten on rebuild or settings modification.
|
||||
- **No settings defined in source**: The provided snippet contains *only* the base infrastructure—no actual settings properties (e.g., `public string SomeSetting { get; set; }`) are visible. Developers must check the corresponding `.settings` designer file (e.g., `Properties/Settings.settings`) to see configured values.
|
||||
- **Internal visibility**: The `Settings` class and its `Default` property are `internal`, meaning they are only accessible within the `AddEditHardware` assembly. External consumers (e.g., other modules) must reference this assembly and access it via `AddEditHardware.Properties.Settings.Default`.
|
||||
- **Thread-safety overhead**: The use of `Synchronized()` implies a performance cost for every access; if settings are read frequently, consider caching locally.
|
||||
- **Versioning**: Assembly version is fixed at `1.0.0.0` (both `AssemblyVersion` and `AssemblyFileVersion`), which may impact upgrade behavior for user-scoped settings (e.g., migration logic in `Settings.Default.Upgrade()`).
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/AddEditHardware/Resources/TranslateExtension.cs
|
||||
- DataPRO/Modules/Hardware/AddEditHardware/Resources/StringResources.Designer.cs
|
||||
generated_at: "2026-04-16T04:36:34.790176+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "df6887e304a35dc7"
|
||||
---
|
||||
|
||||
# Resources
|
||||
|
||||
## Documentation: `TranslateExtension` Markup Extension
|
||||
|
||||
### 1. Purpose
|
||||
This module provides a WPF `MarkupExtension` (`TranslateExtension`) that enables declarative localization of UI strings in XAML. It allows UI elements (e.g., `TextBlock.Text`, `Button.Content`) to bind to localized string resources defined in `StringResources` by specifying a resource key. Its role is to abstract away manual resource lookup and support runtime culture switching in the `AddEditHardware` module’s UI.
|
||||
|
||||
### 2. Public Interface
|
||||
- **`TranslateExtension(string key)`**
|
||||
Constructor. Accepts a string `key` corresponding to a resource name in `StringResources`. Stores the key for later lookup.
|
||||
|
||||
- **`object ProvideValue(IServiceProvider serviceProvider)`**
|
||||
Overrides `MarkupExtension.ProvideValue`. Performs resource lookup at XAML load time:
|
||||
- Returns `"#stringnotfound#"` if `_key` is `null` or empty.
|
||||
- Returns the localized string from `StringResources.ResourceManager.GetString(_key)` if found.
|
||||
- Returns `"#stringnotfound# <key>"` (e.g., `"#stringnotfound# MyKey"`) if the key is non-empty but no matching resource exists.
|
||||
|
||||
### 3. Invariants
|
||||
- `_key` is immutable after construction (no setter or mutation).
|
||||
- The extension **always returns a `string`** (per `[MarkupExtensionReturnType(typeof(string))]`).
|
||||
- Lookup is **case-sensitive** (relies on `ResourceManager.GetString(string)` behavior).
|
||||
- If a resource key is missing, the fallback string explicitly includes the original key for debugging visibility.
|
||||
|
||||
### 4. Dependencies
|
||||
- **Depends on**:
|
||||
- `System.Windows.Markup` (for `MarkupExtension` base class).
|
||||
- `AddEditHardware.Resources.StringResources` (strongly-typed resource class generated from `.resx`).
|
||||
- `System.Resources.ResourceManager` (used internally via `StringResources.ResourceManager`).
|
||||
- **Used by**:
|
||||
- XAML files in the `AddEditHardware` module (e.g., `AddEditHardwareView.xaml`) to localize UI elements.
|
||||
- No direct runtime dependencies beyond WPF framework and the `StringResources` assembly.
|
||||
|
||||
### 5. Gotchas
|
||||
- **Static resource resolution**: `ProvideValue` is called **once at XAML load time**, not at runtime. Changing `StringResources.Culture` *after* XAML is parsed will **not** update already-bound UI elements.
|
||||
- **Fallback format**: Missing keys yield `"#stringnotfound# <key>"`, which may appear in UI if keys are misspelled or missing from `.resx`. This is intentional for debugging but may confuse end users.
|
||||
- **No null-safety for `serviceProvider`**: The implementation does not validate `serviceProvider`, though WPF typically provides a valid instance.
|
||||
- **Hardcoded fallback**: The `"#stringnotfound#"` prefix is hardcoded and not configurable.
|
||||
- **No async or caching optimization**: Each usage triggers a `ResourceManager.GetString()` call; no caching is applied within `TranslateExtension` (though `ResourceManager` itself caches resources internally).
|
||||
- **Auto-generated resource class**: `StringResources` is auto-generated; manual edits will be overwritten. Resource keys must match exactly (case-sensitive) with entries in the `.resx` file.
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,109 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/AddEditHardware/View/AddEditHardwareView.xaml.cs
|
||||
generated_at: "2026-04-16T04:35:38.785908+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "0ee538e93daa667b"
|
||||
---
|
||||
|
||||
# View
|
||||
|
||||
## Documentation: `AddEditHardwareView` (WPF View for Hardware Configuration)
|
||||
|
||||
---
|
||||
|
||||
### **1. Purpose**
|
||||
|
||||
The `AddEditHardwareView` class is the WPF UI view layer for configuring and editing hardware devices in the system. It implements the `IAddEditHardwareView` interface and `INotifyPropertyChanged` to support data binding, and is responsible for rendering hardware type selection, module management (add/remove), and dynamic UI updates based on database version and view model state. It acts as the presentation layer for the `AddEditHardwareViewModel`, coordinating user interactions (e.g., button clicks, selection changes, text input) with the underlying data model via event handlers and property synchronization.
|
||||
|
||||
---
|
||||
|
||||
### **2. Public Interface**
|
||||
|
||||
#### **Properties**
|
||||
- **`public bool AllowStandin { get; }`**
|
||||
Determines whether the SLICE6TreeView UI element should be visible. Returns `true` if `DataContext` is null or not an `IAddEditHardwareViewModel`; otherwise, delegates to `vm.AllowStandin`.
|
||||
|
||||
- **`public int ViewDbVersion { get; set; }`**
|
||||
Gets or sets the database version used to filter available hardware types. Setting this clears the cached hardware type list (`_allDASTypes`) and refreshes the `cbHardwareTypes.ItemsSource`.
|
||||
|
||||
#### **Methods**
|
||||
- **`public void Activated()`**
|
||||
Called when the view is activated. Triggers a property change notification for `AllowStandin`, and if `vm.SLICE6TreeView` is non-null, assigns it to `SLICE6TreeView.Content`.
|
||||
|
||||
#### **Event Handlers (Private, but part of public behavior via XAML wiring)**
|
||||
- **`private void btnRemoveModule_Click(object sender, RoutedEventArgs e)`**
|
||||
Removes the module associated with the clicked button’s `DataContext` from its owning hardware, then notifies the view model of modification.
|
||||
|
||||
- **`private void btnAdd_Click(object sender, RoutedEventArgs e)`**
|
||||
Adds a new module to the hardware associated with the clicked button’s `DataContext`, then notifies the view model of modification.
|
||||
|
||||
- **`private void cb_SelectionChanged(object sender, SelectionChangedEventArgs e)`**,
|
||||
**`private void cb_Checked(object sender, RoutedEventArgs e)`**,
|
||||
**`private void cb_Unchecked(object sender, RoutedEventArgs e)`**,
|
||||
**`private void tb_TextChanged(object sender, TextChangedEventArgs e)`**
|
||||
All invoke `vm.NotifyModified()` to signal that the underlying data has changed.
|
||||
|
||||
#### **Protected/Helper Methods (Not public API, but part of implementation)**
|
||||
- **`protected bool SetProperty<T>(ref T storage, T value, string propertyName = null)`**
|
||||
Implements `INotifyPropertyChanged` semantics: updates `storage` only if value differs, raises `PropertyChanged`, and returns `true` if changed.
|
||||
|
||||
- **`protected void OnPropertyChanged(string propertyName = null)`**
|
||||
Raises the `PropertyChanged` event.
|
||||
|
||||
---
|
||||
|
||||
### **3. Invariants**
|
||||
|
||||
- **Thread Safety for Hardware Type Caching**:
|
||||
`_allDASTypes` is populated and cleared under a `lock` on the static list. `AvailableDASType()` and `PopulateDASTypes()` use this lock to ensure thread-safe initialization and version-based filtering.
|
||||
|
||||
- **Database Version Dependency**:
|
||||
The list of available hardware types (`_allDASTypes`) is *dynamically filtered* based on `ViewDbVersion`. Specific hardware types (e.g., `SLICE6_AIR_BR`, `SLICE6_AIR_TC`, `SLICE_PRO_CAN_FD`) are only included if `ConnectionDbVersion` meets or exceeds their respective version constants (`Constants.SLICE6AIR_BR_DB_VERSION`, etc.).
|
||||
|
||||
- **View Model Contract**:
|
||||
The view assumes `DataContext` is an `IAddEditHardwareViewModel` (or `AddEditHardwareViewModel` in handlers). If not, operations silently exit (e.g., `vm.NotifyModified()` is not called).
|
||||
|
||||
- **Module Ownership**:
|
||||
Module removal (`btnRemoveModule_Click`) requires the `DataContext` of the clicked control to be an `IAddEditHardwareDASModule` with a valid `OwningHardware` reference.
|
||||
|
||||
---
|
||||
|
||||
### **4. Dependencies**
|
||||
|
||||
#### **Imports / Dependencies Used**
|
||||
- **`DTS.Common`**: Core types, including `Constants`, `DbOperations`, `EnumDescriptionTypeConverter`.
|
||||
- **`DTS.Common.Converters`**: `EnumDescriptionTypeConverter` used for sorting hardware types by description.
|
||||
- **`DTS.Common.Enums.Hardware`**: `HardwareTypes`, `SLICEPROSIMConfigurations`, `SLICETCConfigurations`, `RackSizes`.
|
||||
- **`DTS.Common.Interface.Hardware.AddEditHardware`**: `IAddEditHardwareView`, `IAddEditHardwareViewModel`, `IAddEditHardwareDASModule`, `IAddEditHardwareHardware`.
|
||||
- **WPF Framework**: `System.Windows`, `System.Windows.Controls`, `System.ComponentModel`.
|
||||
|
||||
#### **Assumed Dependencies**
|
||||
- **`AddEditHardwareViewModel`**: Concrete implementation of `IAddEditHardwareViewModel`, used in handlers (e.g., `vm.NotifyModified()`).
|
||||
- **XAML file `AddEditHardwareView.xaml`**: Defines UI controls like `cbHardwareTypes`, `cbSliceProSimConfigurations`, `SLICE6TreeView`, etc., which are referenced in code-behind.
|
||||
- **`Constants` class**: Must define `SLICE6AIR_BR_DB_VERSION`, `SLICE_TC_DB_VERSION`, `SLICE_PRO_CAN_FD_DB_VERSION`, and `MINIMUM_LTS_DB_VERSION`.
|
||||
|
||||
---
|
||||
|
||||
### **5. Gotchas**
|
||||
|
||||
- **Static State Mutation on Version Change**:
|
||||
Setting `ViewDbVersion` clears `_allDASTypes` *globally*, affecting all instances of `AddEditHardwareView` in the app domain. This is a shared static cache—changing version for one view resets hardware type availability for others.
|
||||
|
||||
- **Silent Failures on Invalid Contexts**:
|
||||
Event handlers (`btnRemoveModule_Click`, `btnAdd_Click`, `cb_*`, `tb_TextChanged`) exit early if `DataContext` is not the expected type or if `ctrlView.DataContext` is not `AddEditHardwareViewModel`. No error is logged or thrown—behavior is silently skipped.
|
||||
|
||||
- **`AllowStandin` Logic is Inverted in Edge Cases**:
|
||||
Returns `true` (i.e., *show* the tree view) when `DataContext` is null or not an `IAddEditHardwareViewModel`. This may be counterintuitive—typically, missing view model would imply *hiding* UI elements.
|
||||
|
||||
- **Hardware Type Sorting Relies on Enum Descriptions**:
|
||||
`_allDASTypes.Sort()` uses `EnumDescriptionTypeConverter.GetEnumDescription()` for ordering. If descriptions are missing, empty, or non-unique, sorting may be inconsistent or throw.
|
||||
|
||||
- **No Validation on `ViewDbVersion`**:
|
||||
`ViewDbVersion` accepts any `int`. If set to a value below `MINIMUM_LTS_DB_VERSION`, behavior is undefined (though `_allDASTypes` is cleared and repopulated using the provided version).
|
||||
|
||||
- **Hardcoded Configuration Arrays**:
|
||||
`_availableSliceProSimConfigurations`, `_availableSliceTCConfigurations`, and `_availableRackSizes` are static and unversioned—no dynamic filtering based on database version is applied to these.
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,147 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/AddEditHardware/ViewModel/AddEditHardwareViewModel.cs
|
||||
generated_at: "2026-04-16T04:36:54.084304+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "eb93c7718734fde3"
|
||||
---
|
||||
|
||||
# ViewModel
|
||||
|
||||
## Documentation: `AddEditHardwareViewModel`
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
|
||||
This module implements the `AddEditHardwareViewModel` class, which serves as the view model for the Add/Edit Hardware UI flow. It encapsulates the logic for displaying, editing, and saving hardware configuration data (e.g., DAS units, SLICE6 devices), including validation, state management, and integration with other system modules (e.g., SLICE6 tree view, event aggregation, region navigation). It supports two operational modes: *adding* new hardware and *editing* existing hardware, and enforces constraints such as disallowing *StandIn* hardware in contexts where it is not permitted (e.g., data recorders). It acts as the intermediary between the UI (`IAddEditHardwareView`) and the underlying domain model (`IAddEditHardwareHardware`, `IISOHardware`), coordinating persistence and inter-module communication via Prism events.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
#### `AddEditHardwareViewModel(IAddEditHardwareView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`
|
||||
- **Behavior**: Primary constructor. Initializes the view, sets up event subscriptions (`RaiseNotification`, `BusyIndicatorChangeNotification`), and assigns dependencies. Assigns `this` as the view’s `DataContext`.
|
||||
|
||||
#### `AddEditHardwareViewModel()`
|
||||
- **Behavior**: Parameterless constructor required for XAML binding (e.g., design-time or Unity resolution fallback). Does *not* initialize dependencies.
|
||||
|
||||
#### `void SetSLICE6TreeView(ISLICE6TreeView treeView, IHardwareListViewModel treeViewModel)`
|
||||
- **Behavior**: Injects references to the SLICE6 tree view and its view model. Required for SLICE6-specific operations (e.g., saving associations, reloading tree). May be called after construction.
|
||||
|
||||
#### `void Activated()`
|
||||
- **Behavior**: Called when the view is activated. Enforces that `StandIn` is disabled if `AllowStandin` is `false` and the hardware instance is non-null.
|
||||
|
||||
#### `void SetHardware(IDASHardware hw, IISOHardware isoHW)`
|
||||
- **Behavior**: Initializes or resets the `Hardware` property. If `hw` is `null`, creates a new `Model.Hardware` instance; otherwise, constructs a new `Model.Hardware` from the provided `hw` and `isoHW`.
|
||||
|
||||
#### `IISOHardware GetISOHardware()`
|
||||
- **Behavior**: Converts the internal `Hardware` to an `IISOHardware`. If `Hardware.StandIn` is `true` and `SerialNumber` is not a valid GUID, generates a new GUID, updates both `Hardware.SerialNumber` and `isoHW.SerialNumber`, sets `FirstUseDate` to `null`, `IsFirstUseValid` to `true`, and `CalDate` to `DateTime.Today`.
|
||||
|
||||
#### `bool Validate(IISOHardware isoHW, ref List<string> errors, ref List<string> warnings, bool displayWindow, bool IsAdd)`
|
||||
- **Behavior**: Performs validation on `isoHW`. Checks:
|
||||
- Serial number validity (`ValidateSerialNumber`)
|
||||
- Uniqueness of serial number *only if* `IsAdd` is `true` (via `Model.Hardware.CheckUniqueSN`)
|
||||
- IP address validity (`ValidateIPAddress`)
|
||||
- Appends error/warning messages to `errors`/`warnings`. Calls `PublishPageError` if `displayWindow` is `true`. Returns `false` if any validation fails.
|
||||
|
||||
#### `void PublishPageError(bool displayWindow, List<string> errors, List<string> warnings)`
|
||||
- **Behavior**: If `displayWindow` is `true` and either `errors` or `warnings` is non-empty, publishes a `PageErrorEvent` with combined messages.
|
||||
|
||||
#### `void SaveSLICE6Associations()`
|
||||
- **Behavior**: If `Hardware.HardwareType` is `SLICE6DB`, `SLICE6DB3`, or `SLICE6DB_InDummy`, calls `SLICE6TreeViewModel.SaveSLICE6Associations(Hardware.SerialNumber)`.
|
||||
|
||||
#### `void Save()`
|
||||
- **Behavior**: Persists the current `Hardware` via `Model.Hardware.Save(...)`, passing `TestId`, and `model.IsAdd`. Then:
|
||||
- Calls `SaveSLICE6Associations()`
|
||||
- Publishes a `HardwareSavedEvent` with `(DASId, SerialNumber)`
|
||||
- Calls `SLICE6TreeViewModel.LoadTreeView(SerialNumber)` if `SLICE6TreeViewModel` is non-null.
|
||||
|
||||
#### `void NotifyModified()`
|
||||
- **Behavior**: If `NotificationsOn` is `true`, publishes a `PageModifiedEvent` with status `Modified`.
|
||||
|
||||
#### `void Cleanup()`, `Task CleanupAsync()`, `void Initialize()`, `void Initialize(object)`, `void Initialize(object, object)`, `Task InitializeAsync()`, `Task InitializeAsync(object)`, `void Unset()`
|
||||
- **Behavior**: No-op stubs. Present to satisfy interface contracts (e.g., `IInitialize`, `ICleanup`), but contain no logic.
|
||||
|
||||
#### `void OnPropertyChanged(string propertyName)`
|
||||
- **Behavior**: Raises the `PropertyChanged` event for the specified property.
|
||||
|
||||
#### `event PropertyChangedEventHandler PropertyChanged`
|
||||
- **Behavior**: Standard `INotifyPropertyChanged` implementation.
|
||||
|
||||
#### Properties:
|
||||
- `bool AllowStandin { get; set; } = true`
|
||||
Controls whether *StandIn* hardware is permitted. Defaults to `true`. Set externally (e.g., `false` for data recorders).
|
||||
|
||||
- `IAddEditHardwareView View { get; set; }`
|
||||
Reference to the associated view.
|
||||
|
||||
- `IAddEditHardwareHardware Hardware { get; set; }`
|
||||
The current hardware instance. Setting it triggers property change notifications for `Hardware`, `SerialNumber`, `FirmwareVersion`, `IPAddress`, and calls `SLICE6TreeViewModel.LoadTreeView(...)`.
|
||||
|
||||
- `int? TestId { get; set; }`
|
||||
Optional test context ID, used during save.
|
||||
|
||||
- `bool NotificationsOn { get; set; } = false`
|
||||
Enables/disables `PageModifiedEvent` publishing.
|
||||
|
||||
- `bool IsBusy { get; set; }`
|
||||
Bound to busy indicator UI. Set via `OnBusyIndicatorNotification`.
|
||||
|
||||
- `bool IsMenuIncluded { get; set; }`, `bool IsNavigationIncluded { get; set; }`
|
||||
UI layout flags; trigger `OnPropertyChanged` on change.
|
||||
|
||||
- `ISLICE6TreeView SLICE6TreeView { get; private set; }`, `IHardwareListViewModel SLICE6TreeViewModel { get; private set; }`
|
||||
References injected via `SetSLICE6TreeView`. May be `null`.
|
||||
|
||||
- `InteractionRequest<Notification> NotificationRequest { get; }`, `InteractionRequest<Confirmation> ConfirmationRequest { get; }`
|
||||
Prism interaction requests used to show popups (e.g., notifications, confirmations).
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- `Hardware` is never `null`; defaults to `new Model.Hardware()` if `SetHardware(null, ...)` is called.
|
||||
- `Hardware.StandIn` is forced to `false` during `Activated()` if `AllowStandin` is `false` and `Hardware` is non-null.
|
||||
- `Hardware.SerialNumber` may be overwritten (replaced with a new GUID) in `GetISOHardware()` if `StandIn` is `true` and the current `SerialNumber` is not a valid GUID.
|
||||
- `Validate(...)` only enforces serial number uniqueness (`CheckUniqueSN`) when `IsAdd` is `true`.
|
||||
- `IsBusy` is updated synchronously on the publisher thread via `OnBusyIndicatorNotification(bool)`.
|
||||
- `SLICE6TreeViewModel` may be `null`; all calls to it are guarded with `?.`.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
#### Imports / Dependencies:
|
||||
- **Prism Framework**: `IEventAggregator`, `IRegionManager`, `Unity`, `Prism.Events`, `Prism.Interactivity`, `Prism.Regions`.
|
||||
- **Common Libraries**:
|
||||
- `DTS.Common.Events.*` (e.g., `RaiseNotification`, `PageModifiedEvent`, `PageErrorEvent`, `HardwareSavedEvent`)
|
||||
- `DTS.Common.Interface.Hardware.AddEditHardware` (`IAddEditHardwareView`, `IAddEditHardwareHardware`)
|
||||
- `DTS.Common.Interface.DataRecorders` (`IDASHardware`, `IISOHardware`)
|
||||
- `DTS.Common.Interface.DASFactory.Diagnostics` (`ISLICE6TreeView`)
|
||||
- `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` (`IHardwareListViewModel`)
|
||||
- `DTS.Common.Utilities.Logging` (`APILogger`)
|
||||
- `DTS.Common.Interactivity` (`InteractionRequest<...>`)
|
||||
- `DTS.Common.Enums.Hardware.HardwareTypes` (used in `SaveSLICE6Associations`)
|
||||
- **Model Layer**: `Model.Hardware` (internal namespace, used for persistence, conversion, validation, and uniqueness checks).
|
||||
|
||||
#### Consumed By:
|
||||
- `IAddEditHardwareView` (XAML view) binds to this view model.
|
||||
- Other modules (e.g., `HardwareListViewModel`) may call `SetSLICE6TreeView(...)` to wire SLICE6 tree integration.
|
||||
- Event subscribers for `PageModifiedEvent`, `PageErrorEvent`, `HardwareSavedEvent`.
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **Dual constructors**: The parameterless constructor is required for XAML but leaves dependencies (`_eventAggregator`, `_regionManager`, etc.) uninitialized. Calling methods like `Activated()` or `SetHardware(...)` without prior injection may cause `NullReferenceException`.
|
||||
- **`GetISOHardware()` mutates state**: If `StandIn` is `true` and `SerialNumber` is not a GUID, it *modifies* `Hardware.SerialNumber` and `isoHW.SerialNumber` in-place. This side effect is not obvious from the method name.
|
||||
- **`Validate(...)` only checks uniqueness on *add***: `CheckUniqueSN` is skipped during edit (`IsAdd == false`), even if the serial number was changed.
|
||||
- **`SLICE6TreeViewModel.LoadTreeView(...)` is called on `Hardware` setter**: This may trigger expensive tree reloads even when `Hardware` is set to the same instance (e.g., via property binding updates).
|
||||
- **`NotificationsOn` defaults to `false`**: `NotifyModified()` does nothing unless explicitly enabled. This may lead to missed “page modified” signals if forgotten.
|
||||
- **`OnRaiseNotification` strips title from `NotificationContentEventArgs`**: The original `eventArgsWithTitle.Title` is used as the popup title, but the message content is reconstructed with an empty string for the third parameter (likely legacy or for compatibility).
|
||||
- **No-op lifecycle methods**: `Initialize`, `Cleanup`, etc., are present but empty. Developers may assume they do work; they do not.
|
||||
- **`IsAdd` is not stored in the view model**: It is passed only to `Validate(...)` and `Save(...)`. If the view model is reused across multiple add/edit operations, `IsAdd` must be tracked externally (e.g., via `parameter` or `model.IsAdd`).
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,112 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/HardwareListModule.cs
|
||||
generated_at: "2026-04-16T04:36:26.091510+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "253455657d30760d"
|
||||
---
|
||||
|
||||
# HardwareList
|
||||
|
||||
## Documentation: HardwareListModule
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
The `HardwareListModule` is a Prism-based modular component responsible for registering core views and view models related to hardware inventory management within the application’s UI framework. It integrates with Unity as the dependency injection container to expose singleton instances of interfaces such as `IHardwareListView`, `ISLICE6TreeView`, and `IHardwareListViewModel`, enabling modular UI composition and decoupled view-model binding. The module also contributes metadata (name, image, group, region) to the host application’s module discovery and presentation system via assembly-level attributes.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `HardwareListModule` class
|
||||
- **Namespace**: `HardwareList`
|
||||
- **Inherits**: `IModule` (Prism)
|
||||
- **Constructor**:
|
||||
```csharp
|
||||
public HardwareListModule(IUnityContainer unityContainer)
|
||||
```
|
||||
Injects the Unity container for later type registration.
|
||||
- **`Initialize()`**:
|
||||
```csharp
|
||||
public void Initialize()
|
||||
```
|
||||
Registers the following view and view model types as *transient* (note: despite the comment, Unity’s `RegisterType<TInterface, TImplementation>()` defaults to transient unless `ContainerControlledLifetimeManager` is specified):
|
||||
- `IHardwareListView` → `HardwareListView`
|
||||
- `ISLICE6TreeView` → `SLICE6TreeView`
|
||||
- `IHardwareListOverdueView` → `HardwareListOverdueView`
|
||||
- `IHardwareListSelectView` → `HardwareListSelectView`
|
||||
- `IHardwareListViewModel` → `HardwareListViewModel`
|
||||
- `IHardwareListReplaceView` → `HardwareListReplaceView`
|
||||
|
||||
- **`OnInitialized(IContainerProvider containerProvider)`**:
|
||||
```csharp
|
||||
public void OnInitialized(IContainerProvider containerProvider)
|
||||
```
|
||||
Empty implementation; no post-initialization logic.
|
||||
|
||||
- **`RegisterTypes(IContainerRegistry containerRegistry)`**:
|
||||
```csharp
|
||||
public void RegisterTypes(IContainerRegistry containerRegistry)
|
||||
```
|
||||
Delegates to `Initialize()`, which uses the injected `IUnityContainer` (not `containerRegistry`). *Note: This is likely a bug or legacy pattern—`containerRegistry` is unused.*
|
||||
|
||||
#### Assembly-level attributes
|
||||
|
||||
- **`HardwareListModuleNameAttribute`**
|
||||
- **Usage**: `[assembly: HardwareListModuleName]`
|
||||
- **Purpose**: Exposes the module’s assembly name (`AssemblyNames.HardwareList.ToString()`) for runtime identification.
|
||||
- **Key properties**:
|
||||
- `AssemblyName`: Returns `"HardwareList"` (via `AssemblyNames.HardwareList`).
|
||||
- `GetAttributeType()`: Returns `typeof(TextAttribute)`.
|
||||
|
||||
- **`HardwareListModuleImageAttribute`**
|
||||
- **Usage**: `[assembly: HardwareListModuleImageAttribute]`
|
||||
- **Purpose**: Supplies UI metadata (image, group, region) for display on the main screen’s module summary.
|
||||
- **Key properties**:
|
||||
- `AssemblyImage`: Loads image via `AssemblyInfo.GetImage("HardwareList")`.
|
||||
- `AssemblyGroup`: Returns `"Prepare"` (via `eAssemblyGroups.Prepare`).
|
||||
- `AssemblyRegion`: Returns `eAssemblyRegion.HardwareListRegion`.
|
||||
- `AssemblyName`: Returns `"HardwareList"`.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- **Module registration order**: Views/view models are registered during `Initialize()`; no guarantees about registration order relative to other modules (depends on Prism’s module loading sequence).
|
||||
- **Lifetime management**: All registrations use Unity’s default transient lifetime (despite the comment claiming "singleton"). No singleton behavior is enforced.
|
||||
- **Attribute constraints**:
|
||||
- `HardwareListModuleNameAttribute` and `HardwareListModuleImageAttribute` are assembly-level, non-repeatable (`AllowMultiple = false`).
|
||||
- `AssemblyRegion` must be `eAssemblyRegion.HardwareListRegion`.
|
||||
- `AssemblyGroup` must be `eAssemblyGroups.Prepare`.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
#### Dependencies *of* this module:
|
||||
- **Prism.Modularity**: For `IModule` interface.
|
||||
- **Unity**: For `IUnityContainer` and `IContainerRegistry` (though `RegisterTypes` uses Unity, not the Prism container registry).
|
||||
- **DTS.Common** and **DTS.Common.Interface**: Specifically:
|
||||
- `AssemblyNames.HardwareList` (enum)
|
||||
- `AssemblyInfo.GetImage()`
|
||||
- `eAssemblyGroups` and `eAssemblyRegion` enums
|
||||
- **System.Windows.Media.Imaging**: For `BitmapImage` in `HardwareListModuleImageAttribute`.
|
||||
|
||||
#### Dependencies *on* this module:
|
||||
- Host application likely depends on `HardwareListModule` to resolve hardware-related views (e.g., `IHardwareListView`) via DI.
|
||||
- Other modules may depend on interfaces like `ISLICE6TreeView` or `IHardwareListViewModel` for composition.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **`RegisterTypes` ignores `containerRegistry`**: The `RegisterTypes` method calls `Initialize()`, which uses the pre-injected `_unityContainer`. This contradicts Prism’s recommended pattern (where `RegisterTypes` should use `containerRegistry`) and may cause issues if the module is loaded in a Prism container that does not share Unity’s container instance.
|
||||
- **Misleading comment**: The `Initialize()` method’s comment claims registrations are "singleton", but Unity’s `RegisterType<TInterface, TImplementation>()` without a lifetime manager is transient.
|
||||
- **Attribute duplication**: Both `HardwareListModuleNameAttribute` and `HardwareListModuleImageAttribute` define `AssemblyName` identically, but only `HardwareListModuleImageAttribute` provides UI-relevant metadata.
|
||||
- **No error handling**: `AssemblyInfo.GetImage()` may fail (e.g., missing image resource), but no fallback or logging is present in the attributes.
|
||||
- **Unused `OnInitialized`**: The `OnInitialized` method is empty and unused—potential dead code.
|
||||
- **Namespace `HardwareList`**: The namespace matches the module name, which may cause confusion with the `HardwareList` folder path or other similarly named components.
|
||||
|
||||
None identified from source alone beyond the above.
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/Converters/FirstUseDateConverter.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/Converters/StandInFieldConverter.cs
|
||||
generated_at: "2026-04-16T04:37:34.782938+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "aee017cd34357419"
|
||||
---
|
||||
|
||||
# Converters
|
||||
|
||||
## Documentation: `HardwareList.Converters` Module
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
|
||||
This module provides WPF value converters for formatting and conditional display of hardware-related properties in UI-bound data grids or forms. Specifically, `FirstUseDateConverter` and `StandInFieldConverter` translate raw model data into user-friendly string representations (e.g., `"N/A"`, `"---"`, or actual `DateTime` values), handling edge cases such as missing, invalid, or inapplicable data based on hardware state (e.g., `StandIn` flag). These converters enable consistent, declarative UI formatting without cluttering view models with presentation logic.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
#### `FirstUseDateConverter`
|
||||
*Namespace:* `HardwareList.Converters`
|
||||
*Implements:* `IValueConverter`
|
||||
|
||||
- **`Convert(object value, Type targetType, object parameter, CultureInfo culture)`**
|
||||
- **Behavior:**
|
||||
- If `value` is not a `HardareList.Model.HardwareModel`, returns `Strings.Table_NA`.
|
||||
- If `model.IsFirstUseValid` is `false`, returns `Strings.NotApplicable`.
|
||||
- If `model.FirstUseDate` is non-null, returns `model.FirstUseDate` (as `DateTime?`).
|
||||
- Otherwise, returns `Strings.Table_NA`.
|
||||
- **Return type:** `object` (typically `string` or `DateTime?`).
|
||||
|
||||
- **`ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)`**
|
||||
- **Behavior:**
|
||||
- If `value` is a `DateTime`, returns it.
|
||||
- Otherwise, returns `Strings.Table_NA`.
|
||||
- **Note:** This is a minimal reverse converter; it does not validate or parse strings.
|
||||
- **Return type:** `object`.
|
||||
|
||||
---
|
||||
|
||||
#### `StandInFieldConverter`
|
||||
*Namespace:* `HardwareList.Converters`
|
||||
*Implements:* `IValueConverter`
|
||||
|
||||
- **`Convert(object value, Type targetType, object parameter, CultureInfo culture)`**
|
||||
- **Behavior:**
|
||||
- If `value` is not a `HardareList.Model.HardwareModel`, returns `Strings.Table_NA`.
|
||||
- If `model.Hardware` does not implement `IISOHardware`, returns `string.Empty`.
|
||||
- If `isoHW.StandIn` is `true`, returns `Strings.Table_NA`.
|
||||
- If `parameter` is a `string` matching `"CalDueDate"`, `"CalDate"`, or `"Firmware"`, returns the corresponding property (`model.CalDueDate`, `model.CalDate`, or `model.Firmware`).
|
||||
- Otherwise, returns `Strings.Table_NA`.
|
||||
- **Return type:** `object` (typically `string`, `DateTime?`, or `object` depending on the requested field).
|
||||
|
||||
- **`ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)`**
|
||||
- **Behavior:**
|
||||
- If `value` is a `DateTime`, returns it.
|
||||
- Otherwise, returns `Strings.Table_NA`.
|
||||
- **Return type:** `object`.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- **Type Safety:** Both converters expect the input `value` to be a `HardareList.Model.HardwareModel`. Failure to meet this results in fallback to `Strings.Table_NA`.
|
||||
- **Null Handling:**
|
||||
- `FirstUseDateConverter` treats `null` `FirstUseDate` as `"---"` (`Strings.Table_NA`), distinct from `IsFirstUseValid == false` which yields `"N/A"` (`Strings.NotApplicable`).
|
||||
- `StandInFieldConverter` short-circuits to `Strings.Table_NA` if `isoHW.StandIn` is `true`, regardless of the requested field.
|
||||
- **Parameter Dependency (StandInFieldConverter only):**
|
||||
- The converter’s output depends critically on the `parameter` being a `string` matching one of the three known keys (`"CalDueDate"`, `"CalDate"`, `"Firmware"`). Any other parameter yields `Strings.Table_NA`.
|
||||
- **No Validation on ConvertBack:** Both converters perform no validation or parsing in `ConvertBack`; they only pass through `DateTime` values or return `Strings.Table_NA`.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
- **Internal Dependencies (from source):**
|
||||
- `HardareList.Model.HardwareModel` (note: likely typo in namespace `HardareList` vs. `HardwareList`).
|
||||
- `DTS.Common.Strings` (provides `Strings.Table_NA`, `Strings.NotApplicable`).
|
||||
- `DTS.Common.Interface.DASFactory.Diagnostics.IISOHardware` (used in `StandInFieldConverter`).
|
||||
- `System.Windows.Data.IValueConverter` (WPF base interface).
|
||||
|
||||
- **External Dependencies:**
|
||||
- WPF framework (for `IValueConverter` usage in XAML).
|
||||
- `DTS.Common` assembly (contains `Strings` and `IISOHardware`).
|
||||
|
||||
- **Depended Upon By:**
|
||||
- UI layers (XAML bindings) referencing these converters in `DataGrid` columns or `TextBlock` bindings for hardware properties.
|
||||
- No direct code dependencies inferred—converters are consumed via XAML markup extension or resource references.
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **Typo in Namespace:** The model type is referenced as `HardareList.Model.HardwareModel` (missing 'w' in "Hardware"), which may cause runtime binding failures if the actual namespace is `HardwareList`.
|
||||
- **Ambiguous `parameter` Usage:** `StandInFieldConverter` relies on string literals for field selection (`"CalDueDate"`, etc.). Typos or case mismatches in XAML parameter values will silently fall back to `Strings.Table_NA`.
|
||||
- **Inconsistent `ConvertBack` Behavior:** Both converters return `Strings.Table_NA` for non-`DateTime` inputs in `ConvertBack`, which may be misleading if the UI expects a `null` or `DateTime?` result (e.g., for nullable fields like `CalDueDate`).
|
||||
- **No Handling for Invalid `IISOHardware` Cast:** In `StandInFieldConverter`, if `model.Hardware` is non-null but not `IISOHardware`, the converter returns `string.Empty`—a subtle distinction from `Strings.Table_NA` (`"---"`), which could cause visual inconsistency.
|
||||
- **Missing Documentation for `Strings` Values:** While `Strings.Table_NA` and `Strings.NotApplicable` are used, their exact string values (e.g., `"---"` vs `"N/A"`) are not visible in this source and must be verified in `DTS.Common.Strings`.
|
||||
|
||||
*None identified beyond the above.*
|
||||
@@ -0,0 +1,270 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/Model/HardwareChannelAssignment.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/Model/SLICE6TreeNode.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/Model/Hardware.cs
|
||||
generated_at: "2026-04-16T04:38:28.250792+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "e010e06b613fee2c"
|
||||
---
|
||||
|
||||
# HardwareList.Model Module Documentation
|
||||
|
||||
## 1. Purpose
|
||||
This module provides data models and persistence logic for representing and managing hardware devices (DAS units) in the DataPRO diagnostics system. It defines core entities (`HardwareChannelAssignment`, `SLICE6TreeNode`, `HardwareModel`) that model hardware topology, channel assignments, and device metadata. The module enables querying device hierarchies (e.g., SLICE6DB parent-child relationships), persisting association changes to the database, and exposing hardware properties for UI binding (via `INotifyPropertyChanged`). It serves as the data layer for the Hardware List view, supporting configuration, sorting, filtering, and calibration tracking.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `HardwareChannelAssignment`
|
||||
- **`HardwareChannelAssignment(string channelNumber, string sensor, string name)`**
|
||||
Constructor. Initializes immutable properties with provided values. Represents a mapping between a hardware channel, its connected sensor type, and a user-defined name.
|
||||
|
||||
- **`string ChannelNumber { get; }`**
|
||||
Channel identifier (e.g., "CH1", "A0").
|
||||
|
||||
- **`string Sensor { get; }`**
|
||||
Type of sensor connected to the channel.
|
||||
|
||||
- **`string Name { get; }`**
|
||||
User-assigned name for the channel.
|
||||
|
||||
---
|
||||
|
||||
### `SLICE6TreeNode`
|
||||
- **`SLICE6TreeNode(int dasId, string serialNumber, int port, int number, int positionOnChain)`**
|
||||
Constructor. Initializes properties for a SLICE6 device node in a tree structure.
|
||||
|
||||
- **`int DASId { get; set; }`**
|
||||
Primary key ID from the DAS database table.
|
||||
|
||||
- **`string SerialNumber { get; set; }`**
|
||||
Device serial number.
|
||||
|
||||
- **`int Port { get; set; }`**
|
||||
Physical port number on the S6DB (distributor) to which the device is connected.
|
||||
|
||||
- **`string PortString { get; }`**
|
||||
Readable string representation of `Port`; returns `"---"` if `Port < 0`.
|
||||
|
||||
- **`int Number { get; set; }`**
|
||||
Order of the device on the S6DB (i.e., its position index among siblings).
|
||||
|
||||
- **`int PositionOnChain { get; set; }`**
|
||||
Position of the device within its daisy-chain on a given port.
|
||||
|
||||
- **`string PositionOnChainString { get; }`**
|
||||
Readable string representation of `PositionOnChain`; returns `"---"` if `PositionOnChain < 0`.
|
||||
|
||||
- **`static ISLICE6TreeNode[] GetAvailableTreeNodes(string serialNumberParent)`**
|
||||
Queries the database for all SLICE6 devices *not* associated with `serialNumberParent`. Returns an array of `ISLICE6TreeNode` instances sorted by `SerialNumber`. Returns empty array if `serialNumberParent` is null/empty.
|
||||
|
||||
- **`static ISLICE6TreeNode[] GetTreeNodes(string serialNumberParent)`**
|
||||
Queries the database for all SLICE6 devices *associated* with `serialNumberParent`. Returns an array of `ISLICE6TreeNode` instances sorted by `Number` (i.e., `PositionOnDistributor`). Returns empty array if `serialNumberParent` is null/empty.
|
||||
|
||||
- **`static void SwapNodes(string serialNumberA, string serialNumberB)`**
|
||||
Swaps all child devices between two SLICE6DB units (`serialNumberA` and `serialNumberB`) in the database. *Note: There is a bug in the implementation—both `listA` and `listB` are associated to `serialNumberB` in the second `Associate` call, not `serialNumberA` and `serialNumberB` respectively.*
|
||||
|
||||
- **`static void SaveAssociations(string serialNumber, ISLICE6TreeNode[] attachedSLICE6)`**
|
||||
Commits the current association state of SLICE6 devices to a parent SLICE6DB (`serialNumber`). First clears all existing associations for `serialNumber`, then updates each device in `attachedSLICE6` with its new `ParentDAS`, `PositionOnDistributor`, `PositionOnChain`, and `Port`.
|
||||
|
||||
---
|
||||
|
||||
### `HardwareModel`
|
||||
- **`HardwareModel(IISOHardware d, ...)`**
|
||||
Constructor. Populates properties from an `IISOHardware` instance and calculates derived values (e.g., `CalDueDate`, `ChannelCount`). Requires calibration period parameters per hardware type.
|
||||
|
||||
- **`int DASId { get; set; }`**
|
||||
Database ID of the device.
|
||||
|
||||
- **`bool Disabled { get; set; }`**
|
||||
Whether the device is disabled.
|
||||
|
||||
- **`string SerialNumber { get; set; }`**
|
||||
Device serial number.
|
||||
|
||||
- **`string HardwareType { get; set; }`**
|
||||
Localized string description of the hardware type (e.g., `"SLICE6_BASE"`).
|
||||
|
||||
- **`string ChannelCount { get; set; }`**
|
||||
Human-readable string listing channel types and counts (e.g., `"8 Analog, 2 Digital In"`).
|
||||
|
||||
- **`bool HasIncludedChildren { get; set; }`**
|
||||
Indicates if this device has child devices marked as `Included`.
|
||||
|
||||
- **`string Firmware { get; set; }`**
|
||||
Firmware version string.
|
||||
|
||||
- **`double? MaxSampleRate { get; set; }`**
|
||||
Maximum supported sample rate (Hz); `null` if unknown or not applicable.
|
||||
|
||||
- **`double TestSampleRate { get; set; }`**
|
||||
Current test/sample rate selected for the device.
|
||||
|
||||
- **`double TestAAFilterRateHz { get; set; }`**
|
||||
Anti-aliasing filter rate (Hz) corresponding to `TestSampleRate`.
|
||||
|
||||
- **`DateTime? CalDate { get; set; }`**
|
||||
Last calibration date.
|
||||
|
||||
- **`DateTime? CalDueDate { get; set; }`**
|
||||
Calculated calibration due date based on `CalDate` and hardware-specific period.
|
||||
|
||||
- **`string[] AvailableSampleRates { get; set; }`**
|
||||
Array of available sample rate strings (e.g., `["1000", "2000"]`).
|
||||
|
||||
- **`string SelectedSampleRateItem { get; set; }`**
|
||||
Currently selected sample rate string.
|
||||
|
||||
- **`int SelectedSampleRateIndex { get; set; }`**
|
||||
Index of the current sample rate in `_availableSampleRates`. Setter updates `TestSampleRate` and `TestAAFilterRateHz`.
|
||||
|
||||
- **`object Hardware { get; set; }`**
|
||||
Backing `IISOHardware` instance.
|
||||
|
||||
- **`int AnalogChannels { get; set; }`**
|
||||
Number of analog input channels.
|
||||
|
||||
- **`int SquibChannels { get; set; }`**
|
||||
Number of squib (explosive device) channels.
|
||||
|
||||
- **`int DigitalInChannels { get; set; }`**, **`int DigitalOutChannels { get; set; }`**, **`int UartChannels { get; set; }`**, **`int StreamOutChannels { get; set; }`**, **`int StreamInChannels { get; set; }`**, **`int CanChannels { get; set; }`**
|
||||
Channel counts for respective interface types.
|
||||
|
||||
- **`string IPAddress { get; set; }`**
|
||||
IP address or `"USB"` if connected via USB.
|
||||
|
||||
- **`bool Included { get; set; }`**
|
||||
Whether the device is included in the current configuration.
|
||||
|
||||
- **`double DSPStreamingFilter { get; set; }`**
|
||||
DSP streaming filter value.
|
||||
|
||||
- **`DTS.Common.ClockSyncProfile MasterProfile { get; set; }`**, **`DTS.Common.ClockSyncProfile SlaveProfile { get; set; }`**
|
||||
Clock synchronization profiles (master/slave).
|
||||
|
||||
- **`bool IsClockMaster { get; set; }`**
|
||||
Whether the device is configured as a clock master. Only valid if `IsClockedDAS` is true.
|
||||
|
||||
- **`bool IsClockedDAS { get; }`**
|
||||
Returns `true` if the device type supports clocking (e.g., SLICE6, S6A_EthernetRecorder, TSR_AIR).
|
||||
|
||||
- **`byte PTPDomainID { get; set; }`**
|
||||
PTP domain ID for precision time protocol.
|
||||
|
||||
- **`bool IsPTPSync { get; }`**
|
||||
Returns `true` if PTP synchronization is active (E2E profile in use).
|
||||
|
||||
- **`bool MixedRates { get; set; }`**
|
||||
Whether the device is part of a mixed-sample-rate configuration.
|
||||
|
||||
- **`bool IsDistributor { get; }`**
|
||||
Returns `true` if the device is a distributor (e.g., SLICE6DB, SLICE_Distributor).
|
||||
|
||||
- **`bool IsBattery { get; }`**
|
||||
Returns `true` if the device is a PowerPro.
|
||||
|
||||
- **`bool IsTSRAIR { get; }`**
|
||||
Returns `true` if the device is a TSR_AIR or embedded sensor type.
|
||||
|
||||
- **`bool IncludedAndNotMixedRatesAndCompactOrNotDistributor { get; }`**, **`bool IncludedAndMixedRatesAndCompact { get; }`**
|
||||
Derived UI flags for conditional rendering.
|
||||
|
||||
- **`string ParentDAS { get; set; }`**
|
||||
Serial number of the parent device (distributor).
|
||||
|
||||
- **`int PositionOnChain { get; set; }`**, **`int PositionOnDistributor { get; set; }`**, **`int Port { get; set; }`**
|
||||
Position metadata for hierarchical placement.
|
||||
|
||||
- **`bool HasTreeView { get; set; }`**
|
||||
Indicates if a tree view should be shown for this device (e.g., for SLICE6DB).
|
||||
|
||||
- **`string SerialNumberDisplay { get; }`**
|
||||
Display name: `SerialNumber` unless `StandIn` is true, in which case it returns the hardware type description.
|
||||
|
||||
- **`static IHardware[] GetAvailableSLICE6DB(string serialNumber)`**
|
||||
Returns all SLICE6DB devices (including `SLICE6DB_InDummy`) not currently assigned to any parent, excluding `serialNumber`.
|
||||
|
||||
- **`void DetermineChannelCount(bool showCompact, IHardware[] allHardware)`**
|
||||
Updates `ChannelCount` and `MaxSampleRate` based on device type and child devices. For distributors, calculates min sample rate among children if `showCompact` is true.
|
||||
|
||||
- **`void SetIncluded(bool bIncluded)`**, **`void SetMixedRates(bool mixedRates)`**
|
||||
Updates state and fires property change notifications.
|
||||
|
||||
- **`bool Filter(string term)`**
|
||||
Returns `true` if `SerialNumber`, `Firmware`, or `HardwareType` contains `term` (case-insensitive).
|
||||
|
||||
- **`class HardwareComparer : IComparer<IHardware>`**
|
||||
Implements sorting for `IHardware` objects. Supports sorting by `HardwareListTags` (e.g., `SerialNumber`, `CalDate`, `FirstUseDate`). Handles nulls and `double?/DateTime?` comparisons. `FirstUseDate` sorts nulls last when valid.
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`SLICE6TreeNode`**
|
||||
- `Port`, `Number`, and `PositionOnChain` must be non-negative integers for valid hardware placements. Negative values are represented as `"---"` in UI via `PortString`/`PositionOnChainString`.
|
||||
- `GetAvailableTreeNodes` and `GetTreeNodes` only query devices with `Type = SLICE6_Base` and `Position ≠ 'Prototype'` (for `GetAvailableTreeNodes`).
|
||||
- `SwapNodes` assumes all child devices of both parents are retrieved in one query and re-associated. *Bug: Both lists are associated to `serialNumberB`.*
|
||||
|
||||
- **`HardwareModel`**
|
||||
- `CalDueDate` is derived from `CalDate` (or `FirstUseDate` if `IsFirstUseValid`) plus a hardware-specific calibration period.
|
||||
- `MaxSampleRate` is `null` if `d.MaxSampleRate` is `<= 0` or `uint.MaxValue`.
|
||||
- `IsClockedDAS` is determined by a fixed set of `HardwareTypes`.
|
||||
- `Included` and `MixedRates` flags affect derived properties (`IncludedAndNotMixedRatesAndCompactOrNotDistributor`, `IncludedAndMixedRatesAndCompact`).
|
||||
- `ChannelCount` for distributors is `"N/A"` if `showCompact` is false or no children exist.
|
||||
|
||||
- **General**
|
||||
- All database operations use `DTS.Common.Storage.DbOperations.GetSQLCommand()` and explicitly dispose connections in `finally` blocks.
|
||||
- `HardwareModel` instances are constructed with a non-null `HardwareListViewModel` (`_vm`) reference for event callbacks.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **`DTS.Common.*`**
|
||||
- `DTS.Common.Base.BasePropertyChanged` (base class for `SLICE6TreeNode`)
|
||||
- `DTS.Common.Storage.DbOperations` (database access)
|
||||
- `DTS.Common.Enums.Hardware.HardwareTypes` (device type enumeration)
|
||||
- `DTS.Common.Interface.DASFactory.Diagnostics.IISOHardware`, `IHardware` (hardware abstraction interfaces)
|
||||
- `DTS.Common.Converters.EnumDescriptionTypeConverter` (localized enum descriptions)
|
||||
- `DTS.Common.ClockSyncProfile` (clock sync profiles)
|
||||
|
||||
- **`HardwareList.Resources.StringResources`**
|
||||
- Used for localized strings (e.g., `"Analog"`, `"USB"`, `"N/A"`).
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- **`HardwareList.HardwareListViewModel`**
|
||||
- Passed into `HardwareModel` constructor; used for event callbacks (`FireSampleRate`, `FireClockMaster`, etc.).
|
||||
- **UI Layer**
|
||||
- `HardwareModel` properties (e.g., `Included`, `CalDueDate`, `ChannelCount`) are bound to views.
|
||||
- `SLICE6TreeNode` is used to populate tree views for SLICE6DB hierarchies.
|
||||
- **HardwareList Module**
|
||||
- `HardwareList.Model` is the core data model for the `HardwareList` module.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`SLICE6TreeNode.SwapNodes` Bug**:
|
||||
The `Associate` method is called twice—once for `listA` with `serialNumberB`, and again for `listB` *also* with `serialNumberB`. This means devices originally under `serialNumberB` are incorrectly moved to `serialNumberB` (no-op), and devices under `serialNumberA` are moved to `serialNumberB`, but the reverse move does not occur. The intended behavior is likely `Associate(serialNumberB, listA)` and `Associate(serialNumberA, listB)`.
|
||||
|
||||
- **`HardwareModel.CalDueDate` Calculation**:
|
||||
Uses `FirstUseDate` only if `IsFirstUseValid` is true. If `FirstUseDate` is `null` and `IsFirstUseValid` is true, it defaults to `DateTime.Today`. This may cause unexpected recalculations if `FirstUseDate` is set later.
|
||||
|
||||
- **`HardwareModel.TestSampleRate` Setter Side Effect**:
|
||||
Setting `TestSampleRate` triggers `OnPropertyChanged("SelectedSampleRateIndex")`, but the getter for `SelectedSampleRateIndex` re-computes `SelectedSampleRateItem` and calls `_vm.FireSampleRate`. This could cause redundant UI updates if `TestSampleRate` is set multiple times.
|
||||
|
||||
- **`HardwareModel.DetermineChannelCount` for Distributors**:
|
||||
`MaxSampleRate` is recalculated as the *minimum* sample rate of child devices. If children have no sample rate (`null`), `ChannelCount` becomes `"N/A"` and `MaxSampleRate` is set to `null`. This may mask missing configuration.
|
||||
|
||||
- **`HardwareModel.Filter` Case Sensitivity**:
|
||||
Filtering is case-insensitive (`term.ToLower()`), but `SerialNumberDisplay` uses `isoHW.StandIn` logic, which may cause display mismatches if `StandIn` is toggled dynamically.
|
||||
|
||||
- **`HardwareModel.Hardware` is `object`**:
|
||||
The `Hardware` property is typed as `object`, requiring casting to `IISOHardware` for type-specific checks (e.g., `IsClockedDAS`, `IsDistributor`). This risks runtime errors if the underlying type is not `IISOHardware`.
|
||||
|
||||
- **`SLICE6TreeNode` SQL Injection Risk**:
|
||||
`GetAvailableTreeNodes` uses string interpolation for `HardwareTypes.SLICE6_Base` in the `WHERE` clause (`[(int)HardwareTypes.SLICE6_Base]`). While the enum value is fixed, this pattern is fragile and error-prone.
|
||||
|
||||
- **`HardwareModel` Constructor Side Effects**:
|
||||
The constructor calls `d.GetChannelsString(...)` and computes `CalDueDate` based on `d.DASTypeEnum`. If `Hardware` is `null` or `DASTypeEnum` is invalid, it throws `ArgumentOutOfRangeException`.
|
||||
|
||||
- **`HardwareComparer.NumericCompare` Logic**:
|
||||
For `double`/`DateTime`, `a > b` returns `-1` (descending order), but the method returns `1` for all other cases. This may cause inconsistent sorting if types are mixed (e.g., `double` vs `DateTime`).
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/Properties/Settings.Designer.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/Properties/AssemblyInfo.cs
|
||||
generated_at: "2026-04-16T04:37:43.934636+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "5208913b7b0145de"
|
||||
---
|
||||
|
||||
# Properties
|
||||
|
||||
## Documentation Page: HardwareList.Properties.Settings
|
||||
|
||||
### 1. Purpose
|
||||
This module defines the application settings infrastructure for the `HardwareList` module within the DataPRO system. Specifically, it provides a strongly-typed, thread-safe singleton accessor (`Settings.Default`) for reading application-level configuration values stored in the standard .NET configuration system (e.g., `app.config` or `user.config`). It serves as the runtime interface to persisted settings but contains no user-defined settings properties itself—only the infrastructure class required to expose them.
|
||||
|
||||
### 2. Public Interface
|
||||
The module exposes a single internal sealed class with the following public members:
|
||||
|
||||
- **`Settings.Default` (static property)**
|
||||
- **Type**: `HardwareList.Properties.Settings`
|
||||
- **Signature**: `public static Settings Default { get; }`
|
||||
- **Behavior**: Returns the singleton instance of the `Settings` class. The instance is created via `ApplicationSettingsBase.Synchronized(...)`, ensuring thread-safe access to settings values. This is the *only* public entry point to the settings system in this file.
|
||||
|
||||
> **Note**: No user-defined settings properties (e.g., `string SomeSetting { get; set; }`) are declared in this file. Their absence indicates that either:
|
||||
> - Settings are defined elsewhere (e.g., in `Settings.settings` designer file or `app.config`), or
|
||||
> - This module is intentionally minimal and relies on external configuration sources.
|
||||
|
||||
### 3. Invariants
|
||||
- The `defaultInstance` is lazily initialized on first access to `Settings.Default` and remains constant thereafter.
|
||||
- Thread safety is guaranteed via `ApplicationSettingsBase.Synchronized(...)`, which wraps the instance in a `SyncRoot`-based synchronization mechanism.
|
||||
- The class is `sealed` and `internal`, preventing external inheritance or instantiation.
|
||||
- No validation or transformation logic is present in this file; settings values are assumed to be validated/typed by the underlying .NET configuration system at runtime.
|
||||
|
||||
### 4. Dependencies
|
||||
- **Depends on**:
|
||||
- `System.Configuration` (specifically `System.Configuration.ApplicationSettingsBase`)
|
||||
- `System.Runtime.CompilerServices.CompilerGeneratedAttribute`
|
||||
- `System.CodeDom.Compiler.GeneratedCodeAttribute`
|
||||
- **Depended on by**:
|
||||
- Other modules in the `HardwareList` assembly (e.g., code that reads settings via `Settings.Default.SomeProperty`, though *no such usage is visible in the provided source*).
|
||||
- The .NET configuration system at runtime (via `app.config`/`user.config`), which must contain matching `<setting>` entries for any properties defined in `Settings.settings`.
|
||||
|
||||
### 5. Gotchas
|
||||
- **Auto-generated file**: This file is auto-generated by the Visual Studio Settings Designer (`SettingsSingleFileGenerator`). Manual edits will be overwritten on regeneration.
|
||||
- **No settings defined here**: Despite the class name `Settings`, this file contains *no property declarations*. Any settings used at runtime must be defined in the corresponding `Settings.settings` file (not provided) or in `app.config`.
|
||||
- **Thread-safety caveat**: While `Synchronized()` ensures thread-safe *access*, it does *not* guarantee atomicity for compound operations (e.g., read-modify-write).
|
||||
- **Versioning ambiguity**: Assembly version is fixed at `1.0.0.0` (with `AssemblyFileVersion` identical), which may complicate deployment or rollback if settings schema evolves.
|
||||
- **COM visibility disabled**: `ComVisible(false)` means this module is not exposed to COM clients—intentional for a .NET-only module.
|
||||
@@ -0,0 +1,92 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/Resources/TranslateExtension.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/Resources/StringResources.Designer.cs
|
||||
generated_at: "2026-04-16T04:37:17.643250+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "41df486c1d53cd9a"
|
||||
---
|
||||
|
||||
# Resources
|
||||
|
||||
## Documentation: `TranslateExtension` Markup Extension
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
|
||||
The `TranslateExtension` class is a WPF `MarkupExtension` used to enable localized string binding in XAML. It resolves a given string key at runtime by querying the `StringResources` strongly-typed resource class (which wraps the application’s `.resx`-based resources), returning the corresponding localized value. If the key is missing or empty, it returns a consistent fallback string (`#stringnotfound#` or `#stringnotfound# <key>`), allowing UI elements to gracefully handle missing translations. This extension is essential for internationalization of the HardwareList module’s UI.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `TranslateExtension` class
|
||||
|
||||
- **Namespace**: `HardwareList`
|
||||
- **Base Type**: `System.Windows.Markup.MarkupExtension`
|
||||
|
||||
##### Constructor
|
||||
|
||||
```csharp
|
||||
public TranslateExtension(string key)
|
||||
```
|
||||
|
||||
- **Parameters**:
|
||||
- `key` (`string`): The resource key used to look up a localized string in `StringResources`.
|
||||
- **Behavior**: Stores the key for later resolution during `ProvideValue`.
|
||||
|
||||
##### Override
|
||||
|
||||
```csharp
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
```
|
||||
|
||||
- **Parameters**:
|
||||
- `serviceProvider` (`IServiceProvider`): WPF service provider (unused in current implementation).
|
||||
- **Returns**:
|
||||
- `string`: The localized string corresponding to `_key`, or a fallback string if the key is null/empty or not found.
|
||||
- **Behavior**:
|
||||
- If `_key` is `null` or empty → returns `"#stringnotfound#"`.
|
||||
- Otherwise, calls `StringResources.ResourceManager.GetString(_key)`.
|
||||
- If a matching resource exists → returns the string value.
|
||||
- If no match → returns `"#stringnotfound# " + _key`.
|
||||
|
||||
> **Note**: The `MarkupExtensionReturnType` attribute indicates the extension always returns a `string`.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- `_key` is immutable after construction (no setter or mutation).
|
||||
- `StringResources.ResourceManager.GetString(key)` is assumed to be thread-safe (as per .NET `ResourceManager` behavior).
|
||||
- The fallback string `#stringnotfound#` is **hardcoded** and must not be localized itself.
|
||||
- Empty or null keys are treated identically and return the base fallback string (no key suffix).
|
||||
- If a key exists in `StringResources.Designer.cs` but the underlying `.resx` file lacks the entry, `GetString` returns `null`, triggering the fallback.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
#### Dependencies *on* this module:
|
||||
- **WPF Framework**: Requires `System.Windows.Markup` and `System` (for `ResourceManager`, `IServiceProvider`).
|
||||
- **`HardwareList.Resources.StringResources`**: This module depends on the auto-generated `StringResources` class for resource lookup.
|
||||
- **XAML Parser**: Used via `MarkupExtension` mechanism in XAML (e.g., `{local:Translate KeyName}`).
|
||||
|
||||
#### Dependencies *of* this module:
|
||||
- None beyond standard .NET libraries (`System`, `System.Windows`).
|
||||
- `StringResources` is generated from `.resx` files (not visible here), but the module assumes its existence and structure.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **No caching of resolved values**: Each `ProvideValue` call re-queries `ResourceManager.GetString`, which is acceptable but could be optimized if performance becomes critical.
|
||||
- **Fallback format is not user-friendly**: The fallback `"#stringnotfound# <key>"` may appear in the UI if keys are missing—ensure translators or developers catch these during testing.
|
||||
- **Case sensitivity**: Resource keys are case-sensitive (e.g., `"Add"` ≠ `"add"`). A mismatch yields the fallback string.
|
||||
- **Culture handling**: Uses the current UI culture (`CultureInfo.CurrentUICulture`) implicitly via `ResourceManager.GetString`, unless `StringResources.Culture` is explicitly set (which is possible but not done here).
|
||||
- **No null-safety for `serviceProvider`**: While `serviceProvider` is unused, `ProvideValue` does not guard against null—though WPF guarantees non-null in normal usage.
|
||||
- **Auto-generated resource class**: `StringResources.Designer.cs` is auto-generated; manual edits will be overwritten. Ensure keys used in `TranslateExtension` exist in the `.resx` file.
|
||||
|
||||
> **None identified from source alone.**
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListOverdueView.xaml.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListReplaceView.xaml.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/View/SLICE6TreeView.xaml.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListSelectView.xaml.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListView.xaml.cs
|
||||
generated_at: "2026-04-16T04:38:01.309494+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "19f25015f9f12fa7"
|
||||
---
|
||||
|
||||
# View
|
||||
|
||||
### **Purpose**
|
||||
This module provides WPF view implementations for the hardware diagnostics hardware list feature, serving as the UI layer that binds to `IHardwareListViewModel` and related interfaces. It enables users to view, sort, filter, and manipulate hardware items—including overdue items, replaceable units, and SLICE6 associations—through a set of specialized views (`HardwareListView`, `HardwareListOverdueView`, `HardwareListReplaceView`, `HardwareListSelectView`, `SLICE6TreeView`). These views handle user interactions (e.g., column header clicks, button presses, tree node operations) and delegate business logic to the underlying view model, while also publishing `PageModifiedEvent` to signal state changes.
|
||||
|
||||
---
|
||||
|
||||
### **Public Interface**
|
||||
All classes implement interfaces in the `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` namespace (e.g., `IHardwareListView`, `IHardwareListOverdueView`). They expose no public methods beyond their constructors; all behavior is driven via event handlers wired in XAML. The interfaces they implement are assumed to define the contract for view-model binding, but the *actual* public surface is minimal and consists solely of:
|
||||
|
||||
| Class | Constructor | Notes |
|
||||
|-------|-------------|-------|
|
||||
| `HardwareListOverdueView()` | `public HardwareListOverdueView()` | Initializes component; handles `ListViewHeader_Click` for sorting overdue items. |
|
||||
| `HardwareListReplaceView()` | `public HardwareListReplaceView()` | Initializes component; handles `Replace_Click` to invoke `IHardwareListViewModel.Replace()`. |
|
||||
| `SLICE6TreeView()` | `public SLICE6TreeView()` | Initializes component; handles `Remove_Click`, `Add_Click`, and `Swap_Click` to manage SLICE6 associations and publish `PageModifiedEvent`. |
|
||||
| `HardwareListSelectView()` | `public HardwareListSelectView()` | Initializes component; provides `InitializeColumns(bool bSteamingTest)` to dynamically show/hide the `DSPStreamingColumn`. Also handles sorting, filtering, inclusion, and chain sample rate mixed button clicks. |
|
||||
| `HardwareListView()` | `public HardwareListView()` | Initializes component; handles search, sorting, double-click (via `MouseDoubleClick`), and tree view popup invocation (`TreeviewButton_Click`). |
|
||||
|
||||
> **Note**: No public methods beyond constructors exist in the source. All functionality is exposed via private event handlers (`ListViewHeader_Click`, `Replace_Click`, etc.) bound in XAML.
|
||||
|
||||
---
|
||||
|
||||
### **Invariants**
|
||||
- **View Model Contract**: All views assume their `DataContext` implements a specific interface (`IHardwareListViewModel`, `ISLICE6TreeNode`, or `IHardware`) and that required properties (e.g., `SelectedSLICE6`, `SelectedSLICE6DB`, `ShowCompact`) are non-null when used. Null checks are performed before use, but no fallback behavior is defined.
|
||||
- **Event Publishing**: In `SLICE6TreeView`, after `Associate`, `UnAssociate`, or `Swap` operations, a `PageModifiedEvent` with status `Modified` is *always* published—regardless of whether the operation succeeded or the tree node was valid.
|
||||
- **Column Management**: In `HardwareListSelectView.InitializeColumns`, the `CalDateColumn` index is used as a reference point for inserting `DSPStreamingColumn`; if `CalDateColumn` is not found (index < 0), index `0` is used as fallback.
|
||||
- **Sorting Consistency**: All column header click handlers (`ListViewHeader_Click`, `GridViewColumnHeader_OnClick`, `GridViewColumnHeaderCheckBox_OnClick`) invoke `Sort(..., true)`, implying ascending sort order is hardcoded (or `true` indicates a toggle flag—source does not clarify).
|
||||
- **Popup State**: In `HardwareListView.TreeviewButton_Click`, the `SLICE6TreeViewPopup` is explicitly closed before reassigning its `Child` and reopening—ensuring only one instance is active at a time.
|
||||
|
||||
---
|
||||
|
||||
### **Dependencies**
|
||||
**External Dependencies (imports):**
|
||||
- `System.Windows.*` (WPF core: `Controls`, `Data`, `Media`, `Input`)
|
||||
- `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` — defines core interfaces: `IHardwareListOverdueView`, `IHardwareListReplaceView`, `ISLICE6TreeView`, `IHardwareListSelectView`, `IHardwareListView`, `IHardwareListViewModel`, `IHardware`, `ISLICE6TreeNode`.
|
||||
- `DTS.Common.Controls` — provides custom controls like `GridViewColumnHeaderSearchable`, `GridViewColumnHeaderSelectable`, `Popup` (`SLICE6TreeViewPopup`).
|
||||
- `DTS.Common.Utils` — utility methods: `Utils.FindChild<T>` (used in `HardwareListSelectView` and `HardwareListView` for tag resolution).
|
||||
- `Prism.Ioc`, `Prism.Events` — used in `SLICE6TreeView` to resolve `IEventAggregator` and publish `PageModifiedEvent`.
|
||||
|
||||
**Consumed by:**
|
||||
- The module’s view model layer (`IHardwareListViewModel` implementations) — binds to these views via `DataContext`.
|
||||
- Likely the main hardware list module shell (e.g., Prism module initialization) — instantiates and hosts these views.
|
||||
|
||||
---
|
||||
|
||||
### **Gotchas**
|
||||
- **Typo in `InitializeColumns` parameter**: The parameter is named `bSteamingTest`, likely intended to be `bStreamingTest` (note missing 'r'). This may cause confusion or mismatches in downstream code.
|
||||
- **Ambiguous sort flag**: All `Sort(..., true)` calls use a literal `true`. Without the interface definition or implementation, it is unclear whether this indicates ascending order, a toggle reset, or a secondary sort flag.
|
||||
- **Redundant null checks**: In `HardwareListSelectView` and `HardwareListView`, `sender` is cast to `Control` before checking `control.DataContext`. This is safe but verbose; could be simplified with pattern matching (e.g., `if (sender is Control control && control.DataContext is IHardwareListViewModel vm)`).
|
||||
- **EventAggregator resolution in SLICE6TreeView**: `ContainerLocator.Container.Resolve<IEventAggregator>()` is called *synchronously* on each `Add_Click`, `Remove_Click`, and `Swap_Click`. This is inefficient and violates Prism best practices (should be injected via constructor). No DI constructor is present, suggesting tight coupling to Prism’s static locator.
|
||||
- **Missing error handling**: All click handlers silently return on failed casts (e.g., `if (!(control.DataContext is IHardwareListViewModel vm)) { return; }`). No logging or user feedback occurs if expectations are violated.
|
||||
- **`GetCurrentIndex` logic**: In `HardwareListView`, `GetCurrentIndex` iterates over all items and uses `VisualTreeHelper.GetDescendantBounds` and `IsMouseOverTarget` to determine the clicked item. This is computationally expensive for large lists and may be fragile if item containers are virtualized or not yet generated.
|
||||
|
||||
> **None identified from source alone.** → *Not applicable; multiple gotchas found.*
|
||||
@@ -0,0 +1,280 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/ViewModel/HardwareListViewModel.cs
|
||||
generated_at: "2026-04-16T04:37:43.305054+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "529cbbf4accc9016"
|
||||
---
|
||||
|
||||
# ViewModel
|
||||
|
||||
**Documentation: HardwareListViewModel.cs**
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
|
||||
The `HardwareListViewModel` class serves as the central MVVM ViewModel for the hardware list UI module in the DASFactory diagnostics system. It manages the presentation and interaction logic for hardware inventory—including filtering, sorting, selection, calibration status tracking, sample rate configuration, and SLICE6/SLICE6DB association management. It aggregates raw hardware data from `DTS.Common.ISO.Hardware.GetAllDAS`, wraps it in `HardwareModel` instances, and exposes structured collections (`Hardware`, `OverdueHardware`, `AvailableHardware`, etc.) to views. It also coordinates inter-view communication via Prism’s `IEventAggregator`, handles user actions (e.g., editing, replacing, associating hardware), and enforces domain-specific rules such as parent–child DAS sample rate consistency and channel assignment tracking during hardware replacement.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
All methods and properties are `public` unless otherwise noted. The class implements `IHardwareListViewModel` (inferred from `: IHardwareListViewModel`).
|
||||
|
||||
#### **Constructors**
|
||||
- **`HardwareListViewModel(IHardwareListView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`**
|
||||
Initializes the ViewModel with required dependencies, sets up event subscriptions (`RaiseNotification`, `BusyIndicatorChangeNotification`), and initializes `SelectedHardwareItems` as an `ObservableCollection<IHardware>`.
|
||||
|
||||
#### **Public Methods**
|
||||
- **`void LoadTreeView(string serialNumber)`**
|
||||
Populates `SLICE6TreeNodes`, `AvailableSLICE6`, `SelectedSLICE6DB`, and `AvailableSLICE6DB` for the given SLICE6DB serial number using `SLICE6TreeNode.GetTreeNodes()` and `HardwareModel.GetAvailableSLICE6DB()`.
|
||||
|
||||
- **`void GetHardware(bool bIncludeModules, bool bIncludeOverdue, bool bIncludeBridges, int? testId, int? groupId)`**
|
||||
Loads and processes hardware from `DTS.Common.ISO.Hardware.GetAllDAS()`, constructs `HardwareModel` instances, aggregates channel counts for parent DAS with child modules, and filters based on overdue status and inclusion flags. Stores results in `_allHardware`, then calls `Filter()` and `Sort()`.
|
||||
|
||||
- **`void SetTestSampleRates(Dictionary<string, double> testSampleRates)`**
|
||||
Applies sample rates from `testSampleRates` to all hardware in `_allHardware`. If a rate is unavailable, uses the next highest available rate. Updates `TestSampleRate`, `SelectedSampleRateIndex`, and calls `SetDSPRate()` and `CheckForMixedDAS()`.
|
||||
|
||||
- **`void UpdateTestSampleRate(string childSerialNumber, double testSampleRate)`**
|
||||
Updates sample rate and AAF rate for a specific child hardware (by `SerialNumber`), then updates DSP filter rate.
|
||||
|
||||
- **`void SetTestAAFRates(Dictionary<string, float> testAAFRates)`**
|
||||
Applies AAF rates from `testAAFRates`. If missing for a hardware item, computes default via `GetAAFForHardware()` and logs a warning via `PageErrorEvent`.
|
||||
|
||||
- **`void UpdateTestAAFilterRate(string childSerialNumber, float testAAFilterRate)`**
|
||||
Updates AAF rate for a specific hardware item.
|
||||
|
||||
- **`void SetTestClockMasters(Dictionary<string, bool> testClockMasters)`**
|
||||
Sets `IsClockMaster` for hardware whose `SerialNumber` appears in the dictionary.
|
||||
|
||||
- **`void UpdateTestClockMaster(string childSerialNumber, bool testClockMaster)`**
|
||||
Sets `IsClockMaster` for a specific hardware item.
|
||||
|
||||
- **`void SetTestPTPDomainIDs(Dictionary<string, byte> testPTPDomainIDs)`**
|
||||
Sets `PTPDomainID` for hardware whose `SerialNumber` appears in the dictionary.
|
||||
|
||||
- **`void UpdateTestPTPDomainID(string childSerialNumber, byte ptpDomainId)`**
|
||||
Sets `PTPDomainID` for a specific hardware item.
|
||||
|
||||
- **`void CheckForMixedDAS(string nonParentSerialNumber, double testSampleRate)`**
|
||||
Ensures sample rate consistency between a child DAS and its parent. If siblings have differing rates, marks the parent as `MixedRates = true`; otherwise, aligns parent rate to child.
|
||||
|
||||
- **`void SetParentMixedRates(string parentDAS, bool mixedRates)`**
|
||||
Sets `MixedRates` property on the parent DAS.
|
||||
|
||||
- **`void SetHasIncludedChildren()`**
|
||||
Sets `HasIncludedChildren = true` for distributors that have at least one included child.
|
||||
|
||||
- **`bool AnyChildren(string distributorDAS)`**
|
||||
Returns `true` if any included hardware has `ParentDAS == distributorDAS`.
|
||||
|
||||
- **`void Filter(object tag, string term)`**
|
||||
Updates filter criteria for a specific field (`Fields` enum) and re-applies filtering.
|
||||
|
||||
- **`void Filter(string term)`**
|
||||
Applies `_currentSearchTerm` and field-specific filters to `_allHardware`, populating `Hardware` and `OverdueHardware`. Handles compact view logic (hides rack modules under certain conditions) and recalculates channel counts.
|
||||
|
||||
- **`void Sort(object o, bool bColumnClick)`**
|
||||
Sorts `Hardware` by field (`HardwareListTags`) and direction (toggle on repeated column click). Uses `HardwareComparer`.
|
||||
|
||||
- **`void SortOverdue(object o, bool bColumnClick)`**
|
||||
Sorts `OverdueHardware` similarly.
|
||||
|
||||
- **`void SetIncluded(string[] serialNumbers, bool included)`**
|
||||
Sets `Included` flag for hardware matching `serialNumbers` in the *filtered* `Hardware` list.
|
||||
|
||||
- **`void SetIncluded(int[] ids)`**
|
||||
Sets `Included = true` for hardware matching `DASId` in `_allHardware`.
|
||||
|
||||
- **`void IncludeChildren(IHardware hardware)`**
|
||||
Sets `Included` for all child modules (via `IsPseudoRackModule()`) of the given hardware to match its `Included` value.
|
||||
|
||||
- **`void RemoveMultipleButton(IHardware hardware)`**
|
||||
Clears sample rate display (`TestSampleRate = 0`) and `MixedRates` flag for the given hardware.
|
||||
|
||||
- **`void Unset()`**
|
||||
Resets all hardware collections, SLICE6 associations, and channel assignments; publishes `ListViewStatusEvent.Unloaded`.
|
||||
|
||||
- **`void ClearAllFilters()`**
|
||||
Clears `_filterByField`.
|
||||
|
||||
- **`void Cleanup()` / `Task CleanupAsync()` / `void Initialize()` / `Task InitializeAsync()` / `void Activated()`**
|
||||
No-op stubs (likely required by Prism interfaces).
|
||||
|
||||
- **`void SaveSLICE6Associations(string serialNumber)`**
|
||||
Commits SLICE6 associations to DB via `SLICE6TreeNode.SaveAssociations()`. If `_swappedHardware` is set, swaps nodes first.
|
||||
|
||||
- **`void Associate(ISLICE6TreeNode node)`**
|
||||
Adds a `SLICE6TreeNode` to `SLICE6TreeNodes`, assigns `Number`, `Port`, `PositionOnChain`, and removes from `AvailableSLICE6`.
|
||||
|
||||
- **`void Associate(IHardware node)`**
|
||||
Sets `_swappedHardware`, reloads tree view for `node.SerialNumber`, and updates `AvailableSLICE6`/`SLICE6TreeNodes`.
|
||||
|
||||
- **`void UnAssociate(ISLICE6TreeNode node)`**
|
||||
Removes `node` from `SLICE6TreeNodes`, renumbers remaining nodes, resets its metadata, and adds back to `AvailableSLICE6`.
|
||||
|
||||
- **`void Replace()`**
|
||||
Commits hardware replacement: sets `ReplacementHardware.Included = true`, publishes `HardwareReplaceEvent`, and clears `HardwareToReplace`/`ReplacementHardware`.
|
||||
|
||||
- **`IHardware[] GetSelectedItems()`**
|
||||
Returns `SelectedHardwareItems.ToArray()`.
|
||||
|
||||
- **`void SetCalPeriods(...)`**
|
||||
Sets all `*CalPeriod` properties (e.g., `G5CalPeriod`, `SLICE6_CalPeriod`) for use in `HardwareModel` construction.
|
||||
|
||||
#### **Public Properties**
|
||||
- **`IHardwareListView View`, `IHardwareListOverdueView OverdueView`, `IHardwareListSelectView SelectView`, `IHardwareListReplaceView ReplaceView`, `ISLICE6TreeView SLICE6TreeView`**
|
||||
View interfaces bound to this ViewModel.
|
||||
|
||||
- **`InteractionRequest<Notification> NotificationRequest`, `InteractionRequest<Confirmation> ConfirmationRequest`**
|
||||
Prism interaction triggers for modal dialogs.
|
||||
|
||||
- **`event PropertyChangedEventHandler PropertyChanged`**
|
||||
Standard `INotifyPropertyChanged` implementation.
|
||||
|
||||
- **`IHardware[] Hardware`**
|
||||
Filtered and sorted list of hardware for display.
|
||||
|
||||
- **`IHardware[] OverdueHardware`**
|
||||
Hardware with `CalDueDate <= DateTime.Today`.
|
||||
|
||||
- **`IHardware[] AvailableHardware`**
|
||||
Hardware suitable for replacement (excludes included items, matches `HardwareType`, respects rack size constraints).
|
||||
|
||||
- **`IHardware HardwareToReplace`, `IHardware ReplacementHardware`**
|
||||
Current hardware being replaced and its candidate replacement.
|
||||
|
||||
- **`Model.HardwareChannelAssignment[] AssignedChannels`**
|
||||
Channels assigned to `HardwareToReplace` (populated in `InitializeReplace()` and `PopulateAvailableHardware()`).
|
||||
|
||||
- **`ISLICE6TreeNode[] SLICE6TreeNodes`, `ISLICE6TreeNode[] AvailableSLICE6`**
|
||||
Associated and available SLICE6 units for a given SLICE6DB.
|
||||
|
||||
- **`IHardware[] AvailableSLICE6DB`**
|
||||
SLICE6DB units available for association.
|
||||
|
||||
- **`bool ShowCompact`**
|
||||
Controls whether rack modules are hidden (default `true`). Triggers re-filtering and publishes `HardwareListShowCompactEvent`.
|
||||
|
||||
- **`ObservableCollection<IHardware> SelectedHardwareItems`**
|
||||
Tracks selected hardware items; raises `HardwareListHardwareSelectedEvent` on change.
|
||||
|
||||
- **`bool IsBusy`**
|
||||
Bound to busy indicator; set via `BusyIndicatorChangeNotification` event.
|
||||
|
||||
- **`bool IsDirty`**
|
||||
Always `false`; not updated anywhere in source.
|
||||
|
||||
- **`string ListViewId => "HardwareListView"`**
|
||||
Identifier for the view.
|
||||
|
||||
- **`int TDASCalPeriod`, `int G5CalPeriod`, ..., `int SLICE_PRO_CAN_FD_CalPeriod`**
|
||||
Calibration period constants passed to `HardwareModel`.
|
||||
|
||||
- **`IStreamingFilterProfile StreamingDSPProfile`**
|
||||
Used to compute `DSPStreamingFilter` via `GetDSPFilterRate()`.
|
||||
|
||||
#### **Internal/Protected Methods (Not Public Interface)**
|
||||
- **`void FireAAFilterRate(...)`, `FireSampleRate(...)`, `FireClockMaster(...)`, `FireIncluded(...)`, `FirePTPDomainID(...)`**
|
||||
Publish corresponding `HardwareListHardware*Event` instances.
|
||||
|
||||
- **`private void FireSelectionChanged()`**
|
||||
Publishes `HardwareListHardwareSelectedEvent` with selected serial numbers.
|
||||
|
||||
- **`private void Hardware_PropertyChanged(...)`**
|
||||
Handles `TestAAFilterRateHz` changes to call `SetDSPRate()`.
|
||||
|
||||
- **`private void SetDSPRate(HardwareModel hardware)`**, **`private void UpdateDSP(HardwareModel hardware)`**
|
||||
Computes `DSPStreamingFilter` using `StreamingDSPProfile`.
|
||||
|
||||
- **`private double GetNextHighestAvailableSampleRate(...)`**
|
||||
Helper for `SetTestSampleRates`.
|
||||
|
||||
- **`internal float GetAAFForHardware(IISOHardware h, int sampleRate)`**
|
||||
Returns AAF rate based on DAS type (TDAS vs SLICE).
|
||||
|
||||
- **`private bool AnyMixedChildren(...)`**, **`private void PopulateAvailableHardware()`**, **`private void OnRaiseNotification(...)`, `OnBusyIndicatorNotification(...)`**
|
||||
Internal helpers.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- **Hardware Uniqueness**: `_allHardware` must contain no duplicate `SerialNumber`s. Duplicates are logged via `APILogger.Log()` during `GetHardware()`.
|
||||
|
||||
- **Parent–Child Sample Rate Consistency**: For any child DAS with `ParentDAS` set, `CheckForMixedDAS()` ensures the parent’s `MixedRates` flag reflects whether any included siblings have differing `TestSampleRate`. If all children match, the parent’s rate is updated to match.
|
||||
|
||||
- **Calibration Overdue Logic**: `OverdueHardware` includes all hardware where `CalDueDate <= DateTime.Today`. This is recomputed on every `Filter()` call.
|
||||
|
||||
- **Channel Aggregation for Parent DAS**: When `bIncludeModules == false`, parent DAS channel counts (`AnalogChannels`, `SquibChannels`, etc.) are aggregated from included child modules. If a parent has only one analog channel, it is reset to `0` before adding child channels.
|
||||
|
||||
- **SLICE6 Association Integrity**: `SLICE6TreeNode.Number`, `Port`, and `PositionOnChain` are managed during `Associate()`/`UnAssociate()` to maintain ordering and uniqueness.
|
||||
|
||||
- **Replacement Hardware Constraints**: In `PopulateAvailableHardware()`, replacement hardware must match `HardwareType`. For `TDAS_Pro_Rack`, replacement must have `MaxModules >=` original’s `MaxModules`.
|
||||
|
||||
- **Filtering Scope**: `Filter(string term)` operates on `_allHardware`, but `SetIncluded(string[])` operates on the *filtered* `Hardware` list.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
#### **Imports/Usings**
|
||||
- **Core**: `System.Collections.Generic`, `System.Linq`, `System.Threading.Tasks`, `System.ComponentModel`, `System.Collections.Specialized`.
|
||||
- **Prism**: `Prism.Regions`, `Prism.Events`, `Unity` (`IUnityContainer`, `IRegionManager`, `IEventAggregator`).
|
||||
- **Common Libraries**:
|
||||
- `DTS.Common.Classes.Hardware`, `DTS.Common.Enums.Hardware`, `DTS.Common.Events.Hardware.HardwareList`
|
||||
- `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` (e.g., `IHardwareListView`, `ISLICE6TreeNode`)
|
||||
- `HardareList.Model` (e.g., `HardwareModel`, `HardwareChannelAssignment`)
|
||||
- `DTS.Common.Interface.TestSetups.TestSetupsList` (`ITestSetup`)
|
||||
- `DTS.Common.Utilities.Logging` (`APILogger`)
|
||||
- `DTS.Common.Classes.DSP` (`IStreamingFilterProfile`)
|
||||
- `DTS.Common.Interactivity` (`InteractionRequest<T>`)
|
||||
|
||||
#### **External Types Referenced**
|
||||
- `IHardware`, `IISOHardware`, `HardwareModel`, `ISLICE6TreeNode`, `ISLICE6TreeView`, `ITestSetup`, `HardwareTypes`, `SerializableAAF.DAS_TYPE`, `DTS.Common.ClockSyncProfile`, `DTS.Common.ISO.Hardware`, `DFConstantsAndEnums.TSRAIR_ValidSampleRates`.
|
||||
|
||||
#### **Event Types Published/Consumed**
|
||||
- **Consumed**: `RaiseNotification`, `BusyIndicatorChangeNotification`, `PageErrorEvent`.
|
||||
- **Published**: `HardwareListEditHardwareEvent`, `HardwareListHardwareTestAAFilterRateEvent`, `HardwareListHardwareTestSampleRateEvent`, `HardwareListHardwareTestClockMasterEvent`, `HardwareListHardwareIncludedEvent`, `HardwareListHardwareSelectedEvent`, `HardwareListHardwareTestPTPDomainIDEvent`, `HardwareReplaceEvent`, `HardwareListShowCompactEvent`, `ListViewStatusEvent`.
|
||||
|
||||
#### **Dependents**
|
||||
- Views (`IHardwareListView`, `IHardwareListOverdueView`, etc.) bind to this ViewModel.
|
||||
- Other modules subscribe to its published events (e.g., `HardwareReplaceEvent`).
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **`IsDirty` is never set**: The property is declared but always `false`. This may indicate incomplete implementation or unused state tracking.
|
||||
|
||||
- **`HardwareFilter` uses `Fields` enum, but `Filter(string term)` uses `_currentSearchTerm` for global search**: Field-specific filters are stored in `_filterByField`, but the primary `Filter(string term)` method only uses `_currentSearchTerm`. This may cause confusion—field filters are only applied via `Filter(object tag, string term)`.
|
||||
|
||||
- **`SetTestSampleRates` silently overrides unavailable rates**: If a requested sample rate is not in `hardware._availableSampleRates`, it jumps to the next highest *without user confirmation*. This could mask configuration errors.
|
||||
|
||||
- **`GetAAFForHardware` uses `DASTypeEnum` to choose between `TDAS` and `SLICE` AAF profiles**: The `default` case assumes all non-TDAS hardware is SLICE, which may be incorrect for future hardware types.
|
||||
|
||||
- **`SLICE6TreeNode.Number` assignment assumes sequential numbering**: `node.Number = 1 + SLICE6TreeNodes.Length` may cause conflicts if nodes are added out-of-order or reloaded from persistent state.
|
||||
|
||||
- **`Hardware_PropertyChanged` only handles `TestAAFilterRateHz`**: Other property changes (e.g., `Included`, `TestSampleRate`) do not trigger DSP recalculation unless explicitly handled elsewhere (e.g., `SetTestSampleRates`).
|
||||
|
||||
- **`Unset()` does not clear `_dasIdToChannels`**: While `InitializeReplace()` clears it, `Unset()` does not. If `Unset()` is called mid-replace operation, stale channel assignments may persist.
|
||||
|
||||
- **`ShowCompact` triggers re-filtering but not re-sorting**: Changing `ShowCompact` calls `Filter()` but not `Sort()`, potentially leaving the list in an inconsistent order until the user re-sorts.
|
||||
|
||||
- **`SelectedHardwareItems.CollectionChanged` handler `SelectedHardwareItemsOnCollectionChanged` calls `FireSelectionChanged()`**: This may fire multiple times if items are added/removed in bulk (e.g., via `SetIncluded()`), though `SelectedItemsStatus.GetUpdating()` is checked in `FireSelectionChanged()` (source of `SelectedItemsStatus` not provided—behavior uncertain).
|
||||
|
||||
- **`GetHardware()` aggregates child channels only when `bIncludeModules == false`**: When `bIncludeModules == true`, parent DAS channel counts are *not* aggregated, leading to inconsistent channel counts depending on view mode.
|
||||
|
||||
- **`GetAAFForHardwareFunc` is a public property**: Allows external override of AAF computation logic, but no usage is shown in this file.
|
||||
|
||||
- **`IsEdit`, `IsMenuIncluded`, `IsNavigationIncluded` are exposed but never set in this file**: Their purpose is unclear without context from other modules.
|
||||
|
||||
- **Typo in namespace import**: `using HardareList.Model;` (missing 'd' in "Hardware")—likely a ReSharper suppression or legacy artifact.
|
||||
|
||||
- **`SLICE6TreeNode.SwapNodes()` and `SaveAssociations()` are called in `SaveSLICE6Associations()`**: The order (swap first, then save) may be critical for data integrity, but no error handling is visible.
|
||||
|
||||
- **`SelectedHardwareItems` is initialized as `new ObservableCollection<IHardware>()` but never cleared in `Unset()`**: `Unset()` reassigns `SelectedHardwareItems = null`? No—`Unset()` does not modify it. This may leave stale selections after unloading.
|
||||
|
||||
- **`Hardware` and `OverdueHardware` arrays are reassigned directly**: This bypasses `OnPropertyChanged` unless explicitly triggered (e.g., `OnPropertyChanged("Hardware")`), which is done—but only after sorting/filtering. Direct array mutation (e.g
|
||||
Reference in New Issue
Block a user