feat(ui): chrome-framed confirm/info/warning dialogs replace QMessageBox statics

This commit is contained in:
2026-06-10 14:43:42 -04:00
parent e841df7942
commit 47079686b0
11 changed files with 42 additions and 59 deletions

View File

@@ -1,4 +1,4 @@
"""Reusable "Setting history…" dialog: Timestamp / Setting / Value, newest first,
"""Reusable "Setting history…" dialog: Timestamp / Setting / Value, newest first,
with a text filter and xlsx export. Module-agnostic — it only reads pre-formatted
``display`` from the store, never calling back into any module's formatter."""
@@ -14,13 +14,14 @@ from PySide6.QtWidgets import (
QHBoxLayout,
QLineEdit,
QMenu,
QMessageBox,
QPushButton,
QTableWidget,
QTableWidgetItem,
QVBoxLayout,
)
from cim_suite.core.ui.chrome import message_box
from cim_suite.core.export import Cell, Sheet, write_xlsx
from cim_suite.core.ui.chrome import ChromeDialog
@@ -129,15 +130,12 @@ class SettingHistoryDialog(ChromeDialog):
def _apply(self, src, writer) -> None:
label = src["label"]
display = src["display"] or ""
confirmed = QMessageBox.question(
if not message_box.question(
self,
"Set to this value",
f"Set “{label}” to “{display}”?\n\n"
"This will be written to the connected station.",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
QMessageBox.StandardButton.No,
)
if confirmed != QMessageBox.StandardButton.Yes:
):
return
writer(src["value"])
# The recorder logs the revert on a short debounce; reload just past it so

View File

