File indexing completed on 2024-12-22 04:41:15

0001 /* ============================================================
0002 * Falkon - Qt web browser
0003 * Copyright (C) 2018 Anmol Gautam <tarptaeya@gmail.com>
0004 *
0005 * This program is free software: you can redistribute it and/or modify
0006 * it under the terms of the GNU General Public License as published by
0007 * the Free Software Foundation, either version 3 of the License, or
0008 * (at your option) any later version.
0009 *
0010 * This program is distributed in the hope that it will be useful,
0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 * GNU General Public License for more details.
0014 *
0015 * You should have received a copy of the GNU General Public License
0016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017 * ============================================================ */
0018 #include "qmlplugininterface.h"
0019 #include "mainapplication.h"
0020 #include "pluginproxy.h"
0021 #include "statusbar.h"
0022 #include "browserwindow.h"
0023 #include "navigationbar.h"
0024 #include "sidebar.h"
0025 #include "api/menus/qmlmenu.h"
0026 #include "api/menus/qmlwebhittestresult.h"
0027 #include "api/events/qmlqzobjects.h"
0028 #include "api/events/qmlmouseevent.h"
0029 #include "api/events/qmlwheelevent.h"
0030 #include "api/events/qmlkeyevent.h"
0031 #include "api/tabs/qmltab.h"
0032 #include "webpage.h"
0033 #include "qztools.h"
0034 #include "qml/qmlengine.h"
0035 #include <QDebug>
0036 #include <QQuickWidget>
0037 #include <QDialog>
0038 #include <QVBoxLayout>
0039 
0040 QmlPluginInterface::QmlPluginInterface()
0041     : m_qmlReusableTab(new QmlTab())
0042 {
0043 }
0044 
0045 QmlPluginInterface::~QmlPluginInterface()
0046 {
0047     m_qmlReusableTab->deleteLater();
0048 }
0049 
0050 void QmlPluginInterface::init(InitState state, const QString &settingsPath)
0051 {
0052     if (!m_init.isCallable()) {
0053         qWarning() << "Unable to call" << __FUNCTION__ << "on" << m_name << "plugin";
0054         return;
0055     }
0056 
0057     QJSValueList args;
0058     args.append(state);
0059     args.append(settingsPath);
0060     m_init.call(args);
0061 }
0062 
0063 void QmlPluginInterface::unload()
0064 {
0065     if (!m_unload.isCallable()) {
0066         qWarning() << "Unable to call" << __FUNCTION__ << "on" << m_name << "plugin";
0067         return;
0068     }
0069 
0070     m_unload.call();
0071 
0072     for (QObject *childItem : std::as_const(m_childItems)) {
0073         childItem->deleteLater();
0074     }
0075 
0076     Q_EMIT qmlPluginUnloaded();
0077 }
0078 
0079 bool QmlPluginInterface::testPlugin()
0080 {
0081     if (!m_testPlugin.isCallable()) {
0082         qWarning() << "Unable to call" << __FUNCTION__ << "on" << m_name << "plugin";
0083         return false;
0084     }
0085 
0086     QJSValue ret = m_testPlugin.call();
0087     return ret.toBool();
0088 }
0089 
0090 void QmlPluginInterface::populateWebViewMenu(QMenu *menu, WebView *webview, const WebHitTestResult &webHitTestResult)
0091 {
0092     Q_UNUSED(webview)
0093 
0094     if (!m_populateWebViewMenu.isCallable()) {
0095         return;
0096     }
0097 
0098     auto *qmlMenu = new QmlMenu(menu, m_engine);
0099     auto *qmlWebHitTestResult = new QmlWebHitTestResult(webHitTestResult);
0100     QJSValueList args;
0101     args.append(m_engine->newQObject(qmlMenu));
0102     args.append(m_engine->newQObject(qmlWebHitTestResult));
0103     m_populateWebViewMenu.call(args);
0104     menu->addSeparator();
0105 }
0106 
0107 void QmlPluginInterface::showSettings(QWidget *parent)
0108 {
0109     if (!m_settingsWindow) {
0110         qWarning() << "No dialog to show";
0111         return;
0112     }
0113 
0114     auto *widget = new QQuickWidget();
0115     widget->setContent(m_settingsWindow->url(), m_settingsWindow, m_settingsWindow->create(m_settingsWindow->creationContext()));
0116     widget->show();
0117 
0118     QzTools::centerWidgetToParent(widget, parent);
0119 }
0120 
0121 bool QmlPluginInterface::mouseDoubleClick(Qz::ObjectName type, QObject *obj, QMouseEvent *event)
0122 {
0123     Q_UNUSED(obj)
0124     if (!m_mouseDoubleClick.isCallable()) {
0125         return false;
0126     }
0127     auto qmlMouseEvent = new QmlMouseEvent(event);
0128     QJSValueList args;
0129     args.append(QmlQzObjects::ObjectName(type));
0130     args.append(m_engine->newQObject(qmlMouseEvent));
0131     m_mouseDoubleClick.call(args);
0132     qmlMouseEvent->clear();
0133     return false;
0134 }
0135 
0136 bool QmlPluginInterface::mousePress(Qz::ObjectName type, QObject *obj, QMouseEvent *event)
0137 {
0138     Q_UNUSED(obj)
0139     if (!m_mousePress.isCallable()) {
0140         return false;
0141     }
0142     auto qmlMouseEvent = new QmlMouseEvent(event);
0143     QJSValueList args;
0144     args.append(QmlQzObjects::ObjectName(type));
0145     args.append(m_engine->newQObject(qmlMouseEvent));
0146     m_mousePress.call(args);
0147     qmlMouseEvent->clear();
0148     return false;
0149 }
0150 
0151 bool QmlPluginInterface::mouseRelease(Qz::ObjectName type, QObject *obj, QMouseEvent *event)
0152 {
0153     Q_UNUSED(obj)
0154     if (!m_mouseRelease.isCallable()) {
0155         return false;
0156     }
0157     auto qmlMouseEvent = new QmlMouseEvent(event);
0158     QJSValueList args;
0159     args.append(QmlQzObjects::ObjectName(type));
0160     args.append(m_engine->newQObject(qmlMouseEvent));
0161     m_mouseRelease.call(args);
0162     qmlMouseEvent->clear();
0163     return false;
0164 }
0165 
0166 bool QmlPluginInterface::mouseMove(Qz::ObjectName type, QObject *obj, QMouseEvent *event)
0167 {
0168     Q_UNUSED(obj)
0169     if (!m_mouseMove.isCallable()) {
0170         return false;
0171     }
0172     auto qmlMouseEvent = new QmlMouseEvent(event);
0173     QJSValueList args;
0174     args.append(QmlQzObjects::ObjectName(type));
0175     args.append(m_engine->newQObject(qmlMouseEvent));
0176     m_mouseMove.call(args);
0177     qmlMouseEvent->clear();
0178     return false;
0179 }
0180 
0181 bool QmlPluginInterface::wheelEvent(Qz::ObjectName type, QObject *obj, QWheelEvent *event)
0182 {
0183     Q_UNUSED(obj)
0184     if (!m_wheelEvent.isCallable()) {
0185         return false;
0186     }
0187     auto qmlWheelEvent = new QmlWheelEvent(event);
0188     QJSValueList args;
0189     args.append(QmlQzObjects::ObjectName(type));
0190     args.append(m_engine->newQObject(qmlWheelEvent));
0191     m_wheelEvent.call(args);
0192     qmlWheelEvent->clear();
0193     return false;
0194 }
0195 
0196 bool QmlPluginInterface::keyPress(Qz::ObjectName type, QObject *obj, QKeyEvent *event)
0197 {
0198     Q_UNUSED(obj)
0199     if (!m_keyPress.isCallable()) {
0200         return false;
0201     }
0202     auto qmlKeyEvent = new QmlKeyEvent(event);
0203     QJSValueList args;
0204     args.append(QmlQzObjects::ObjectName(type));
0205     args.append(m_engine->newQObject(qmlKeyEvent));
0206     m_keyPress.call(args);
0207     qmlKeyEvent->clear();
0208     return false;
0209 }
0210 
0211 bool QmlPluginInterface::keyRelease(Qz::ObjectName type, QObject *obj, QKeyEvent *event)
0212 {
0213     Q_UNUSED(obj)
0214     if (!m_keyRelease.isCallable()) {
0215         return false;
0216     }
0217     auto qmlKeyEvent = new QmlKeyEvent(event);
0218     QJSValueList args;
0219     args.append(QmlQzObjects::ObjectName(type));
0220     args.append(m_engine->newQObject(qmlKeyEvent));
0221     m_keyRelease.call(args);
0222     qmlKeyEvent->clear();
0223     return false;
0224 }
0225 
0226 bool QmlPluginInterface::acceptNavigationRequest(WebPage *page, const QUrl &url, QWebEnginePage::NavigationType type, bool isMainFrame)
0227 {
0228     if (!m_acceptNavigationRequest.isCallable()) {
0229         return true;
0230     }
0231     m_qmlReusableTab->setWebPage(page);
0232     QJSValueList args;
0233     args.append(m_engine->newQObject(m_qmlReusableTab));
0234     args.append(QString::fromUtf8(url.toEncoded()));
0235     args.append(type);
0236     args.append(isMainFrame);
0237     return m_acceptNavigationRequest.call(args).toBool();
0238 }
0239 
0240 QJSValue QmlPluginInterface::readInit() const
0241 {
0242     return m_init;
0243 }
0244 
0245 void QmlPluginInterface::setInit(const QJSValue &init)
0246 {
0247     m_init = init;
0248 }
0249 
0250 QJSValue QmlPluginInterface::readUnload() const
0251 {
0252     return m_unload;
0253 }
0254 
0255 void QmlPluginInterface::setUnload(const QJSValue &unload)
0256 {
0257     m_unload = unload;
0258 }
0259 
0260 QJSValue QmlPluginInterface::readTestPlugin() const
0261 {
0262     return m_testPlugin;
0263 }
0264 
0265 void QmlPluginInterface::setTestPlugin(const QJSValue &testPlugin)
0266 {
0267     m_testPlugin = testPlugin;
0268 }
0269 
0270 void QmlPluginInterface::setEngine(QQmlEngine *engine)
0271 {
0272     m_engine = engine;
0273 }
0274 
0275 void QmlPluginInterface::setName(const QString &name)
0276 {
0277     m_name = name;
0278 }
0279 
0280 QJSValue QmlPluginInterface::readPopulateWebViewMenu() const
0281 {
0282     return m_populateWebViewMenu;
0283 }
0284 
0285 void QmlPluginInterface::setPopulateWebViewMenu(const QJSValue &value)
0286 {
0287     m_populateWebViewMenu = value;
0288 }
0289 
0290 QQmlComponent *QmlPluginInterface::settingsWindow() const
0291 {
0292     return m_settingsWindow;
0293 }
0294 
0295 void QmlPluginInterface::setSettingsWindow(QQmlComponent *settingsWindow)
0296 {
0297     m_settingsWindow = settingsWindow;
0298 }
0299 
0300 QJSValue QmlPluginInterface::readMouseDoubleClick() const
0301 {
0302     return m_mouseDoubleClick;
0303 }
0304 
0305 void QmlPluginInterface::setMouseDoubleClick(const QJSValue &mouseDoubleClick)
0306 {
0307     m_mouseDoubleClick = mouseDoubleClick;
0308     mApp->plugins()->registerAppEventHandler(PluginProxy::MouseDoubleClickHandler, this);
0309 }
0310 
0311 QJSValue QmlPluginInterface::readMousePress() const
0312 {
0313     return m_mousePress;
0314 }
0315 
0316 void QmlPluginInterface::setMousePress(const QJSValue &mousePress)
0317 {
0318     m_mousePress = mousePress;
0319     mApp->plugins()->registerAppEventHandler(PluginProxy::MousePressHandler, this);
0320 }
0321 
0322 QJSValue QmlPluginInterface::readMouseRelease() const
0323 {
0324     return m_mouseRelease;
0325 }
0326 
0327 void QmlPluginInterface::setMouseRelease(const QJSValue &mouseRelease)
0328 {
0329     m_mouseRelease = mouseRelease;
0330     mApp->plugins()->registerAppEventHandler(PluginProxy::MouseReleaseHandler, this);
0331 }
0332 
0333 QJSValue QmlPluginInterface::readMouseMove() const
0334 {
0335     return m_mouseMove;
0336 }
0337 
0338 void QmlPluginInterface::setMouseMove(const QJSValue &mouseMove)
0339 {
0340     m_mouseMove = mouseMove;
0341     mApp->plugins()->registerAppEventHandler(PluginProxy::MouseMoveHandler, this);
0342 }
0343 
0344 QJSValue QmlPluginInterface::readWheelEvent() const
0345 {
0346     return m_wheelEvent;
0347 }
0348 
0349 void QmlPluginInterface::setWheelEvent(const QJSValue &wheelEvent)
0350 {
0351     m_wheelEvent = wheelEvent;
0352     mApp->plugins()->registerAppEventHandler(PluginProxy::WheelEventHandler, this);
0353 }
0354 
0355 QJSValue QmlPluginInterface::readKeyPress() const
0356 {
0357     return m_keyPress;
0358 }
0359 
0360 void QmlPluginInterface::setKeyPress(const QJSValue &keyPress)
0361 {
0362     m_keyPress = keyPress;
0363     mApp->plugins()->registerAppEventHandler(PluginProxy::KeyPressHandler, this);
0364 }
0365 
0366 QJSValue QmlPluginInterface::readKeyRelease() const
0367 {
0368     return m_keyRelease;
0369 }
0370 
0371 void QmlPluginInterface::setKeyRelease(const QJSValue &keyRelease)
0372 {
0373     m_keyRelease = keyRelease;
0374     mApp->plugins()->registerAppEventHandler(PluginProxy::KeyReleaseHandler, this);
0375 }
0376 
0377 QJSValue QmlPluginInterface::readAcceptNavigationRequest() const
0378 {
0379     return m_acceptNavigationRequest;
0380 }
0381 
0382 void QmlPluginInterface::setAcceptNavigationRequest(const QJSValue &acceptNavigationRequest)
0383 {
0384     m_acceptNavigationRequest = acceptNavigationRequest;
0385 }
0386 
0387 QQmlListProperty<QObject> QmlPluginInterface::childItems()
0388 {
0389     return QQmlListProperty<QObject>(this, &m_childItems);
0390 }