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 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<ActorType>(group). This function wraps the actor type in an MGenericActorFactory<ActorType> 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.

Listing 4 Adding a user configuration option.
 1class MUserConfiguration : public QObject
 2{
 3    ...
 4public: // Static interface
 5    ...
 6  static int exampleOption()
 7  { return getInstance()->exampleOptionProp; }
 8  ...
 9private:
10  ...
11  MIntProperty exampleOptionProp;
12  ...
13}

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.

Listing 5 Initializing a user configuration option.
1...
2
3exampleOptionProp = MIntProperty("Example Option", 0);
4exampleOptionProp.setConfigKey("example_option");
5exampleOptionProp.toggleUndoable(false); // All user settings are not undoable.
6exampleOptionProp.registerValueCallback(this, &MUserConfiguration::configurationChanged);
7generalSettingsProp.addSubProperty(exampleOptionsProp);
8...

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<T> &list).

For example:

Listing 6 Storing values inside the user cache.
1int value = 10;
2MUserCache::setValue("ExampleNamespace", "example_key", value);
3
4QList<int> values = ...;
5MUserCache::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.

Listing 7 Reading values from the user cache.
1int value = MUserCache::value<int>("ExampleNamespace", "example_key");
2
3QList<int> values = MUserCache::readList("ExampleNamespace", "example_list_key");