# Architecture KVitals is a KDE Plasma 6 widget (plasmoid) with a modular architecture connecting native **KSysGuard sensors** to a **QML UI** through dedicated sensor components. ## Data Flow ![KVitals Data Flow](dataflow.svg) ## Sensor Modules (`contents/ui/sensors/`) Each system metric has its own QML component under `sensors/`. These components encapsulate all sensor subscriptions, data parsing, and value formatting for their metric. | Module | Sensors | Exposed Properties | |---|---|---| | `CpuSensors.qml` | `cpu/all/usage` | `cpuValue` | | `MemorySensors.qml` | `memory/physical/used`, `total` | `ramValue` | | `TempSensors.qml` | `cpu/all/averageTemperature` | `tempValue` | | `GpuSensors.qml` | `gpu/all/usage`, `totalVram`, `usedVram`, `temperature` | `gpuValue`, `gpuRamValue`, `gpuTempValue`, `gpuDisplayValue`, `hasGpuData` | | `BatterySensors.qml` | `power//chargePercentage`, `chargeRate` | `batValue`, `powerValue` | | `NetworkSensors.qml` | `network//download`, `upload` | `netDownValue`, `netUpValue` | A shared `Utils.qml` singleton provides formatting helpers (`formatBytes`, `formatRate`) and sensor-reading utilities (`sensorValueOrNaN`, `firstReadyNumber`, `maxReadyNumber`, `firstReadyVramPair`). ### Performance Benefits 1. **Zero Subprocesses**: No `bash`, `awk`, or `cat` commands are spawned. 2. **Stable File Descriptors**: No CLI pipes need to be kept open, eliminating Plasma 6 Wayland FD-exhaustion crashes. 3. **Low Latency**: The widget reads the exact same backend API as the official KDE System Monitor. ## Orchestrator (`main.qml`) `main.qml` acts as a lightweight orchestrator: 1. **Reads configuration** from `Plasmoid.configuration` 2. **Instantiates sensor modules** with the configured `updateInterval` 3. **Builds metrics models** using the `orderedKeys` array (derived from the `metricOrder` config) 4. **Applies view-specific visibility rules** such as `compactShow*` settings and compact grouping 5. **Passes models** to `CompactView` and `FullView` for rendering ``` main.qml ├── CpuSensors { id: cpu } ├── MemorySensors { id: memory } ├── TempSensors { id: temp } ├── GpuSensors { id: gpu } ├── BatterySensors { id: battery } ├── NetworkSensors { id: network } ├── compactRepresentation: CompactView { metricsModel: ... } └── fullRepresentation: FullView { metricsModel: ... } ``` ## Views ### CompactView (Panel) A `RowLayout` with a `Repeater` that renders each compact-visible metric as: - **Icon** (optional, via `Kirigami.Icon` with `isMask: true`) - **Label** (optional, e.g., "CPU:") - **Value** (always shown, e.g., "26%") - **Separator** (`|` between metrics) Visibility of icons/labels is controlled by the `displayMode` property. Metric inclusion is controlled by both the metric-level `show*` settings and the compact-panel `compactShow*` settings, allowing a metric to remain visible in the popup/tooltip while being hidden from the panel. The compact panel also supports horizontal and vertical delegates through the `layoutType` setting. !!! tip Icons use `isMask: true` to render as monochrome, matching the panel's text color regardless of the icon theme. ### FullView (Popup) A `ColumnLayout` with a `Repeater` showing a detailed row per enabled metric with label and bold value, displayed when clicking the widget. ### Tooltip Multi-line text showing all enabled metrics, displayed on hover. Compact-panel visibility settings do not filter the tooltip. ## Configuration System ``` config/main.xml ← Config schema (entry names, types, defaults) config/config.qml ← Tab registration (General, Metrics, Icons, Colors) ui/configGeneral.qml ← General tab (display mode, layout, font, interval) ui/configMetrics.qml ← Metrics tab (show/hide toggles, compact panel visibility, metric order, grouping, network interface, battery device) ui/configIcons.qml ← Icons tab (per-metric icon picker) ui/configColors.qml ← Colors tab (font color, warning/critical colors, thresholds) ``` All config values are accessed in `main.qml` via `Plasmoid.configuration.`. !!! tip "Adding a New Sensor" 1. Create `contents/ui/sensors/NewSensor.qml` exposing formatted value properties 2. Register it in `sensors/qmldir` 3. Instantiate it in `main.qml` 4. Add it to the `orderedKeys` loop in compact/full/tooltip builders 5. Add `show*` and `compactShow*` config entries in `main.xml` 6. Add the metric and compact panel checkboxes in `configMetrics.qml` ## Project Structure ``` kvitals/ ├── metadata.json # Plasmoid metadata (name, version, id) ├── install.sh # Local install script ├── install-remote.sh # Remote install (curl/wget) ├── CHANGELOG.md # Version history ├── docs/ # Documentation │ ├── installation.md │ ├── configuration.md │ ├── architecture.md │ ├── contributing.md │ └── troubleshooting.md └── contents/ ├── config/ │ ├── config.qml # Tab registration │ └── main.xml # Config schema └── ui/ ├── main.qml # Widget orchestrator ├── CompactView.qml # Panel representation ├── FullView.qml # Popup representation ├── configGeneral.qml # General settings tab ├── configMetrics.qml # Metrics settings tab ├── configIcons.qml # Icons settings tab ├── configColors.qml # Colors settings tab └── sensors/ # Sensor modules ├── qmldir # QML module definition ├── CpuSensors.qml # CPU usage ├── MemorySensors.qml # RAM usage ├── TempSensors.qml # CPU temperature ├── GpuSensors.qml # GPU usage, VRAM, temp ├── BatterySensors.qml # Battery & power ├── NetworkSensors.qml # Network speed └── Utils.qml # Shared formatting helpers ```