ImFusion SDK 4.3
Settings Migration Guide

We have introduced a new persistent settings framework which will replace Qt/QSettings within our SDK. This is intended to allows us to further decouple the SDK from Qt, while hopefully also providing a more intuitive and powerful way to manage settings. We also used this opportunity to refactor other settings-related infrastructure, such as the Settings and SettingsDialog classes. Deprecation layers are provided for the new interfaces, so breaking changes should be minimal.

Migration

Base Settings

Previously, the Settings class had three responsibilities:

  1. Managing a set of "base" settings for ImFusionLib.
  2. Providing an interface for registering new settings so they can be shown in the SettingsDialog.
  3. Providing a wrapper for QSettings through Settings::Setting.

After the refactor, only the first of these responsibilities remains. You may continue using the base settings as before:

bool showToolbarText = Settings().showToolbarText; // read from global settings
Settings().showToolbarText = true; // write to global settings

Settings::Setting is deprecated, but the instances in Settings will remain and can be accessed without deprecation warnings. These will be migrated later along with redistributing some of the settings to other places.

See Settings Dialog for information on interaction with the SettingsDialog.

Plugin Settings

Instead of inheriting from Settings, plugin settings now should be simple Configurable Configurables which call GlobalSettings::load(*this) in their constructors and GlobalSettings::store(*this) in their destructors:

class MyPluginSettings : public Configurable
{
public:
MyPluginSettings() { GlobalSettings::load(*this); }
~MyPluginSettings() { GlobalSettings::store(*this); }
Parameter<bool> boolSetting{"boolSetting", false, this};
Parameter<vec4> vec4Setting{"vec4Setting", vec4(0, 0, 0, 0), this};
};

You can then use this settings class exactly as before:

MyPluginSettings settings;
bool b = settings.boolSetting; // read from global settings on construction of the settings object
settings.vec4Setting = vec4(1, 2, 3, 4); // written to global settings on destruction of the settings object

You can also set the attributes for you Parameters in the constructor in case you want to create automatically generated UI using the SettingsDialog, or directly with the PropertiesWidget. If you want your settings to show up in the SettingsDialog, you must register them.

Settings Dialog

Some settings such as the ones in Settings are automatically shown in the SettingsDialog. To add your own custom settings you should use:

static void addCustomSettings()
Add a Configurable type T to the settings dialog.
Definition SettingsDialog.h:51

This way there will be an automatically generated widget for your settings in the Settings Dialog. You can also specify your own custom widget:

static void addCustomSettingsWidget()
Add a custom settings widget W for configurable type T.
Definition SettingsDialog.h:76

You can also show only a subset of your settings by providing the SettingsDialog with a Properties instance instead. Note that only the settings that are registered with the SettingsDialog will be shown in the dialog, even if the settings storage on the system contains other parameters for the same Configurable.

Recommended Practices

Decoupling Settings from Logic

While you can put settings in a central place and access them in your code, this approach is bad practice if you're writing library code. Persistent settings are inherently side-effects and are best avoided in a library when possible. Instead consider having the settings you depend on as parameters for your classes in the library, and load them in the concrete application.

The new GlobalSettings allows you to easily configure these parameters from the settings storage:

// === Library code ===
class MyClass : public Configurable
{
public:
void doComplexStuff()
{
if(boolSetting)
{
// do stuff
}
}
Parameter<bool> boolSetting{"boolSetting", false, this};
};
// === Application code ===
MyClass myClass;
myClass.doComplexStuff();
static std::optional< Properties > load()
Load the parameters for Configurable type T from the global settings.
Definition GlobalSettings.h:175

This way the behavior of MyClass is always deterministic/reproducible, and the outside application decides if and when it is configured from the global settings storage.

Loading and Storing Values

GlobalSettings provides an interface to load an store individual values based on a simple name string similar to QSettings:

GlobalSettings::storeValue("myValues/answer", 42);
static void storeValue(const std::string &name, const T &value)
Store the value for name in the global settings.
Definition GlobalSettings.h:202
static std::optional< T > loadValue(const std::string &name)
Load the value for name from the global settings.
Definition GlobalSettings.h:181

While this is very flexible, it's recommended to use the Configurable interfaces of GlobalSettings instead to avoid problems with typos and duplication.

Search Tab / S to search, Esc to close