Skip to content

Commit

Permalink
add load plugin action , Currently only one path can be added
Browse files Browse the repository at this point in the history
  • Loading branch information
zmoth committed Dec 18, 2022
1 parent 6214f2c commit 49779db
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 63 deletions.
2 changes: 1 addition & 1 deletion examples/plugin_text/PluginDefinition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
using QtNodes::NodeDelegateModelRegistry;
using QtNodes::PluginInterface;

#define PLUGIN_NAME "plugin_text"
#define PLUGIN_NAME "pluginText"

class DLL_EXPORT Plugin
: public QObject
Expand Down
38 changes: 27 additions & 11 deletions examples/plugins_load/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include <QApplication>
#include <QMenuBar>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QObject>

#include <QtNodes/DataFlowGraphModel>
#include <QtNodes/DataFlowGraphicsScene>
#include <QtNodes/GraphicsView>
Expand Down Expand Up @@ -44,17 +47,36 @@ main(int argc, char* argv[])
PluginsManager* pluginsManager = PluginsManager::instance();
std::shared_ptr<NodeDelegateModelRegistry> registry = pluginsManager->registry();
pluginsManager->loadPlugins(R"(./nodes)");
for (auto plugin : pluginsManager->pluginList())
for (auto plugin : pluginsManager->plugins())
{
plugin->registerDataModels(registry);
plugin.second->registerDataModels(registry);
}

QWidget mainWidget;

auto menuBar = new QMenuBar();
QMenu* menu = menuBar->addMenu("File");
auto saveAction = menu->addAction("Save Scene");
auto loadAction = menu->addAction("Load Scene");
QMenu* menu = menuBar->addMenu("Plugins");
auto loadAction = menu->addAction("Load Plugin");
auto unloadAction = menu->addAction("Unload Plugin");

QObject::connect(loadAction, &QAction::triggered,
[&]()
{
// TODO: load plugins
QString fileName =
QFileDialog::getOpenFileName(nullptr,
"Load Plugin",
QDir::homePath());

if (!QFileInfo::exists(fileName))
return;

auto plugin = pluginsManager->loadPluginFromPath(fileName);
if (plugin)
{
plugin->registerDataModels(registry);
}
});

QVBoxLayout* l = new QVBoxLayout(&mainWidget);

Expand All @@ -69,12 +91,6 @@ main(int argc, char* argv[])
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);

QObject::connect(saveAction, &QAction::triggered,
scene, &DataFlowGraphicsScene::save);

QObject::connect(loadAction, &QAction::triggered,
scene, &DataFlowGraphicsScene::load);

QObject::connect(scene, &DataFlowGraphicsScene::sceneLoaded,
view, &GraphicsView::centerScene);

Expand Down
57 changes: 28 additions & 29 deletions include/QtNodes/internal/PluginsManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,22 @@
#include "Export.hpp"
#include "PluginInterface.hpp"

#include <QHash>
#include <QObject>
#include <QPluginLoader>
#include <vector>
#include <unordered_map>

