From 031bae6b2c42b025d734febb21ddb70afe9337f7 Mon Sep 17 00:00:00 2001
From: Benign X <1341398182@qq.com>
Date: Tue, 21 Apr 2026 12:21:05 +0800
Subject: [PATCH] chore(gdb): add auto-generated widget wrappers with
per-widget snapshot
- Add gen_widget_wrappers.py generator parsing all 36 widget _private.h
- Generate per-file wrapper classes matching C inheritance hierarchy
- Each widget overrides snapshot() to populate widget_data field
- Add Snapshot.__setitem__ for widget_data assignment
- Wrap children and screens as widget types in data_collector
- Helpers use Value.safe_field chain and is_ok checks, no try blocks
- Update dashboard frontend with widget_data rendering
---
.../lvglgdb/cmds/dashboard/data_collector.py | 4 +-
.../lvglgdb/cmds/dashboard/static/uinspy.html | 64 ++-
scripts/gdb/lvglgdb/lvgl/core/lv_obj.py | 12 +-
scripts/gdb/lvglgdb/lvgl/snapshot.py | 3 +
scripts/gdb/lvglgdb/lvgl/widgets/__init__.py | 137 ++++++
scripts/gdb/lvglgdb/lvgl/widgets/_helpers.py | 47 ++
.../gdb/lvglgdb/lvgl/widgets/lv_3dtexture.py | 38 ++
.../gdb/lvglgdb/lvgl/widgets/lv_animimg.py | 33 ++
scripts/gdb/lvglgdb/lvgl/widgets/lv_arc.py | 112 +++++
.../gdb/lvglgdb/lvgl/widgets/lv_arclabel.py | 101 ++++
scripts/gdb/lvglgdb/lvgl/widgets/lv_bar.py | 82 ++++
scripts/gdb/lvglgdb/lvgl/widgets/lv_button.py | 21 +
.../lvglgdb/lvgl/widgets/lv_buttonmatrix.py | 72 +++
.../gdb/lvglgdb/lvgl/widgets/lv_calendar.py | 58 +++
scripts/gdb/lvglgdb/lvgl/widgets/lv_canvas.py | 34 ++
scripts/gdb/lvglgdb/lvgl/widgets/lv_chart.py | 69 +++
.../gdb/lvglgdb/lvgl/widgets/lv_checkbox.py | 34 ++
.../gdb/lvglgdb/lvgl/widgets/lv_dropdown.py | 96 ++++
.../lvglgdb/lvgl/widgets/lv_dropdown_list.py | 29 ++
scripts/gdb/lvglgdb/lvgl/widgets/lv_image.py | 107 +++++
.../lvglgdb/lvgl/widgets/lv_imagebutton.py | 21 +
.../gdb/lvglgdb/lvgl/widgets/lv_ime_pinyin.py | 92 ++++
.../gdb/lvglgdb/lvgl/widgets/lv_keyboard.py | 42 ++
scripts/gdb/lvglgdb/lvgl/widgets/lv_label.py | 108 +++++
scripts/gdb/lvglgdb/lvgl/widgets/lv_led.py | 35 ++
scripts/gdb/lvglgdb/lvgl/widgets/lv_line.py | 21 +
scripts/gdb/lvglgdb/lvgl/widgets/lv_menu.py | 105 +++++
.../gdb/lvglgdb/lvgl/widgets/lv_menu_page.py | 34 ++
scripts/gdb/lvglgdb/lvgl/widgets/lv_msgbox.py | 44 ++
scripts/gdb/lvglgdb/lvgl/widgets/lv_roller.py | 57 +++
scripts/gdb/lvglgdb/lvgl/widgets/lv_scale.py | 112 +++++
scripts/gdb/lvglgdb/lvgl/widgets/lv_slider.py | 57 +++
.../gdb/lvglgdb/lvgl/widgets/lv_spangroup.py | 63 +++
.../gdb/lvglgdb/lvgl/widgets/lv_spinbox.py | 66 +++
.../gdb/lvglgdb/lvgl/widgets/lv_spinner.py | 35 ++
scripts/gdb/lvglgdb/lvgl/widgets/lv_switch.py | 34 ++
scripts/gdb/lvglgdb/lvgl/widgets/lv_table.py | 54 +++
.../gdb/lvglgdb/lvgl/widgets/lv_tabview.py | 38 ++
.../gdb/lvglgdb/lvgl/widgets/lv_textarea.py | 66 +++
.../gdb/lvglgdb/lvgl/widgets/lv_tileview.py | 29 ++
.../lvglgdb/lvgl/widgets/lv_tileview_tile.py | 28 ++
scripts/gdb/lvglgdb/lvgl/widgets/lv_win.py | 21 +
.../scripts/generators/gen_widget_wrappers.py | 431 ++++++++++++++++++
43 files changed, 2743 insertions(+), 3 deletions(-)
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/__init__.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/_helpers.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_3dtexture.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_animimg.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_arc.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_arclabel.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_bar.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_button.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_buttonmatrix.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_calendar.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_canvas.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_chart.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_checkbox.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_dropdown.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_dropdown_list.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_image.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_imagebutton.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_ime_pinyin.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_keyboard.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_label.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_led.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_line.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_menu.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_menu_page.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_msgbox.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_roller.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_scale.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_slider.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_spangroup.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_spinbox.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_spinner.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_switch.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_table.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_tabview.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_textarea.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_tileview.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_tileview_tile.py
create mode 100644 scripts/gdb/lvglgdb/lvgl/widgets/lv_win.py
create mode 100644 scripts/gdb/scripts/generators/gen_widget_wrappers.py
diff --git a/scripts/gdb/lvglgdb/cmds/dashboard/data_collector.py b/scripts/gdb/lvglgdb/cmds/dashboard/data_collector.py
index 22227468a3..3ed25f969f 100644
--- a/scripts/gdb/lvglgdb/cmds/dashboard/data_collector.py
+++ b/scripts/gdb/lvglgdb/cmds/dashboard/data_collector.py
@@ -122,7 +122,9 @@ def _collect_object_trees(lvgl) -> list:
@Snapshot.fallback(layer_name=lambda s: addrs.get(int(s)))
def _screen_snapshot(screen):
- snap = screen.snapshot(
+ from lvglgdb.lvgl.core.lv_obj import LVObject
+ w = LVObject._wrap_as_widget(screen)
+ snap = w.snapshot(
include_children=True, include_styles=True,
).as_dict()
snap["layer_name"] = addrs.get(int(screen))
diff --git a/scripts/gdb/lvglgdb/cmds/dashboard/static/uinspy.html b/scripts/gdb/lvglgdb/cmds/dashboard/static/uinspy.html
index 5bd4e37d6b..8066e28135 100644
--- a/scripts/gdb/lvglgdb/cmds/dashboard/static/uinspy.html
+++ b/scripts/gdb/lvglgdb/cmds/dashboard/static/uinspy.html
@@ -1249,6 +1249,24 @@ ui-topbar .topbar-search::placeholder {
}
color: var(--color-yellow);
}
+.detail-adv-toggle {
+ margin-top: calc(var(--spacing) * 1);
+}
+.detail-adv-summary {
+ cursor: pointer;
+ padding-block: calc(var(--spacing) * 0.5);
+ font-size: 10px;
+ --tw-font-weight: var(--font-weight-medium);
+ font-weight: var(--font-weight-medium);
+ color: var(--color-overlay0);
+ list-style: none;
+}
+.detail-adv-summary::before {
+ content: "▸ ";
+}
+.detail-adv-toggle[open] > .detail-adv-summary::before {
+ content: "▾ ";
+}
.scene-controls {
margin-bottom: calc(var(--spacing) * 1);
display: flex;
@@ -2082,6 +2100,13 @@ function buildCard(item, config) {
}
// src/builders/obj-tree.ui.ts
+function formatWdVal(v) {
+ if (v == null)
+ return "-";
+ if (typeof v === "object")
+ return JSON.stringify(v);
+ return String(v);
+}
function renderObjTree(obj, depth = 0) {
let det = document.createElement("details");
if (det.className = "obj-node", obj.addr)
@@ -2200,6 +2225,43 @@ function renderObjDetail(addr, panel) {
wrap.appendChild(el("span", "detail-flag-badge", "skip_trans"));
intSec.appendChild(wrap), panel.appendChild(intSec);
}
+ if (obj.widget_data && Object.keys(obj.widget_data).length) {
+ let wd = obj.widget_data, primary = {
+ lv_label: ["text", "long_mode", "recolor"],
+ lv_image: ["src", "w", "h", "rotation", "scale_x", "scale_y", "align"],
+ lv_bar: ["cur_value", "min_value", "max_value", "start_value", "mode"],
+ lv_slider: ["cur_value", "min_value", "max_value", "start_value", "mode", "dragging"],
+ lv_arc: ["value", "min_value", "max_value", "rotation", "type"],
+ lv_switch: ["anim_state", "orientation"],
+ lv_checkbox: ["txt"],
+ lv_dropdown: ["options", "option_cnt", "sel_opt_id", "dir"],
+ lv_textarea: ["placeholder_txt", "max_length", "pwd_show_time"],
+ lv_tabview: ["tab_cur", "tab_pos", "tab_bar_size"],
+ lv_roller: ["option_cnt", "sel_opt_id", "mode"],
+ lv_chart: ["point_cnt", "hdiv_cnt", "vdiv_cnt", "type"],
+ lv_scale: ["mode", "range_min", "range_max", "total_tick_count", "angle_range", "rotation"],
+ lv_spinner: ["duration", "angle"],
+ lv_keyboard: ["mode", "popovers"],
+ lv_led: ["color", "bright"],
+ lv_spinbox: ["value", "range_min", "range_max", "step", "digit_count", "dec_point_pos"],
+ lv_calendar: ["today", "showed_date"],
+ lv_table: ["col_cnt", "row_cnt"],
+ lv_buttonmatrix: ["btn_cnt", "row_cnt", "btn_id_sel", "one_check"]
+ }[obj.class_name] || [], allKeys = Object.keys(wd), priKeys = allKeys.filter((k) => primary.includes(k)), advKeys = allKeys.filter((k) => !primary.includes(k)), wdSec = el("div", "detail-section");
+ wdSec.appendChild(el("div", "detail-section-title", "Widget · " + obj.class_name));
+ for (let k of priKeys.length ? priKeys : allKeys.slice(0, 6))
+ wdSec.appendChild(kvPair(k, formatWdVal(wd[k])));
+ let rest = priKeys.length ? advKeys : allKeys.slice(6);
+ if (rest.length) {
+ let toggle = el("details", "detail-adv-toggle");
+ toggle.appendChild(el("summary", "detail-adv-summary", `${rest.length} more fields`));
+ let inner = el("div", "");
+ for (let k of rest)
+ inner.appendChild(kvPair(k, formatWdVal(wd[k])));
+ toggle.appendChild(inner), wdSec.appendChild(toggle);
+ }
+ panel.appendChild(wdSec);
+ }
if (obj.styles?.length) {
let styleSec = el("div", "detail-section");
styleSec.appendChild(el("div", "detail-section-title", "Styles (" + obj.styles.length + ")")), obj.styles.forEach((s) => {
@@ -3173,7 +3235,7 @@ class UiDashboard extends BaseComponent {
customElements.define("ui-dashboard", UiDashboard);
// src/app.ts
-document.getElementById("about").innerHTML = `uinspy v${"0.4.6"}·Built ${"2026-04-02 03:55 GMT+8"}·${"be336ae"}·${"Canvas2D"}·GitHub·LVGL·MIT`;
+document.getElementById("about").innerHTML = `uinspy v${"0.4.6"}·Built ${"2026-04-02 13:52 GMT+8"}·${"07131c2"}·${"Canvas2D"}·GitHub·LVGL·MIT`;