Settings & settings pages¶
Three related services cover configuration: ISettings (persistent
key/value storage), IDocumentSettings (.editorconfig-layered reads),
and ISettingsRegistry (a UI page in the Preferences dialog).
ISettings — persistent key/value config¶
ctx.settings() returns a store scoped to your plugin: the host roots
it under plugins/<plugin.id>/, so short local key names never collide
with the editor or other plugins. Keys use / as a path separator
("ui/fontSize").
class ISettings {
public:
bool contains(std::string_view key) const;
void remove(std::string_view key);
// Typed accessors -- defaultValue is returned when the key is missing
// or the stored value cannot convert to the requested type.
bool getBool (std::string_view key, bool defaultValue = false) const;
std::int64_t getInt (std::string_view key, std::int64_t defaultValue = 0) const;
double getDouble(std::string_view key, double defaultValue = 0.0) const;
std::string getString(std::string_view key, std::string_view defaultValue = {}) const;
std::vector<std::uint8_t> getBytes(std::string_view key) const;
void setBool / setInt / setDouble / setString / setBytes(...);
void sync(); // flush now; the host also syncs on shutdown
};
The default implementation is QSettings-backed (INI), but that is an
implementation detail — the interface is Qt-free and a Python plugin uses
the same store through ctx.settings.
App-wide settings (read-only)¶
ctx.appSettings() is a const view of the editor's own configuration.
Use the key constants from PluginApi/AppSettingsKeys.h rather than
hard-coding strings. To react to changes, subscribe to
events::SettingsChanged (an empty scope means "anything changed").
Document-scoped settings (.editorconfig)¶
ctx.documentSettings() reads per-document values that layer a project's
.editorconfig over your stored settings: for a key k it resolves
mte.<plugin.id>.<k> from the .editorconfig sections applying to the
document's path, falls back to ctx.settings(), then to your default.
Writes always go through ctx.settings() — never back into
.editorconfig.
A page in the Preferences dialog¶
The page interface is Qt-aware, so it lives in the opt-in header
PluginApi/Qt/ISettingsPage.h:
class ISettingsPage {
public:
std::string category() const; // tree path, e.g. "Plugins/Hello World"
std::string title() const; // page heading
QWidget* createWidget(QWidget* parent); // built lazily, at most once per dialog
void apply(); // OK/Apply -> write widget state to ISettings
void reset(); // Cancel/re-show -> reload from ISettings (optional)
std::string scope() const; // published via events::SettingsChanged (optional)
};
Register it in initialize() and keep the token:
category()groups pages in the dialog's tree; intermediate segments create or reuse groups. Plugin pages conventionally live under"Plugins/<Name>".apply()is where you persist;reset()is where you reload after a cancel. Don't write settings from widget signals — the dialog contract is deferred apply.- By convention
scope()returns"plugins/<plugin.id>"so other code can react selectively to your page's changes viaevents::SettingsChanged. - The returned
SettingsPageTokenrevokes the page (and frees it) on destruction —reset()it inshutdown()like every other token.
Localise every string on the page and ship all four catalogs — see Translations.
Python plugins
A Python plugin declares the equivalent page declaratively — a
JSON form built with mte.ui passed to
ctx.settings_page.register(...); values bound with
binds="settings:<key>" persist to the same per-plugin store. See the
Python ctx reference.