fix(ui): protected-bands edit dialog opened EMPTY — grab_set before viewable #46
No reviewers
Labels
No labels
accessibility
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
ykp/gensig!46
Loading…
Reference in a new issue
No description provided.
Delete branch "fix-protected-dialog-empty"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why the dialog was empty
ProtectedBandsDialog.__init__calledgrab_set()immediately after creating the Toplevel — before the body was built and before the window was mapped. On Windows (and any WM where the toplevel isn't yet viewable)grab_set()raisesTclError: grab failed: window not viewable; the constructor aborted before_build_body()ran, leaving the dialog window open and completely empty. The button-callback traceback goes to an invisible stderr (pythonw), so the only visible symptom was an empty "Protected bands" window.The CI widget tier never caught it because the edit test monkeypatched the constructor away — the real construction path had zero coverage.
Fix
protocol(WM_DELETE_WINDOW → cancel)→deiconify()→wait_visibility()→grab_set()→focus_set()._on_edit_protected_bandsnow blocks withwait_window(dialog): proper modal semantics, keeps a live reference to the dialog for its whole life (an unreferenced Toplevel can be garbage-collected — a second classic bug the old code was exposed to), and refreshes the count label after the dialog closes (matching the documented commit-on-OK behavior; the previous code refreshed while the dialog was still open).wait_windowreturns at once; two new real-dialog tests (no monkeypatch, CI widget tier): the dialog opens with content (tree rows, status label, copy semantics — add-on-copy leaves the project untouched until OK), OK commits, cancel/WM-close discards. These exercise the fixed construction path end-to-end.Gate
pytest: 1278 passed / 64 skipped (headless tier), coverage 93.51 %ruff+mypy: clean