Release 1.4.2: load-only dialog when nothing is selected
tests / fedora:latest (push) Successful in 1m15s
tests / ubuntu-latest · py3.11 (push) Successful in 1m32s
tests / ubuntu-latest · py3.13 (push) Successful in 1m1s
tests / archlinux:latest (push) Successful in 53s
tests / debian:12 (push) Successful in 51s
tests / ubuntu:24.04 (push) Successful in 1m8s
tests / NixOS (FHS wrapper from docs/NIXOS.md) (push) Skipped
Build PCM package / build (push) Successful in 10s
tests / fedora:latest (push) Successful in 1m15s
tests / ubuntu-latest · py3.11 (push) Successful in 1m32s
tests / ubuntu-latest · py3.13 (push) Successful in 1m1s
tests / archlinux:latest (push) Successful in 53s
tests / debian:12 (push) Successful in 51s
tests / ubuntu:24.04 (push) Successful in 1m8s
tests / NixOS (FHS wrapper from docs/NIXOS.md) (push) Skipped
Build PCM package / build (push) Successful in 10s
With neither mode derivable (nothing selected, no marker rectangles, no config) the dialog now opens anyway instead of failing with an error figure: both radios disabled with their reasons, OK/Save disabled, Load config… live - a saved config can bootstrap the run. README: note that macOS/NixOS field tests last ran with plugin v1.3. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HjSRLWQ8ywBBYyakvr3YTx
This commit is contained in:
+47
-19
@@ -26,7 +26,11 @@ Two run modes share the dialog, chosen by a radio at the top:
|
||||
|
||||
"Load config…" swaps the whole setup for another config file: ask()
|
||||
then returns a LoadRequest instead of a Selection and main re-derives
|
||||
everything from that file and reopens the dialog.
|
||||
everything from that file and reopens the dialog. The dialog even
|
||||
opens with NO runnable mode at all (nothing selected, no marker
|
||||
rectangles, no config) - load-only: both radios unchecked and
|
||||
disabled with their reasons, OK/Save disabled - so a saved config can
|
||||
bootstrap the run.
|
||||
|
||||
Row identity is POSITIONAL: the tables never sort or reorder, so
|
||||
main.py zips Selection.pdn_rows with its own parallel terminal list.
|
||||
@@ -205,16 +209,28 @@ class _Dialog(QDialog):
|
||||
self.mode_pdn = QRadioButton("PDN")
|
||||
self.mode_classic.setEnabled(self._classic_ok)
|
||||
self.mode_pdn.setEnabled(self._pdn_ok)
|
||||
start_pdn = self._pdn_ok and (not self._classic_ok
|
||||
or start_mode == "pdn")
|
||||
(self.mode_pdn if start_pdn else self.mode_classic).setChecked(True)
|
||||
reason = None
|
||||
# with NEITHER mode derivable (nothing selected, no marker
|
||||
# rectangles, no config terminals) the dialog still opens
|
||||
# LOAD-ONLY: no radio checked, OK/Save disabled below - so
|
||||
# "Load config…" can pull in a saved setup instead of the
|
||||
# launch dying with an error figure
|
||||
self._no_mode = not (self._classic_ok or self._pdn_ok)
|
||||
if not self._no_mode:
|
||||
start_pdn = self._pdn_ok and (not self._classic_ok
|
||||
or start_mode == "pdn")
|
||||
(self.mode_pdn if start_pdn
|
||||
else self.mode_classic).setChecked(True)
|
||||
reasons = []
|
||||
if not self._classic_ok and classic_reason:
|
||||
reason = f"Classic unavailable: {classic_reason}"
|
||||
reasons.append(f"Classic unavailable: {classic_reason}")
|
||||
self.mode_classic.setToolTip(classic_reason)
|
||||
elif not self._pdn_ok and pdn_reason:
|
||||
reason = f"PDN unavailable: {pdn_reason}"
|
||||
if not self._pdn_ok and pdn_reason:
|
||||
reasons.append(f"PDN unavailable: {pdn_reason}")
|
||||
self.mode_pdn.setToolTip(pdn_reason)
|
||||
if self._no_mode and load_dir is not None:
|
||||
reasons.append("Load config… below can still set up a run "
|
||||
"from a saved config file.")
|
||||
reason = "\n".join(reasons) if reasons else None
|
||||
|
||||
# --- shared form #1 --------------------------------------------
|
||||
form1 = QFormLayout()
|
||||
@@ -387,14 +403,23 @@ class _Dialog(QDialog):
|
||||
buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
buttons.accepted.connect(self._try_accept)
|
||||
buttons.rejected.connect(self.reject)
|
||||
self.ok_button = buttons.button(QDialogButtonBox.Ok)
|
||||
self.load_button = None
|
||||
self.save_button = None
|
||||
if load_dir is not None:
|
||||
load_btn = buttons.addButton("Load config…",
|
||||
QDialogButtonBox.ActionRole)
|
||||
load_btn.clicked.connect(self._load_config)
|
||||
self.load_button = buttons.addButton(
|
||||
"Load config…", QDialogButtonBox.ActionRole)
|
||||
self.load_button.clicked.connect(self._load_config)
|
||||
if save_callback is not None:
|
||||
save_btn = buttons.addButton("Save config…",
|
||||
QDialogButtonBox.ActionRole)
|
||||
save_btn.clicked.connect(self._save_config)
|
||||
self.save_button = buttons.addButton(
|
||||
"Save config…", QDialogButtonBox.ActionRole)
|
||||
self.save_button.clicked.connect(self._save_config)
|
||||
if self._no_mode:
|
||||
# nothing to run or to save until a load re-derives; Load
|
||||
# config… and Cancel stay live
|
||||
self.ok_button.setEnabled(False)
|
||||
if self.save_button is not None:
|
||||
self.save_button.setEnabled(False)
|
||||
|
||||
content = QWidget()
|
||||
lay = QVBoxLayout(content)
|
||||
@@ -405,11 +430,12 @@ class _Dialog(QDialog):
|
||||
mode_row.addWidget(self.mode_pdn)
|
||||
mode_row.addStretch(1)
|
||||
lay.addLayout(mode_row)
|
||||
self.reason_label = None
|
||||
if reason is not None:
|
||||
rl = QLabel(reason)
|
||||
rl.setWordWrap(True)
|
||||
rl.setStyleSheet("color: gray; font-size: 10px;")
|
||||
lay.addWidget(rl)
|
||||
self.reason_label = QLabel(reason)
|
||||
self.reason_label.setWordWrap(True)
|
||||
self.reason_label.setStyleSheet("color: gray; font-size: 10px;")
|
||||
lay.addWidget(self.reason_label)
|
||||
lay.addLayout(form1)
|
||||
if self.classic_section is not None:
|
||||
lay.addWidget(self.classic_section)
|
||||
@@ -997,7 +1023,9 @@ def ask(candidates: dict[str, list[str]], layer_order: list[str],
|
||||
config file); pdn: the PDN terminal setup (editable tables);
|
||||
pdn_candidates: net candidates for PDN mode (classic uses
|
||||
`candidates`); classic_reason / pdn_reason: why a mode is
|
||||
unavailable (its radio is disabled with the reason shown);
|
||||
unavailable (its radio is disabled with the reason shown; with
|
||||
BOTH unavailable the dialog opens load-only - OK and Save disabled
|
||||
until Load config… returns a LoadRequest);
|
||||
save_callback(selection, target_path) -> saved name string enables
|
||||
the "Save config…" button in both modes (the file name is asked
|
||||
per save, seeded with save_target); load_dir (the board directory)
|
||||
|
||||
Reference in New Issue
Block a user