diff --git a/openpilot/selfdrive/ui/sunnypilot/layouts/settings/models.py b/openpilot/selfdrive/ui/sunnypilot/layouts/settings/models.py index b9db390440..5c4db49440 100644 --- a/openpilot/selfdrive/ui/sunnypilot/layouts/settings/models.py +++ b/openpilot/selfdrive/ui/sunnypilot/layouts/settings/models.py @@ -13,7 +13,7 @@ from openpilot.cereal import custom from openpilot.sunnypilot.models.helpers import ACTIVE_BUNDLE_KEYS, get_selected_bundle, resolve_bundle_by_ref from openpilot.common.constants import CV from openpilot.selfdrive.ui.ui_state import device, ui_state -from openpilot.selfdrive.ui.sunnypilot.model_info import active_source, bundles_for_source, default_model_name, model_info +from openpilot.selfdrive.ui.sunnypilot.model_info import active_source, bundles_for_source, default_model, default_model_name, model_info from openpilot.system.ui.lib.multilang import tr from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.widgets import DialogResult, Widget @@ -163,26 +163,23 @@ class ModelsLayout(Widget): state = self._download_row_state(progresses, bundle.internalName) if queued := self._queued_name(bundle.ref): - state["name"] += f" ยท {queued} {tr('queued')}" + state["name"] += f" | {queued} {tr('queued')}" self.download_item.action_item.update(**state) self._downloading = self.download_item.action_item.downloading ds = custom.ModelManagerSP.DownloadStatus self._verifying = any(getattr(p.status, 'raw', p.status) == ds.verifying for p in progresses) def _slot_segments(self): - """One segment per slot: name, downloaded check or empty-slot mark, active in green.""" + """small and big slots side by side; the active side is green, an empty slot shows its default.""" active = active_source() segments = [] - for source in ("qcom", "usbgpu"): + for source, label in (("qcom", tr("small")), ("usbgpu", tr("big"))): + if segments: + segments.append(("|", rl.GRAY, None, None)) bundle = get_selected_bundle(ui_state.params, source) - name = bundle.internalName if bundle else tr("Default") - if source == active: - name += f" ({tr('active')})" - color = ON_COLOR if source == active else rl.GRAY - if bundle: - segments.append((name, color, "icons/checkmark.png", None)) - else: - segments.append((name, color, "icons/circled_slash.png", rl.WHITE)) + name = bundle.internalName if bundle else default_model(source) + segments.append((label, rl.GRAY, None, None)) + segments.append((name, ON_COLOR if source == active else rl.LIGHTGRAY, "icons/checkmark.png", None)) return segments def _queued_name(self, current_ref): diff --git a/openpilot/selfdrive/ui/sunnypilot/model_info.py b/openpilot/selfdrive/ui/sunnypilot/model_info.py index 2c88ac2358..8348d68426 100644 --- a/openpilot/selfdrive/ui/sunnypilot/model_info.py +++ b/openpilot/selfdrive/ui/sunnypilot/model_info.py @@ -22,8 +22,12 @@ def bundles_for_source(source: str): return get_cached_bundles(ui_state.params, source) +def default_model(source: str) -> str: + return DEFAULT_BIG_MODEL if source == 'usbgpu' else DEFAULT_MODEL + + def default_model_name(source: str) -> str: - return f"{DEFAULT_BIG_MODEL if source == 'usbgpu' else DEFAULT_MODEL} (Default)" + return f"{default_model(source)} (Default)" def model_info() -> tuple[str, str, str]: diff --git a/openpilot/system/ui/sunnypilot/widgets/download_status.py b/openpilot/system/ui/sunnypilot/widgets/download_status.py index cd71970c03..8af4d98f62 100644 --- a/openpilot/system/ui/sunnypilot/widgets/download_status.py +++ b/openpilot/system/ui/sunnypilot/widgets/download_status.py @@ -25,6 +25,7 @@ ICON_PADDING = 12 BAR_WIDTH = 1100 BAR_HEIGHT = 20 SEGMENT_GAP = 24 +SEGMENT_NAME_MAX_WIDTH = 380 BAR_GAP = 16 BAR_RADIUS = BAR_HEIGHT / 2 CAPSULE_POINTS = 24 @@ -47,6 +48,7 @@ class DownloadStatusAction(ItemAction): self.name = "" self.status_text = "" self.segments: list[tuple[str, rl.Color, str | None, rl.Color | None]] | None = None + self._segment_labels: list[UnifiedLabel] = [] self.downloading = False self.text_color = rl.GRAY self.icon: str | None = None @@ -99,7 +101,7 @@ class DownloadStatusAction(ItemAction): """[(segment, text width, total width incl. icon and gap)]""" out = [] for i, seg in enumerate(self.segments or []): - text_width = measure_text_cached(self._font, seg[0], FONT_SIZE).x + text_width = min(measure_text_cached(self._font, seg[0], FONT_SIZE).x, SEGMENT_NAME_MAX_WIDTH) total = text_width + (ICON_PADDING + ICON_SIZE if seg[2] else 0) + (SEGMENT_GAP if i else 0) out.append((seg, text_width, total)) return out @@ -182,12 +184,20 @@ class DownloadStatusAction(ItemAction): def _render_segments(self, rect: rl.Rectangle): measured = self._measured_segments() + while len(self._segment_labels) < len(measured): + self._segment_labels.append(UnifiedLabel("", font_size=FONT_SIZE, max_width=SEGMENT_NAME_MAX_WIDTH, + scroll=True, wrap_text=False)) x = rect.x + rect.width - sum(total for _, _, total in measured) for i, ((text, color, icon, icon_color), text_width, _) in enumerate(measured): if i: x += SEGMENT_GAP + label = self._segment_labels[i] + if label.text != text: + label.set_text(text) + label.set_text_color(color) text_height = measure_text_cached(self._font, text, FONT_SIZE).y - rl.draw_text_ex(self._font, text, rl.Vector2(x, rect.y + (rect.height - text_height) / 2), FONT_SIZE, 0, color) + label.set_position(x, rect.y + (rect.height - text_height) / 2) + label.render() x += text_width if icon: texture = gui_app.texture(icon, ICON_SIZE, ICON_SIZE, keep_aspect_ratio=True)