WingHexExplorer/WingHexExplorer/plugin/pluginsystem.cpp

239 lines
6.8 KiB
C++

#include "pluginsystem.h"
#include <QDir>
#include <QFileInfoList>
#include <QMessageBox>
#include <QPluginLoader>
#include <QtConcurrent>
#include <QtCore>
PluginSystem::PluginSystem(QObject *parent)
: QObject(parent), curpluginctl(nullptr) {
logger = Logger::getInstance();
// init plugin dispathcer
#define InitDispathcer(hookindex) \
dispatcher.insert(hookindex, QList<IWingPlugin *>());
InitDispathcer(HookIndex::OpenFileBegin);
InitDispathcer(HookIndex::OpenFileEnd);
InitDispathcer(HookIndex::OpenDriverBegin);
InitDispathcer(HookIndex::OpenDriverEnd);
InitDispathcer(HookIndex::CloseFileBegin);
InitDispathcer(HookIndex::CloseFileEnd);
InitDispathcer(HookIndex::NewFileBegin);
InitDispathcer(HookIndex::NewFileEnd);
InitDispathcer(HookIndex::DocumentSwitched);
}
PluginSystem::~PluginSystem() {
for (auto item : loadedplgs) {
item->plugin2MessagePipe(WingPluginMessage::PluginUnLoading, emptyparam);
item->controller.disconnect();
item->reader.disconnect();
item->plugin2MessagePipe(WingPluginMessage::PluginUnLoaded, emptyparam);
item->unload();
item->deleteLater();
}
}
QList<IWingPlugin *> PluginSystem::plugins() { return loadedplgs; }
void PluginSystem::raiseDispatch(HookIndex hookindex, QList<QVariant> params) {
auto dispatch = dispatcher[hookindex];
params.push_front(hookindex);
for (auto item : dispatch) {
item->plugin2MessagePipe(WingPluginMessage::HookMessage, params);
}
}
void PluginSystem::loadPlugin(QFileInfo fileinfo) {
if (fileinfo.exists()) {
QPluginLoader loader(fileinfo.absoluteFilePath());
logger->logMessage(
INFOLOG(QString(">> ") + tr("LoadingPlugin") + fileinfo.fileName()));
QList<WingPluginInfo> loadedplginfos;
auto p = qobject_cast<IWingPlugin *>(loader.instance());
if (p) {
if (p->signature() != WINGSUMMER) {
logger->logMessage(ERRLOG(tr("ErrLoadPluginSign")));
loader.unload();
return;
}
if (p->sdkVersion() != SDKVERSION) {
logger->logMessage(ERRLOG(tr("ErrLoadPluginSDKVersion")));
loader.unload();
return;
}
if (!p->pluginName().trimmed().length()) {
logger->logMessage(ERRLOG(tr("ErrLoadPluginNoName")));
loader.unload();
return;
}
auto puid = PluginUtils::GetPUID(p);
if (puid != p->puid()) {
logger->logMessage(ERRLOG(tr("ErrLoadPluginPUID")));
loader.unload();
return;
}
if (loadedpuid.contains(puid)) {
logger->logMessage(ERRLOG(tr("ErrLoadLoadedPlugin")));
loader.unload();
return;
}
emit p->plugin2MessagePipe(WingPluginMessage::PluginLoading, emptyparam);
if (!p->init(loadedplginfos)) {
logger->logMessage(ERRLOG(tr("ErrLoadInitPlugin")));
loader.unload();
return;
}
WingPluginInfo info;
info.puid = p->puid();
info.pluginName = p->pluginName();
info.pluginAuthor = p->pluginAuthor();
info.pluginComment = p->pluginComment();
info.pluginVersion = p->pluginVersion();
loadedplginfos.push_back(info);
loadedplgs.push_back(p);
loadedpuid << puid;
logger->logMessage(WARNLOG(tr("PluginWidgetRegister")));
auto menu = p->registerMenu();
if (menu) {
emit this->PluginMenuNeedAdd(menu);
}
auto tbtn = p->registerToolButton();
if (tbtn) {
emit this->PluginToolButtonAdd(tbtn);
}
auto dockw = p->registerDockWidget();
if (dockw) {
emit this->PluginDockWidgetAdd(dockw, p->registerDockWidgetDockArea());
}
emit ConnectBase(p);
auto sub = p->getHookSubscribe();
#define INSERTSUBSCRIBE(HOOK) \
if (sub & HOOK) \
dispatcher[HOOK].push_back(p);
INSERTSUBSCRIBE(HookIndex::OpenFileBegin);
INSERTSUBSCRIBE(HookIndex::OpenFileEnd);
INSERTSUBSCRIBE(HookIndex::OpenDriverBegin);
INSERTSUBSCRIBE(HookIndex::OpenDriverEnd);
INSERTSUBSCRIBE(HookIndex::CloseFileBegin);
INSERTSUBSCRIBE(HookIndex::CloseFileEnd);
INSERTSUBSCRIBE(HookIndex::NewFileBegin);
INSERTSUBSCRIBE(HookIndex::NewFileEnd);
INSERTSUBSCRIBE(HookIndex::DocumentSwitched);
emit p->plugin2MessagePipe(WingPluginMessage::PluginLoaded, emptyparam);
} else {
logger->logMessage(ERRLOG(loader.errorString()));
loader.unload();
}
}
}
bool PluginSystem::LoadPlugin() {
#ifdef QT_DEBUG
QDir plugindir("/home/wingsummer/QT Project/");
//这是我的插件调试目录,如果调试插件,请更换路径
plugindir.setNameFilters(QStringList("*.so"));
#else
QDir plugindir(QCoreApplication::applicationDirPath() + "/plugin");
plugindir.setNameFilters(QStringList("*.wingplg"));
#endif
auto plgs = plugindir.entryInfoList();
logger->logMessage(
INFOLOG(tr("FoundPluginCount") + QString::number(plgs.count())));
for (auto item : plgs) {
loadPlugin(item);
}
return true;
}
bool PluginSystem::requestControl(IWingPlugin *plugin, int timeout) {
if (plugin == nullptr)
return false;
auto res = mutex.tryLock(timeout);
if (!res)
return false;
auto oldctl = curpluginctl;
if (oldctl) {
if (plugintimeout[oldctl]) {
initControl(plugin);
oldctl->plugin2MessagePipe(
WingPluginMessage::ConnectTimeout,
QList<QVariant>({plugin->pluginName(), plugin->puid()}));
}
} else {
initControl(plugin);
}
mutex.unlock();
return true;
}
bool PluginSystem::requestRelease(IWingPlugin *plugin) {
if (plugin == nullptr)
return false;
if (mutex.tryLock(1500)) {
plugin->controller.disconnect();
plugintimer[plugin]->stop();
plugintimeout[plugin] = false;
curpluginctl = nullptr;
mutex.unlock();
return true;
}
return false;
}
void PluginSystem::resetTimeout(IWingPlugin *plugin) {
if (plugin == nullptr)
return;
plugintimer[plugin]->start(1000);
plugintimeout[plugin] = false;
}
void PluginSystem::initControl(IWingPlugin *plugin) {
if (!plugintimer.contains(plugin)) {
auto timer = new QTimer(this);
plugintimer.insert(plugin, timer);
connect(timer, &QTimer::timeout, [=] {
plugintimeout[plugin] = true;
timer->stop();
});
}
if (plugintimeout.contains(plugin)) {
plugintimeout[plugin] = false;
} else {
plugintimeout.insert(plugin, false);
}
if (curpluginctl)
requestRelease(plugin);
emit ConnectControl(plugin);
curpluginctl = plugin;
plugintimer[plugin]->start(1000);
}
bool PluginSystem::hasControl() { return curpluginctl != nullptr; }
IWingPlugin *PluginSystem::currentControlPlugin() { return curpluginctl; }
bool PluginSystem::currentControlTimeout() {
if (hasControl())
return plugintimeout[curpluginctl];
return true;
}