|
|
@@ -0,0 +1,240 @@
|
|
|
+#include "pluginmanager.h"
|
|
|
+#include <QDir>
|
|
|
+#include <QJsonParseError>
|
|
|
+#include <QJsonDocument>
|
|
|
+#include <QJsonObject>
|
|
|
+#include <QJsonArray>
|
|
|
+#include "logger.h"
|
|
|
+
|
|
|
+PluginManager::PluginManager(QObject *parent)
|
|
|
+ : QObject{parent}
|
|
|
+{
|
|
|
+ initPluginInfo();
|
|
|
+ loadPlugins();
|
|
|
+}
|
|
|
+
|
|
|
+PluginManager::~PluginManager()
|
|
|
+{
|
|
|
+ savePluginInfo();
|
|
|
+ clear();
|
|
|
+}
|
|
|
+
|
|
|
+void PluginManager::initPluginInfo()
|
|
|
+{
|
|
|
+ QString fileName = QString("%1/%2").arg(QDir::currentPath(), "plugininfo.json");
|
|
|
+ QFile file(fileName);
|
|
|
+ if(file.exists() && file.open(QIODevice::ReadOnly))
|
|
|
+ {
|
|
|
+ QJsonParseError error;
|
|
|
+ QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
|
|
|
+ if(error.error == QJsonParseError::NoError && doc.isObject())
|
|
|
+ {
|
|
|
+ QJsonObject obj = doc.object();
|
|
|
+ QJsonArray array = obj["configure"].toArray();
|
|
|
+ foreach(auto item, array)
|
|
|
+ {
|
|
|
+ LOG_INFO("record plugin name: {}", item["name"].toString().toUtf8().data());
|
|
|
+ LOG_INFO("record plugin path: {}", item["path"].toString().toUtf8().data());
|
|
|
+ LOG_INFO("record plugin enabled: {}", item["enabled"].toBool());
|
|
|
+
|
|
|
+ QFileInfo fileInfo(item["path"].toString());
|
|
|
+ if(fileInfo.exists())
|
|
|
+ {
|
|
|
+ plugin_info_st info;
|
|
|
+ info.fileName = item["name"].toString();
|
|
|
+ info.filePath = item["path"].toString();
|
|
|
+ info.isEnabled = item["enabled"].toBool();
|
|
|
+ m_pluginInfoMap.insert(info.fileName, info);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ QDir dir;
|
|
|
+ QString path;
|
|
|
+ QFileInfoList fileInfoList;
|
|
|
+ path = QString("%1/%2").arg(QDir::currentPath(), "plugins");
|
|
|
+ dir.setPath(path);
|
|
|
+ fileInfoList = dir.entryInfoList(QStringList() << "*.so", QDir::Files | QDir::NoSymLinks);
|
|
|
+
|
|
|
+ foreach(auto fileInfo, fileInfoList)
|
|
|
+ {
|
|
|
+ if(m_pluginInfoMap.contains(fileInfo.fileName()))
|
|
|
+ continue;
|
|
|
+ plugin_info_st info;
|
|
|
+ info.fileName = fileInfo.fileName();
|
|
|
+ info.filePath = fileInfo.filePath();
|
|
|
+ info.isEnabled = true;
|
|
|
+ m_pluginInfoMap.insert(fileInfo.fileName(), info);
|
|
|
+ }
|
|
|
+
|
|
|
+ savePluginInfo();
|
|
|
+}
|
|
|
+
|
|
|
+void PluginManager::savePluginInfo()
|
|
|
+{
|
|
|
+ QJsonObject info;
|
|
|
+ QJsonArray array;
|
|
|
+
|
|
|
+ QList<plugin_info_st> pluginInfoList = m_pluginInfoMap.values();
|
|
|
+ foreach(auto info, pluginInfoList)
|
|
|
+ {
|
|
|
+ QJsonObject obj;
|
|
|
+ obj["name"] = info.fileName;
|
|
|
+ obj["path"] = info.filePath;
|
|
|
+ obj["enabled"] = info.isEnabled;
|
|
|
+ array.push_back(obj);
|
|
|
+ }
|
|
|
+ info["configure"] = array;
|
|
|
+
|
|
|
+ QJsonDocument doc(info);
|
|
|
+ QString fileName = QString("%1/%2").arg(QDir::currentPath(), "plugininfo.json");
|
|
|
+ QFile file(fileName);
|
|
|
+ if(file.open(QIODevice::ReadWrite | QIODevice::Truncate))
|
|
|
+ {
|
|
|
+ file.write(doc.toJson(QJsonDocument::Indented));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LOG_ERROR("{}", file.errorString().toUtf8().data());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void PluginManager::loadPlugins()
|
|
|
+{
|
|
|
+ QList<plugin_info_st> pluginInfoList = m_pluginInfoMap.values();
|
|
|
+ foreach(auto info, pluginInfoList)
|
|
|
+ {
|
|
|
+ PluginLoader *pPluginLoader = new PluginLoader(info.filePath);
|
|
|
+ if(pPluginLoader->load())
|
|
|
+ {
|
|
|
+ if(info.isEnabled)
|
|
|
+ m_customWidgets << pPluginLoader->customWidgets();
|
|
|
+ else
|
|
|
+ pPluginLoader->unload();
|
|
|
+ m_pluginLoaderMap.insert(info.fileName, pPluginLoader);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LOG_ERROR("plugin loader load failed: {}", info.filePath.toUtf8().data());
|
|
|
+ delete pPluginLoader;
|
|
|
+ pPluginLoader = nullptr;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void PluginManager::loadPlugin(QString fileName)
|
|
|
+{
|
|
|
+ auto it = m_pluginLoaderMap.find(fileName);
|
|
|
+ if(it == m_pluginLoaderMap.end())
|
|
|
+ {
|
|
|
+ plugin_info_st info = m_pluginInfoMap.value(fileName);
|
|
|
+ PluginLoader *pPluginLoader = new PluginLoader(info.filePath);
|
|
|
+ if(pPluginLoader->load())
|
|
|
+ {
|
|
|
+ if(info.isEnabled)
|
|
|
+ m_customWidgets << pPluginLoader->customWidgets();
|
|
|
+ else
|
|
|
+ pPluginLoader->unload();
|
|
|
+ m_pluginLoaderMap.insert(info.fileName, pPluginLoader);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ it.value()->load();
|
|
|
+ QList<QDesignerCustomWidgetInterface *> widgets = it.value()->customWidgets();
|
|
|
+ m_customWidgets << widgets;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void PluginManager::unloadPlugin(QString fileName)
|
|
|
+{
|
|
|
+ auto it = m_pluginLoaderMap.find(fileName);
|
|
|
+ if(it == m_pluginLoaderMap.end())
|
|
|
+ return;
|
|
|
+ QList<QDesignerCustomWidgetInterface *> widgets = it.value()->customWidgets();
|
|
|
+ foreach(auto widget, widgets)
|
|
|
+ {
|
|
|
+ if(m_customWidgets.contains(widget))
|
|
|
+ m_customWidgets.removeOne(widget);
|
|
|
+ }
|
|
|
+ it.value()->unload();
|
|
|
+}
|
|
|
+
|
|
|
+bool PluginManager::delPlugin(QString fileName, bool keepInfo)
|
|
|
+{
|
|
|
+ auto it = m_pluginLoaderMap.find(fileName);
|
|
|
+ if(it == m_pluginLoaderMap.end())
|
|
|
+ return false;
|
|
|
+ QFile file(it.value()->fileName());
|
|
|
+ QList<QDesignerCustomWidgetInterface *> widgets = it.value()->customWidgets();
|
|
|
+ foreach(auto widget, widgets)
|
|
|
+ {
|
|
|
+ if(m_customWidgets.contains(widget))
|
|
|
+ m_customWidgets.removeOne(widget);
|
|
|
+ }
|
|
|
+ delete it.value();
|
|
|
+ it.value() = nullptr;
|
|
|
+ m_pluginLoaderMap.erase(it);
|
|
|
+ if(!keepInfo)
|
|
|
+ m_pluginInfoMap.remove(fileName);
|
|
|
+ return file.remove();
|
|
|
+}
|
|
|
+
|
|
|
+bool PluginManager::upgradePlugin(QString fileName, QString srcFile)
|
|
|
+{
|
|
|
+ bool ret;
|
|
|
+ ret = delPlugin(fileName, true);
|
|
|
+ if(ret)
|
|
|
+ {
|
|
|
+ QString dstFile = QString("%1/%2").arg(QDir::currentPath(), fileName);
|
|
|
+ ret = QFile::copy(srcFile, dstFile);
|
|
|
+ if(ret)
|
|
|
+ {
|
|
|
+ auto it = m_pluginInfoMap.find(fileName);
|
|
|
+ if(it != m_pluginInfoMap.end() && it.value().isEnabled)
|
|
|
+ loadPlugin(fileName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+bool PluginManager::addPlugin(QString srcFile)
|
|
|
+{
|
|
|
+ QFileInfo fileInfo(srcFile);
|
|
|
+ QString dstFile = QString("%1/%2").arg(QDir::currentPath(), fileInfo.fileName());
|
|
|
+ bool ret = QFile::copy(srcFile, dstFile);
|
|
|
+ if(ret)
|
|
|
+ {
|
|
|
+ plugin_info_st info;
|
|
|
+ info.fileName = fileInfo.fileName();
|
|
|
+ info.filePath = dstFile;
|
|
|
+ info.isEnabled = true;
|
|
|
+ m_pluginInfoMap.insert(info.fileName, info);
|
|
|
+ loadPlugin(info.fileName);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+bool PluginManager::contains(QString fileName)
|
|
|
+{
|
|
|
+ return m_pluginInfoMap.contains(fileName);
|
|
|
+}
|
|
|
+
|
|
|
+void PluginManager::clear()
|
|
|
+{
|
|
|
+ qDeleteAll(m_pluginLoaderMap);
|
|
|
+ m_pluginLoaderMap.clear();
|
|
|
+ m_customWidgets.clear();
|
|
|
+ m_pluginInfoMap.clear();
|
|
|
+}
|
|
|
+
|
|
|
+QList<plugin_info_st> PluginManager::pluginInfoList() const
|
|
|
+{
|
|
|
+ return m_pluginInfoMap.values();
|
|
|
+}
|
|
|
+
|
|
|
+QList<QDesignerCustomWidgetInterface *> PluginManager::customWidgets() const
|
|
|
+{
|
|
|
+ return m_customWidgets;
|
|
|
+}
|