fix(gui): build missing power panel + wire dead entries; 2x2 selection grid (step 020a) #32

Merged
ykp merged 1 commit from fix/020a-gui-wiring into main 2026-09-28 23:49:41 +02:00
Owner

Implements step 020a from docs/backlog/020a-gui-wiring-fixes.md (P0 — the generation flow was broken).

Problems fixed

  1. Crash on first selection — _on_model_change (app.py line 153) called self._power_sat_var.config(...), but the per-satellite power panel was never built. Toggling any signal checkbox raised AttributeError: 'GengnssApp' object has no attribute '_power_sat_var' inside the Tk callback, aborting the AppModel observer loop so FeasibilityController never recomputed, can_generate stayed False and the Generate button stayed grayed — one root cause, both reported symptoms.
  2. Window height overflow — the four constellation panels (GPS / Galileo / GLONASS / BeiDou) were stacked vertically; the Signal selection tab overflowed a standard screen. They are now laid out in a 2x2 grid with even row/column weights.
  3. Dead widgets (the other 020a gaps that also kept Generate unreachable):
    • Settings entries (fs, center, duration, full scale, seed, output path) → _on_setting on FocusOut + Return (keeps the red-highlight error behavior, avoids flashing on partial input while typing)
    • Doppler / code-delay span entries → _on_span on FocusOut + Return
    • fmt / placeholder_bits comboboxes → model.update via trace_add

Changes

  • src/gengnss/gui/app.py: build the power panel in the Channel-model tab (satellite combobox tracking _sat_ids(), dB entry, Set/Remove offset buttons); hasattr guard in _on_model_change so early model notifications can never crash again; 2x2 grid layout; widget wiring.
  • tests/test_gui_app.py: gui-marked regression tests — selection toggle no longer raises and enables Generate, power offset set/remove, and the 2x2 grid layout (skip cleanly headless).

Verification

  • ruff check src tests clean on touched files (pre-existing unrelated errors in untracked src/main/ junk dir untouched)
  • pytest: 192 passed, 1 skipped (GUI tests skip headless; the regressions run in CI with a display)
  • Headless smoke of the real GengnssApp (tkinter shim): 12/12 checks — no AttributeError, can_generate → True, Generate enabled, power offsets set/remove, panels at grid cells (0,0)/(0,1)/(1,0)/(1,1)

Closes the P0 item of 020a; 020b (Browse/Save/Load) and 020c are unblocked.

Implements step 020a from `docs/backlog/020a-gui-wiring-fixes.md` (P0 — the generation flow was broken). ## Problems fixed 1. **Crash on first selection** — `_on_model_change` (app.py line 153) called `self._power_sat_var.config(...)`, but the per-satellite power panel was never built. Toggling any signal checkbox raised `AttributeError: 'GengnssApp' object has no attribute '_power_sat_var'` inside the Tk callback, aborting the `AppModel` observer loop so `FeasibilityController` never recomputed, `can_generate` stayed `False` and the **Generate button stayed grayed** — one root cause, both reported symptoms. 2. **Window height overflow** — the four constellation panels (GPS / Galileo / GLONASS / BeiDou) were stacked vertically; the Signal selection tab overflowed a standard screen. They are now laid out in a **2x2 grid** with even row/column weights. 3. **Dead widgets** (the other 020a gaps that also kept Generate unreachable): - Settings entries (fs, center, duration, full scale, seed, output path) → `_on_setting` on FocusOut + Return (keeps the red-highlight error behavior, avoids flashing on partial input while typing) - Doppler / code-delay span entries → `_on_span` on FocusOut + Return - `fmt` / `placeholder_bits` comboboxes → `model.update` via `trace_add` ## Changes - `src/gengnss/gui/app.py`: build the power panel in the Channel-model tab (satellite combobox tracking `_sat_ids()`, dB entry, Set/Remove offset buttons); `hasattr` guard in `_on_model_change` so early model notifications can never crash again; 2x2 grid layout; widget wiring. - `tests/test_gui_app.py`: gui-marked regression tests — selection toggle no longer raises and enables Generate, power offset set/remove, and the 2x2 grid layout (skip cleanly headless). ## Verification - `ruff check src tests` clean on touched files (pre-existing unrelated errors in untracked `src/main/` junk dir untouched) - `pytest`: **192 passed, 1 skipped** (GUI tests skip headless; the regressions run in CI with a display) - Headless smoke of the real `GengnssApp` (tkinter shim): 12/12 checks — no AttributeError, `can_generate → True`, Generate enabled, power offsets set/remove, panels at grid cells (0,0)/(0,1)/(1,0)/(1,1) Closes the P0 item of 020a; 020b (Browse/Save/Load) and 020c are unblocked.
fix(gui): build missing power panel + wire dead entries; 2x2 selection grid
Some checks failed
ci / test (3.12) (push) Failing after 1m4s
ci / test (3.14) (push) Failing after 2m34s
ci / test (3.9) (push) Successful in 2m24s
ci / test (3.12) (pull_request) Failing after 1m45s
ci / test (3.14) (pull_request) Failing after 2m23s
ci / test (3.9) (pull_request) Successful in 2m31s
26c94158d9
Step 020a (P0) from docs/backlog/020a-gui-wiring-fixes.md:

- build the per-satellite power panel (satellite combobox, dB entry,
  Set/Remove offset buttons) that _on_model_change/_on_set_power assumed;
  its absence raised AttributeError: 'GengnssApp' object has no attribute
  '_power_sat_var' on the first selection, aborting the observer loop so
  can_generate never became True and Generate stayed disabled
- guard _on_model_change with hasattr so early model notifications
  (before the tabs are built) can never crash again
- lay the four constellation panels out as a 2x2 grid instead of stacking
  them, keeping the window within a standard screen height
- wire the Settings entries (fs, center, duration, full scale, seed,
  output path) to _on_setting and the doppler/delay spans to _on_span on
  FocusOut + Return; wire fmt/placeholder_bits comboboxes via trace_add
- tests: gui-marked regressions for the crash, Generate enablement +
  power panel, and the 2x2 layout (skip headless)

ruff clean on touched files; pytest 192 passed, 1 skipped (headless GUI).
ykp merged commit c25399fe29 into main 2026-09-28 23:49:41 +02:00
ykp deleted branch fix/020a-gui-wiring 2026-09-28 23:49:42 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
ykp/gengnss!32
No description provided.