# app/tabs/dashboard.py from __future__ import annotations import tkinter as tk from tkinter import ttk class DashboardTab: """Zeigt dynamisch alle im Vehicle registrierten Dashboard-Metriken.""" def __init__(self, parent, sim): self.sim = sim self.frame = ttk.Frame(parent, padding=8) self.tree = ttk.Treeview(self.frame, columns=("label","value","unit","key","source"), show="headings", height=12) self.tree.heading("label", text="Parameter") self.tree.heading("value", text="Wert") self.tree.heading("unit", text="Einheit") self.tree.heading("key", text="Key") self.tree.heading("source",text="Modul") self.tree.column("label", width=180, anchor="w") self.tree.column("value", width=120, anchor="e") self.tree.column("unit", width=80, anchor="w") self.tree.column("key", width=180, anchor="w") self.tree.column("source",width=100, anchor="w") self.tree.grid(row=0, column=0, sticky="nsew") sb = ttk.Scrollbar(self.frame, orient="vertical", command=self.tree.yview) self.tree.configure(yscrollcommand=sb.set) sb.grid(row=0, column=1, sticky="ns") self.frame.columnconfigure(0, weight=1) self.frame.rowconfigure(0, weight=1) self._last_keys = None self._tick() def _format_value(self, val, fmt): if fmt: try: return f"{val:{fmt}}" except Exception: return str(val) return str(val) def _tick(self): snap = self.sim.v.dashboard_snapshot() specs = snap["specs"] values = snap["values"] keys = sorted(specs.keys(), key=lambda k: (specs[k].get("priority", 999), specs[k].get("label", k))) if keys != self._last_keys: # rebuild table for item in self.tree.get_children(): self.tree.delete(item) for k in keys: spec = specs[k] lbl = spec.get("label", k) unit = spec.get("unit", "") src = spec.get("source", "") val = self._format_value(values.get(k, ""), spec.get("fmt")) self.tree.insert("", "end", iid=k, values=(lbl, val, unit, k, src)) self._last_keys = keys else: # update values only for k in keys: spec = specs[k] val = self._format_value(values.get(k, ""), spec.get("fmt")) try: self.tree.set(k, "value", val) except tk.TclError: pass try: self.frame.after(200, self._tick) except tk.TclError: pass # Config-API no-ops (für Konsistenz mit anderen Tabs) def save_into_config(self, out): # pragma: no cover pass def load_from_config(self, cfg): # pragma: no cover pass