namespace QtNodes
{

class NodeDelegateModelRegistry;

/**
* @brief PluginsManager
*
* @code {.cpp}
* PluginsManager *pluginsManager = PluginsManager::instance();
* std::shared_ptr<NodeDelegateModelRegistry> registry = pluginsManager->registry();
* pluginsManager->loadPlugins(R"(./nodes)");
* for (auto plugin : pluginsManager->pluginList())
* {
* plugin->registerDataModels(registry);
* }
* @endcode
*/
class NODE_EDITOR_PUBLIC PluginsManager
{
PluginsManager();

~PluginsManager();

PluginsManager(const PluginsManager &rhs);

const PluginsManager &operator=(const PluginsManager &rhs);

public:

static
Expand All @@ -45,33 +28,49 @@ class NODE_EDITOR_PUBLIC PluginsManager
std::shared_ptr<NodeDelegateModelRegistry>
registry();

int
void
loadPlugins(const QString &folderPath = "./plugins");

void
unloadPlugins();

int
/**
* @brief Load the plug-in from the full file path
*
* @param filePath "C:/plugin_text.dll"
* @return PluginInterface*
*/
PluginInterface*
loadPluginFromPath(const QString &filePath);

/**
* @brief Unload the plugin from the full file path
*
* @param filePath "C:/plugin_text.dll"
* @return int
*/
int
unloadPluginFromPath(const QString &filePath);

inline
std::vector<PluginInterface*>
pluginList()
{ return _plugins; };
/**
* @brief Uninstall a plugin by its name, not its file name
*
* @param pluginName "pluginText"
* @return int
*/
int
unloadPluginFromName(const QString &pluginName);

inline
QHash<QString, QPluginLoader*>
loaderList()
{ return _loaders; };
std::unordered_map<QString, PluginInterface*>
plugins()
{ return _plugins; };

private:
static PluginsManager* _instance;

std::vector<PluginInterface*> _plugins;
QHash<QString, QPluginLoader*> _loaders; ///< plugin path
std::unordered_map<QString, PluginInterface*> _plugins;
std::unordered_map<QString, QPluginLoader*> _loaders; ///< plugin path

std::shared_ptr<NodeDelegateModelRegistry> _register;
};
Expand Down
73 changes: 51 additions & 22 deletions src/PluginsManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <QDir>
#include <QPluginLoader>
#include <algorithm>
#include <utility>

namespace QtNodes
{
Expand Down Expand Up @@ -49,7 +50,7 @@ registry()
{ return _register; };


int
void
PluginsManager::
loadPlugins(const QString &folderPath)
{
Expand All @@ -68,44 +69,47 @@ loadPlugins(const QString &folderPath)
{
if (fileInfo.isFile())
{
qDebug() << "plugin path: " << fileInfo.absoluteFilePath();
loadPluginFromPath(fileInfo.absoluteFilePath());
}
else
{
loadPlugins(fileInfo.absoluteFilePath());
}
}
return 0;
}


void
PluginsManager::
unloadPlugins()
{
for (QString filePath : _loaders.keys())
unloadPluginFromPath(filePath);
for (auto loadMap : _loaders)
{
unloadPluginFromPath(loadMap.second->fileName());
}
}


int
PluginInterface*
PluginsManager::
loadPluginFromPath(const QString & filePath)
{
if (!QLibrary::isLibrary(filePath))
return -1;
return nullptr;

QPluginLoader* loader = new QPluginLoader(filePath);
if (loader->load())
{
PluginInterface* plugin = qobject_cast<PluginInterface*>(loader->instance());
if (plugin)
{
_plugins.push_back(plugin);
_loaders.insert(filePath, loader);
qDebug() << "add plugin: " << plugin->name();
return 0;
const QString name = plugin->name();
qDebug() << "add plugin: " << name;

_loaders[name] = loader;
_plugins[filePath] = plugin;

return plugin;
}
else
{
Expand All @@ -117,29 +121,54 @@ loadPluginFromPath(const QString & filePath)
{
qCritical() << "loadPlugin:" << filePath << loader->errorString();
}
return -1;
return nullptr;
}


int
PluginsManager::
unloadPluginFromPath(const QString & filePath)
{
QPluginLoader* loader = _loaders.value(filePath);
PluginInterface* plugin = qobject_cast<PluginInterface*>(loader->instance());
if (plugin)
auto pluginIter = _plugins.find(filePath);
if(pluginIter != _plugins.end())
{
// TODO: Verification required
_plugins.erase(std::remove(_plugins.begin(), _plugins.end(), plugin), _plugins.end());
auto loaderIter = _loaders.find(pluginIter->second->name());
if(loaderIter != _loaders.end())
{
// delete loader
loaderIter->second->unload();
delete loaderIter->second;
_loaders.erase(loaderIter->first);
}

// delete plugin
_plugins.erase(pluginIter->first);
return 0;
}
return -1;
}

if (loader->unload())
int
PluginsManager::
unloadPluginFromName(const QString &pluginName)
{
auto loaderIter = _loaders.find(pluginName);
if(loaderIter != _loaders.end())
{
_loaders.remove(filePath);
delete loader;
loader = nullptr;
auto pluginIter = _plugins.find(loaderIter->second->fileName());
if(pluginIter != _plugins.end())
{
// delete plugin
_plugins.erase(pluginIter->first);
}

// delete loaders
loaderIter->second->unload();
delete loaderIter->second;
_loaders.erase(loaderIter->first);
return 0;
}
return 0;
return -1;
}

} // namespace QtNodes

0 comments on commit 49779db

Please sign in to comment.