mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Improve plugin settings
This commit is contained in:
parent
1616db56b1
commit
03ad993ab4
5 changed files with 185 additions and 32 deletions
|
@ -26,9 +26,37 @@ namespace chatterino {
|
|||
|
||||
void PluginController::initialize(Settings &settings, Paths &paths)
|
||||
{
|
||||
(void)(settings);
|
||||
(void)paths;
|
||||
|
||||
auto dir = QDir(paths.pluginsDirectory);
|
||||
settings.enableAnyPlugins.connect([this](bool enabled) {
|
||||
if (enabled)
|
||||
{
|
||||
this->actuallyInitialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
// uninitialize plugins
|
||||
for (const auto &[codename, plugin] : this->plugins_)
|
||||
{
|
||||
this->reload(codename);
|
||||
}
|
||||
// can safely delete them now, after lua freed its stuff
|
||||
this->plugins_.clear();
|
||||
}
|
||||
});
|
||||
this->actuallyInitialize();
|
||||
}
|
||||
|
||||
// this function exists to allow for connecting to enableAnyPlugins option
|
||||
void PluginController::actuallyInitialize()
|
||||
{
|
||||
if (!getSettings()->enableAnyPlugins)
|
||||
{
|
||||
qCDebug(chatterinoLua)
|
||||
<< "Loading plugins disabled via Setting, skipping";
|
||||
return;
|
||||
}
|
||||
auto dir = QDir(getPaths()->pluginsDirectory);
|
||||
qCDebug(chatterinoLua) << "loading plugins from " << dir;
|
||||
for (const auto &info : dir.entryInfoList())
|
||||
{
|
||||
|
@ -110,6 +138,15 @@ void PluginController::load(QFileInfo index, QDir pluginDir, PluginMeta meta)
|
|||
|
||||
auto pluginName = pluginDir.dirName();
|
||||
auto plugin = std::make_unique<Plugin>(pluginName, l, meta, pluginDir);
|
||||
for (const auto &[codename, other] : this->plugins_)
|
||||
{
|
||||
if (other->meta.name == meta.name)
|
||||
{
|
||||
plugin->isDupeName = true;
|
||||
other->isDupeName = true;
|
||||
}
|
||||
}
|
||||
|
||||
this->plugins_.insert({pluginName, std::move(plugin)});
|
||||
|
||||
int err = luaL_dofile(l, index.absoluteFilePath().toStdString().c_str());
|
||||
|
@ -130,14 +167,22 @@ bool PluginController::reload(const QString &codename)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
if (it->second->state_ != nullptr)
|
||||
{
|
||||
lua_close(it->second->state_);
|
||||
it->second->state_ = nullptr;
|
||||
}
|
||||
for (const auto &[cmd, _] : it->second->ownedCommands)
|
||||
{
|
||||
getApp()->commands->unregisterPluginCommand(cmd);
|
||||
}
|
||||
it->second->ownedCommands.clear();
|
||||
if (this->isEnabled(codename))
|
||||
{
|
||||
QDir loadDir = it->second->loadDirectory_;
|
||||
this->plugins_.erase(codename);
|
||||
this->tryLoadFromDir(loadDir);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -291,4 +336,15 @@ void PluginController::loadChatterinoLib(lua_State *L)
|
|||
luaL_setfuncs(L, C2LIB, 0);
|
||||
}
|
||||
|
||||
bool PluginController::isEnabled(const QString &codename)
|
||||
{
|
||||
if (!getSettings()->enableAnyPlugins)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto vec = getSettings()->enabledPlugins.getValue();
|
||||
auto it = std::find(vec.begin(), vec.end(), codename);
|
||||
return it != vec.end();
|
||||
}
|
||||
|
||||
}; // namespace chatterino
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
#include <semver/semver.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
@ -27,16 +29,33 @@ struct PluginMeta {
|
|||
QString description;
|
||||
QString authors;
|
||||
QString homepage;
|
||||
|
||||
QString license;
|
||||
semver::version version;
|
||||
|
||||
std::vector<QString> tags;
|
||||
|
||||
std::set<QString> libraryPermissions;
|
||||
|
||||
explicit PluginMeta(const QJsonObject &obj)
|
||||
: name(obj.value("name").toString())
|
||||
: name(obj.value("name").toString("A Plugin with no name"))
|
||||
, description(obj.value("description").toString())
|
||||
, authors(obj.value("authors").toString())
|
||||
, homepage(obj.value("homepage").toString())
|
||||
, license(obj.value("license").toString("[unknown]"))
|
||||
|
||||
{
|
||||
auto v = semver::from_string_noexcept(
|
||||
obj.value("version").toString().toStdString());
|
||||
if (v.has_value())
|
||||
{
|
||||
this->version = v.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->version = semver::version(0, 0, 0);
|
||||
description.append("\nWarning: invalid version");
|
||||
}
|
||||
for (const auto &t : obj.value("tags").toArray())
|
||||
{
|
||||
this->tags.push_back(t.toString());
|
||||
|
@ -53,6 +72,7 @@ class Plugin
|
|||
public:
|
||||
QString codename;
|
||||
PluginMeta meta;
|
||||
bool isDupeName{};
|
||||
|
||||
Plugin(QString codename, lua_State *state, PluginMeta meta,
|
||||
const QDir &loadDirectory)
|
||||
|
@ -133,8 +153,10 @@ public:
|
|||
}
|
||||
|
||||
bool reload(const QString &codename);
|
||||
bool isEnabled(const QString &codename);
|
||||
|
||||
private:
|
||||
void actuallyInitialize();
|
||||
void load(QFileInfo index, QDir pluginDir, PluginMeta meta);
|
||||
void loadChatterinoLib(lua_State *l);
|
||||
|
||||
|
|
|
@ -520,6 +520,10 @@ public:
|
|||
{"d", 1},
|
||||
{"w", 1}}};
|
||||
|
||||
BoolSetting enableAnyPlugins = {"/plugins/load", false};
|
||||
ChatterinoSetting<std::vector<QString>> enabledPlugins = {
|
||||
"/plugins/enabled", {}};
|
||||
|
||||
private:
|
||||
void updateModerationActions();
|
||||
};
|
||||
|
|
|
@ -8,50 +8,84 @@
|
|||
#include "util/LayoutCreator.hpp"
|
||||
#include "util/RemoveScrollAreaBackground.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <qobject.h>
|
||||
#include <QObject>
|
||||
#include <QPushButton>
|
||||
#include <qwidget.h>
|
||||
#include <QWidget>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
PluginsPage::PluginsPage()
|
||||
: scrollArea_(nullptr)
|
||||
: scrollAreaWidget_(nullptr)
|
||||
, dataFrame_(nullptr)
|
||||
{
|
||||
qDebug() << "plugins page created";
|
||||
LayoutCreator<PluginsPage> layoutCreator(this);
|
||||
this->scrollArea_ = layoutCreator.emplace<QScrollArea>();
|
||||
auto scrollArea = layoutCreator.emplace<QScrollArea>();
|
||||
|
||||
auto widget = scrollArea.emplaceScrollAreaWidget();
|
||||
this->scrollAreaWidget_ = widget;
|
||||
removeScrollAreaBackground(scrollArea.getElement(), widget.getElement());
|
||||
|
||||
auto layout = widget.setLayoutType<QVBoxLayout>();
|
||||
|
||||
{
|
||||
auto group = layout.emplace<QGroupBox>("General plugin settings");
|
||||
this->generalGroup = group.getElement();
|
||||
auto groupLayout = group.setLayoutType<QFormLayout>();
|
||||
auto *description = new QLabel(
|
||||
"You can load plugins by putting them into " +
|
||||
formatRichNamedLink("file:///" + getPaths()->pluginsDirectory,
|
||||
"the Plugins directory") +
|
||||
". Each one is a new directory.");
|
||||
description->setOpenExternalLinks(true);
|
||||
description->setWordWrap(true);
|
||||
description->setStyleSheet("color: #bbb");
|
||||
groupLayout->addRow(description);
|
||||
|
||||
auto *box = this->createCheckBox("Enable plugins",
|
||||
getSettings()->enableAnyPlugins);
|
||||
QObject::connect(box, &QCheckBox::released, [this, box]() {
|
||||
//using namespace std::chrono_literals;
|
||||
//QTimer::singleShot(10000ms, [this]() {
|
||||
this->rebuildContent();
|
||||
//});
|
||||
});
|
||||
groupLayout->addRow(box);
|
||||
}
|
||||
|
||||
this->rebuildContent();
|
||||
}
|
||||
|
||||
void PluginsPage::rebuildContent()
|
||||
{
|
||||
auto widget = this->scrollArea_.emplaceScrollAreaWidget();
|
||||
removeScrollAreaBackground(this->scrollArea_.getElement(),
|
||||
widget.getElement());
|
||||
|
||||
auto layout = widget.setLayoutType<QVBoxLayout>();
|
||||
auto group = layout.emplace<QGroupBox>("Plugins");
|
||||
auto groupLayout = group.setLayoutType<QFormLayout>();
|
||||
|
||||
auto *description = new QLabel(
|
||||
"You can load plugins by putting them into " +
|
||||
formatRichNamedLink("file:///" + getPaths()->pluginsDirectory,
|
||||
"the Plugins directory") +
|
||||
". Each one is a "
|
||||
"new directory.");
|
||||
description->setOpenExternalLinks(true);
|
||||
description->setWordWrap(true);
|
||||
description->setStyleSheet("color: #bbb");
|
||||
groupLayout->addRow(description);
|
||||
|
||||
if (this->dataFrame_ != nullptr)
|
||||
{
|
||||
this->dataFrame_->deleteLater();
|
||||
this->dataFrame_ = nullptr;
|
||||
}
|
||||
auto frame = LayoutCreator<QFrame>(new QFrame(this));
|
||||
this->dataFrame_ = frame.getElement();
|
||||
this->scrollAreaWidget_.append(this->dataFrame_);
|
||||
auto layout = frame.setLayoutType<QVBoxLayout>();
|
||||
for (const auto &[codename, plugin] : getApp()->plugins->plugins())
|
||||
{
|
||||
auto plgroup = groupLayout.emplace<QGroupBox>(plugin->meta.name);
|
||||
auto headerText = QString("%1 (%2)").arg(
|
||||
plugin->meta.name,
|
||||
QString::fromStdString(plugin->meta.version.to_string()));
|
||||
if (plugin->isDupeName)
|
||||
{
|
||||
// add ", from <folder name>)" in place of ")"
|
||||
headerText.chop(1);
|
||||
headerText += ", from " + codename + ")";
|
||||
}
|
||||
auto plgroup = layout.emplace<QGroupBox>(headerText);
|
||||
auto pl = plgroup.setLayoutType<QFormLayout>();
|
||||
auto *descrText = new QLabel(plugin->meta.description);
|
||||
//descrText->setTextFormat(Qt::TextFormat::MarkdownText);
|
||||
descrText->setWordWrap(true);
|
||||
descrText->setStyleSheet("color: #bbb");
|
||||
pl->addRow(descrText);
|
||||
|
@ -60,6 +94,7 @@ void PluginsPage::rebuildContent()
|
|||
homepage->setOpenExternalLinks(true);
|
||||
|
||||
pl->addRow("Homepage", homepage);
|
||||
pl->addRow("License", new QLabel(plugin->meta.license));
|
||||
|
||||
QString libString;
|
||||
bool hasDangerous = false;
|
||||
|
@ -99,6 +134,32 @@ void PluginsPage::rebuildContent()
|
|||
}
|
||||
pl->addRow("Commands", new QLabel(cmds));
|
||||
|
||||
QString enableOrDisableStr = "Enable";
|
||||
if (getApp()->plugins->isEnabled(codename))
|
||||
{
|
||||
enableOrDisableStr = "Disable";
|
||||
}
|
||||
|
||||
auto *enableDisable = new QPushButton(enableOrDisableStr);
|
||||
QObject::connect(
|
||||
enableDisable, &QPushButton::pressed, [name = codename, this]() {
|
||||
std::vector<QString> val =
|
||||
getSettings()->enabledPlugins.getValue();
|
||||
if (getApp()->plugins->isEnabled(name))
|
||||
{
|
||||
val.erase(std::remove(val.begin(), val.end(), name),
|
||||
val.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
val.push_back(name);
|
||||
}
|
||||
getSettings()->enabledPlugins.setValue(val);
|
||||
getApp()->plugins->reload(name);
|
||||
this->rebuildContent();
|
||||
});
|
||||
pl->addRow(enableDisable);
|
||||
|
||||
auto *reload = new QPushButton("Reload");
|
||||
QObject::connect(reload, &QPushButton::pressed,
|
||||
[name = codename, this]() {
|
||||
|
@ -108,4 +169,5 @@ void PluginsPage::rebuildContent()
|
|||
pl->addRow(reload);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QWidget>
|
||||
|
||||
namespace chatterino {
|
||||
class Plugin;
|
||||
|
||||
|
@ -11,10 +14,16 @@ class PluginsPage : public SettingsPage
|
|||
{
|
||||
public:
|
||||
PluginsPage();
|
||||
~PluginsPage() override
|
||||
{
|
||||
qDebug() << "plugins page deleted";
|
||||
}
|
||||
|
||||
private:
|
||||
void rebuildContent();
|
||||
|
||||
LayoutCreator<QScrollArea> scrollArea_;
|
||||
LayoutCreator<QWidget> scrollAreaWidget_;
|
||||
QGroupBox *generalGroup;
|
||||
QFrame *dataFrame_;
|
||||
};
|
||||
} // namespace chatterino
|
||||
|
|
Loading…
Reference in a new issue