Implement Plugin Loading.

This commit adds plugin laoding which are then added as sub winows onto the main window.
This commit also adds 2 plugins however more will follow
This commit is contained in:
2025-11-10 21:42:51 +00:00
parent 0c42ac2c72
commit ac85f22bb5
13 changed files with 309 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ qt_add_executable(SOM
src/mainwindow.cpp src/mainwindow.cpp
src/mainwindow.h src/mainwindow.h
src/mainwindow.ui src/mainwindow.ui
src/interface.h
) )
target_link_libraries(SOM target_link_libraries(SOM
@@ -19,6 +20,8 @@ target_link_libraries(SOM
Qt::Widgets Qt::Widgets
) )
add_subdirectory(plugins)
include(GNUInstallDirs) include(GNUInstallDirs)
install(TARGETS SOM install(TARGETS SOM

2
plugins/CMakeLists.txt Normal file
View File

@@ -0,0 +1,2 @@
add_subdirectory(WebBrowserPlugin)
add_subdirectory(TerminalPlugin)

View File

@@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.16)
project(TerminalPlugin VERSION 1.0 LANGUAGES C CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include(GNUInstallDirs)
find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Gui Widgets)
qt_add_plugin(TerminalPlugin)
target_sources(TerminalPlugin PRIVATE
TerminalPlugin.cpp TerminalPlugin.h
)
target_link_libraries(TerminalPlugin PRIVATE
Qt::Core
Qt::Gui
Qt::Widgets
qtermwidget6
)

View File

@@ -0,0 +1,38 @@
#include "TerminalPlugin.h"
#include <QVBoxLayout>
#include <QWidget>
#include <QApplication>
QString TerminalPlugin::pname()
{
return "Terminal Plugin";
}
QString TerminalPlugin::pdesc()
{
return "Simple Terminal Plugin.";
}
QWidget* TerminalPlugin::pcontent()
{
QWidget *test = new QWidget();
QVBoxLayout *mainLayout = new QVBoxLayout;
console = new QTermWidget(test);
QFont font = QApplication::font();
font.setFamily("Monospace");
font.setPointSize(12);
console->setTerminalFont(font);
console->setScrollBarPosition(QTermWidget::ScrollBarRight);
console->setColorScheme("WhiteOnBlack");
test->setWindowTitle(tr("Terminal Plugin"));
test->resize(600, 400);
mainLayout->addWidget(console);
test->setLayout(mainLayout);
QIcon icon = QIcon(":/images/monkey.png");
test->setWindowIcon(icon);
return test;
}

View File

@@ -0,0 +1,29 @@
#ifndef TESTPLUGIN_H
#define TESTPLUGIN_H
#include <../../src/interface.h>
#include <qtermwidget6/qtermwidget.h>
#include <QObject>
#include <QtPlugin>
#include <QString>
#include <QWidget>
#include <QImage>
class TerminalPlugin : public QObject, public Interface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.SOM.Interface" FILE "TerminalPlugin.json")
Q_INTERFACES(Interface)
public:
QString pname() override;
QString pdesc() override;
QWidget *pcontent() override;
private:
QTermWidget *console;
};
#endif

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.16)
project(WebBrowserPlugin VERSION 1.0 LANGUAGES C CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include(GNUInstallDirs)
find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Gui WebEngineWidgets Widgets)
qt_add_plugin(WebBrowserPlugin)
target_sources(WebBrowserPlugin PRIVATE
WebBrowserPlugin.cpp WebBrowserPlugin.h
)
target_link_libraries(WebBrowserPlugin PRIVATE
Qt::Core
Qt::Gui
Qt::WebEngineWidgets
Qt::Widgets
)

View File

@@ -0,0 +1,78 @@
#include "WebBrowserPlugin.h"
#include <QVBoxLayout>
#include <QWidget>
QString WebBrowserPlugin::pname()
{
return "Web Browser Plugin";
}
QString WebBrowserPlugin::pdesc()
{
return "Simple Web Browser Plugin.";
}
QWidget* WebBrowserPlugin::pcontent()
{
QWidget *test = new QWidget();
test->setWindowTitle(tr("Web Browser Plugin"));
test->resize(1024, 750);
QVBoxLayout *mainLayout = new QVBoxLayout;
view = new QWebEngineView(test);
view->setUrl(QUrl("https://rubenwardy.com/minetest_modding_book/en/index.html"));
view->resize(1024, 750);
horizontalGroupBox = new QGroupBox();
QHBoxLayout *layout = new QHBoxLayout;
back = new QPushButton(tr("Back"));
layout->addWidget(back);
connect(back, &QPushButton::clicked, this, &WebBrowserPlugin::backpage);
forward = new QPushButton(tr("Forward"));
layout->addWidget(forward);
connect(forward, &QPushButton::clicked, this, &WebBrowserPlugin::forwardpage);
refresh = new QPushButton(tr("Refresh"));
layout->addWidget(refresh);
connect(refresh, &QPushButton::clicked, this, &WebBrowserPlugin::refreshpage);
smallEditor = new QLineEdit;
layout->addWidget(smallEditor);
smallEditor->setText("https://rubenwardy.com/minetest_modding_book/en/index.html");
go = new QPushButton(tr("Go"));
layout->addWidget(go);
connect(go, &QPushButton::clicked, this, &WebBrowserPlugin::gotourl);
horizontalGroupBox->setLayout(layout);
mainLayout->addWidget(horizontalGroupBox);
mainLayout->addWidget(view,1);
test->setLayout(mainLayout);
QIcon icon = QIcon(":/images/monkey.png");
test->setWindowIcon(icon);
return test;
}
void WebBrowserPlugin::gotourl()
{
view->setUrl(QUrl(smallEditor->text()));
}
void WebBrowserPlugin::refreshpage()
{
view->reload();
}
void WebBrowserPlugin::backpage()
{
view->back();
}
void WebBrowserPlugin::forwardpage()
{
view->forward();
}

