diff options
author | aqua <aqua@iserlohn-fortress.net> | 2022-08-16 16:19:04 +0300 |
---|---|---|
committer | aqua <aqua@iserlohn-fortress.net> | 2022-08-16 16:19:04 +0300 |
commit | 616e680aa8af8f5056b5133dd44258c252ca656f (patch) | |
tree | 4c89c4fe2b9b2cc77c550c8d52d6d1058ee10846 /src | |
parent | Add rView and WebView (diff) | |
download | rekonq-616e680aa8af8f5056b5133dd44258c252ca656f.tar.xz |
Turn WebEngine into a plugin
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/application.cpp | 37 | ||||
-rw-r--r-- | src/application.h | 4 | ||||
-rw-r--r-- | src/main.cpp | 11 | ||||
-rw-r--r-- | src/plugins/CMakeLists.txt | 7 | ||||
-rw-r--r-- | src/plugins/pluginloader.cpp (renamed from src/rview.cpp) | 11 | ||||
-rw-r--r-- | src/plugins/pluginloader.h | 25 | ||||
-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.cpp | 40 | ||||
-rw-r--r-- | src/webengine/webview.cpp | 25 |
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); -} |