Aller au contenu

Vue d'ensemble de l'architecture

Le sous-système de plugins est constitué de trois composants, tous situés sous Components/ :

Composant Visibilité Responsabilité
PluginApi Publique Interfaces abstraites pures + types valeur. Pas de Qt, pas de Scintilla, pas d'en-têtes internes à MTE — uniquement la bibliothèque standard.
PluginHost Interne Charge, possède et pilote les plugins. Qt y est un détail d'implémentation (il utilise QPluginLoader en coulisses).
Plugins Interne à l'éditeur Plugins d'exemple/intégrés ; chacun est une cible CMake indépendante ne dépendant que de PluginApi (et de Qt, avec le backend natif).

Principes de conception

  • Contrat indépendant du backend. Tous les types de PluginApi vivent dans namespace MTE::plugin et ne doivent inclure aucun en-tête Qt, Scintilla ou interne à MTE. C'est ce qui permet à un futur backend Python de remplir le même contrat sans aucune friction avec Qt.
  • Aucun type tiers dans l'API publique. Les plugins ne voient jamais de types Scintilla ou Qt ; l'hôte fait l'adaptation entre l'IEditorView interne et l'IEditorService public.
  • RAII partout. L'enregistrement d'une commande, d'un élément de menu, d'un panneau ancrable ou d'un abonnement à un événement renvoie un jeton (token) ou une poignée d'abonnement. Sa destruction annule l'enregistrement de la contribution. Les plugins conservent leurs jetons comme membres afin que tout soit démonté automatiquement dans shutdown().

Cycle de vie

Chaque plugin implémente une interface unique, IPlugin :

class IPlugin {
public:
    virtual ~IPlugin() = default;
    virtual PluginInfo info() const = 0;
    virtual bool       initialize(IPluginContext& ctx) = 0;
    virtual void       shutdown() noexcept = 0;
};
  • info() renvoie des métadonnées POD (id, name, version, vendor, description, apiVersion).
  • initialize(ctx) reçoit un localisateur de services IPluginContext. Le plugin récupère les services dont il a besoin et enregistre ses commandes, menus, panneaux et abonnements aux événements.
  • shutdown() s'exécute à la sortie ; comme les contributions sont des jetons RAII, le démontage par défaut consiste généralement à laisser simplement les membres se détruire.

Pas de rechargement à chaud

L'activation, la désactivation, l'installation et la désinstallation d'un plugin ne prennent effet qu'au prochain lancement. L'hôte ne charge ni ne décharge jamais de code de plugin en cours d'exécution — cela garde le modèle simple et évite le problème Windows « impossible de supprimer une DLL chargée ».

Découverte

L'hôte parcourt, dans l'ordre :

  1. <exe-dir>/Plugins/ — les plugins internes livrés avec l'éditeur.
  2. <AppLocalData>/Plugins/ — le répertoire d'installation par utilisateur.
  3. Les chemins de la variable d'environnement MTE_PLUGIN_PATH.

Chaque répertoire est parcouru à la recherche de bibliothèques en vrac et d'un seul niveau de sous-répertoires immédiats (la disposition par plugin <id>/ produite par un installateur). La découverte ne descend pas plus profondément.