543 Commits

Author SHA1 Message Date
b4fde01a14 feat(kit): ToggleSwitch, the 26x14 animated instrument switch 2026-06-10 16:06:29 -04:00
a0c20e751b feat(kit): component-kit package with currentColor-tinted SVG icons 2026-06-10 15:57:33 -04:00
d43e949eee Merge feat/instrument-chrome: Instrument design system phase 2 - frameless window chrome (title bar with breadcrumb + theme toggle, accent strip, declarative status footer, dialog chrome, chrome confirms) 2026-06-10 15:19:22 -04:00
f0812757f3 docs: commit the phase 2 chrome plan; refresh footer conventions in DESIGN-SYSTEM 2026-06-10 15:19:04 -04:00
f6754120cd docs: record Instrument phase 2 (window chrome) in status/backlog 2026-06-10 15:07:45 -04:00
dfd828fe79 fix(chrome): safe No default on confirm dialogs; strip BOM artifact; tidy imports
- _MessageDialog: all buttons get setAutoDefault(False); first rejecting
  button gets setDefault(True) so Enter=No on question dialogs; falls back
  to last button (OK) for single-button info/warning dialogs
- Strip UTF-8 BOM from history_dialog.py (ast.parse-safe, diff-clean)
- Merge duplicate `from cim_suite.core.ui.chrome import …` lines in da07 main_window
- Two new tests: question defaults to No, single-OK defaults to OK (839 pass)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 14:58:23 -04:00
47079686b0 feat(ui): chrome-framed confirm/info/warning dialogs replace QMessageBox statics 2026-06-10 14:43:42 -04:00
e841df7942 fix(ui): keep per-row setting-history menu labels; breadcrumb only the dialog titles
Reverts the six per-row setting_history_action call sites (DA-12 sensors,
limits, station; DA-07 devices, channels, station) back to the default
"Setting history…" label so right-click context menus are concise and
accurate.  The two main_window._open_setting_history call sites that use
the breadcrumb only for the dialog window title are left untouched.
Six test assertions reverted to match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 14:28:03 -04:00
ddfd51c2df feat(ui): all child dialogs adopt the Instrument chrome with breadcrumb titles
Migrates all 12 dialog classes (+ 1 inline dialog) from QDialog to
ChromeDialog; top-level layouts re-parented to self.body; window titles
updated to breadcrumb form (Brand / Tool).  Setting-history action titles
at every call site updated to breadcrumb form; 6 test assertions tracking
those labels updated to match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 14:23:31 -04:00
5d863e231d feat(chrome): ChromeDialog base and message_box confirms with Instrument chrome
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 14:10:10 -04:00
6e2b05be85 feat(modules): DA-07 and IOModbus adopt the StatusFooter; retire legacy footer QSS
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 14:00:19 -04:00
68bf0842ea feat(da12): adopt the StatusFooter instrument readout
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 13:53:17 -04:00
f769f83b84 feat(chrome): declarative StatusFooter readout (dots + fields on QStatusBar) 2026-06-10 13:46:33 -04:00
05ce9df6ea feat(shell): frameless SuiteWindow with Instrument title bar, accent strip, breadcrumb
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 13:40:55 -04:00
8e2a79bb47 fix(chrome): right-align the theme toggle beside the window buttons
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 13:28:56 -04:00
52ad84de9b feat(chrome): Instrument title bar with breadcrumb and theme toggle (BL-DS2)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 13:26:11 -04:00
481676a970 feat(chrome): accent strip widget (the spec 1.3 brand gradient) 2026-06-10 13:19:31 -04:00
102fe9372e feat(chrome): add PySideSix-Frameless-Window dependency with offscreen spike test 2026-06-10 13:12:24 -04:00
b25138559d Merge feat/instrument-foundation: Instrument design system phase 1 - two-theme tokens, IBM Plex type, regenerated QSS, theme manager + launcher toggle 2026-06-10 12:24:21 -04:00
7ee8eb02e4 feat(theme): add the spec 1.3 accent-strip gradient token for phase 2 chrome 2026-06-10 12:23:53 -04:00
fcc3c0c765 docs: record Instrument phase 1 (foundation) in status/backlog; packaging font note 2026-06-10 12:18:39 -04:00
eb9c693b58 test: guard against hard-coded colors and widget stylesheets outside the theme 2026-06-10 12:12:26 -04:00
128a7bd2ef feat(shell): dark/light theme toggle on the launcher (persisted) 2026-06-10 12:06:10 -04:00
e1e63f6d0a test: restore discriminating fills in alarm-vs-staleness smoke test; fix stale docstrings 2026-06-10 12:02:13 -04:00
56c3457e38 refactor(theme): migrate all painters to live theme tokens; drop legacy Color/SEVERITY API
Replace the eight import-time snapshot dicts (Color.*, SEVERITY, STALENESS, CHART)
with call-time current().severity/.staleness/.chart lookups and qcolor() conversion
across loading_overlay, group_band_delegate, serial_edit_dialog, traffic_tab,
alarm_tab, channels_tab (da07), sensors_tab, and history_dialog (da12). Delete the
legacy Color, Type, SEVERITY, STALENESS, CHART exports from tokens.py and their
re-export line in theme/__init__.py. Update two test files to use current() and
qcolor() for reference color values; add autouse _restore_theme_state fixture to
root conftest so theme state never bleeds between tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 11:53:17 -04:00
cf6e433819 feat(theme): theme manager with dark/light switching, persistence, change signal 2026-06-10 11:38:25 -04:00
e1e8d7aaaa docs(theme): note that Qt ignores text-transform; microcaps land via type_styles in phase 3 2026-06-10 11:34:30 -04:00
237f7e312a feat(theme): regenerate QSS from Instrument tokens (light + dark capable)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 11:26:01 -04:00
56c42bee4c feat(theme): IBM Plex font loading + named type styles; retire Lato
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 11:10:26 -04:00
e6e6182ea5 feat(theme): Instrument two-theme tokens (light/dark) + qcolor helper
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 10:54:27 -04:00
c4cb992b54 chore(theme): bundle IBM Plex Sans + Mono (OFL) for the Instrument system 2026-06-10 10:48:08 -04:00
e6155f355c docs: Instrument phase 1 (foundation) implementation plan
Nine bite-sized tasks: bundle IBM Plex, two-theme tokens + qcolor,
font loader + type styles, Instrument QSS rewrite, theme manager with
persistence, consumer migration off the legacy Color/SEVERITY API,
launcher theme toggle, design-discipline guard test, wrap-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 10:43:33 -04:00
6d774e3edf docs: Instrument design system spec, mockups, and rollout design
The visual spec (token tables, type styles, component rules, Qt notes),
the approved mockup HTML (visual reference only - the spec takes
precedence), and the brainstormed six-phase rollout design covering
foundation/theming, frameless chrome, the core component kit, and
per-module adoption (DA-12, DA-07, IOModbus, launcher).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 10:27:50 -04:00
edc8c6cc2d fix(ui): auto-fit table columns to contents as rows arrive
The shared TableTab fit columns to contents exactly once, on the first
non-empty repaint. DA-12 sensors stream in one at a time, so that fit
often saw only row 0 and the Serial column clipped every wider serial
below it. The Station "Description of Setting" column had a parallel
bug: it was fit before mark_cell_help prepended the marker, leaving it
a marker too narrow. Both also lost a few px to Qt's tight size hint.

