Configuration ============= Met.3D requires several components to be configured during startup, including: * Available actor types * Datasets to load before the initial session is created * Batch mode * Development aids * Per-user application settings This page documents the classes responsible for loading, organizing, and applying this configuration. Application configuration -------------------------- ``MApplicationConfigurationManager`` is the central entry point for system-startup configuration. One instance is created in ``MMainWindow``, and Met.3D is configured from the ``MMainWindow`` constructor by calling ``loadConfiguration()``. Rather than implementing all startup configuration itself, ``MApplicationConfigurationManager`` delegates individual configuration tasks to a collection of ``MAbstractApplicationConfiguration`` instances. Each implementation provides a single ``configure()`` method that is invoked during ``loadConfiguration()``. This keeps each configuration concern isolated instead of accumulating all startup logic in one large routine. The following configuration classes are currently registered: * ``MPipelineConfiguration`` -- Initializes the pipeline schedulers and loads the datasets specified via the ``--datasets`` command-line argument. It also creates the required data pipelines for newly loaded datasets, both during startup and when datasets are loaded later from the GUI. * ``MBatchModeConfiguration`` -- Reads the batch mode configuration (see :doc:`../../03_user_manual/batch_mode` for the batch mode configuration format). * ``MDevelopmentAidsConfiguration`` -- Initializes modules that support development and debugging independently of the application's normal runtime configuration. It currently contains tests for ``metroutines.h`` In addition, ``registerActorFactories()`` registers all actor factories known to Met.3D. Unlike the classes above, this is not implemented as an ``MAbstractApplicationConfiguration`` and is called directly from ``loadConfiguration()``. Actor type registry -------------------- ``MActorTypeRegistry`` maintains the set of actor types available in Met.3D. It is responsible for creating actor instances at runtime—for example, when a user creates a new actor through the UI. New actor types are registered via ``MActorTypeRegistry::registerActorType(group)``. This function wraps the actor type in an ``MGenericActorFactory`` and registers it both * in a global registry keyed by ``ActorType::staticActorType()``, and * in the named ``group`` used to organize actor types in the user interface. The registry therefore supports looking up actor factories either directly by name (``getActorFactory()`` and ``hasActorFactory()``) or by UI group (``getActorGroups()`` and ``getActorTypesByGroup()``). Per-user configuration ------------------------ Per-user configuration is handled independently of ``MApplicationConfigurationManager`` by two singleton classes: * ``MUserConfiguration`` stores user-facing application settings in Qt's standard per-platform configuration location (for example, ``$HOME/.config`` on Linux). The configuration is loaded automatically the first time it is accessed, creating default values if necessary. A convenience typedef, ``MConfig``, provides concise static accessors for all configuration options. * ``MUserCache`` stores application state that should persist across sessions but is not considered user-facing configuration. Examples include dock widget layouts and file browser bookmarks. ``MUserCache`` provides templated ``setValue()`` and ``value()`` convenience functions for any type supported by ``QVariant``, while also exposing the underlying ``QSettings`` object for more advanced use cases. Like ``MUserConfiguration``, it is loaded on first access. Extending the user configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When adding a new user configuration option, follow the structure of the existing options and place it into the appropriate configuration group. In ``muserconfiguration.h``, add * a ``static inline`` accessor that exposes the value, and * a property member that stores and edits the value. .. code-block:: c++ :linenos: :caption: Adding a user configuration option. class MUserConfiguration : public QObject { ... public: // Static interface ... static int exampleOption() { return getInstance()->exampleOptionProp; } ... private: ... MIntProperty exampleOptionProp; ... } The property should be to be non-undoable, have a config key for persistence, and an appropriate value callback. The available callbacks are: * ``configurationChanged`` -- Emitted whenever the setting changes, so dependent classes can update immediately. * ``restartRequiredConfigurationChanged`` -- Emitted when the change only takes effect after restarting the application. Initialize the property in ``muserconfiguration.cpp`` and add it to the appropriate property group. .. code-block:: c++ :linenos: :caption: Initializing a user configuration option. ... exampleOptionProp = MIntProperty("Example Option", 0); exampleOptionProp.setConfigKey("example_option"); exampleOptionProp.toggleUndoable(false); // All user settings are not undoable. exampleOptionProp.registerValueCallback(this, &MUserConfiguration::configurationChanged); generalSettingsProp.addSubProperty(exampleOptionsProp); ... This new option can now be read everywhere in Met.3D via ``MConfig::exampleOption()``. Using the user cache ~~~~~~~~~~~~~~~~~~~~ The user cache stores information that should persist across application runs without being part of the user's application settings. Each cache entry belongs to a namespace, allowing independent parts of the application to use identical keys without conflict. To store a single value, use ``MUserCache::setValue(const QString &ns, const QString &key, const T &value)``. The value type must be supported by ``QVariant``. Lists can be stored using ``MUserCache::writeList(const QString &ns, const QString &key, const QList &list)``. For example: .. code-block:: c++ :linenos: :caption: Storing values inside the user cache. int value = 10; MUserCache::setValue("ExampleNamespace", "example_key", value); QList values = ...; MUserCache::writeList("ExampleNamespace", "example_list_key", value); Read individual values using ``MUserCache::value(const QString &ns, const QString &key, T defaultValue = {})``. If no value exists, the supplied default value is returned. Lists can be read using ``MUserCache::readList(const QString &ns, const QString &key)``. If the key does not exist, an empty list is returned. .. code-block:: c++ :linenos: :caption: Reading values from the user cache. int value = MUserCache::value("ExampleNamespace", "example_key"); QList values = MUserCache::readList("ExampleNamespace", "example_list_key");