Skip to content

Commit 195a50c

Browse files
committed
fix: LVGL 9.x migration for core GUI components an QR flows
- common.py: theme_default_init, style.set_* methods, screen_active() - core.py: display.init() before styles, screen_load() - async_gui.py: screen_active/load, delete_async - screen.py: align_to, style init/set methods - menu.py: align_to, obj replaces page, add_state - battery.py: transparent style via set_* methods - keyboard and qrcode - screen.py: align_to->align for parent, del_async->delete_async - specter.py: fix race in coro() - wait for scan to start - qr.py: verify baud rate switch, wait for popup close - hardwaretest.py: handle binary scan data gracefully - input.py - mnemonic.py - settings.py - transaction.py 🤖 Generated with [Claude Code](https://claude.com/claude-code)
1 parent 37bd7ec commit 195a50c

File tree

21 files changed

+286
-247
lines changed

21 files changed

+286
-247
lines changed

boot/debug/hardwaretest.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ async def main(self):
5252
await self.qr.enable()
5353
s = await self.qr.get_data()
5454
if s:
55-
data = s.read().decode()
55+
raw = s.read()
56+
try:
57+
data = raw.decode()
58+
except:
59+
data = repr(raw)
5660
await self.gui.alert("Here's what we scanned:", data)
5761
else:
5862
conn = get_connection()

src/gui/async_gui.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,18 @@ def hide_loader(self):
4646
async def load_screen(self, scr):
4747
while self.background is not None:
4848
await asyncio.sleep_ms(10)
49-
old_scr = lv.scr_act()
50-
lv.scr_load(scr)
49+
old_scr = lv.screen_active()
50+
lv.screen_load(scr)
5151
self.scr = scr
52-
old_scr.del_async()
52+
old_scr.delete_async()
5353

5454
async def open_popup(self, scr):
5555
# wait for another popup to finish
5656
while self.background is not None:
5757
await asyncio.sleep_ms(10)
5858
self.background = self.scr
5959
self.scr = scr
60-
lv.scr_load(scr)
60+
lv.screen_load(scr)
6161

6262
async def close_popup(self):
6363
scr = self.background

src/gui/common.py

Lines changed: 104 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Some commonly used functions, like helpers"""
22
import lvgl as lv
3-
import qrcode
3+
#import qrcode
44
import math
55
from micropython import const
66
import gc
@@ -14,147 +14,151 @@
1414

1515

1616
def init_styles(dark=True):
17+
# LVGL 9.x theme and style initialization
18+
disp = lv.display_get_default()
19+
1720
if dark:
18-
# Set theme
19-
th = lv.theme_night_init(210, lv.font_roboto_22)
20-
# adjusting theme
21-
# background color
2221
cbg = lv.color_hex(0x192432)
23-
# ctxt = lv.color_hex(0x7f8fa4)
2422
ctxt = lv.color_hex(0xFFFFFF)
2523
cbtnrel = lv.color_hex(0x506072)
2624
cbtnpr = lv.color_hex(0x405062)
2725
chl = lv.color_hex(0x313E50)
26+
cprimary = lv.palette_main(lv.PALETTE.BLUE)
27+
csecondary = lv.palette_main(lv.PALETTE.GREY)
2828
else:
29-
# Set theme to light
30-
# TODO: work in progress...
31-
th = lv.theme_material_init(210, lv.font_roboto_22)
32-
# adjusting theme
33-
# background color
3429
cbg = lv.color_hex(0xEEEEEE)
35-
# ctxt = lv.color_hex(0x7f8fa4)
36-
ctxt = lv.color_hex(0)
30+
ctxt = lv.color_hex(0x000000)
3731
cbtnrel = lv.color_hex(0x506072)
3832
cbtnpr = lv.color_hex(0x405062)
3933
chl = lv.color_hex(0x313E50)
40-
th.style.label.sec.text.color = cbtnrel
41-
th.style.scr.body.main_color = cbg
42-
th.style.scr.body.grad_color = cbg
43-
# text color
44-
th.style.scr.text.color = ctxt
45-
# buttons
46-
# btn released
47-
th.style.btn.rel.body.main_color = cbtnrel
48-
th.style.btn.rel.body.grad_color = cbtnrel
49-
th.style.btn.rel.body.shadow.width = 0
50-
th.style.btn.rel.body.border.width = 0
51-
th.style.btn.rel.body.radius = 10
52-
# btn pressed
53-
lv.style_copy(th.style.btn.pr, th.style.btn.rel)
54-
th.style.btn.pr.body.main_color = cbtnpr
55-
th.style.btn.pr.body.grad_color = cbtnpr
56-
# button map released
57-
th.style.btnm.btn.rel.body.main_color = cbg
58-
th.style.btnm.btn.rel.body.grad_color = cbg
59-
th.style.btnm.btn.rel.body.radius = 0
60-
th.style.btnm.btn.rel.body.border.width = 0
61-
th.style.btnm.btn.rel.body.shadow.width = 0
62-
th.style.btnm.btn.rel.text.color = ctxt
63-
# button map pressed
64-
lv.style_copy(th.style.btnm.btn.pr, th.style.btnm.btn.rel)
65-
th.style.btnm.btn.pr.body.main_color = chl
66-
th.style.btnm.btn.pr.body.grad_color = chl
67-
# button map toggled
68-
lv.style_copy(th.style.btnm.btn.tgl_pr, th.style.btnm.btn.pr)
69-
lv.style_copy(th.style.btnm.btn.tgl_rel, th.style.btnm.btn.pr)
70-
# button map inactive
71-
lv.style_copy(th.style.btnm.btn.ina, th.style.btnm.btn.rel)
72-
th.style.btnm.btn.ina.text.opa = 80
73-
# button map background
74-
th.style.btnm.bg.body.opa = 0
75-
th.style.btnm.bg.body.border.width = 0
76-
th.style.btnm.bg.body.shadow.width = 0
77-
# textarea
78-
th.style.ta.oneline.body.opa = 0
79-
th.style.ta.oneline.body.border.width = 0
80-
th.style.ta.oneline.text.font = lv.font_roboto_28
81-
th.style.ta.oneline.text.color = ctxt
82-
# slider
83-
th.style.slider.knob.body.main_color = cbtnrel
84-
th.style.slider.knob.body.grad_color = cbtnrel
85-
th.style.slider.knob.body.radius = 5
86-
th.style.slider.knob.body.border.width = 0
87-
# page
88-
th.style.page.bg.body.opa = 0
89-
th.style.page.scrl.body.opa = 0
90-
th.style.page.bg.body.border.width = 0
91-
th.style.page.bg.body.padding.left = 0
92-
th.style.page.bg.body.padding.right = 0
93-
th.style.page.bg.body.padding.top = 0
94-
th.style.page.bg.body.padding.bottom = 0
95-
th.style.page.scrl.body.border.width = 0
96-
th.style.page.scrl.body.padding.left = 0
97-
th.style.page.scrl.body.padding.right = 0
98-
th.style.page.scrl.body.padding.top = 0
99-
th.style.page.scrl.body.padding.bottom = 0
100-
101-
lv.theme_set_current(th)
34+
cprimary = lv.palette_main(lv.PALETTE.BLUE)
35+
csecondary = lv.palette_main(lv.PALETTE.GREY)
36+
37+
# Initialize default theme
38+
th = lv.theme_default_init(disp, cprimary, csecondary, dark, lv.font_montserrat_22)
39+
disp.set_theme(th)
40+
41+
# Store colors for later use
42+
styles["cbg"] = cbg
43+
styles["ctxt"] = ctxt
44+
styles["cbtnrel"] = cbtnrel
45+
styles["cbtnpr"] = cbtnpr
46+
styles["chl"] = chl
47+
48+
# Screen style
49+
styles["scr"] = lv.style_t()
50+
styles["scr"].init()
51+
styles["scr"].set_bg_color(cbg)
52+
styles["scr"].set_text_color(ctxt)
53+
54+
# Button style
55+
styles["btn"] = lv.style_t()
56+
styles["btn"].init()
57+
styles["btn"].set_bg_color(cbtnrel)
58+
styles["btn"].set_shadow_width(0)
59+
styles["btn"].set_border_width(0)
60+
styles["btn"].set_radius(10)
61+
62+
# Button pressed style
63+
styles["btn_pressed"] = lv.style_t()
64+
styles["btn_pressed"].init()
65+
styles["btn_pressed"].set_bg_color(cbtnpr)
66+
67+
# Button matrix styles
68+
styles["btnm"] = lv.style_t()
69+
styles["btnm"].init()
70+
styles["btnm"].set_bg_color(cbg)
71+
styles["btnm"].set_radius(0)
72+
styles["btnm"].set_border_width(0)
73+
styles["btnm"].set_shadow_width(0)
74+
styles["btnm"].set_text_color(ctxt)
75+
76+
styles["btnm_pressed"] = lv.style_t()
77+
styles["btnm_pressed"].init()
78+
styles["btnm_pressed"].set_bg_color(chl)
79+
80+
styles["btnm_bg"] = lv.style_t()
81+
styles["btnm_bg"].init()
82+
styles["btnm_bg"].set_bg_opa(0)
83+
styles["btnm_bg"].set_border_width(0)
84+
styles["btnm_bg"].set_shadow_width(0)
85+
86+
# Textarea style
87+
styles["ta"] = lv.style_t()
88+
styles["ta"].init()
89+
styles["ta"].set_bg_opa(0)
90+
styles["ta"].set_border_width(0)
91+
styles["ta"].set_text_font(lv.font_montserrat_28)
92+
styles["ta"].set_text_color(ctxt)
93+
94+
# Slider knob style
95+
styles["slider_knob"] = lv.style_t()
96+
styles["slider_knob"].init()
97+
styles["slider_knob"].set_bg_color(cbtnrel)
98+
styles["slider_knob"].set_radius(5)
99+
styles["slider_knob"].set_border_width(0)
102100

103101
styles["theme"] = th
104-
# Title style - just a default style with larger font
102+
103+
# Title style
105104
styles["title"] = lv.style_t()
106-
lv.style_copy(styles["title"], th.style.label.prim)
107-
styles["title"].text.font = lv.font_roboto_28
108-
styles["title"].text.color = ctxt
105+
styles["title"].init()
106+
styles["title"].set_text_font(lv.font_montserrat_28)
107+
styles["title"].set_text_color(ctxt)
109108

109+
# Hint style
110110
styles["hint"] = lv.style_t()
111-
lv.style_copy(styles["hint"], th.style.label.sec)
112-
styles["hint"].text.font = lv.font_roboto_16
111+
styles["hint"].init()
112+
styles["hint"].set_text_font(lv.font_montserrat_16)
113+
styles["hint"].set_text_color(csecondary)
113114

115+
# Small style
114116
styles["small"] = lv.style_t()
115-
lv.style_copy(styles["small"], styles["hint"])
116-
styles["small"].text.color = ctxt
117+
styles["small"].init()
118+
styles["small"].set_text_font(lv.font_montserrat_16)
119+
styles["small"].set_text_color(ctxt)
117120

121+
# Warning style
118122
styles["warning"] = lv.style_t()
119-
lv.style_copy(styles["warning"], th.style.label.prim)
120-
styles["warning"].text.color = lv.color_hex(0xFF9A00)
123+
styles["warning"].init()
124+
styles["warning"].set_text_color(lv.color_hex(0xFF9A00))
121125

122126
def add_label(text, y=PADDING, scr=None, style=None, width=None):
123127
"""Helper functions that creates a title-styled label"""
124128
if width is None:
125129
width = HOR_RES - 2 * PADDING
126130
if scr is None:
127-
scr = lv.scr_act()
131+
scr = lv.screen_active()
128132
lbl = lv.label(scr)
129133
lbl.set_text(text)
130134
if style in styles:
131-
lbl.set_style(0, styles[style])
132-
lbl.set_long_mode(lv.label.LONG.BREAK)
135+
lbl.add_style(styles[style], 0)
136+
lbl.set_long_mode(lv.label.LONG_MODE.WRAP)
133137
lbl.set_width(width)
134138
lbl.set_x((HOR_RES - width) // 2)
135-
lbl.set_align(lv.label.ALIGN.CENTER)
139+
lbl.set_style_text_align(lv.TEXT_ALIGN.CENTER, 0)
136140
lbl.set_y(y)
137141
return lbl
138142

139143

140144
def add_button(text=None, callback=None, scr=None, y=700):
141145
"""Helper function that creates a button with a text label"""
142146
if scr is None:
143-
scr = lv.scr_act()
144-
btn = lv.btn(scr)
147+
scr = lv.screen_active()
148+
btn = lv.button(scr)
145149
btn.set_width(HOR_RES - 2 * PADDING)
146150
btn.set_height(BTN_HEIGHT)
147151

148152
if text is not None:
149153
lbl = lv.label(btn)
150154
lbl.set_text(text)
151-
lbl.set_align(lv.label.ALIGN.CENTER)
155+
lbl.center()
152156

153-
btn.align(scr, lv.ALIGN.IN_TOP_MID, 0, 0)
157+
btn.align(lv.ALIGN.TOP_MID, 0, 0)
154158
btn.set_y(y)
155159

156160
if callback is not None:
157-
btn.set_event_cb(callback)
161+
btn.add_event_cb(callback, lv.EVENT.CLICKED, None)
158162

159163
return btn
160164

@@ -172,14 +176,17 @@ def align_button_pair(btn1, btn2):
172176
w = (HOR_RES - 3 * PADDING) // 2
173177
btn1.set_width(w)
174178
btn2.set_width(w)
179+
# Clear alignment and set explicit x positions
180+
btn1.set_align(lv.ALIGN.DEFAULT)
181+
btn2.set_align(lv.ALIGN.DEFAULT)
175182
btn1.set_x(PADDING)
176-
btn2.set_x(HOR_RES // 2 + PADDING // 2)
183+
btn2.set_x(PADDING + w + PADDING)
177184

178185

179186
def add_qrcode(text, y=QR_PADDING, scr=None, style=None, width=None):
180187
"""Helper functions that creates a title-styled label"""
181188
if scr is None:
182-
scr = lv.scr_act()
189+
scr = lv.screen_active()
183190

184191
if width is None:
185192
width = 350
@@ -188,7 +195,7 @@ def add_qrcode(text, y=QR_PADDING, scr=None, style=None, width=None):
188195
qr.set_text(text)
189196
qr.set_size(width)
190197
qr.set_text(text)
191-
qr.align(scr, lv.ALIGN.IN_TOP_MID, 0, y)
198+
qr.align_to(scr, lv.ALIGN.TOP_MID, 0, y)
192199
return qr
193200

194201

src/gui/components/battery.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ class Battery(lv.obj):
1414

1515
def __init__(self, *args, **kwargs):
1616
super().__init__(*args, **kwargs)
17-
self.set_style(lv.style_transp_tight)
17+
# Make background transparent in LVGL 9.x
18+
self.set_style_bg_opa(0, 0)
19+
self.set_style_border_width(0, 0)
20+
self.set_style_pad_all(0, 0)
1821
self.level = lv.label(self)
1922
self.level.set_recolor(True)
2023
self.icon = lv.label(self)
2124
self.charge = lv.label(self)
22-
self.set_size(30,20)
25+
self.set_size(30, 20)
2326
# self.bar = lv.bar(self)
2427
self.update()
2528

@@ -39,6 +42,6 @@ def update(self):
3942
self.icon.set_text(lv.SYMBOL.BATTERY_EMPTY)
4043
if self.CHARGING:
4144
self.charge.set_text(lv.SYMBOL.CHARGE)
42-
self.charge.align(self.icon, lv.ALIGN.CENTER, 0, 0)
45+
self.charge.align_to(self.icon, lv.ALIGN.CENTER, 0, 0)
4346
else:
4447
self.charge.set_text("")

src/gui/components/keyboard.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,40 @@
44
from .theme import styles
55

66

7-
class HintKeyboard(lv.btnm):
7+
class HintKeyboard(lv.buttonmatrix):
88
def __init__(self, scr, *args, **kwargs):
99
super().__init__(scr, *args, **kwargs)
10-
self.hint = lv.btn(scr)
10+
self.hint = lv.button(scr)
1111
self.hint.set_size(50, 60)
1212
self.hint_lbl = lv.label(self.hint)
1313
self.hint_lbl.set_text(" ")
14-
self.hint_lbl.set_style(0, styles["title"])
14+
self.hint_lbl.add_style(styles["title"], 0)
1515
self.hint_lbl.set_size(50, 60)
16-
self.hint.set_hidden(True)
16+
self.hint.add_flag(lv.obj.FLAG.HIDDEN)
1717
self.callback = None
18-
super().set_event_cb(self.cb)
18+
super().add_event_cb(self.cb, lv.EVENT.ALL, None)
1919

2020
def set_event_cb(self, callback):
2121
self.callback = callback
2222

2323
def get_event_cb(self):
2424
return self.callback
2525

26-
def cb(self, obj, event):
27-
if event == lv.EVENT.PRESSING:
26+
def cb(self, event):
27+
code = event.get_code()
28+
obj = event.get_target()
29+
if code == lv.EVENT.PRESSING:
2830
feed_touch()
29-
c = obj.get_active_btn_text()
31+
c = obj.get_selected_button_text()
3032
if c is not None and len(c) <= 2:
31-
self.hint.set_hidden(False)
33+
self.hint.clear_flag(lv.obj.FLAG.HIDDEN)
3234
self.hint_lbl.set_text(c)
33-
point = lv.point_t()
34-
indev = lv.indev_get_act()
35-
lv.indev_get_point(indev, point)
35+
indev = lv.indev_active()
36+
point = indev.get_point()
3637
self.hint.set_pos(point.x - 25, point.y - 130)
3738

38-
elif event == lv.EVENT.RELEASED:
39-
self.hint.set_hidden(True)
39+
elif code == lv.EVENT.RELEASED:
40+
self.hint.add_flag(lv.obj.FLAG.HIDDEN)
4041

4142
if self.callback is not None:
42-
self.callback(obj, event)
43+
self.callback(obj, code)

0 commit comments

Comments
 (0)