plugin loading gui

This commit is contained in:
Benedek László 2024-05-14 17:29:58 +02:00
parent 1fb3e98146
commit 679b2d3eca
7 changed files with 138 additions and 33 deletions

9
.clang-format Normal file
View File

@ -0,0 +1,9 @@
BasedOnStyle: Chromium
IndentWidth: 2
ColumnLimit: 160
SpaceAfterCStyleCast: false
UseTab: Never
AllowShortIfStatementsOnASingleLine: false
AlignTrailingComments: false
SpacesBeforeTrailingComments: 1
AlignConsecutiveMacros: Consecutive

View File

@ -4,6 +4,7 @@
#include <QMenuBar>
#include <QStatusBar>
#include <QToolBar>
#include <graph/server/plugin.h>
namespace Ui {
class MainWindow;
@ -17,9 +18,12 @@ public:
~MainWindow();
private slots:
void on_actionExit_triggered();
void on_action_Add_triggered();
void on_action_Load_triggered();
private:
Ui::MainWindow *ui;
PluginModel* pluginsModel;
};
} // namespace Graph::GUI

View File

@ -1,18 +1,39 @@
#pragma once
#include <graph/plugins/plugin.h>
#include <QAbstractListModel>
#include <string>
namespace Graph {
class Plugin {
private:
plugin_t *plugin;
private:
plugin_t* plugin;
const std::string path;
const void* handle;
public:
public:
Plugin(const std::string& path);
~Plugin();
bool init(update_callback_t callback);
const std::string& get_path() const { return this->path; }
};
class PluginModel : public QAbstractListModel {
Q_OBJECT
public:
PluginModel(QObject* parent) : QAbstractListModel(parent) {}
~PluginModel();
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role) const override;
void add(Plugin* plugin);
void remove(int index);
private:
QList<Plugin*> plugins;
};
} // namespace Graph

View File

@ -1,15 +1,52 @@
#include <graph/server/gui/mainwindow.h>
#include <graph/server/plugin.h>
#include <graph/server/ui_mainwindow.h>
#include <QFileDialog>
#include <QMessageBox>
#include <iostream>
#include <stdexcept>
namespace Graph::GUI {
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
// plugins
pluginsModel = new PluginModel(this);
ui->pluginsListView->setModel(pluginsModel);
// unload plugin
connect(ui->pluginsListView, &QListView::doubleClicked, [&](const QModelIndex& index) {
pluginsModel->removeRow(index.row());
pluginsModel->remove(index.row());
ui->pluginsListView->doItemsLayout();
});
}
MainWindow::~MainWindow() { delete ui; }
void MainWindow::on_actionExit_triggered() {
this->close();
MainWindow::~MainWindow() {
delete ui;
delete pluginsModel;
}
void MainWindow::on_action_Add_triggered() {}
void MainWindow::on_action_Load_triggered() {
QString file = QFileDialog::getOpenFileName(this, "Load plugin", ".", "Plugins (*.so *.dll *.dylib)");
if (file.isEmpty())
return;
try {
pluginsModel->add(new Plugin(file.toStdString()));
} catch (std::runtime_error e) {
std::cout << e.what() << std::endl;
QMessageBox::critical(this, "Error", "Failed to load plugin.", QMessageBox::StandardButton::Ignore);
}
int row = pluginsModel->rowCount();
pluginsModel->insertRow(row);
QModelIndex index = pluginsModel->index(row);
ui->pluginsListView->doItemsLayout();
ui->pluginsListView->setCurrentIndex(index);
}
} // namespace Graph::GUI

View File

@ -29,7 +29,7 @@
</attribute>
<layout class="QVBoxLayout" name="graphsVerticalLayout">
<item>
<widget class="QListView" name="graphsListView"/>
<widget class="QListWidget" name="graphsListWidget"/>
</item>
</layout>
</widget>

View File

@ -1,16 +1,16 @@
#include <dlfcn.h>
#include <graph/server/gui/mainwindow.h>
#include <graph/server/plugin.h>
#include <dlfcn.h>
#include <iostream>
#include <QtWidgets/QApplication>
#include <iostream>
int main(int argc, char** argv) {
Graph::Plugin plugin("plugins/libhttp.so");
plugin.init((update_callback_t)1);
// Graph::Plugin plugin("plugins/libhttp.so");
// plugin.init((update_callback_t)1);
QApplication app(argc, argv);
Graph::GUI::MainWindow window;
window.show();
QApplication app(argc, argv);
Graph::GUI::MainWindow window;
window.show();
return app.exec();
return app.exec();
}

View File

@ -1,31 +1,65 @@
#include <dlfcn.h>
#include <graph/server/plugin.h>
#include <qnamespace.h>
#include <qobject.h>
#include <qvariant.h>
#include <stdexcept>
#include <string>
namespace Graph {
Plugin::Plugin(const std::string &path) {
this->handle = dlopen(path.c_str(), RTLD_LAZY);
if (!this->handle)
throw std::runtime_error(dlerror());
Plugin::Plugin(const std::string& path) : path(path) {
this->handle = dlopen(path.c_str(), RTLD_LAZY);
if (!this->handle)
throw std::runtime_error(dlerror());
this->plugin = (plugin_t*)dlsym((void*)this->handle, "plugin");
if (!this->plugin)
throw std::runtime_error(dlerror());
this->plugin = (plugin_t*)dlsym((void*)this->handle, "plugin");
if (!this->plugin)
throw std::runtime_error(dlerror());
this->plugin->update_callback = nullptr;
this->plugin->update_callback = nullptr;
}
Plugin::~Plugin() {
if (this->plugin->update_callback)
this->plugin->destroy_method();
if (this->plugin->update_callback)
this->plugin->destroy_method();
if (this->handle)
dlclose((void*)this->handle);
if (this->handle)
dlclose((void*)this->handle);
}
bool Plugin::init(update_callback_t callback) {
this->plugin->update_callback = callback;
return this->plugin->init_method();
this->plugin->update_callback = callback;
return this->plugin->init_method();
}
PluginModel::~PluginModel() {
for (Plugin* plugin : this->plugins) {
delete plugin;
}
}
int PluginModel::rowCount(const QModelIndex& parent) const {
return this->plugins.size();
}
QVariant PluginModel::data(const QModelIndex& index, int role) const {
if (!index.isValid())
return QVariant();
if (role == Qt::DisplayRole) {
return QString(plugins[index.row()]->get_path().c_str());
}
return QVariant();
}
void PluginModel::add(Plugin* plugin) {
plugins << plugin;
}
void PluginModel::remove(int index) {
delete plugins[index];
plugins.removeAt(index);
}
} // namespace Graph