diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f89ba5b --- /dev/null +++ b/.clang-format @@ -0,0 +1,9 @@ +BasedOnStyle: Chromium +IndentWidth: 2 +ColumnLimit: 160 +SpaceAfterCStyleCast: false +UseTab: Never +AllowShortIfStatementsOnASingleLine: false +AlignTrailingComments: false +SpacesBeforeTrailingComments: 1 +AlignConsecutiveMacros: Consecutive \ No newline at end of file diff --git a/inc/graph/server/gui/mainwindow.h b/inc/graph/server/gui/mainwindow.h index d6d21d3..9e89b07 100644 --- a/inc/graph/server/gui/mainwindow.h +++ b/inc/graph/server/gui/mainwindow.h @@ -4,6 +4,7 @@ #include #include #include +#include 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 diff --git a/inc/graph/server/plugin.h b/inc/graph/server/plugin.h index 3f494a5..e44e981 100644 --- a/inc/graph/server/plugin.h +++ b/inc/graph/server/plugin.h @@ -1,18 +1,39 @@ #pragma once #include +#include #include 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 plugins; }; } // namespace Graph diff --git a/src/graph/server/gui/mainwindow.cpp b/src/graph/server/gui/mainwindow.cpp index 4d8ace5..ec85109 100644 --- a/src/graph/server/gui/mainwindow.cpp +++ b/src/graph/server/gui/mainwindow.cpp @@ -1,15 +1,52 @@ #include +#include #include +#include +#include +#include +#include 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 diff --git a/src/graph/server/gui/mainwindow.ui b/src/graph/server/gui/mainwindow.ui index 67a6d68..4646e48 100644 --- a/src/graph/server/gui/mainwindow.ui +++ b/src/graph/server/gui/mainwindow.ui @@ -29,7 +29,7 @@ - + diff --git a/src/graph/server/main.cpp b/src/graph/server/main.cpp index ec489ac..02e25b2 100644 --- a/src/graph/server/main.cpp +++ b/src/graph/server/main.cpp @@ -1,16 +1,16 @@ +#include #include #include -#include -#include #include +#include 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(); } \ No newline at end of file diff --git a/src/graph/server/plugin.cpp b/src/graph/server/plugin.cpp index 5e62c49..9ae9512 100644 --- a/src/graph/server/plugin.cpp +++ b/src/graph/server/plugin.cpp @@ -1,31 +1,65 @@ #include #include +#include +#include +#include #include #include 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 \ No newline at end of file