Task: Reconcile currency's flag image handling and wire the piloted combo-field mechanism
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
Three reconciliation items grouped together (steps 6-8 of the
regenerate plan, task 6E0CD16E), none requiring new template
mechanisms: (1) migrate currency's flag image handling onto the
template's existing has_flag_icon mechanism; (2) wire currency's 3
soft-FK combo fields to the already-piloted
populateDynamicCombo<Entity> helper via the small per-field codegen
emit; (3) decide and land the fetch-failure-signalling gap flagged
during the combo-field pilot (task 8AA363F8) before finalizing the
emit.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Commission: currency |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-07-08 |
Acceptance
- Currency's flag image handling calls the template's
has_flag_iconmechanism instead of hand-rolled code. - Currency's 3 combo fields are wired through the per-field codegen
emit calling
populateDynamicCombo<Entity>. - Fetch-failure signalling has an explicit, documented decision (surfaced error vs. silent empty combo) reflected in the emit.
- Build passes.
Plan
Unlike the 5 prior capability-landing tasks in this story, this one was scoped as a genuine call-site migration of currency's real files — not a land-template-then-verify-by-diff-then-discard pass. Two independent pieces of work:
1. Flag image handling migration
DetailDialogBase already has a complete, mature flag mechanism
(initFlagButton, entityImageId()=/=keyFlagField()=/=keyFlagIcon()
virtual accessors, onSelectFlagClicked, updateFlagDisplay,
flagChanged()=/=selectedImageId()=/=resetFlagChanged()) — confirmed
by CountryDetailDialog already using it end to end. Currency's
~180 lines of hand-rolled equivalent (flagButton_,
pendingImageId_, flagChanged_, onCurrencyImageSet, manual
updateFlagDisplay) were 100% redundant duplication, migrated to
match Country's pattern exactly:
initFlagButton(ui_->iconGroup->layout())replaces the hand-built flag button/container.entityImageId()=/=keyFlagField()=/=keyFlagIcon()overrides added (matching Country's).getCurrency()now usesflagChanged()=/=selectedImageId()instead of the localpendingImageId_staging.- Dropped currency's extra
onCurrencyImageSetNATS-confirmation toast handling — Country doesn't have this either; the genericimagesLoaded=/=allLoaded→updateFlagDisplaywiring (already in base'ssetImageCache) covers the refresh. - Also dropped the "no-flag placeholder ID" auto-seeding quirk in the
old
setCurrency— unique to currency, inconsistent with how every other flag-icon entity handles a nullimage_id.
2. Combo-field codegen wiring
Landed a new combo_domain_type-gated branch in the
detail_dialog template (cpp_qt_detail_dialog.cpp.mustache)
generating a populateDynamicCombo<Entity> call from per-field org
properties (combo_domain_type, combo_fetch_fn,
combo_watcher_name, combo_code_field, combo_tooltip_field,
combo_sort_field, combo_label, combo_setter_pascal) — distinct
from the pre-existing (unused) combo_helper=/=combo_fetch_fn
branches, which don't match the piloted helper's real 9-argument
signature. Added currency's 3 combo fields (rounding_type,
monetary_nature, market_tier) to a new "Detail fields" org table
section (only these 3 — the other 11 currency fields stay unmodelled
until the final sync task populates the full table).
Process note: initially hand-typed the on_error callback
addition directly into CurrencyDetailDialog.cpp before adding the
template capability — caught mid-edit (thanks to a review prompt)
and reverted. Correct order followed after: land the template
capability first, regenerate + diff to verify the generated
populate*Combo() bodies match currency's real code, then copy
the verified generated snippet in (adjusting only the real file's
currentCurrency_ member name vs. the model's generic item_var
naming — a pre-existing, unrelated drift).
3. Fetch-failure-signalling decision
The pilot (task 8AA363F8) flagged that populateDynamicCombo's bare
std::vector<Entity> fetch signature can't distinguish "fetch
failed" from "legitimately empty" — both render a silently-empty
combo. Decision: land the fix, not just document a deferral.
Changed populateDynamicCombo's fetch parameter to
std::function<std::expected<std::vector<Entity>, QString>(ClientManager*)>
and added an on_error callback (default no-op) plus a distinct
"Failed to load" combo placeholder. Updated the 3
LookupFetcher functions currency uses (confirmed sole callers) to
return std::expected, propagating
process_authenticated_request's existing error channel instead of
silently swallowing it. Currency's 3 combo call sites (both hand and
generated) now pass an on_error callback that emits
errorMessage().
Scoped to just the 3 functions currency uses — did not touch the
rest of LookupFetcher's many other bare-vector fetchers (out of
scope, no other entity affected).
Notes
Verified with a real regenerate + rebuild of ores.qt.refdata.lib
(not a diff-only check): CurrencyDetailDialog.cpp compiles clean
with the migrated flag handling and the generated combo methods.
Also regenerated Country (no dynamic-combo fields) to confirm the
new code() accessor generalises cleanly with zero
combo_domain_type leakage into peers without it. All regenerated
trees discarded after verification per this branch's actual
deliverable (the hand-migrated CurrencyDetailDialog.{hpp,cpp}, the
template, and the DynamicComboSetup=/=LookupFetcher API changes).
PRs
| PR | Title |
|---|---|
| #1468 | [codegen,qt] Reconcile currency flag/combo handling |
Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | Debug log lines use human-readable field names ("rounding type") but the codegen template emits snake_case ("rounding_type") — checked-in code doesn't byte-match what regeneration produces | CurrencyDetailDialog.cpp |
Fixed | Fixed in 48b1b0b0f. Three independent review passes found no other issues. |
Result
All three items landed. Currency's flag handling now calls
DetailDialogBase's generic mechanism (real code change, ~180 lines
of duplication removed). The 3 soft-FK combo fields are wired through
a new combo_domain_type codegen emit calling
populateDynamicCombo<Entity>, verified equivalent to currency's
hand-migrated code via regenerate+diff, then applied for real. The
fetch-failure-signalling gap is closed with a real std::expected
propagation + on_error callback, not just documented. Full
whole-app build (cmake --build --preset linux-clang-debug-make)
passes clean. This closes the last of the 6 prerequisites for "Sync
Qt codegen for currency" (EA647CBC) — that task is now unblocked.