Zum Inhalt

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 in namespace MTE::plugin und 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 IEditorView und dem öffentlichen IEditorService.
  • 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 einen IPluginContext als 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:

  1. <exe-dir>/Plugins/ — mitgelieferte First-Party-Plugins.
  2. <AppLocalData>/Plugins/ — das benutzerspezifische Installationsverzeichnis.
  3. 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.