View File

@@ -0,0 +1,35 @@
#ifndef WEBBROWSERPLUGIN_H
#define WEBBROWSERPLUGIN_H
#include <../../src/interface.h>
#include <QWebEngineView>
#include <QtWidgets>
class WebBrowserPlugin : public QObject, public Interface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.SOM.Interface" FILE "WebBrowserPlugin.json")
Q_INTERFACES(Interface)
public:
QString pname() override;
QString pdesc() override;
QWidget *pcontent() override;
private:
QGroupBox *horizontalGroupBox;
QPushButton *back;
QPushButton *forward;
QPushButton *refresh;
QLineEdit *smallEditor;
QPushButton *go;
QWebEngineView *view;
private slots:
void gotourl();
void refreshpage();
void backpage();
void forwardpage();
};
#endif

View File

@@ -0,0 +1 @@
{}

16
src/interface.h Normal file
View File

@@ -0,0 +1,16 @@
#include <QtPlugin>
#include <QWidget>
#include <QString>
class Interface
{
public:
virtual ~Interface() = default;
virtual QString pname() = 0;
virtual QString pdesc() = 0;
virtual QWidget* pcontent() = 0;
};
#define Interface_iid "org.SOM.Interface/1.0"
Q_DECLARE_INTERFACE(Interface, Interface_iid)

View File

@@ -10,6 +10,9 @@ MainWindow::MainWindow(QWidget *parent)
createMenus(); createMenus();
this->setWindowIcon(QIcon::fromTheme(QIcon::ThemeIcon::Computer)); this->setWindowIcon(QIcon::fromTheme(QIcon::ThemeIcon::Computer));
initSettings(); initSettings();
mdi = new QMdiArea;
this->setCentralWidget(mdi);
loadPlugins();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@@ -90,3 +93,54 @@ void MainWindow::settings()
settingsWin->resize(300, 200); settingsWin->resize(300, 200);
settingsWin->show(); settingsWin->show();
} }
void MainWindow::loadPlugins()
{
pluginsDir = QDir(QCoreApplication::applicationDirPath());
pluginsDir.cd("plugins");
const auto entryList = pluginsDir.entryList(QDir::Files);
for (const QString &fileName : entryList) {
QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = loader.instance();
if (plugin) {
populateMenu(plugin);
pluginFileNames += fileName;
}
}
}
void MainWindow::changePlugin()
{
auto action = qobject_cast<QAction *>(sender());
if (!action)
return;
auto iPlugin = qobject_cast<Interface *>(action->parent());
if (!iPlugin)
return;
QWidget* pluginContent = iPlugin->pcontent();
auto *sub = mdi->addSubWindow(pluginContent);
sub->setAttribute(Qt::WA_DeleteOnClose);
sub->show();
}
void MainWindow::populateMenu(QObject *plugin)
{
auto iPlugin = qobject_cast<Interface *>(plugin);
if (iPlugin)
addToMenu(plugin, iPlugin->pname(), toolsMenu, &MainWindow::changePlugin);
}
void MainWindow::addToMenu(QObject *plugin, const QString &text,
QMenu *menu, Member member)
{
auto action = new QAction(text, plugin);
connect(action, &QAction::triggered, this, member);
menu->addAction(action);
}

View File

@@ -4,6 +4,8 @@
#include <QMainWindow> #include <QMainWindow>
#include <QtWidgets> #include <QtWidgets>
#include "interface.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { namespace Ui {
class MainWindow; class MainWindow;
@@ -22,11 +24,15 @@ public:
~MainWindow(); ~MainWindow();
private: private:
typedef void (MainWindow::*Member)();
Ui::MainWindow *ui; Ui::MainWindow *ui;
void createActions(); void createActions();
void createMenus(); void createMenus();
void initSettings(); void initSettings();
void saveSettings(); void saveSettings();
void loadPlugins();
void populateMenu(QObject *plugin);
void addToMenu(QObject *plugin, const QString &text, QMenu *menu,Member member);
QMenu *fileMenu; QMenu *fileMenu;
QMenu *editMenu; QMenu *editMenu;
QMenu *toolsMenu; QMenu *toolsMenu;
@@ -35,10 +41,14 @@ private:
QAction *aboutAct; QAction *aboutAct;
QAction *aboutQtAct; QAction *aboutQtAct;
QAction *settingsAct; QAction *settingsAct;
QStringList pluginFileNames;
QDir pluginsDir;
QMdiArea *mdi;
private slots: private slots:
void about(); void about();
void settings(); void settings();
void changePlugin();
protected: protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;