Przejdź do treści

Przegląd architektury

Podsystem wtyczek zbudowany jest z trzech komponentów, wszystkie w Components/:

Komponent Widoczność Odpowiedzialność
PluginApi Publiczny Czyste abstrakcyjne interfejsy + typy wartości. Bez Qt, bez Scintilli, bez wewnętrznych nagłówków MTE — tylko biblioteka standardowa.
PluginHost Wewnętrzny Ładuje wtyczki, jest ich właścicielem i rozdziela do nich wywołania. Qt jest tu szczegółem implementacyjnym (pod spodem używa QPluginLoader).
Plugins Własne projektu Przykładowe/wbudowane wtyczki; każda jako osobny target CMake zależny wyłącznie od PluginApi (oraz Qt, gdy używa backendu natywnego).

Zasady projektowe

  • Kontrakt niezależny od backendu. Wszystkie typy PluginApi żyją w namespace MTE::plugin i nie mogą dołączać żadnego nagłówka Qt, Scintilli ani wewnętrznego nagłówka MTE. Właśnie dzięki temu przyszły backend Pythona może realizować ten sam kontrakt bez tarcia z Qt.
  • Żadnych typów zewnętrznych w publicznym API. Wtyczki nigdy nie widzą typów Scintilli ani Qt; host tłumaczy między wewnętrznym IEditorView a publicznym IEditorService.
  • RAII wszędzie. Rejestracja polecenia, pozycji menu, panelu dokowanego lub subskrypcji zdarzeń zwraca token/uchwyt subskrypcji. Zniszczenie go wyrejestrowuje daną kontrybucję. Wtyczki trzymają swoje tokeny jako pola składowe, więc w shutdown() wszystko sprząta się automatycznie.

Cykl życia

Każda wtyczka implementuje jeden interfejs, IPlugin:

class IPlugin {
public:
    virtual ~IPlugin() = default;
    virtual PluginInfo info() const = 0;
    virtual bool       initialize(IPluginContext& ctx) = 0;
    virtual void       shutdown() noexcept = 0;
};
  • info() zwraca metadane POD (id, name, version, vendor, description, apiVersion).
  • initialize(ctx) otrzymuje lokator usług IPluginContext. Wtyczka pobiera potrzebne usługi i rejestruje swoje polecenia, menu, panele oraz subskrypcje zdarzeń.
  • shutdown() uruchamiane jest przy zamykaniu; ponieważ kontrybucje to tokeny RAII, domyślne sprzątanie zwykle sprowadza się do destrukcji pól składowych.

Brak przeładowywania na gorąco

Włączenie, wyłączenie, instalacja i deinstalacja wtyczki zaczynają obowiązywać dopiero przy następnym uruchomieniu. Host nigdy nie ładuje ani nie zwalnia kodu wtyczek w trakcie działania — to upraszcza model i omija windowsowy problem „nie można usunąć załadowanej biblioteki DLL".

Wykrywanie

Host skanuje, w kolejności:

  1. <exe-dir>/Plugins/ — dołączone wtyczki własne projektu.
  2. <AppLocalData>/Plugins/ — katalog instalacji per użytkownik.
  3. Ścieżki ze zmiennej środowiskowej MTE_PLUGIN_PATH.

Każdy katalog jest skanowany pod kątem luźnych bibliotek oraz jednego poziomu bezpośrednich podkatalogów (układ <id>/ per wtyczka, jaki tworzy instalator). Wykrywanie nie schodzi głębiej rekurencyjnie.