Skip to content

Commit c60e4d4

Browse files
committed
Add plug-in management dialog, delete plug-in map
1 parent 8e9775b commit c60e4d4

8 files changed

Lines changed: 255 additions & 75 deletions

File tree

examples/plugin_text/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
file(GLOB_RECURSE CPPS ./*.cpp)
22
file(GLOB_RECURSE HPPS ./*.hpp)
33

4+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${PROJECT_BINARY_DIR}/bin/Debug/nodes")
5+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${PROJECT_BINARY_DIR}/bin/Release/nodes")
6+
47
add_library(plugin_text SHARED ${CPPS} ${HPPS})
58

69
target_link_libraries(plugin_text QtNodes)

examples/plugin_text/PluginDefinition.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ Plugin::
88
Plugin()
99
{ _this_plugin = this; }
1010

11+
Plugin::
12+
~Plugin()
13+
{
14+
// TODO: Unregister all models here
15+
}
16+
1117
void
1218
Plugin::
1319
registerDataModels(std::shared_ptr<QtNodes::NodeDelegateModelRegistry> & reg)

examples/plugin_text/PluginDefinition.hpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,12 @@
55
#include <QtNodes/PluginInterface>
66

77
// This needs to be the same as the name of your project file ${PROJECT_NAME}
8-
// 这里需要和您的工程文件名一致 ${PROJECT_NAME}
9-
#if defined(plugin_text_EXPORTS)
8+
#ifdef plugin_text_EXPORTS
109
#define DLL_EXPORT Q_DECL_EXPORT
1110
#else
1211
#define DLL_EXPORT Q_DECL_IMPORT
1312
#endif
1413

15-
using QtNodes::NodeDelegateModelRegistry;
16-
using QtNodes::PluginInterface;
17-
1814
#define PLUGIN_NAME "pluginText"
1915

2016
class DLL_EXPORT Plugin
@@ -27,6 +23,7 @@ class DLL_EXPORT Plugin
2723

2824
public:
2925
Plugin();
26+
~Plugin();
3027

3128
QString
3229
name() const override
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#include "PluginsManagerDlg.hpp"
2+
3+
#include <QTableView>
4+
#include <QPushButton>
5+
#include <QGridLayout>
6+
#include <QHeaderView>
7+
#include <QDir>
8+
#include <QFileDialog>
9+
#include <QDesktopServices>
10+
11+
#include <QtNodes/NodeDelegateModelRegistry>
12+
#include <QtNodes/PluginInterface>
13+
14+
using QtNodes::NodeDelegateModelRegistry;
15+
using QtNodes::PluginInterface;
16+
17+
PluginsManagerDlg::
18+
PluginsManagerDlg(QWidget* parent)
19+
: QDialog(parent)
20+
, _pluginsFolderPath(R"(./nodes)")
21+
{
22+
QGridLayout *layout = new QGridLayout();
23+
setLayout(layout);
24+
25+
QTableView *pluginTable = new QTableView();
26+
pluginTable->setSelectionBehavior(QAbstractItemView::SelectRows);
27+
pluginTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
28+
pluginTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
29+
layout->addWidget(pluginTable, 0, 0, 1, 2);
30+
31+
_model = new QStandardItemModel(pluginTable);
32+
33+
_model->setColumnCount(2);
34+
_model->setHeaderData(0, Qt::Horizontal, "name");
35+
_model->setHeaderData(1, Qt::Horizontal, "version");
36+
pluginTable->setModel(_model);
37+
38+
loadPluginsFromFolder();
39+
40+
// add button
41+
QPushButton *addButton = new QPushButton("+");
42+
layout->addWidget(addButton, 1, 0);
43+
connect(addButton, &QPushButton::clicked, this,
44+
[this]()
45+
{
46+
// TODO: How to switch different suffixes according to different os
47+
QString fileName =
48+
QFileDialog::getOpenFileName(this,
49+
tr("Load Plugin"),
50+
QDir::currentPath(),
51+
tr("*.dll;*.so;*.dylib"));
52+
53+
if (!QFileInfo::exists(fileName))
54+
return;
55+
56+
// Copy to the plug-in directory
57+
QFileInfo f(fileName);
58+
QString newPath = _pluginsFolderPath + "/" + f.fileName();
59+
QFile::copy(fileName, newPath);
60+
61+
PluginsManager* pluginsManager = PluginsManager::instance();
62+
auto plugin = pluginsManager->loadPluginFromPath(newPath);
63+
if (plugin == nullptr)
64+
{
65+
QFile::remove(newPath);
66+
return;
67+
}
68+
69+
QStandardItem *item = new QStandardItem(plugin->name());
70+
item->setCheckable(true);
71+
item->setCheckState(Qt::Unchecked);
72+
_model->appendRow(item);
73+
74+
item->setData(newPath);
75+
76+
std::shared_ptr<NodeDelegateModelRegistry> reg = pluginsManager->registry();
77+
plugin->registerDataModels(reg);
78+
});
79+
80+
// // delete button
81+
// QPushButton *deleteButton = new QPushButton("-", this);
82+
// layout->addWidget(deleteButton, 1, 1);
83+
// connect(deleteButton, &QPushButton::clicked, this,
84+
// [this]()
85+
// {
86+
// for (int i = 0; i < _model->rowCount(); ++i)
87+
// {
88+
// QStandardItem* item = _model->item(i);
89+
// if(item->checkState() == Qt::Checked)
90+
// {
91+
// PluginsManager* pluginsManager = PluginsManager::instance();
92+
93+
// if (pluginsManager->unloadPluginFromName(item->text()))
94+
// {
95+
// qDebug() << item->data().toString();
96+
// if (QFile::remove(item->data().toString()))
97+
// {
98+
// _model->removeRow(i);
99+
// }
100+
// }
101+
// }
102+
// }
103+
// });
104+
}
105+
106+
PluginsManagerDlg::
107+
~PluginsManagerDlg()
108+
{
109+
//
110+
}
111+
112+
void
113+
PluginsManagerDlg::
114+
openPluginsFolder()
115+
{
116+
QDesktopServices::openUrl(QUrl::fromLocalFile(_pluginsFolderPath));
117+
}
118+
119+
QString
120+
PluginsManagerDlg::
121+
pluginsFolderPath() const
122+
{
123+
return _pluginsFolderPath;
124+
}
125+
126+
void
127+
PluginsManagerDlg::
128+
loadPluginsFromFolder()
129+
{
130+
PluginsManager* pluginsManager = PluginsManager::instance();
131+
std::shared_ptr<NodeDelegateModelRegistry> registry = pluginsManager->registry();
132+
pluginsManager->loadPlugins(_pluginsFolderPath);
133+
134+
for(auto l : pluginsManager->loaders())
135+
{
136+
PluginInterface* plugin = qobject_cast<PluginInterface*>(l.second->instance());
137+
if (plugin == nullptr)
138+
continue;
139+
140+
QStandardItem *item = new QStandardItem(plugin->name());
141+
item->setCheckable(true);
142+
item->setCheckState(Qt::Unchecked);
143+
_model->appendRow(item);
144+
145+
item->setData(l.second->fileName());
146+
147+
plugin->registerDataModels(registry);
148+
}
149+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
3+
#include <QDialog>
4+
#include <QStandardItemModel>
5+
6+
#include <QtNodes/PluginsManager>
7+
8+
using QtNodes::PluginsManager;
9+
10+
class PluginsManagerDlg : public QDialog
11+
{
12+
public:
13+
PluginsManagerDlg(QWidget* parent = nullptr);
14+
15+
virtual
16+
~PluginsManagerDlg();
17+
18+
public:
19+
void
20+
openPluginsFolder();
21+
22+
QString
23+
pluginsFolderPath() const;
24+
25+
private:
26+
void
27+
loadPluginsFromFolder();
28+
29+
private:
30+
QString _pluginsFolderPath;
31+
32+
QStandardItemModel* _model = nullptr;
33+
};

examples/plugins_load/main.cpp

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <QtNodes/NodeDelegateModelRegistry>
1111
#include <QtNodes/PluginsManager>
1212

13+
#include "PluginsManagerDlg.hpp"
14+
1315
using QtNodes::DataFlowGraphicsScene;
1416
using QtNodes::DataFlowGraphModel;
1517
using QtNodes::GraphicsView;
@@ -37,50 +39,32 @@ main(int argc, char* argv[])
3739
{
3840
qSetMessagePattern(
3941
"[%{time yyyyMMdd h:mm:ss.zzz}] [%{time process}] "
40-
"[%{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-"
41-
"fatal}F%{endif}]: %{message}\t| (%{function}) [%{file}:%{line}]");
42+
"[%{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}"
43+
"%{if-fatal}F%{endif}]: %{message}\t| (%{function}) [%{file}:%{line}]");
4244

4345
QApplication app(argc, argv);
4446

4547
setStyle();
4648

47-
PluginsManager* pluginsManager = PluginsManager::instance();
48-
std::shared_ptr<NodeDelegateModelRegistry> registry = pluginsManager->registry();
49-
pluginsManager->loadPlugins(R"(./nodes)");
50-
for (auto plugin : pluginsManager->plugins())
51-
{
52-
plugin.second->registerDataModels(registry);
53-
}
54-
5549
QWidget mainWidget;
5650

51+
// Load plugins and register models
52+
PluginsManagerDlg pluginsManagerDlg(&mainWidget);
53+
5754
auto menuBar = new QMenuBar();
5855
QMenu* menu = menuBar->addMenu("Plugins");
59-
auto loadAction = menu->addAction("Load Plugin");
60-
auto unloadAction = menu->addAction("Unload Plugin");
61-
62-
QObject::connect(loadAction, &QAction::triggered,
63-
[&]()
64-
{
65-
// TODO: load plugins
66-
QString fileName =
67-
QFileDialog::getOpenFileName(nullptr,
68-
"Load Plugin",
69-
QDir::homePath());
70-
71-
if (!QFileInfo::exists(fileName))
72-
return;
73-
74-
auto plugin = pluginsManager->loadPluginFromPath(fileName);
75-
if (plugin)
76-
{
77-
plugin->registerDataModels(registry);
78-
}
79-
});
56+
auto pluginsManagerAction = menu->addAction("Plugins Manager");
57+
auto pluginsFloderAction = menu->addAction("Open Plugins Folder");
58+
59+
QObject::connect(pluginsManagerAction, &QAction::triggered,
60+
&pluginsManagerDlg, &PluginsManagerDlg::exec);
61+
62+
QObject::connect(pluginsFloderAction, &QAction::triggered,
63+
&pluginsManagerDlg, &PluginsManagerDlg::openPluginsFolder);
8064

8165
QVBoxLayout* l = new QVBoxLayout(&mainWidget);
8266

83-
DataFlowGraphModel dataFlowGraphModel(registry);
67+
DataFlowGraphModel dataFlowGraphModel(PluginsManager::instance()->registry());
8468

8569
l->addWidget(menuBar);
8670
auto scene = new DataFlowGraphicsScene(dataFlowGraphModel,

include/QtNodes/internal/PluginsManager.hpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,34 +43,36 @@ class NODE_EDITOR_PUBLIC PluginsManager
4343
PluginInterface*
4444
loadPluginFromPath(const QString &filePath);
4545

46+
std::vector<PluginInterface*>
47+
loadPluginFromPaths(const QStringList filePaths);
48+
4649
/**
4750
* @brief Unload the plugin from the full file path
4851
*
4952
* @param filePath "C:/plugin_text.dll"
50-
* @return int
53+
* @return bool
5154
*/
52-
int
55+
bool
5356
unloadPluginFromPath(const QString &filePath);
5457

5558
/**
5659
* @brief Uninstall a plugin by its name, not its file name
5760
*
5861
* @param pluginName "pluginText"
59-
* @return int
62+
* @return bool
6063
*/
61-
int
64+
bool
6265
unloadPluginFromName(const QString &pluginName);
6366

6467
inline
65-
std::unordered_map<QString, PluginInterface*>
66-
plugins()
67-
{ return _plugins; };
68+
std::unordered_map<QString, QPluginLoader*>
69+
loaders()
70+
{ return _loaders; };
6871

6972
private:
7073
static PluginsManager* _instance;
7174

72-
std::unordered_map<QString, PluginInterface*> _plugins;
73-
std::unordered_map<QString, QPluginLoader*> _loaders; ///< plugin path
75+
std::unordered_map<QString, QPluginLoader*> _loaders; // plugin name
7476

7577
std::shared_ptr<NodeDelegateModelRegistry> _register;
7678
};

0 commit comments

Comments
 (0)