Aller au contenu

Architecture overview

The plugin subsystem is built from three components, all under Components/:

Component Visibility Responsibility
PluginApi Public Pure abstract interfaces + value types. No Qt, no Scintilla, no MTE-internal headers — only the standard library.
PluginHost Internal Loads, owns, and dispatches plugins. Qt is an implementation detail here (it uses QPluginLoader behind the scenes).
Plugins First-party Example/built-in plugins; each its own CMake target depending only on PluginApi (and Qt, when using the native backend).

Design principles

  • Backend-agnostic contract. All PluginApi types live in namespace MTE::plugin and must not include any Qt, Scintilla, or MTE-internal header. This is what lets a future Python backend fulfil the same contract with no Qt impedance.
  • No third-party types across the public API. Plugins never see Scintilla or Qt types; the host adapts between the internal IEditorView and the public IEditorService.
  • RAII everywhere. Registering a command, menu item, dock panel, or event subscription returns a token/subscription handle. Destroying it unregisters the contribution. Plugins hold their tokens as members so everything is torn down automatically in shutdown().

Lifecycle

Every plugin implements a single interface, IPlugin:

class IPlugin {
public:
    virtual ~IPlugin() = default;
    virtual PluginInfo info() const = 0;
    virtual bool       initialize(IPluginContext& ctx) = 0;
    virtual void       shutdown() noexcept = 0;
};
  • info() returns POD metadata (id, name, version, vendor, description, apiVersion).
  • initialize(ctx) receives an IPluginContext service locator. The plugin grabs the services it needs and registers its commands, menus, panels, and event subscriptions.
  • shutdown() runs on the way out; because contributions are RAII tokens, the default teardown is usually just letting members destruct.

No hot reload

Enabling, disabling, installing, and uninstalling a plugin all take effect on the next launch. The host never loads or unloads plugin code while running — this keeps the model simple and sidesteps the Windows "cannot delete a loaded DLL" problem.

Discovery

The host scans, in order:

  1. <exe-dir>/Plugins/ — bundled first-party plugins.
  2. <AppLocalData>/Plugins/ — the per-user install directory.
  3. Paths from the MTE_PLUGIN_PATH environment variable.

Each directory is scanned for loose libraries and one level of immediate subdirectories (the per-plugin <id>/ layout an installer produces). Discovery does not recurse deeper.