@@ -14,9 +14,10 @@ from pathlib import Path
from typing import Callable
from PySide6.QtGui import QAction
from PySide6.QtWidgets import QFileDialog, QMessageBox, QTabWidget, QToolBar, QWidget
from PySide6.QtWidgets import QFileDialog, QTabWidget, QToolBar, QWidget
from cim_suite.core.export import Sheet, write_xlsx
from cim_suite.core.ui.chrome import message_box
MetadataProvider = Callable[[], dict[str, str]]
@@ -47,7 +48,7 @@ def save_sheets_dialog(
try:
write_xlsx(path, sheets)
except OSError as exc:
QMessageBox.warning(parent, "Export failed", f"Could not write the file:\n{exc}")
message_box.warning(parent, "Export failed", f"Could not write the file:\n{exc}")
return None
remember_dir(str(Path(path).parent))
return path
@@ -103,7 +104,7 @@ def add_export_actions(
def _save(default_name: str, sheets: list[Sheet]) -> None:
if not sheets:
QMessageBox.information(parent, "Export", "Nothing to export on this screen.")
message_box.information(parent, "Export", "Nothing to export on this screen.")
return
save_sheets_dialog(
parent, default_name, sheets, last_dir=last_dir, remember_dir=remember_dir

View File

@@ -9,6 +9,7 @@ and severity-tinted; "—" until the first 'H' arrives. M/N frames populate the
from __future__ import annotations
from cim_suite.core.ui.chrome import message_box
from cim_suite.core.ui.table_tab import TableTab
from cim_suite.core.ui.theme import current, qcolor
@@ -45,11 +46,10 @@ class AlarmTab(TableTab):
vbox.addWidget(bar)
def _clear(self) -> None:
from PySide6.QtWidgets import QMessageBox
if QMessageBox.question(
if message_box.question(
self, "Clear Indicators",
"Clear all alarm-indicator settings on the station?",
) == QMessageBox.StandardButton.Yes:
):
self._ctrl.clear_alarm_indicators()
def _ensure_columns(self, n_dev: int) -> None:

View File

@@ -7,12 +7,13 @@ from pathlib import Path
from PySide6.QtWidgets import (
QApplication,
QHBoxLayout,
QMessageBox,
QPushButton,
QVBoxLayout,
QWidget,
)
from cim_suite.core.ui.chrome import message_box
from cim_suite.core.ui.table_tab import TableTab
from .. import config
@@ -74,8 +75,7 @@ class CalibrationTab(TableTab):
self._rewrite()
def _erase(self) -> None:
if QMessageBox.question(self, "Erase All", "Erase the entire calibration history?") \
!= QMessageBox.StandardButton.Yes:
if not message_box.question(self, "Erase All", "Erase the entire calibration history?"):
return
self._records = []
self._rewrite()

View File

@@ -4,6 +4,7 @@ from __future__ import annotations
from PySide6.QtCore import Qt, Signal
from cim_suite.core.ui.chrome import message_box
from cim_suite.core.ui.combo_delegate import ComboBoxDelegate
from cim_suite.core.ui.copy_menu import set_extra_actions
from cim_suite.core.ui.help import normalize_label
@@ -26,15 +27,10 @@ _EMPTY_TYPE_HINT = "— pick a type to add —"
def _confirm_remove(parent) -> bool:
from PySide6.QtWidgets import QMessageBox
return (
QMessageBox.question(
parent,
"Remove Device",
"Remove the selected device from this station?",
)
== QMessageBox.StandardButton.Yes
return message_box.question(
parent,
"Remove Device",
"Remove the selected device from this station?",
)
@@ -178,12 +174,10 @@ class DevicesTab(TableTab):
self._ctrl.remove_device(index)
def _reacquire(self, index: int) -> None:
from PySide6.QtWidgets import QMessageBox
if QMessageBox.question(
if message_box.question(
self,
"Re-acquire Device",
f"Flag device {index + 1} for reset/re-acquire? It stays on the station "
"but re-runs its acquisition.",
) == QMessageBox.StandardButton.Yes:
):
self._ctrl.reacquire_device(index)

View File

@@ -9,12 +9,13 @@ from PySide6.QtGui import QAction
from PySide6.QtWidgets import (
QLabel,
QMainWindow,
QMessageBox,
QSizePolicy,
QTabWidget,
QWidget,
)
from cim_suite.core.ui.chrome import message_box
from cim_suite.core.ui.chrome import StatusFooter
from cim_suite.core.ui.copy_menu import enable_copy_in
from cim_suite.core.ui.export_action import add_export_actions
@@ -203,8 +204,7 @@ class MainWindow(QMainWindow):
self._connector(port)
def _reset(self) -> None:
if QMessageBox.question(self, "Reboot Station", "Reboot the station now?") \
== QMessageBox.StandardButton.Yes:
if message_box.question(self, "Reboot Station", "Reboot the station now?"):
self._ctrl.reboot_station()
# --- signal handlers ---------------------------------------------------

View File

@@ -7,12 +7,13 @@ from pathlib import Path
from PySide6.QtWidgets import (
QApplication,
QHBoxLayout,
QMessageBox,
QPushButton,
QVBoxLayout,
QWidget,
)
from cim_suite.core.ui.chrome import message_box
from .. import config
from ..domain import calibration as cal
from cim_suite.core.sensor_models import identify
@@ -79,8 +80,7 @@ class CalibrationTab(TableTab):
self._rewrite()
def _erase(self) -> None:
if QMessageBox.question(self, "Erase All", "Erase the entire calibration history?") \
!= QMessageBox.StandardButton.Yes:
if not message_box.question(self, "Erase All", "Erase the entire calibration history?"):
return
self._records = []
self._rewrite()

View File

@@ -13,12 +13,13 @@ from cim_suite.core.ui.export_action import add_export_actions
from PySide6.QtWidgets import (
QLabel,
QMainWindow,
QMessageBox,
QSizePolicy,
QTabWidget,
QWidget,
)
from cim_suite.core.ui.chrome import message_box
from ..domain.server_link import ServerLinkState, ServerLinkStatus
from ..protocol import messages as m
from .alarm_limits_tab import AlarmLimitsTab
@@ -182,8 +183,7 @@ class MainWindow(QMainWindow):
self._connector(port)
def _reset(self) -> None:
if QMessageBox.question(self, "Reboot Station", "Reboot the station now?") \
== QMessageBox.StandardButton.Yes:
if message_box.question(self, "Reboot Station", "Reboot the station now?"):
self._ctrl.reboot_station()
# --- signal handlers ---------------------------------------------------

View File

@@ -126,11 +126,8 @@ def test_menu_enabled_for_writable_disabled_for_readonly(qtbot):
def test_apply_writes_value_after_confirm(qtbot, monkeypatch):
from PySide6.QtWidgets import QMessageBox
monkeypatch.setattr(
QMessageBox, "question",
lambda *a, **k: QMessageBox.StandardButton.Yes,
)
from cim_suite.core.ui.chrome import message_box
monkeypatch.setattr(message_box, "question", lambda *a, **k: True)
repo = _repo_with_rows()
writes, resolver = _writer_for_scale_only(repo)
dlg = SettingHistoryDialog(repo, "MAC1", key_prefix="da12:sensor:1:", writer_for=resolver)
@@ -141,11 +138,8 @@ def test_apply_writes_value_after_confirm(qtbot, monkeypatch):
def test_apply_aborts_when_declined(qtbot, monkeypatch):
from PySide6.QtWidgets import QMessageBox
monkeypatch.setattr(
QMessageBox, "question",
lambda *a, **k: QMessageBox.StandardButton.No,
)
from cim_suite.core.ui.chrome import message_box
monkeypatch.setattr(message_box, "question", lambda *a, **k: False)
repo = _repo_with_rows()
writes, resolver = _writer_for_scale_only(repo)
dlg = SettingHistoryDialog(repo, "MAC1", key_prefix="da12:sensor:1:", writer_for=resolver)

View File

@@ -351,7 +351,7 @@ def test_alarm_tab_edit_address_reaches_station(qtbot):
def test_alarm_tab_clear_button_clears_indicators(qtbot, monkeypatch):
from PySide6.QtWidgets import QMessageBox
from cim_suite.core.ui.chrome import message_box
from cim_suite.modules.da07.ui.alarm_tab import AlarmTab
ctrl, _ = _wired(devices=2, channels=2)
@@ -359,8 +359,7 @@ def test_alarm_tab_clear_button_clears_indicators(qtbot, monkeypatch):
qtbot.addWidget(tab)
assert ctrl.alarms.get(0).active is True # seeded active
# auto-confirm the dialog
monkeypatch.setattr(QMessageBox, "question",
lambda *a, **k: QMessageBox.StandardButton.Yes)
monkeypatch.setattr(message_box, "question", lambda *a, **k: True)
tab.btn_clear.click()
ctrl.refresh()
assert ctrl.alarms.get(0).active is False
@@ -531,8 +530,7 @@ def test_remove_action_calls_controller(qtbot, monkeypatch):
def test_reacquire_action_present_and_calls_controller(qtbot, monkeypatch):
# BL-E9: a configured device row offers "Re-acquire Device…" -> controller.reacquire.
from PySide6.QtWidgets import QMessageBox
from cim_suite.core.ui.chrome import message_box
from cim_suite.core.ui.copy_menu import build_menu_for_test
from cim_suite.modules.da07.ui.devices_tab import DevicesTab
@@ -545,7 +543,7 @@ def test_reacquire_action_present_and_calls_controller(qtbot, monkeypatch):
empty_menu = build_menu_for_test(tab.table, 3, 0)
assert not any("Re-acquire" in a.text() for a in empty_menu.actions())
monkeypatch.setattr(QMessageBox, "question", lambda *a, **k: QMessageBox.StandardButton.Yes)
monkeypatch.setattr(message_box, "question", lambda *a, **k: True)
called = []
monkeypatch.setattr(ctrl, "reacquire_device", lambda idx: called.append(idx))
tab._reacquire(0)

View File

@@ -1,5 +1,3 @@
from PySide6.QtWidgets import QMessageBox
from cim_suite.modules.da12.domain.controller import StationController
from cim_suite.modules.da12.transport.simulator import SimulatedStation
from cim_suite.modules.da12.ui.main_window import MainWindow
@@ -82,9 +80,9 @@ def test_banner_button_runs_confirm_then_reboot(qtbot, monkeypatch):
qtbot.addWidget(win)
# User confirms the reboot dialog.
monkeypatch.setattr(
QMessageBox, "question", lambda *a, **k: QMessageBox.StandardButton.Yes
)
from cim_suite.core.ui.chrome import message_box
monkeypatch.setattr(message_box, "question", lambda *a, **k: True)
sent = []
monkeypatch.setattr(ctrl, "reboot_station", lambda: sent.append(True))