Een inheemse plug-in schrijven¶
Een minimale inheemse plug-in is één klasse, één fabrieksmacro, één
JSON-bestand en een korte CMakeLists.txt. U kunt haar volledig buiten de
broncodeboom schrijven, tegen de plug-in-SDK aan — er is geen uitcheck van de
MTE-broncode voor nodig.
Inheems of Python?
Deze pagina behandelt inheemse C++-plug-ins (gecompileerd tot een
.dll/.so/.dylib en door de Qt-lader geladen). Levert u liever een map
met .py-bestanden die de editor als subproces start, zie dan
Python-plug-ins — hetzelfde vlak van PluginApi,
een andere backend, geen compiler nodig.
Concept
Deze doorloop is gebaseerd op PLUGIN_ARCHITECTURE.md; controleer de precieze
pakketnaam van de SDK en de argumenten van mte_add_plugin() tegen de
geleverde SDK voordat u erop vertrouwt.
1. Implementeer IPlugin¶
#include <PluginApi/IPlugin.h>
#include <PluginApi/IPluginContext.h>
class HelloWorldPlugin : public MTE::plugin::IPlugin {
public:
MTE::plugin::PluginInfo info() const override {
return { "org.mte.helloworld", "Hello World", "1.0.0",
"Example Vendor", "Says hi.", MTE_PLUGIN_API_VERSION };
}
bool initialize(MTE::plugin::IPluginContext& ctx) override {
m_cmd = ctx.commands().registerCommand(
{ "helloworld.sayHi", "Say Hi", "Ctrl+Alt+H", "Hello" },
[&ctx] { ctx.log().log(MTE::plugin::LogLevel::Info, "Hi!"); });
m_menu = ctx.menus().addItem("Plugins/Say Hi", "helloworld.sayHi");
return true;
}
void shutdown() noexcept override {} // tokens tear down automatically
private:
MTE::plugin::CommandToken m_cmd;
MTE::plugin::MenuToken m_menu;
};
2. Voer de fabriek uit (inheemse Qt-backend)¶
#include <PluginApi/Qt/PluginQtGlue.h>
class HelloWorldFactory : public QObject, public MTE::plugin::IPluginFactory {
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mte.IPluginFactory/1" FILE "plugin.json")
Q_INTERFACES(MTE::plugin::IPluginFactory)
public:
std::unique_ptr<MTE::plugin::IPlugin> create() override {
return std::make_unique<HelloWorldPlugin>();
}
};
3. Beschrijf haar in plugin.json¶
{
"id": "org.mte.helloworld",
"name": "Hello World",
"version": "1.0.0",
"apiVersion": 1,
"entry": "native",
"requires": [],
"order": 600,
"menus": [
{ "title": "Plugins", "barPriority": 570, "itemPriority": 100 }
]
}
De apiVersion hier en die welke info() oplevert moeten beide gelijk zijn
aan MTE_PLUGIN_API_VERSION, anders weigert de host de plug-in te laden.
Er horen twee optionele sleutels bij:
apiMinorVersion(standaard0) — de laagste minorversie van de host-API die je plug-in nodig heeft. Een host waarvanMTE_PLUGIN_API_MINOR_VERSIONlager is, toont de plug-in met «Vereist een nieuwere versie van OctoEdit» en laadt hem niet. De host controleert deze manifestwaarde voordat hij iets laadt, en daarna nogmaalsPluginInfo::apiMinorVersionuitinfo()— die is standaard de minor van de headers waartegen je hebt gecompileerd, dus laat hem met rust tenzij je weet dat je niets nieuwers gebruikt. Zie Versiebeheer.requires(standaard[]) — de id's van plug-ins zonder welke je plug-in niet kan werken, bijvoorbeeld["org.mte.lsp"]. Alleen id's: er is geen versiebereik en geen optionele vorm — een plug-in waarmee de jouwe alleen beter werkt, hoort hier niet; praat er tijdens de uitvoering mee via gebeurtenissen en leveranciersregisters. De editor initialiseert je afhankelijkheden vóór jou, watorderook zegt, en sluit ze na jou af. Ontbreekt er een, is die uitgeschakeld, heeft die een licentie nodig die niet actief is, of is die niet geladen, dan wordt je plug-in helemaal niet geladen, en zegt Voorkeuren ▸ Plug-ins welke plug-in hij nodig heeft en waarom («Vereist de plug-in LSP Provider, die is uitgeschakeld»). Een cyclus blokkeert elke plug-in die erin zit. Dezelfde sleutel betekent hetzelfde in deplugin.jsonvan een Python-plug-in.
Meegeleverde bibliotheken vermelden — thirdParty¶
Levert uw plug-in een onderdeel van derden mee of koppelt zij daaraan, verklaar
het dan in een optionele array thirdParty, zodat de editor de
vermeldingsverplichtingen ervan kan nakomen:
"thirdParty": [
{ "name": "Qt WebEngine", "license": "LGPL-3.0",
"url": "https://doc.qt.io/qt-6/qtwebengine-index.html",
"file": "QtWebEngine-LGPLv3.txt" }
]
Elk item heeft een name nodig (items zonder naam vallen af); license, url
en file zijn optioneel. De licentieteksten zijn van uw plug-in: lever ze
naast de plug-in mee onder Plugins/Licenses/<your-plugin-id>/, waar file de
kale bestandsnaam is. Het venster Over somt de thirdParty-onderdelen van
elke geïnstalleerde plug-in op en wijst gebruikers naar die map; de kern draagt
de teksten van derden van een plug-in nooit voor haar. (De meegeleverde
HtmlPreviewPlugin, die QtWebEngine + Chromium inbedt, is het
referentievoorbeeld.)
4. Compileer haar¶
Gebruik het CMake-hulpmiddel van de SDK:
find_package(MTEPluginSDK REQUIRED)
mte_add_plugin(NAME HelloWorldPlugin
SOURCES Src/HelloWorldPlugin.cpp
# TRANSLATIONS Translations/HelloWorld_en.ts ...
)
Bouwvereisten¶
Een inheemse plug-in wordt in het proces van de editor geladen, dus zij moet gebouwd worden met een toolchain die binair compatibel is met de editorbuild waarvoor zij bedoeld is. Dit zijn de vereisten voor de huidige uitgave (gebouwd met Qt 6.11.2):
| Windows | macOS | |
|---|---|---|
| Compiler | Visual Studio 2022, MSVC-toolset 14.44 of een ouder 14.x (VS 2015–2022 delen één C++-ABI); clang-cl werkt ook. Builds met MinGW / GCC kunnen niet geladen worden. |
Apple clang uit Xcode (Xcode 27, Apple clang 21.0.0); alleen arm64 |
| Bouwconfiguratie | Release, dynamische runtime (/MD, de standaard van CMake). Een Debug-plug-in wordt door de lader geweigerd; een plug-in met statische runtime (/MT) crasht wanneer geheugen de plug-ingrens oversteekt |
Release; deployment target 14.4 (hetzelfde als de editor) |
| Qt | Qt 6.11, kit msvc2022_64. Een plug-in die tegen een oudere 6.x-minor gebouwd is laadt; een die tegen een nieuwere minor gebouwd is misschien niet |
Qt 6.11, dezelfde architectuur |
| C++-standaard | C++20 (de API-headers gebruiken std::span en concepts) |
C++20 |
| CMake | 3.16+ | 3.16+ |
| Plug-in-API | de MTE_PLUGIN_API_VERSION van de SDK die met de editorversie meekwam waarop u mikt |
idem |
Twee gevolgen die de moeite van het weten waard zijn op Windows:
- De Visual C++ Redistributable die op de machine van de gebruiker geïnstalleerd is moet minstens zo nieuw zijn als de nieuwste MSVC-toolset die door de editor of een geladen plug-in gebruikt wordt. Uw plug-in met een nieuwere toolset bouwen dan die van de editor verhoogt die eis voor uw gebruikers; bouwen met de toolset van de editor of met een oudere niet.
- De versie van de Windows SDK waartegen u compileert beïnvloedt de compatibiliteit met de editor niet; die bepaalt alleen welke Windows-API's uw plug-in kan aanroepen, en de editor ondersteunt Windows 10 1809 en later.
En op macOS:
- De editor wordt alleen voor arm64 geleverd; een plug-in die alleen
x86_64is kan niet geladen worden (een universeel binair bestand is prima). Houd het deployment target op 14.4: een plug-in die voor een nieuwere minimale macOS gebouwd is wordt op oudere Macs door de lader van het systeem geweigerd, en omdat de libc++ van het besturingssysteem zelf de runtime is, speelt er geen vraag rond een redistributable. - Verwijs naar de Qt-frameworks via
@rpath, zodat de plug-in de kopieën oppikt die binnenOctoEdit.appmeegeleverd zijn. Qt-kits waarvan de frameworks absolute installatienamen dragen (die van Homebrew bijvoorbeeld) hebben vóór de leveringinstall_name_toolop de gebouwde plug-in nodig; anders zoekt de plug-in Qt op het pad van de bouwmachine.
Niets hiervan geldt voor Python-plug-ins: die draaien in een apart proces en delen geen binaire interface met de editor.
5. Installeren en uitvoeren¶
U kunt de gebouwde bibliotheek + plugin.json als <name>.mteplugin
comprimeren en haar via Voorkeuren ▸ Plug-ins ▸ Plug-in installeren... installeren (het
pakket wordt gevalideerd — manifest, veiligheid van het archief en de metagegevens
die in het binaire bestand ingebed zijn — voordat er iets aangeraakt wordt), of de
bestanden met de hand in een gevonden plug-inmap neerzetten (zie
Overzicht van de architectuur). Herstart de editor en
schakel haar zo nodig in bij Voorkeuren ▸ Plug-ins.
Volgende stappen¶
- Overzicht van de plug-in-API — levenscyclus, tokens en de volledige dienstentabel
- Opdrachten en menu's
- Dokken, tabbladen en statusbalk
- Instellingenpagina's
- Gebeurtenissen
- Vertalingen