summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt9
-rw-r--r--src/application.cpp37
-rw-r--r--src/application.h4
-rw-r--r--src/main.cpp11
-rw-r--r--src/plugins/CMakeLists.txt7
-rw-r--r--src/plugins/pluginloader.cpp (renamed from src/rview.cpp)11
-rw-r--r--src/plugins/pluginloader.h25
-rw-r--r--src/plugins/rplugininterface.hpp (renamed from src/webengine/webview.h)18
-rw-r--r--src/plugins/rview.hpp (renamed from src/rview.h)2
-rw-r--r--src/plugins/test/pluginloader.cpp40
-rw-r--r--src/webengine/webview.cpp25
11 files changed, 143 insertions, 46 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4aa141c9..5f154e3f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,6 +1,7 @@
### ------- sub dirs -------
ADD_SUBDIRECTORY( data )
+add_subdirectory(plugins)
### ------- SETTING REKONQ FILES..
@@ -216,15 +217,17 @@ ADD_DEFINITIONS ( ${KDE4_DEFINITIONS} )
add_executable(rekonq
main.cpp application.cpp application.h
# ----------------------------------------
- rview.cpp rview.h webengine/webview.cpp webengine/webview.h
+ plugins/rplugininterface.hpp plugins/rview.hpp
)
### --------------- TARGETTING LINK LIBRARIES...
target_link_libraries(rekonq
- Qt6::Widgets Qt6::WebEngineWidgets
- SingleApplication::SingleApplication)
+ Qt6::Widgets
+ SingleApplication::SingleApplication
+ pluginloader
+)
# Nepomuk optional target link libraries
IF(SOPRANO_FOUND AND NepomukCore_FOUND)
diff --git a/src/application.cpp b/src/application.cpp
index 54a7db88..9e34e5e2 100644
--- a/src/application.cpp
+++ b/src/application.cpp
@@ -10,8 +10,9 @@
* ============================================================ */
#include "application.h"
-#include "rview.h"
-#include "webengine/webview.h"
+#include "plugins/pluginloader.h"
+#include "plugins/rplugininterface.hpp"
+#include <QPluginLoader>
// ---------------------------------------------------------------------------------------------------------------
// Ctor and Dtor
@@ -42,9 +43,29 @@ Application::~Application()
// Destroy all web apps
for (auto *webApp : m_webApps) delete webApp;
+
+ // Unload all plugins
+ for (auto *plugin : m_plugins) {
+ plugin->unload();
+ delete plugin;
+ }
}
// ---------------------------------------------------------------------------------------------------------------
+// Plugin management
+
+bool Application::registerPlugin(const QString &path)
+{
+ auto *loader = new PluginLoader(path);
+ if (!loader->load()) {
+ delete loader;
+ return false;
+ }
+
+ m_plugins.append(loader);
+ return true;
+}
+// ---------------------------------------------------------------------------------------------------------------
/*
int Application::newInstance()
{
@@ -388,7 +409,17 @@ void Application::setWindowInfo(RekonqWindow *w)
rView *Application::newWebApp(const QUrl &url)
{
- auto *view = new WebView(url);
+ RekonqPluginInterface *interface = nullptr;
+ for (auto *plugin : m_plugins)
+ if (plugin->hasScheme(url.scheme())) {
+ interface = plugin->interface();
+ break;
+ }
+
+ if (interface == nullptr) return nullptr;
+
+ auto *view = interface->view(url);
+ Q_CHECK_PTR(view);
// tab->installEventFilter(this);
m_webApps.append(view);
diff --git a/src/application.h b/src/application.h
index 761bc89b..407a8681 100644
--- a/src/application.h
+++ b/src/application.h
@@ -18,6 +18,7 @@
// Forward Declarations
class rView;
+class PluginLoader;
// class RekonqWindow;
// class WebTab;
@@ -38,6 +39,8 @@ public:
Application(int &argc, char *argv[]);
~Application() override;
+ bool registerPlugin(const QString &path);
+
// int newInstance();
static Application *instance() { return (qobject_cast<Application *>(QCoreApplication::instance())); }
@@ -107,6 +110,7 @@ private slots:
// void pageCreated(WebPage *);
private:
+ QList<PluginLoader *> m_plugins;
// RekonqWindowList m_rekonqWindows;
QList<rView *> m_webApps;
};
diff --git a/src/main.cpp b/src/main.cpp
index 20c30c68..6db6f36c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -19,6 +19,9 @@ static const char *description = "A lightweight Web Browser based on Qt WebEngin
int main(int argc, char **argv)
{
+ // When loading QtWebEngine from a plugin, set Qt::AA_ShareOpenGLContexts using QCoreApplication::setAttribute
+ QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
+
Application app(argc, argv);
// Set application data
QCoreApplication::setApplicationName(QL1S("rekonq"));
@@ -34,13 +37,19 @@ int main(int argc, char **argv)
QCommandLineOption options_incognito("incognito", QCoreApplication::translate("main", "Open in incognito mode"));
QCommandLineOption options_webapp("webapp",
QCoreApplication::translate("main", "Open URL as web app (in a simple window)"));
- parser.addOptions({options_incognito, options_webapp});
+ QCommandLineOption options_plugin({"l", "load"}, QCoreApplication::translate("main", "Add plugin to load path"),
+ "path");
+ parser.addOptions({options_incognito, options_webapp, options_plugin});
// Define the positional arguments
parser.addPositionalArgument("URL", QCoreApplication::translate("main", "Location to open"));
parser.process(app);
+ if (parser.isSet(options_plugin)) {
+ for (const auto &plugin : parser.values(options_plugin)) app.registerPlugin(plugin);
+ }
+
const auto positionalArguments = parser.positionalArguments();
if (parser.isSet(options_webapp))
positionalArguments.isEmpty() ? app.newWebApp() : app.newWebApp(QUrl::fromUserInput(positionalArguments.first()));
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
new file mode 100644
index 00000000..01b13ae1
--- /dev/null
+++ b/src/plugins/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_library(pluginloader STATIC pluginloader.cpp pluginloader.h)
+target_link_libraries(pluginloader PUBLIC Qt6::Core Qt6::Widgets)
+
+if(TESTING)
+ add_executable(load_plugin test/pluginloader.cpp)
+ target_link_libraries(load_plugin GTest::gtest GTest::gtest_main Qt6::Core)
+endif()
diff --git a/src/rview.cpp b/src/plugins/pluginloader.cpp
index 2da3096c..ad5dbc14 100644
--- a/src/rview.cpp
+++ b/src/plugins/pluginloader.cpp
@@ -4,9 +4,14 @@
* SPDX-License-Identifier: GPL-3.0-only
* Copyright (C) 2022 aqua <aqua@iserlohn-fortress.net>
* ============================================================
- * Description: View Interface
+ * Description: rekonq plugin loader
* ============================================================ */
-#include "rview.h"
+#include "pluginloader.h"
+#include <QJsonArray>
-rView::rView(const QUrl &url, QWidget *parent) : QWidget(parent) {}
+PluginLoader::PluginLoader(const QString &fileName, QObject *parent) : QPluginLoader(fileName, parent)
+{
+ const auto metadata = metaData()["MetaData"].toObject();
+ for (const auto &value : metadata["schemes"].toArray()) { m_schemes.append(value.toString()); }
+}
diff --git a/src/plugins/pluginloader.h b/src/plugins/pluginloader.h
new file mode 100644
index 00000000..f764da9f
--- /dev/null
+++ b/src/plugins/pluginloader.h
@@ -0,0 +1,25 @@
+/* ============================================================
+ * The rekonq project
+ * ============================================================
+ * SPDX-License-Identifier: GPL-3.0-only
+ * Copyright (C) 2022 aqua <aqua@iserlohn-fortress.net>
+ * ============================================================
+ * Description: rekonq plugin loader
+ * ============================================================ */
+
+#pragma once
+
+#include "rplugininterface.hpp"
+#include <QPluginLoader>
+
+class PluginLoader : public QPluginLoader {
+
+public:
+ explicit PluginLoader(const QString &path, QObject *parent = nullptr);
+ [[nodiscard]] bool hasScheme(const QString &scheme) { return m_schemes.contains(scheme); }
+
+ [[nodiscard]] RekonqPluginInterface *interface() { return qobject_cast<RekonqPluginInterface *>(instance()); }
+
+private:
+ QStringList m_schemes;
+};
diff --git a/src/webengine/webview.h b/src/plugins/rplugininterface.hpp
index b838c5ac..16186591 100644
--- a/src/webengine/webview.h
+++ b/src/plugins/rplugininterface.hpp
@@ -4,22 +4,20 @@
* SPDX-License-Identifier: GPL-3.0-only
* Copyright (C) 2022 aqua <aqua@iserlohn-fortress.net>
* ============================================================
- * Description: Qt WebEngine View
+ * Description: rekonq plugin interface
* ============================================================ */
#pragma once
-#include "rview.h"
+#include "rview.hpp"
+#include <QtPlugin>
-class QWebEngineView;
-
-class WebView final : public rView {
+class RekonqPluginInterface : public QObject {
Q_OBJECT
public:
- explicit WebView(const QUrl &url = QUrl(), QWidget *parent = nullptr);
- ~WebView() final = default;
-
-private:
- QWebEngineView *view;
+ virtual rView *view(const QUrl &url) = 0;
};
+
+#define RekonqPluginInterface_iid "rekonq.3.RekongPluginInterface"
+Q_DECLARE_INTERFACE(RekonqPluginInterface, RekonqPluginInterface_iid)
diff --git a/src/rview.h b/src/plugins/rview.hpp
index 4f4cc897..71bf5ddf 100644
--- a/src/rview.h
+++ b/src/plugins/rview.hpp
@@ -16,7 +16,7 @@ class rView : public QWidget {
Q_OBJECT
public:
- explicit rView(const QUrl &url = QUrl(), QWidget *parent = nullptr);
+ explicit rView(const QUrl &url = QUrl(), QWidget *parent = nullptr) : QWidget(parent) {}
signals:
void iconChanged(const QIcon &);
diff --git a/src/plugins/test/pluginloader.cpp b/src/plugins/test/pluginloader.cpp
new file mode 100644
index 00000000..83b30c40
--- /dev/null
+++ b/src/plugins/test/pluginloader.cpp
@@ -0,0 +1,40 @@
+#include <QJsonArray>
+#include <QPluginLoader>
+#include <gtest/gtest.h>
+#include <iostream>
+
+char *pluginPath;
+
+class PluginLoaderTest : public ::testing::Test {
+
+protected:
+ void SetUp() override { loader = new QPluginLoader; }
+ void TearDown() override { delete loader; }
+
+ QPluginLoader *loader = nullptr;
+};
+
+TEST_F(PluginLoaderTest, InterfaceTest)
+{
+ // Ensure plugin loads
+ loader->setFileName(pluginPath);
+ EXPECT_TRUE(loader->load()) << "For plugin: " << pluginPath << '\n' << qUtf8Printable(loader->errorString());
+
+ // Ensure plugin has metadata
+ const auto metadata = loader->metaData()["MetaData"].toObject();
+ EXPECT_TRUE(metadata.contains("name"));
+ EXPECT_FALSE(metadata["name"].toString().isEmpty());
+ EXPECT_TRUE(metadata.contains("schemes"));
+ EXPECT_FALSE(metadata["schemes"].toArray().isEmpty());
+}
+
+int main(int argc, char **argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ if (argc != 2) {
+ std::cerr << "Usage: " << argv[0] << " [path to plugin]" << std::endl;
+ return -1;
+ }
+ pluginPath = argv[1];
+ return RUN_ALL_TESTS();
+}
diff --git a/src/webengine/webview.cpp b/src/webengine/webview.cpp
deleted file mode 100644
index 1aef01e2..00000000
--- a/src/webengine/webview.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/* ============================================================
- * The rekonq project
- * ============================================================
- * SPDX-License-Identifier: GPL-3.0-only
- * Copyright (C) 2022 aqua <aqua@iserlohn-fortress.net>
- * ============================================================
- * Description: Qt WebEngine View
- * ============================================================ */
-
-#include "webview.h"
-#include <QVBoxLayout>
-#include <QWebEngineView>
-
-WebView::WebView(const QUrl &url, QWidget *parent) : rView(url, parent), view(new QWebEngineView(this))
-{
- auto *layout = new QVBoxLayout;
- layout->setContentsMargins(0, 0, 0, 0);
- layout->addWidget(view);
- setLayout(layout);
-
- connect(view, &QWebEngineView::iconChanged, this, [this](const QIcon &icon) { emit iconChanged(icon); });
- connect(view, &QWebEngineView::urlChanged, this, [this](const QUrl &url) { emit urlChanged(url); });
- connect(view, &QWebEngineView::titleChanged, this, [this](const QString &title) { emit titleChanged(title); });
- view->load(url);
-}