LoadoutManager

LoadoutManager is the singleton that owns the persistent collection of HardwareLoadout records and the FTMW presets they contain. It is the sole writer of the Loadouts/ QSettings subtree: every other component in the application observes loadouts through this manager, and every CRUD operation funnels through one of its public methods. Loadout-level changes propagate to the rest of the application through the manager’s Qt signals; the user-facing model is described in the Loadouts and FTMW Presets chapters.

The manager loads every known loadout into an in-memory QHash cache during construction, then services subsequent reads against that cache. Writes update both the cache and QSettings under the appropriate sub-group, then emit the matching loadoutAdded, loadoutChanged, ftmwPresetChanged, or currentFtmwPresetChanged signal so observing widgets can refresh. All public methods are thread-safe via an internal QMutex; signals are emitted on the thread of the caller that triggered the change.

Loadouts and FTMW presets are paired, but the manager exposes them through separate CRUD surfaces: putLoadout / removeLoadout / getLoadout for whole-loadout operations, and putFtmwPreset / removeFtmwPreset / renameFtmwPreset for individual preset operations within a named loadout. The loadoutsMatchingHwKey helper supports the hardware-profile rename flow by enumerating every loadout whose hardware map references a given hardware key.

The __LastUsed__ sentinel

Each loadout reserves the preset name __LastUsed__ (BC::Store::LM::lastUsedFtmwPresetName) for an automatic sentinel preset that captures the most recent fully accepted FTMW configuration. The sentinel is hidden from all user-facing dropdowns and is never user-deletable; ftmwPresetNames excludes it unless its includeLastUsed flag is set.

The sentinel is updated only on two events:

  • FtmwConfigDialog::accept — when the user dismisses the FTMW configuration dialog with OK.

  • Experiment start — when an experiment begins with the current FTMW configuration.

It is not updated on Apply, on Cancel, or on incidental edits to the live configuration. The semantics ensure that, after restoring a loadout, the application can fall back to __LastUsed__ to recover the configuration the user most recently committed to, even if no named preset matches.

QSettings storage layout

The keys that name each field and sub-group below are declared in the BC::Store::LM namespace at the top of loadoutmanager.h. The RF-side keys used inside rfClocks/ array entries belong to the BC::Store::RFC namespace; the loadout-specific extensions of that namespace are declared in hardwareloadout.h and documented on HardwareLoadout.

Loadouts/
  currentLoadout = "<name>"
  defaultLoadout = "Default"
  names/                               # array of {name}
  <name>/
    name = "<name>"
    hardwareMap/                       # array of {key, value}
    currentFtmwPreset = "<presetName>" # may be "__LastUsed__"
    ftmwPresetNames/                   # array of {name}
    lastModified = <ISO timestamp>
    ftmwPresets/
      <presetName>/
        rfScalars/
        rfClocks/
        chirpScalars/
        chirpSegments/
        chirpMarkers/
        digiScalars/
        digiAnalog/
        digiDigital/
        digiHwKey = "<hwKey>"
        lastModified = <ISO timestamp>

The flattening from HardwareLoadout and FtmwPreset into this layout is performed by the BC::Loadout free-function helpers; see HardwareLoadout for the helper signatures.

Relationship to other configuration singletons

LoadoutManager is one of three loosely coupled configuration singletons. HardwareProfileManager owns profile metadata and persistence; RuntimeHardwareConfig tracks which profiles are active for the running session; LoadoutManager stores named hardware maps and the FTMW presets that ride on top of them. Switching the active loadout via the Hardware menu causes RuntimeHardwareConfigDialog to drive RuntimeHardwareConfig to the loadout’s stored hardware map, after the drift-detection prompt described in Loadouts.

API Reference

class LoadoutManager : public QObject, public SettingsStorage

Singleton that owns the persistent collection of HardwareLoadout records and their FTMW presets.

LoadoutManager is the sole writer of the Loadouts/ QSettings subtree. It loads every known loadout into an in-memory cache at construction, services CRUD operations against that cache, and flushes changes back to QSettings under the appropriate sub-groups. Read access is unrestricted; write access is funneled through the public CRUD methods, which emit Qt signals so the UI can refresh in response to changes from any caller.

