mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Add support for reloading plugins
This commit is contained in:
parent
03de6869c4
commit
56c7e78f48
5 changed files with 75 additions and 33 deletions
|
@ -3233,6 +3233,11 @@ bool CommandController::registerPluginCommand(const QString &commandName)
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CommandController::unregisterPluginCommand(const QString &commandName)
|
||||||
|
{
|
||||||
|
return this->commands_.erase(commandName) != 0;
|
||||||
|
}
|
||||||
void CommandController::registerCommand(const QString &commandName,
|
void CommandController::registerCommand(const QString &commandName,
|
||||||
CommandFunctionVariants commandFunction)
|
CommandFunctionVariants commandFunction)
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,6 +44,7 @@ public:
|
||||||
std::unordered_map<QString, QString> context = {});
|
std::unordered_map<QString, QString> context = {});
|
||||||
|
|
||||||
bool registerPluginCommand(const QString &commandName);
|
bool registerPluginCommand(const QString &commandName);
|
||||||
|
bool unregisterPluginCommand(const QString &commandName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load(Paths &paths);
|
void load(Paths &paths);
|
||||||
|
|
|
@ -34,27 +34,32 @@ void PluginController::initialize(Settings &settings, Paths &paths)
|
||||||
{
|
{
|
||||||
if (info.isDir())
|
if (info.isDir())
|
||||||
{
|
{
|
||||||
// look for index.lua
|
|
||||||
auto pluginDir = QDir(info.absoluteFilePath());
|
auto pluginDir = QDir(info.absoluteFilePath());
|
||||||
|
this->tryLoadFromDir(pluginDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool PluginController::tryLoadFromDir(const QDir &pluginDir)
|
||||||
|
{
|
||||||
|
// look for index.lua
|
||||||
auto index = QFileInfo(pluginDir.filePath("index.lua"));
|
auto index = QFileInfo(pluginDir.filePath("index.lua"));
|
||||||
qCDebug(chatterinoLua)
|
qCDebug(chatterinoLua) << "looking for index.lua and info.json in"
|
||||||
<< "trying" << info << "," << index << "at" << pluginDir;
|
<< pluginDir.path();
|
||||||
if (!index.exists())
|
if (!index.exists())
|
||||||
{
|
{
|
||||||
qCDebug(chatterinoLua)
|
qCDebug(chatterinoLua)
|
||||||
<< "Missing index.lua in plugin directory" << pluginDir;
|
<< "Missing index.lua in plugin directory" << pluginDir;
|
||||||
continue;
|
return false;
|
||||||
}
|
}
|
||||||
qCDebug(chatterinoLua)
|
qCDebug(chatterinoLua) << "found index.lua, now looking for info.json!";
|
||||||
<< "found index.lua, now looking for info.json!";
|
auto infojson = QFileInfo(pluginDir.filePath("info.json"));
|
||||||
auto info = QFileInfo(pluginDir.filePath("info.json"));
|
if (!infojson.exists())
|
||||||
if (!info.exists())
|
|
||||||
{
|
{
|
||||||
qCDebug(chatterinoLua)
|
qCDebug(chatterinoLua)
|
||||||
<< "Missing info.json in plugin directory" << pluginDir;
|
<< "Missing info.json in plugin directory" << pluginDir;
|
||||||
continue;
|
return false;
|
||||||
}
|
}
|
||||||
QFile infoFile(info.absoluteFilePath());
|
QFile infoFile(infojson.absoluteFilePath());
|
||||||
infoFile.open(QIODevice::ReadOnly);
|
infoFile.open(QIODevice::ReadOnly);
|
||||||
auto everything = infoFile.readAll();
|
auto everything = infoFile.readAll();
|
||||||
auto doc = QJsonDocument::fromJson(everything);
|
auto doc = QJsonDocument::fromJson(everything);
|
||||||
|
@ -62,12 +67,11 @@ void PluginController::initialize(Settings &settings, Paths &paths)
|
||||||
{
|
{
|
||||||
qCDebug(chatterinoLua)
|
qCDebug(chatterinoLua)
|
||||||
<< "info.json root is not an object" << pluginDir;
|
<< "info.json root is not an object" << pluginDir;
|
||||||
continue;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->load(index, pluginDir, PluginMeta(doc.object()));
|
this->load(index, pluginDir, PluginMeta(doc.object()));
|
||||||
}
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginController::load(QFileInfo index, QDir pluginDir, PluginMeta meta)
|
void PluginController::load(QFileInfo index, QDir pluginDir, PluginMeta meta)
|
||||||
|
@ -78,13 +82,31 @@ void PluginController::load(QFileInfo index, QDir pluginDir, PluginMeta meta)
|
||||||
this->loadChatterinoLib(l);
|
this->loadChatterinoLib(l);
|
||||||
|
|
||||||
auto pluginName = pluginDir.dirName();
|
auto pluginName = pluginDir.dirName();
|
||||||
auto plugin = std::make_unique<Plugin>(pluginName, l, meta);
|
auto plugin = std::make_unique<Plugin>(pluginName, l, meta, pluginDir);
|
||||||
this->plugins_.insert({pluginName, std::move(plugin)});
|
this->plugins_.insert({pluginName, std::move(plugin)});
|
||||||
|
|
||||||
luaL_dofile(l, index.absoluteFilePath().toStdString().c_str());
|
luaL_dofile(l, index.absoluteFilePath().toStdString().c_str());
|
||||||
qCInfo(chatterinoLua) << "Loaded" << pluginName << "plugin from" << index;
|
qCInfo(chatterinoLua) << "Loaded" << pluginName << "plugin from" << index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PluginController::reload(const QString &codename)
|
||||||
|
{
|
||||||
|
auto it = this->plugins_.find(codename);
|
||||||
|
if (it == this->plugins_.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lua_close(it->second->state_);
|
||||||
|
for (const auto &[cmd, _] : it->second->ownedCommands)
|
||||||
|
{
|
||||||
|
getApp()->commands->unregisterPluginCommand(cmd);
|
||||||
|
}
|
||||||
|
QDir loadDir = it->second->loadDirectory_;
|
||||||
|
this->plugins_.erase(codename);
|
||||||
|
this->tryLoadFromDir(loadDir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void PluginController::callEvery(const QString &functionName)
|
void PluginController::callEvery(const QString &functionName)
|
||||||
{
|
{
|
||||||
for (const auto &[name, plugin] : this->plugins_)
|
for (const auto &[name, plugin] : this->plugins_)
|
||||||
|
|
|
@ -47,9 +47,12 @@ class Plugin
|
||||||
public:
|
public:
|
||||||
QString codename;
|
QString codename;
|
||||||
PluginMeta meta;
|
PluginMeta meta;
|
||||||
Plugin(QString codename, lua_State *state, PluginMeta meta)
|
|
||||||
|
Plugin(QString codename, lua_State *state, PluginMeta meta,
|
||||||
|
const QDir &loadDirectory)
|
||||||
: codename(std::move(codename))
|
: codename(std::move(codename))
|
||||||
, meta(std::move(meta))
|
, meta(std::move(meta))
|
||||||
|
, loadDirectory_(loadDirectory)
|
||||||
, state_(state)
|
, state_(state)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -71,6 +74,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QDir loadDirectory_;
|
||||||
lua_State *state_;
|
lua_State *state_;
|
||||||
|
|
||||||
// maps command name -> function name
|
// maps command name -> function name
|
||||||
|
@ -112,9 +116,12 @@ public:
|
||||||
return this->plugins_;
|
return this->plugins_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool reload(const QString &codename);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load(QFileInfo index, QDir pluginDir, PluginMeta meta);
|
void load(QFileInfo index, QDir pluginDir, PluginMeta meta);
|
||||||
void loadChatterinoLib(lua_State *l);
|
void loadChatterinoLib(lua_State *l);
|
||||||
|
bool tryLoadFromDir(const QDir &pluginDir);
|
||||||
std::map<QString, std::unique_ptr<Plugin>> plugins_;
|
std::map<QString, std::unique_ptr<Plugin>> plugins_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
|
@ -47,6 +48,12 @@ PluginsPage::PluginsPage()
|
||||||
homepage->setOpenExternalLinks(true);
|
homepage->setOpenExternalLinks(true);
|
||||||
|
|
||||||
pl->addRow("Homepage", homepage);
|
pl->addRow("Homepage", homepage);
|
||||||
|
|
||||||
|
auto *reload = new QPushButton("Reload");
|
||||||
|
QObject::connect(reload, &QPushButton::pressed, [=]() {
|
||||||
|
getApp()->plugins->reload(codename);
|
||||||
|
});
|
||||||
|
pl->addRow(reload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
Loading…
Reference in a new issue