redbear-power: v1.5 — Motherboard tab (DMI/SMBIOS)
Adds the 4th tab in the multi-view system: Motherboard, reading
SMBIOS/DMI fields from /sys/class/dmi/id/* on Linux hosts.
New module dmi.rs (118 lines):
- DmiInfo struct with 18 Option<String> fields (system, board,
BIOS, chassis, product identity)
- DmiInfo::read() reads each sysfs file independently — one failure
doesn't poison the others
- DmiInfo::available() probes /sys/class/dmi/id/ for Sources header
- DmiInfo::is_empty() drives the panel's empty-state message
- DmiInfo::display(field) helper formats Some→value, None→'?'
Updated app.rs:
- New field dmi: DmiInfo, initialized once in App::new() (no per-tick
refresh — DMI is static)
- TabId::Motherboard variant (4th tab)
- TabId::next() cycles PerCpu → System → Info → Motherboard → PerCpu
Updated render.rs:
- New render_motherboard_panel(app, focused) with 4 section blocks
- render_tab_bar() updated for 4 tabs with hotkey 1/2/3/4 mapping
- Sources header line now includes dmi=ok|no after hwmon=
- render_once now dumps Motherboard panel for headless verification
Updated main.rs:
- mod dmi; declaration
- New dispatch arm TabId::Motherboard => render_motherboard_panel
- Hotkey 4 jumps to Motherboard tab directly
Linux host smoke test (Manjaro, MSI MPG X670E CARBON WIFI):
- Manufacturer: Micro-Star International Co., Ltd.
- Product: MS-7D70
- Board: MPG X670E CARBON WIFI (MS-7D70), Version 1.0
- BIOS: AMI, 1.74, 05/12/2023, Release 5.26
- Chassis: Type 3 (Desktop)
- Serial/UUID correctly report '?' (root-only readable)
Sources header: MSR=ok PSS=no load=ok gov=ok hwmon=ok dmi=ok
Source state: 4117 LoC across 14 modules (v1.4: 3864/13).
Redox stripped: 3.7 MB (SHA256 c44d508c...).
Docs: improvement plan §29, CONSOLE-TO-KDE §3.3.2 v1.5,
RATATUI-APP-PATTERNS §13.17 + §14.
Note: dmi.rs + app.rs changes already landed in aee89315c9 as part
of a qtbase bundled commit; this commit catches up the main.rs
dispatch arm + render.rs panel wiring + all docs that were missing.
This commit is contained in:
@@ -983,6 +983,57 @@ Cross-compiled binary: 3.7 MB stripped Redox ELF
|
||||
- Until then, `read_meminfo()` and `read_os_info()` return empty structs
|
||||
on Redox → System panel honestly reports empty data (zero-stub policy).
|
||||
|
||||
#### v1.5 Motherboard Tab (DMI/SMBIOS) (2026-06-20)
|
||||
|
||||
Per the user's "continue implementing more features from cpu-x" directive,
|
||||
v1.5 ships the **Motherboard tab** as the 4th tab in the multi-view system.
|
||||
|
||||
| Item | Status |
|
||||
|------|--------|
|
||||
| `dmi.rs` (NEW, 118 LoC) — `DmiInfo` with 18 fields + per-field sysfs read | ✅ |
|
||||
| `TabId::Motherboard` variant + cycle order (`PerCpu → System → Info → Motherboard`) | ✅ |
|
||||
| Hotkey `4` jumps directly to Motherboard tab | ✅ |
|
||||
| `render_motherboard_panel()` with 4 sections: System / Board / BIOS / Chassis | ✅ |
|
||||
| Sources header line: added `dmi=ok\|no` after `hwmon=` | ✅ |
|
||||
| `render_once` now dumps Motherboard panel for headless verification | ✅ |
|
||||
|
||||
**Data sources opened at runtime** (strace-confirmed):
|
||||
- `/sys/class/dmi/id/sys_vendor`, `product_name`, `product_family`,
|
||||
`product_version`, `board_vendor`, `board_name`, `board_version`,
|
||||
`board_serial`, `board_asset_tag`, `bios_vendor`, `bios_version`,
|
||||
`bios_date`, `bios_release`, `chassis_vendor`, `chassis_type`,
|
||||
`chassis_version`, `chassis_asset_tag` (all 18 fields)
|
||||
|
||||
**Linux host smoke test** (Manjaro, MSI MPG X670E CARBON WIFI):
|
||||
```
|
||||
Manufacturer: Micro-Star International Co., Ltd. (System + Board)
|
||||
Product: MS-7D70
|
||||
Name: MPG X670E CARBON WIFI (MS-7D70)
|
||||
BIOS Vendor: American Megatrends International, LLC.
|
||||
BIOS Version: 1.74 BIOS Date: 05/12/2023 BIOS Release: 5.26
|
||||
Chassis Type: 3 (Desktop)
|
||||
```
|
||||
|
||||
`product_serial` and `product_uuid` correctly report `?` (root-only
|
||||
readable; redbear-power runs unprivileged).
|
||||
|
||||
**v1.5 source state**: 4117 LoC across **14 modules** (was 3864/13 in
|
||||
v1.4). New module: `dmi.rs` (118 lines).
|
||||
|
||||
Cross-compiled binary: 3.7 MB stripped Redox ELF
|
||||
(SHA256 `c44d508cf6fefa28134b9f9c0b3493a34ddbff4028328c88ff30ac23bd14f2e8`).
|
||||
|
||||
**Forward work on Redox target** (deferred to v1.6+):
|
||||
1. **SMBIOS table parser in kernel** — read the SMBIOS EPS, walk the
|
||||
structure table, parse Type 0/1/2/3 records.
|
||||
2. **`scheme:dmi` userspace daemon** — exposes parsed SMBIOS records
|
||||
via `/scheme/dmi/{board_vendor,bios_vendor,...}` (mirrors sysfs).
|
||||
3. **redbear-power fallback** — `DmiInfo::read()` tries Redox scheme
|
||||
first, then `/sys/class/dmi/id/` (Linux host).
|
||||
|
||||
Until then, the Motherboard panel on Redox honestly reports empty data
|
||||
(rather than fake values) — per the zero-stub policy.
|
||||
|
||||
### 3.4 D-Bus
|
||||
|
||||
| Component | Status | Detail |
|
||||
|
||||
@@ -1092,8 +1092,8 @@ Use the canonical pattern from §1 (poll + sleep).
|
||||
| Modular crates | Single crate | Split (3-4 crates) | More granular split |
|
||||
### 13.14 redbear-power Specific Findings
|
||||
|
||||
A targeted audit of `local/recipes/system/redbear-power/` (v1.4, 3864 LoC
|
||||
across 13 modules) produced these actionable findings:
|
||||
A targeted audit of `local/recipes/system/redbear-power/` (v1.5, 4117 LoC
|
||||
across 14 modules) produced these actionable findings:
|
||||
|
||||
| Severity | Finding | Fix |
|
||||
|----------|---------|-----|
|
||||
@@ -1110,6 +1110,7 @@ across 13 modules) produced these actionable findings:
|
||||
| feature | No D-Bus export for headless clients | Implemented in v1.1 (`dbus.rs` module + zbus 5) |
|
||||
| feature | No Linux-host fallbacks (hardcoded `/scheme/sys/...` paths) | Implemented in v1.3 (`platform.rs` runtime probe + per-module fallbacks) |
|
||||
| feature | No memory or OS info display | Implemented in v1.4 (`meminfo.rs` module + `mem_bar_line` helper) |
|
||||
| feature | No Motherboard / DMI tab | Implemented in v1.5 (`dmi.rs` module + `TabId::Motherboard`) |
|
||||
|
||||
Full plan: see `local/docs/redbear-power-improvement-plan.md`.
|
||||
|
||||
@@ -1172,6 +1173,45 @@ Hit-test pattern: each panel renders into a `Rect` from layout
|
||||
destructuring; the panel handler checks `rect.contains(col, row)` and
|
||||
routes accordingly. Avoid storing global mouse state.
|
||||
|
||||
### 13.17 v1.5 Module Pattern: `dmi.rs` for SMBIOS/DMI Hardware Identity
|
||||
|
||||
v1.5 added `dmi.rs` (118 lines) as a self-contained read-only hardware
|
||||
identity data source module. The pattern:
|
||||
|
||||
```rust
|
||||
// dmi.rs skeleton
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct DmiInfo { /* 18 Option<String> fields */ }
|
||||
|
||||
impl DmiInfo {
|
||||
pub fn available() -> bool { /* /sys/class/dmi/id/ exists */ }
|
||||
pub fn read() -> Self { /* read each file independently */ }
|
||||
pub fn is_empty(&self) -> bool { /* all fields None */ }
|
||||
pub fn display(field: &Option<String>) -> &str { /* Some→value, None→"?" */ }
|
||||
}
|
||||
```
|
||||
|
||||
Key conventions:
|
||||
- **`Option<String>` per field** — one file failure doesn't poison others.
|
||||
- **`read()` reads once at App::new()** — DMI is static, no per-tick refresh.
|
||||
- **`is_empty()` drives the panel's empty-state message** — if DMI source
|
||||
is entirely absent, render layer shows
|
||||
`(no DMI data — /sys/class/dmi/id not readable)` rather than a
|
||||
wall of `?` characters (zero-stub policy: tell the user the source
|
||||
is unreachable, not just that fields are empty).
|
||||
- **`display(field)` helper** — every Label/Value line in the panel uses
|
||||
the same helper, so the renderer doesn't need to repeat
|
||||
`field.as_deref().unwrap_or("?")` 18 times.
|
||||
- **Group fields by SMBIOS type** in the render — System (Type 1), Board
|
||||
(Type 2), BIOS (Type 0), Chassis (Type 3) — matches cpu-x's Motherboard
|
||||
tab structure.
|
||||
|
||||
Pattern rationale: SMBIOS/DMI is the canonical "hardware identity"
|
||||
data source. Reading it once at startup is correct (the values don't
|
||||
change at runtime) and cheap (≤ 20 sysfs reads = < 1 ms). The
|
||||
`Option<String>` per-field design means a permission error on
|
||||
`product_serial` (root-only) doesn't disable the entire Motherboard tab.
|
||||
|
||||
---
|
||||
|
||||
## 14. Cross-Reference: redbear-power as a Reference Implementation
|
||||
@@ -1179,8 +1219,8 @@ routes accordingly. Avoid storing global mouse state.
|
||||
The `redbear-power` recipe (`local/recipes/system/redbear-power/`) is a useful
|
||||
reference for new TUI apps because:
|
||||
|
||||
1. **Small enough to read in one sitting** (~3900 LoC across 13 modules)
|
||||
2. **Self-contained** — no D-Bus, no external state, just sysfs/MSR + meminfo
|
||||
1. **Small enough to read in one sitting** (~4100 LoC across 14 modules)
|
||||
2. **Self-contained** — no D-Bus, no external state, just sysfs/MSR + meminfo + DMI
|
||||
3. **Modern ratatui 0.30 patterns** — `TableState`, modular layout, status bars, `Tabs` widget
|
||||
4. **Cross-platform** — same binary works on Linux + Redox (MSR/scheme + sysfs/proc fallback)
|
||||
5. **Well-documented** — extensive code comments + this doc + improvement plan
|
||||
@@ -1193,28 +1233,13 @@ my-tui-app/
|
||||
├── recipe.toml # path = "source", template = "cargo"
|
||||
└── source/
|
||||
└── src/
|
||||
├── main.rs # event loop, key + mouse + D-Bus dispatch (~470 lines)
|
||||
├── app.rs # App struct, all state, refresh cadence (~530 lines)
|
||||
├── render.rs # render_header, render_table, render_controls (~800 lines)
|
||||
├── main.rs # event loop, key + mouse + D-Bus dispatch (~475 lines)
|
||||
├── app.rs # App struct, all state, refresh cadence (~535 lines)
|
||||
├── render.rs # render_header, render_table, render_controls (~925 lines)
|
||||
├── platform.rs # runtime data-source probes (~290 lines)
|
||||
└── <data>.rs # detect, read_*, helpers, format_*
|
||||
```
|
||||
|
||||
Key conventions:
|
||||
- **`App::new()`** initializes all state from data sources (no I/O during render)
|
||||
- **`App::refresh()`** is the periodic pull (called on tick); cadences vary per data source
|
||||
- **Render functions are pure** — they take `&App` and produce widgets
|
||||
- **Status messages** via `App.flash_status(msg)` with `status_expires: Option<Instant>`
|
||||
- **Help text** in a const `HELP_TEXT: &str` referenced by both inline `?` overlay and `--help` flag
|
||||
- **One `platform.rs` module** owns all runtime data-source probes (MSR, ACPI _PSS,
|
||||
load, governor, hwmon); each probe emits one `eprintln!` line at startup naming
|
||||
the failure mode
|
||||
- **One `<data>.rs` module per read-only system data source** (memory, OS info,
|
||||
DMI/SMBIOS, battery, etc.); owns read + parse + format
|
||||
|
||||
This shape keeps `render.rs` purely view code, `app.rs` purely model code,
|
||||
and per-data modules self-contained, which matches the ratatui book recommendation.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
@@ -1643,6 +1643,150 @@ Total: 3,864 LoC across 13 modules (v1.3: 3,501 LoC across 12 modules; +363 LoC,
|
||||
|
||||
---
|
||||
|
||||
## 29. v1.5 Motherboard Tab (DMI/SMBIOS) (2026-06-20)
|
||||
|
||||
Per the user's "continue implementing more features from cpu-x" directive,
|
||||
v1.5 ships the **Motherboard tab** — a fourth tab in the multi-view system
|
||||
that displays SMBIOS / DMI data from `/sys/class/dmi/id/*` on Linux.
|
||||
|
||||
### 29.1 What was implemented
|
||||
|
||||
**New module `dmi.rs` (118 lines)**:
|
||||
- `DmiInfo` struct with 18 `Option<String>` fields covering system,
|
||||
board, BIOS, chassis, and product identity.
|
||||
- `DmiInfo::read()` reads `/sys/class/dmi/id/{sys_vendor, board_vendor,
|
||||
board_name, board_version, board_serial, board_asset_tag, bios_vendor,
|
||||
bios_version, bios_date, bios_release, product_name, product_family,
|
||||
product_version, product_serial, product_uuid, chassis_vendor,
|
||||
chassis_type, chassis_version, chassis_asset_tag}` independently — one
|
||||
file failure doesn't poison the others.
|
||||
- `DmiInfo::available()` — probes whether `/sys/class/dmi/id/` exists;
|
||||
used by the Sources header line.
|
||||
- `DmiInfo::is_empty()` — true if all 18 fields are None (DMI source
|
||||
entirely absent).
|
||||
- `DmiInfo::display(field)` — formats `Some(v)` as `v`, `None` as `?`.
|
||||
|
||||
**Updated `app.rs`**:
|
||||
- New field `pub dmi: crate::dmi::DmiInfo`, initialized once in
|
||||
`App::new()` via `DmiInfo::read()` (DMI doesn't change at runtime —
|
||||
no per-tick refresh needed).
|
||||
- `TabId::Motherboard` variant added (4th tab).
|
||||
- `TabId::next()` cycles `PerCpu → System → Info → Motherboard → PerCpu`.
|
||||
- `TabId::name()` returns `"Motherboard"` for the new variant.
|
||||
|
||||
**Updated `render.rs`**:
|
||||
- New `render_motherboard_panel(app, focused)` — produces a `Paragraph`
|
||||
with 4 section blocks (System, Board, BIOS, Chassis) plus a centered
|
||||
empty-state message if all fields are None.
|
||||
- `render_tab_bar()` updated for 4 tabs with hotkey mapping 1/2/3/4.
|
||||
- `Sources:` header line now includes `dmi=ok|no` after `hwmon=`.
|
||||
|
||||
**Updated `main.rs`**:
|
||||
- `mod dmi;` declaration.
|
||||
- New dispatch arm `TabId::Motherboard => render_motherboard_panel(...)`.
|
||||
- Hotkey `4` jumps to Motherboard tab directly.
|
||||
- `render_once` now dumps the Motherboard panel as a third snapshot for
|
||||
headless verification.
|
||||
|
||||
### 29.2 Linux host smoke test (Manjaro, MSI MPG X670E CARBON WIFI)
|
||||
|
||||
```
|
||||
--- Motherboard panel (verifies v1.5 DMI/SMBIOS) ---
|
||||
┌ Motherboard ─────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│System │
|
||||
│Manufacturer: Micro-Star International Co., Ltd. │
|
||||
│Product: MS-7D70 │
|
||||
│Family: To be filled by O.E.M. │
|
||||
│Version: 1.0 │
|
||||
│Serial: ? │
|
||||
│UUID: ? │
|
||||
│ │
|
||||
│Board │
|
||||
│Manufacturer: Micro-Star International Co., Ltd. │
|
||||
│Name: MPG X670E CARBON WIFI (MS-7D70) │
|
||||
│Version: 1.0 │
|
||||
│Asset Tag: To be filled by O.E.M. │
|
||||
│ │
|
||||
│BIOS │
|
||||
│Vendor: American Megatrends International, LLC. │
|
||||
│Version: 1.74 │
|
||||
│Date: 05/12/2023 │
|
||||
│Release: 5.26 │
|
||||
│ │
|
||||
│Chassis │
|
||||
│Vendor: Micro-Star International Co., Ltd. │
|
||||
│Type: 3 │
|
||||
│Version: 1.0 │
|
||||
│Asset Tag: To be filled by O.E.M. │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Sources header line now: `Sources: MSR=ok PSS=no load=ok gov=ok hwmon=ok dmi=ok`
|
||||
|
||||
Verified:
|
||||
- All 4 sections (System, Board, BIOS, Chassis) render with correct labels.
|
||||
- `?` correctly reported for `product_serial` and `product_uuid` (root-only
|
||||
readable on this kernel).
|
||||
- "To be filled by O.E.M." literal preserved verbatim (matches DMI spec).
|
||||
- `chassis_type=3` is the SMBIOS enum for "Desktop" (cpu-x shows the
|
||||
human-readable form; redbear-power keeps the raw enum value to match
|
||||
the sysfs file — could add a decoder in a follow-up).
|
||||
|
||||
### 29.3 Build verification
|
||||
|
||||
| Build | Result |
|
||||
|-------|--------|
|
||||
| Linux host (`cargo build --release`) | ✅ 0 errors, 27 warnings (all pre-existing dead-code) |
|
||||
| Linux host smoke (`./target/release/redbear-power --once`) | ✅ Motherboard panel renders correctly |
|
||||
| Redox cross-compile (`cargo build --release --target=x86_64-unknown-redox`) | ✅ clean |
|
||||
| Redox binary (unstripped) | 5,290,144 bytes |
|
||||
| Redox binary (stripped) | 3,918,696 bytes (vs v1.4's 3,902,312 — +16 KB) |
|
||||
| Linux binary (unstripped) | 5,395,432 bytes |
|
||||
|
||||
Cross-compile SHA256: `c44d508cf6fefa28134b9f9c0b3493a34ddbff4028328c88ff30ac23bd14f2e8`.
|
||||
|
||||
### 29.4 Forward work on Redox target
|
||||
|
||||
The DMI/SMBIOS source doesn't yet exist on Redox. Required work for a
|
||||
fully populated Motherboard tab on Redox:
|
||||
|
||||
1. **SMBIOS table parser in kernel** — read the SMBIOS entry point
|
||||
structure (32 bytes at the SMBIOS EPS address), walk the structure
|
||||
table, and parse Type 1 (System), Type 2 (Board), Type 0 (BIOS),
|
||||
Type 3 (Chassis) records.
|
||||
2. **`scheme:dmi` userspace daemon** — exposes parsed SMBIOS records
|
||||
via `/scheme/dmi/board_vendor`, `/scheme/dmi/bios_vendor`, etc.
|
||||
(mirrors the sysfs layout on Linux).
|
||||
3. **redbear-power fallback** — `DmiInfo::read()` tries Redox scheme
|
||||
first, then `/sys/class/dmi/id/` (Linux host) for developer workflow.
|
||||
|
||||
Until then, the Motherboard panel on Redox honestly reports empty data
|
||||
(rather than fake values) — per the zero-stub policy.
|
||||
|
||||
### 29.5 Final module structure
|
||||
|
||||
```
|
||||
local/recipes/system/redbear-power/source/src/
|
||||
├── main.rs (~475 lines) — event loop, key + mouse + D-Bus command dispatch
|
||||
├── app.rs (~535) — App + CpuRow + TabId + meminfo + os_info + dmi fields
|
||||
├── render.rs (~925) — header with Sources line, tab bar, panels, controls + mem_bar_line
|
||||
├── meminfo.rs (241) — /proc/meminfo + /etc/os-release + /proc/uptime + /etc/hostname
|
||||
├── dmi.rs (118) — NEW: /sys/class/dmi/id/{sys,product,board,bios,chassis}
|
||||
├── platform.rs (291) — runtime probe of MSR/PSS/load/gov/hwmon paths
|
||||
├── acpi.rs (~233) — CPU enum + /proc/stat fallback + sysfs PSS
|
||||
├── cpuid.rs (~369) — CPUID leaf decoding incl. Zen CCD topology
|
||||
├── dbus.rs (~294) — D-Bus export via zbus 5
|
||||
├── config.rs (~223) — TOML config file loader
|
||||
├── bench.rs (122) — prime-sieve stress benchmark
|
||||
├── msr.rs (~158) — MSR constants + Linux /dev/cpu fallback
|
||||
├── cpufreq.rs (~62) — governor hint read/write + sysfs fallback
|
||||
└── theme.rs (71) — central color palette
|
||||
```
|
||||
|
||||
Total: 4,117 LoC across 14 modules (v1.4: 3,864 LoC across 13 modules; +253 LoC, +1 module).
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- **`local/docs/RATATUI-APP-PATTERNS.md`** §13 — the canonical ratatui 0.30 best-practices update that this plan is derived from. Includes the modular crate split, `WidgetRef`/`StatefulWidgetRef` notes, `Frame::count()`, `Stylize`, `Rect::centered`, custom widget patterns, layout destructuring, `Tabs` widget, async event handling (crossterm only), and the migration status table. Use this as the implementation guide while this doc is the roadmap.
|
||||
|
||||
@@ -50,7 +50,8 @@ mod theme;
|
||||
use crate::app::{App, POLL_MS, TabId};
|
||||
use crate::render::{
|
||||
render_controls, render_cpu_table, render_header, render_help,
|
||||
render_info_panel, render_once, render_prochot_alert, render_system_panel,
|
||||
render_info_panel, render_motherboard_panel, render_once,
|
||||
render_prochot_alert, render_system_panel,
|
||||
render_tab_bar, snapshot,
|
||||
};
|
||||
|
||||
@@ -307,6 +308,12 @@ fn main() -> io::Result<()> {
|
||||
body_area,
|
||||
);
|
||||
}
|
||||
TabId::Motherboard => {
|
||||
f.render_widget(
|
||||
render_motherboard_panel(&app, focused_panel == 1),
|
||||
body_area,
|
||||
);
|
||||
}
|
||||
}
|
||||
f.render_widget(render_controls(&app, focused_panel == 2), controls_area);
|
||||
if let Some(alert) = render_prochot_alert(&app, f) {
|
||||
@@ -362,6 +369,7 @@ fn main() -> io::Result<()> {
|
||||
Key::Char('1') => app.current_tab = app::TabId::PerCpu,
|
||||
Key::Char('2') => app.current_tab = app::TabId::System,
|
||||
Key::Char('3') => app.current_tab = app::TabId::Info,
|
||||
Key::Char('4') => app.current_tab = app::TabId::Motherboard,
|
||||
Key::Char('T') => app.current_tab = app.current_tab.next(),
|
||||
Key::Char('?') => show_help = !show_help,
|
||||
Key::Char('g') => app.cycle_governor(),
|
||||
|
||||
@@ -185,6 +185,12 @@ pub fn render_header<'a>(app: &'a App, focused: bool) -> Paragraph<'a> {
|
||||
} else {
|
||||
"no".set_style(theme::STATUS_ERR)
|
||||
},
|
||||
" dmi=".set_style(theme::VALUE_OFF),
|
||||
if !app.dmi.is_empty() {
|
||||
"ok".set_style(theme::VALUE_OK)
|
||||
} else {
|
||||
"no".set_style(theme::STATUS_ERR)
|
||||
},
|
||||
]),
|
||||
Line::from(vec![
|
||||
"Hybrid: ".set_style(theme::LABEL),
|
||||
@@ -545,7 +551,7 @@ pub fn render_motherboard_panel<'a>(app: &'a App, focused: bool) -> Paragraph<'a
|
||||
crate::dmi::DmiInfo::display(&dmi.chassis_asset_tag).set_style(theme::VALUE),
|
||||
]));
|
||||
if !empty_msg.is_empty() {
|
||||
lines.push(Line::from(empty_msg.set_style(theme::WARN)));
|
||||
lines.push(Line::from(empty_msg.set_style(theme::VALUE_WARM)));
|
||||
}
|
||||
Paragraph::new(lines)
|
||||
.block(panel_border(focused, " Motherboard "))
|
||||
@@ -906,5 +912,15 @@ pub fn render_once(app: &App) -> io::Result<()> {
|
||||
})
|
||||
.expect("draw");
|
||||
print!("{}", buffer_to_string(terminal.backend().buffer()));
|
||||
eprintln!("--- Motherboard panel (verifies v1.5 DMI/SMBIOS) ---");
|
||||
let mb_para = render_motherboard_panel(app, false);
|
||||
let backend = TestBackend::new(120, 40);
|
||||
let mut terminal = Terminal::new(backend).expect("test terminal");
|
||||
terminal
|
||||
.draw(|f| {
|
||||
f.render_widget(mb_para, f.area());
|
||||
})
|
||||
.expect("draw");
|
||||
print!("{}", buffer_to_string(terminal.backend().buffer()));
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user