Architekturüberblick¶
Das Plugin-Subsystem besteht aus drei Komponenten, alle unter Components/:
| Komponente | Sichtbarkeit | Verantwortung |
|---|---|---|
PluginApi |
Öffentlich | Rein abstrakte Schnittstellen + Wertetypen. Kein Qt, kein Scintilla, keine MTE-internen Header — nur die Standardbibliothek. |
PluginHost |
Intern | Lädt, besitzt und dispatcht Plugins. Qt ist hier ein Implementierungsdetail (hinter den Kulissen wird QPluginLoader verwendet). |
Plugins |
First-Party | Beispiel-/mitgelieferte Plugins; jedes ein eigenes CMake-Target, das nur von PluginApi abhängt (und von Qt, wenn das native Backend verwendet wird). |
Designprinzipien¶
- Backend-agnostischer Vertrag. Alle
PluginApi-Typen liegen innamespace MTE::pluginund dürfen keinen Qt-, Scintilla- oder MTE-internen Header einbinden. Genau das erlaubt es einem künftigen Python-Backend, denselben Vertrag ohne Qt-Reibungsverluste zu erfüllen. - Keine Drittanbieter-Typen in der öffentlichen API. Plugins sehen niemals
Scintilla- oder Qt-Typen; der Host vermittelt zwischen dem internen
IEditorViewund dem öffentlichenIEditorService. - RAII überall. Das Registrieren eines Commands, Menüeintrags, Dock-Panels
oder Event-Abonnements liefert ein Token bzw. ein Subscription-Handle zurück.
Wird es zerstört, wird der Beitrag deregistriert. Plugins halten ihre Tokens
als Member, sodass in
shutdown()alles automatisch abgebaut wird.
Lebenszyklus¶
Jedes Plugin implementiert eine einzige Schnittstelle, IPlugin:
class IPlugin {
public:
virtual ~IPlugin() = default;
virtual PluginInfo info() const = 0;
virtual bool initialize(IPluginContext& ctx) = 0;
virtual void shutdown() noexcept = 0;
};
info()liefert POD-Metadaten (id,name,version,vendor,description,apiVersion).initialize(ctx)erhält einenIPluginContextals Service-Locator. Das Plugin holt sich die benötigten Dienste und registriert seine Commands, Menüs, Panels und Event-Abonnements.shutdown()läuft beim Beenden; da Beiträge RAII-Tokens sind, besteht der Standard-Abbau meist einfach darin, die Member destruieren zu lassen.
Kein Hot Reload
Das Aktivieren, Deaktivieren, Installieren und Deinstallieren eines Plugins wird erst beim nächsten Start wirksam. Der Host lädt oder entlädt Plugin-Code niemals zur Laufzeit — das hält das Modell einfach und umgeht das Windows-Problem „eine geladene DLL kann nicht gelöscht werden“.
Erkennung¶
Der Host durchsucht, in dieser Reihenfolge:
<exe-dir>/Plugins/— mitgelieferte First-Party-Plugins.<AppLocalData>/Plugins/— das benutzerspezifische Installationsverzeichnis.- Pfade aus der Umgebungsvariable
MTE_PLUGIN_PATH.
Jedes Verzeichnis wird nach losen Bibliotheken sowie einer Ebene unmittelbarer
Unterverzeichnisse durchsucht (das Pro-Plugin-Layout <id>/, das ein Installer
erzeugt). Die Erkennung steigt nicht tiefer hinab.