All public methods are thread-safe via an internal QMutex. The helper signals (loadoutAdded, currentFtmwPresetChanged, etc.) are emitted on the thread of the caller that triggered the change.

Public Functions

~LoadoutManager() override
QStringList loadoutNames() const

Names of all loadouts currently known to the manager.

bool loadoutExists(const QString &name) const

Whether a loadout with the given name exists in the cache.

std::optional<HardwareLoadout> getLoadout(const QString &name) const

Fetch a copy of the named loadout, or std::nullopt if it does not exist.

bool putLoadout(const HardwareLoadout &loadout)

Insert or replace a loadout, persisting it to QSettings and emitting the appropriate signal.

bool removeLoadout(const QString &name)

Remove the named loadout, including all of its FTMW presets, from cache and QSettings.

QString currentLoadoutName() const

Name of the loadout marked active for the running session.

void setCurrentLoadoutName(const QString &name)

Set the active loadout, emitting currentLoadoutChanged.

std::optional<HardwareLoadout> currentLoadout() const

Convenience accessor that returns the active loadout, if any.

QString defaultLoadoutName() const

Name of the loadout selected on application startup when no other selection is in force.

void setDefaultLoadoutName(const QString &name)

Set the default loadout, emitting defaultLoadoutChanged.

std::optional<HardwareLoadout> defaultLoadout() const

Convenience accessor that returns the default loadout, if any.

QStringList loadoutsMatchingHwKey(const QString &hwKey) const

Names of all loadouts whose member set includes the given profile identity.

std::optional<FtmwPreset> getFtmwPreset(const QString &loadoutName, const QString &presetName) const

Fetch a copy of a named preset from the named loadout.

bool putFtmwPreset(const QString &loadoutName, const QString &presetName, const FtmwPreset &preset)

Insert or replace an FTMW preset in the named loadout.

bool removeFtmwPreset(const QString &loadoutName, const QString &presetName)

Remove the named preset from the named loadout. Cannot remove the active preset.

bool renameFtmwPreset(const QString &loadoutName, const QString &oldName, const QString &newName)

Rename a preset within the named loadout, updating the current-preset pointer if needed.

bool ftmwPresetExists(const QString &loadoutName, const QString &presetName) const

Whether the named loadout contains a preset with the given name.

QStringList ftmwPresetNames(const QString &loadoutName, bool includeLastUsed = false) const

Names of the FTMW presets owned by the named loadout.

Parameters:
  • loadoutName – Loadout whose preset names should be returned.

  • includeLastUsed – If true, the __LastUsed__ sentinel is included in the returned list.

bool clearFtmwPresets(const QString &loadoutName)

Remove every FTMW preset from the named loadout.

QString currentFtmwPresetName(const QString &loadoutName) const

Name of the named loadout’s currently active FTMW preset.

bool setCurrentFtmwPresetName(const QString &loadoutName, const QString &presetName)

Set the active FTMW preset for the named loadout, emitting currentFtmwPresetChanged.

std::optional<FtmwPreset> currentFtmwPreset(const QString &loadoutName) const

Convenience accessor that returns the named loadout’s active preset, if any.

Signals

void loadoutAdded(QString name)

Emitted after a new loadout is inserted into the cache.

void loadoutRemoved(QString name)

Emitted after a loadout is removed from the cache.

void loadoutChanged(QString name)

Emitted after the contents of an existing loadout are replaced.

void currentLoadoutChanged(QString name)

Emitted after the active loadout selection changes.

void defaultLoadoutChanged(QString name)

Emitted after the default loadout selection changes.

void ftmwPresetAdded(QString loadoutName, QString presetName)

Emitted after a new FTMW preset is added to a loadout.

void ftmwPresetRemoved(QString loadoutName, QString presetName)

Emitted after an FTMW preset is removed from a loadout.

void ftmwPresetChanged(QString loadoutName, QString presetName)

Emitted after an FTMW preset’s contents are replaced.

void currentFtmwPresetChanged(QString loadoutName, QString presetName)

Emitted after a loadout’s active FTMW preset selection changes.

Public Static Functions

static LoadoutManager &instance()

Access the process-wide singleton.

Private Functions

