Task: Land NATS notification-wiring capability in the qt-profile controller template

Table of Contents

This page documents a task in the Commission: currency story. It captures the goal, current status, acceptance, and any notes or results.

Goal

Land the handler-generation half of the controller template's changed_event_class mechanism: currently it wires the subscription but generates no onNotificationReceived=/staleness-propagation handler, so that logic is 100% hand-added in =CurrencyController. Generalise it, with currency as the first real consumer — no peer currently configures changed_event_class. Step 5 of the regenerate plan (task 6E0CD16E).

Status

Field Value
State DONE
Parent story Commission: currency
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-07-08

Acceptance

  • The controller template generates the notification-handling/ staleness-propagation logic for any entity with changed_event_class set, not just a subscription stub.
  • Regenerating currency's controller reproduces equivalent behaviour to the current hand-added onNotificationReceived.
  • Build passes.

Plan

Investigated the base class first: EntityController already subscribes to changed_event_class and has a private onNotificationReceived slot that filters by event name and marks listWindow() stale generically — that half was never missing. CurrencyController doesn't override listWindow(), so it never used the base mechanism; instead it hand-rolled its own parallel onNotificationReceived, connected directly, which (a) duplicates the list-marking the base already does and (b) additionally iterates managed_windows_ to mark open detail/history dialogs stale by qobject_cast-ing to the concrete CurrencyDetailDialog=/ =CurrencyHistoryDialog types and calling their entity-specific isoCode()=/=code() accessors.

Rather than regenerate that duplication, added a clean extension point to the base class: a new protected virtual notifyOpenDialogs(const QStringList&) hook, called from the base's existing onNotificationReceived right after the list-window marking. Default no-op. Generated controllers (gated by changed_event_class, already-existing flag) override it.

The override needed a way to identify open dialogs generically without knowing their concrete type. HistoryDialogBase already had a virtual code() accessor (added earlier for exactly this purpose); added the symmetric code() to DetailDialogBase (default empty) and generated an override in the detail_dialog template returning the entity's key field as a QString via the existing key_to_string_prefix=/=suffix convention (works for both text and uuid keys). The generated notifyOpenDialogs() then iterates managed_windows_, qobject_casts each tracked widget to DetailDialogBase*=/=HistoryDialogBase* (generic — no concrete type needed), and calls markAsStale() on matches — same "details:"/"history:" key-prefix + entityIds-match semantics as currency's hand-written version, just against the base types instead of duplicating an onNotificationReceived slot.

Verified by regenerating currency's ores.cpp.qt profile with changed_event_class flipped on and rebuilding ores.qt.refdata.lib for real (not just diffed): caught and fixed a real bug from the earlier version-nav PR in the process (onRevertClicked's confirmation string used the wrong mustache path, domain_entity.key_field instead of domain_entity.qt.key_field, rendering empty and breaking compilation) — replaced with a call to the newly-generated code() accessor, which is both correct and more generic (handles uuid keys too). CurrencyController.cpp and CurrencyDetailDialog.cpp (the two files this task's and the version-nav capability touch) compiled clean after the fix. CurrencyHistoryDialog.cpp and CurrencyMdiWindow.cpp still fail to compile when regenerated — pre-existing, unrelated drift (the iso_code=/=iso_codes singular/plural mismatch on the delete request, and currency's documented split history-protocol gap), tracked by the "Sync Qt codegen for currency" task, not this one. Discarded all regenerated currency files after verification; only the templates, EntityController=/=DetailDialogBase base-class additions, and currency's model flags are kept.

Notes

notifyOpenDialogs generalises further than currency's hand-written mechanism: it works off the generic DetailDialogBase=/ =HistoryDialogBase pointers rather than the concrete per-entity dialog types, so any future entity with changed_event_class gets correct dialog staleness-propagation with zero extra per-entity code.

PRs

PR Title
#1460 [codegen,qt] Land NATS notification-wiring capability in qt-profile controller

Review

# Comment summary File Decision Notes
1 notifyOpenDialogs() window-key check uses colon (details:=/=history:) but build_window_key() joins with a dot (details.), so it never matches — dead code cpp_qt_controller.cpp.mustache, ores.cpp.qt.controller_impl.org, CurrencyController.cpp Fixed Fixed in 1c6e441: separator corrected in template + org source + currency's hand-maintained file (same bug, not yet regenerated). Verified via clean rebuild. Same bug in WorkspaceController.cpp=/=SystemSettingController.cpp left out of scope — capture filed separately.

Result

Landed a protected virtual notifyOpenDialogs() hook on EntityController, called after list-window staleness marking; generated controllers (gated by changed_event_class) override it to propagate staleness to open detail/history dialogs generically via a new DetailDialogBase::code() accessor (symmetric to the existing HistoryDialogBase::code()), generated by the detail_dialog template. Currency flipped on as first consumer. Verified by a real regenerate + rebuild (not just diff) of CurrencyController.cpp=/ =CurrencyDetailDialog.cpp, which also caught and fixed a live bug from the previous version-nav PR. 5 of 6 prerequisites for "Sync Qt codegen for currency" (EA647CBC) are now DONE — only the flag/combo reconciliation task remains.

Emacs 29.3 (Org mode 9.6.15)