Replace the one-shot _sized guard with: re-fit on row-set size change
(not on value ticks, so live numbers don't jiggle), re-fit a help cell's
column after the marker is added, add headroom so the last glyph never
clips, and record user-dragged columns so auto-fit leaves them alone.

Fixes apply to every TableTab grid in DA-12 and DA-07.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 09:25:31 -04:00
2744ab9535 Merge feat/end-user-distribution: end-user distribution — per-user installer + portable zip, signing-ready (BL-P1)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 11:25:25 -04:00
24ad18df42 fix(packaging): track icon source art; pipe-delimit CIM_SIGN_PARAMS
- Commit docs/samples/icon.png so make_icon.py can regenerate the committed
  icon.ico / app_icon.png from source.
- build.ps1 split CIM_SIGN_PARAMS on '|' not ' ', so a cert subject name with
  spaces (e.g. /n|CIMTechniques, Inc.) reaches signtool intact when signing is
  enabled. Doc example updated to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 11:23:49 -04:00
df5466b7f6 docs: release-packaging guide + track distribution (BL-P1..P4)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 11:09:36 -04:00
2b25c40f84 feat(packaging): one-shot build script (installer + portable, gated signing)
Copies READ-ME-FIRST.txt to the dist root so it sits beside the exe in the zip
and at {app} root after install. Degrades gracefully to portable-only when Inno
Setup is absent. Signing of inner exe + installer is gated on CIM_SIGN_CERT.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 11:07:27 -04:00
c7ab790218 feat(packaging): per-user no-admin installer + versioned output name
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 11:03:34 -04:00
24cdfc0019 fix(packaging): keep README at bundle root, exclude build-only Pillow
READ-ME-FIRST.txt as a PyInstaller data file lands in _internal\ (sys._MEIPASS),
where users never see it; build.ps1 will copy it to the dist root instead. Also
exclude PIL — it is a build-time-only dep (make_icon.py), not shipped runtime.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 11:01:40 -04:00
db56cda0ca feat(packaging): embed app icon + version metadata in the frozen exe
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:55:54 -04:00
60186b8eba docs(packaging): bundle an end-user READ-ME-FIRST run guide
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:50:33 -04:00
dc7dbd5229 feat(shell): set the suite window/taskbar icon at runtime 2026-06-08 10:47:40 -04:00
8790364ec0 feat(packaging): generate committed app icon (.ico + runtime png) 2026-06-08 10:42:16 -04:00
81b66ffcb7 test(packaging): cover version truncation + render syntax validity
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:39:12 -04:00
2d39c4f5ec feat(packaging): version-resource helper for the frozen exe 2026-06-08 10:34:37 -04:00
b349099357 docs(plan): end-user distribution implementation plan
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:30:14 -04:00
98d0ac7191 docs(spec): end-user distribution — per-user installer + portable zip, signing-ready
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:21:55 -04:00
66fb01f6b1 fix(da12): match real-hardware station-setting labels (BL-D3)
A real DA-12 sends station-setting labels with parenthetical hints and
slightly different wording than our curated keys (e.g. "Subnet bits
(0=class A B C)", "Acquire sensors (0=off, 1=on)", "Station's mac
address"). Matching keyed off normalize_label (whitespace+case only), so
help text, subnet editing, and the reboot prompt silently missed on real
hardware while passing in the simulator -- whose seed labels were copied
from our keys, not from the device.

- Add core.ui.help.setting_match_key: strips the trailing parenthetical
  hint before normalizing, so a verbose wire label matches its short key.
  Used by station_tab (help + subnet) and reboot_settings.
- Seed the simulator with the EXACT labels a real DA-12 sends (captured
  in docs/samples screenshots), closing the test gap that hid this. Adds
  the 7 settings the capture revealed we weren't modeling.
- Fix repo_snapshot MAC lookup ("Station's mac address", not "MAC
  Addr") -- station_mac() returned None on real hardware, so the settings
  repository recorded nothing.
- Re-key STATION_SETTINGS to the real labels; fix Battery (run-time hrs,
  not capacity %); promote Local port / Local IP / Gateway out of the
  parked DA-06-tainted list using the verified docs/da12c_status.py
  reference. Firmware-internal fields stay help-less by design.

783 tests pass; ruff clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 09:35:18 -04:00
fb08c8e896 Merge feat/revert-setting-to-historical-value: revert a setting to a historical value (BL-R1) 2026-06-08 09:05:27 -04:00