LoadoutManager()
LoadoutManager(QAnyStringView orgName, QAnyStringView appName)
void p_loadAll()
HardwareLoadout p_readLoadout(const QString &name) const
void p_writeLoadout(const HardwareLoadout &loadout)
void p_removeFromSettings(const QString &name)
void p_syncIndex()
FtmwPreset p_readFtmwPreset(const QString &loadoutName, const QString &presetName) const
void p_writeFtmwPreset(const QString &loadoutName, const QString &presetName, const FtmwPreset &preset)
void p_removeFtmwPresetFromSettings(const QString &loadoutName, const QString &presetName)
void p_syncFtmwPresetIndex(const QString &loadoutName)
void p_writeFtmwPresetPointers(const QString &loadoutName)

Private Members

QHash<QString, HardwareLoadout> d_loadouts
QString d_current
QString d_default
mutable QMutex d_mutex

Private Static Attributes

static LoadoutManager *s_instance = nullptr

Friends

friend class LoadoutManagerTest
class LoadoutHelper : public SettingsStorage

Public Functions

inline LoadoutHelper(const QStringList &keys)

Friends

friend class LoadoutManager
namespace LM

QSettings field keys for the LoadoutManager storage tree.

All loadout state is persisted under the top-level Loadouts/ group named by key. The remaining identifiers name the scalar fields and array sub-groups used by LoadoutManager and the BC::Loadout free-function helpers. lastUsedFtmwPresetName is the reserved name used for the per-loadout __LastUsed__ sentinel preset.

Variables

constexpr QLatin1StringView key = {"Loadouts"}

Top-level QSettings group that holds all loadout state.

constexpr QLatin1StringView current = {"currentLoadout"}

Field that stores the active loadout name.

constexpr QLatin1StringView defaultName = {"defaultLoadout"}

Field that stores the default loadout name.

constexpr QLatin1StringView namesKey = {"names"}

Array group that lists all known loadout names.

constexpr QLatin1StringView nameField = {"name"}

Field used inside name-array entries to hold the loadout or preset name.

constexpr QLatin1StringView hwMapKey = {"hardwareMap"}

Array group that holds the loadout’s hardware map entries.

constexpr QLatin1StringView digiHwKeyField = {"DigiHwKey"}

Field that records which digitizer hardware key a preset was captured against.

constexpr QLatin1StringView rfScalarsKey = {"rfScalars"}

Sub-group that holds an FTMW preset’s RF scalar fields.

constexpr QLatin1StringView rfClocksKey = {"rfClocks"}

Array group that holds an FTMW preset’s RF clock entries.

constexpr QLatin1StringView chirpScalarsKey = {"chirpScalars"}

Sub-group that holds an FTMW preset’s chirp scalar fields.

constexpr QLatin1StringView chirpSegmentsKey = {"chirpSegments"}

Array group that holds an FTMW preset’s chirp segment table.

constexpr QLatin1StringView chirpMarkersKey = {"chirpMarkers"}

Array group that holds an FTMW preset’s chirp marker table.

constexpr QLatin1StringView digiScalarsKey = {"digiScalars"}

Sub-group that holds an FTMW preset’s digitizer scalar fields.

constexpr QLatin1StringView digiAnalogKey = {"digiAnalog"}

Array group that holds an FTMW preset’s digitizer analog channel entries.

constexpr QLatin1StringView digiDigitalKey = {"digiDigital"}

Array group that holds an FTMW preset’s digitizer digital channel entries.

constexpr QLatin1StringView ftmwPresetsKey = {"ftmwPresets"}

Sub-group under each loadout that holds its FTMW presets.

constexpr QLatin1StringView ftmwPresetNamesKey = {"ftmwPresetNames"}

Array group that lists the FTMW preset names owned by a loadout.

constexpr QLatin1StringView currentFtmwPresetKey = {"currentFtmwPreset"}

Field that names a loadout’s currently active FTMW preset.

constexpr QLatin1StringView lastModifiedKey = {"lastModified"}

Field that records the last-modified timestamp of a loadout or preset.

constexpr QLatin1StringView lastUsedFtmwPresetName = {"__LastUsed__"}

Reserved preset name used for the per-loadout last-used sentinel.