From 37f5d1bb6ef756bcdaf539c98ea9eb9c8726c406 Mon Sep 17 00:00:00 2001 From: nowrep Date: Wed, 22 Feb 2012 18:33:44 +0100 Subject: [PATCH] Improved Plugin API. Plugins can now receive input events. - mousePress, mouseRelease, mouseMove - keyPress, keyRelease - only WebView class is sending these events now --- .gitignore | 1 + README.md | 2 +- plugins.pri | 6 +- plugins/TestPlugin/testplugin.cpp | 12 ++- plugins/TestPlugin/testplugin.h | 2 + scripts/coding_style.sh | 30 ++++--- scripts/cppcheck.sh | 17 ++-- src/app/proxystyle.cpp | 2 +- src/plugins/plugininterface.h | 8 +- src/plugins/pluginproxy.cpp | 126 ++++++++++++++++++++++++++---- src/plugins/pluginproxy.h | 34 ++++---- src/plugins/plugins.cpp | 31 +++++++- src/plugins/plugins.h | 19 ++++- src/webview/webview.cpp | 30 +++++++ src/webview/webview.h | 2 + 15 files changed, 267 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index f09b0027d..cfd478ffb 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ tools_ *.autosave *~ *.a +*.orig *.qm !qt_*.qm headers*.tar.gz diff --git a/README.md b/README.md index 4984dc34a..2a3613b77 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ To install QupZilla, you will have to run this command: (it may be neccessary to Current version ---------------------------------------------------------------------------------------- -The current released version of QupZilla is 1.1.5. You can download precompiled packages +The current released version of QupZilla is 1.1.8. You can download precompiled packages and the sources from the download section. However, if you want the latest revision, just take the latest code snapshot either by downloading a tarball or running: diff --git a/plugins.pri b/plugins.pri index c501ece22..b56290420 100644 --- a/plugins.pri +++ b/plugins.pri @@ -1,3 +1,5 @@ +include(defines.pri) + INCLUDEPATH += $$PWD/src/3rdparty\ $$PWD/src/app\ $$PWD/src/autofill\ @@ -24,7 +26,7 @@ INCLUDEPATH += $$PWD/src/3rdparty\ TEMPLATE = lib CONFIG += plugin -DESTDIR = $$PWD/bin/plugins +DESTDIR = $$PWD/bin/plugins/ OBJECTS_DIR = build MOC_DIR = build @@ -33,8 +35,6 @@ UI_DIR = build LIBS += -L $$PWD/bin -lqupzilla -include(defines.pri) - !mac:unix { target.path = $$library_folder/qupzilla diff --git a/plugins/TestPlugin/testplugin.cpp b/plugins/TestPlugin/testplugin.cpp index cd9036083..910b7fedf 100644 --- a/plugins/TestPlugin/testplugin.cpp +++ b/plugins/TestPlugin/testplugin.cpp @@ -1,6 +1,7 @@ #include "testplugin.h" #include "qupzilla.h" #include "webview.h" +#include "pluginproxy.h" PluginSpec TestPlugin::pluginSpec() { @@ -26,6 +27,8 @@ void TestPlugin::init(const QString &sPath) m_settingsPath = sPath; m_view = 0; + + QZ_REGISTER_EVENT_HANDLER(PluginProxy::MousePressHandler); } void TestPlugin::unload() @@ -52,7 +55,7 @@ QTranslator* TestPlugin::getTranslator(const QString &locale) return translator; } -void TestPlugin::showSettings(QWidget *parent) +void TestPlugin::showSettings(QWidget* parent) { QDialog* dialog = new QDialog(parent); QPushButton* b = new QPushButton("Example Plugin v0.0.1"); @@ -94,6 +97,13 @@ void TestPlugin::populateWebViewMenu(QMenu* menu, WebView* view, const QWebHitTe menu->addAction(tr("My first plugin action") + title, this, SLOT(actionSlot())); } +bool TestPlugin::mousePress(const Qz::ObjectName &type, QObject* obj, QMouseEvent* event) +{ + qDebug() << "mousePress" << type << obj << event; + + return false; +} + void TestPlugin::actionSlot() { QMessageBox::information(m_view, tr("Hello"), tr("First plugin action works :-)")); diff --git a/plugins/TestPlugin/testplugin.h b/plugins/TestPlugin/testplugin.h index b1254ec1a..2854f9da7 100644 --- a/plugins/TestPlugin/testplugin.h +++ b/plugins/TestPlugin/testplugin.h @@ -32,6 +32,8 @@ public: void populateWebViewMenu(QMenu* menu, WebView* view, const QWebHitTestResult &r); + bool mousePress(const Qz::ObjectName &type, QObject* obj, QMouseEvent* event); + private slots: void actionSlot(); diff --git a/scripts/coding_style.sh b/scripts/coding_style.sh index e1f127c59..8c1cbd8f2 100755 --- a/scripts/coding_style.sh +++ b/scripts/coding_style.sh @@ -4,26 +4,38 @@ # astyle >=2.02 # -echo "running astyle for *.cpp ..." - -cd ../src - -astyle --indent=spaces=4 --style=1tbs \ +function format_sources { + astyle --indent=spaces=4 --style=1tbs \ --indent-labels --pad-oper --unpad-paren --pad-header \ --convert-tabs --indent-preprocessor --break-closing-brackets \ --align-pointer=type --align-reference=name \ `find -type f -name '*.cpp'` + + rm */*.orig +} -echo "running astyle for *.h ..." - -astyle --indent=spaces=4 --style=linux \ +function format_headers { + astyle --indent=spaces=4 --style=linux \ --indent-labels --pad-oper --unpad-paren --pad-header \ --keep-one-line-statements --keep-one-line-blocks \ --indent-preprocessor --convert-tabs \ --align-pointer=type --align-reference=name \ `find -type f -name '*.h'` -rm */*.orig + rm */*.orig +} + +cd ../src +echo "running astyle for *.cpp ..." +format_sources + +echo "running astyle for *.h ..." +format_headers + +echo "running astyle for plugins ..." +cd ../plugins +format_sources +format_headers read -p "Press [ENTER] to close terminal" exit diff --git a/scripts/cppcheck.sh b/scripts/cppcheck.sh index 8df3ce38b..05bb06218 100755 --- a/scripts/cppcheck.sh +++ b/scripts/cppcheck.sh @@ -3,14 +3,21 @@ # cppcheck # +function check_code { + cppcheck \ + --enable=all \ + --force \ + --verbose \ + . > /dev/null +} + echo "cppcheck..." cd ../src -cppcheck \ ---enable=all \ ---force \ ---verbose \ -. > /dev/null +check_code + +cd ../plugins +check_code read -p "Press [ENTER] to close terminal" exit diff --git a/src/app/proxystyle.cpp b/src/app/proxystyle.cpp index 3b6c83cef..6f31dd515 100644 --- a/src/app/proxystyle.cpp +++ b/src/app/proxystyle.cpp @@ -8,7 +8,7 @@ ProxyStyle::ProxyStyle() int ProxyStyle::styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const { if (hint == QStyle::SH_Menu_Scrollable) { - return 1; + return int(true); } return QProxyStyle::styleHint(hint, option, widget, returnData); diff --git a/src/plugins/plugininterface.h b/src/plugins/plugininterface.h index 1f2b877f8..2afd01e6a 100644 --- a/src/plugins/plugininterface.h +++ b/src/plugins/plugininterface.h @@ -63,7 +63,13 @@ public: virtual void showSettings(QWidget* parent = 0) { Q_UNUSED(parent) } virtual void populateWebViewMenu(QMenu* menu, WebView* view, const QWebHitTestResult &r) { Q_UNUSED(menu) Q_UNUSED(view) Q_UNUSED(r) } - virtual bool processEvent(const Qz::ObjectName &type, QObject* obj, QEvent* event) { Q_UNUSED(type) Q_UNUSED(obj) Q_UNUSED(event) return false; } + + virtual bool mousePress(const Qz::ObjectName &type, QObject* obj, QMouseEvent* event) { Q_UNUSED(type) Q_UNUSED(obj) Q_UNUSED(event) return false; } + virtual bool mouseRelease(const Qz::ObjectName &type, QObject* obj, QMouseEvent* event) { Q_UNUSED(type) Q_UNUSED(obj) Q_UNUSED(event) return false; } + virtual bool mouseMove(const Qz::ObjectName &type, QObject* obj, QMouseEvent* event) { Q_UNUSED(type) Q_UNUSED(obj) Q_UNUSED(event) return false; } + + virtual bool keyPress(const Qz::ObjectName &type, QObject* obj, QKeyEvent* event) { Q_UNUSED(type) Q_UNUSED(obj) Q_UNUSED(event) return false; } + virtual bool keyRelease(const Qz::ObjectName &type, QObject* obj, QKeyEvent* event) { Q_UNUSED(type) Q_UNUSED(obj) Q_UNUSED(event) return false; } }; Q_DECLARE_INTERFACE(PluginInterface, "QupZilla.Browser.PluginInterface/1.1") diff --git a/src/plugins/pluginproxy.cpp b/src/plugins/pluginproxy.cpp index 8533b4662..07a95919f 100644 --- a/src/plugins/pluginproxy.cpp +++ b/src/plugins/pluginproxy.cpp @@ -18,14 +18,62 @@ #include "pluginproxy.h" #include "plugininterface.h" #include "mainapplication.h" -#include "speeddial.h" #include "settings.h" PluginProxy::PluginProxy() : Plugins() - , m_speedDial(new SpeedDial(this)) { - c2f_loadSettings(); +} + +void PluginProxy::unloadPlugin(Plugins::Plugin* plugin) +{ + m_mousePressHandlers.removeOne(plugin->instance); + m_mouseReleaseHandlers.removeOne(plugin->instance); + m_mouseMoveHandlers.removeOne(plugin->instance); + + m_keyPressHandlers.removeOne(plugin->instance); + m_keyReleaseHandlers.removeOne(plugin->instance); + + Plugins::unloadPlugin(plugin); +} + +void PluginProxy::registerAppEventHandler(const PluginProxy::EventHandlerType &type, PluginInterface* obj) +{ + switch (type) { + case MousePressHandler: + if (!m_mousePressHandlers.contains(obj)) { + m_mousePressHandlers.append(obj); + } + break; + + case MouseReleaseHandler: + if (!m_mouseReleaseHandlers.contains(obj)) { + m_mouseReleaseHandlers.append(obj); + } + break; + + case MouseMoveHandler: + if (!m_mouseMoveHandlers.contains(obj)) { + m_mouseMoveHandlers.append(obj); + } + break; + + case KeyPressHandler: + if (!m_keyPressHandlers.contains(obj)) { + m_keyPressHandlers.append(obj); + } + break; + + case KeyReleaseHandler: + if (!m_keyReleaseHandlers.contains(obj)) { + m_keyReleaseHandlers.append(obj); + } + break; + + default: + qWarning("PluginProxy::registerAppEventHandler registering unknown event handler type"); + break; + } } void PluginProxy::populateWebViewMenu(QMenu* menu, WebView* view, const QWebHitTestResult &r) @@ -46,20 +94,68 @@ void PluginProxy::populateWebViewMenu(QMenu* menu, WebView* view, const QWebHitT } } -void PluginProxy::c2f_loadSettings() +bool PluginProxy::processMousePress(const Qz::ObjectName &type, QObject* obj, QMouseEvent* event) { - Settings settings; - settings.beginGroup("ClickToFlash"); - c2f_whitelist = settings.value("whitelist", QStringList()).toStringList(); - c2f_enabled = settings.value("Enabled", true).toBool(); - settings.endGroup(); + bool accepted = false; + + foreach(PluginInterface * iPlugin, m_mousePressHandlers) { + if (iPlugin->mousePress(type, obj, event)) { + accepted = true; + } + } + + return accepted; } -void PluginProxy::c2f_saveSettings() +bool PluginProxy::processMouseRelease(const Qz::ObjectName &type, QObject* obj, QMouseEvent* event) { - Settings settings; - settings.beginGroup("ClickToFlash"); - settings.setValue("whitelist", c2f_whitelist); - settings.setValue("Enabled", c2f_enabled); - settings.endGroup(); + bool accepted = false; + + foreach(PluginInterface * iPlugin, m_mouseReleaseHandlers) { + if (iPlugin->mouseRelease(type, obj, event)) { + accepted = true; + } + } + + return accepted; } + +bool PluginProxy::processMouseMove(const Qz::ObjectName &type, QObject* obj, QMouseEvent* event) +{ + bool accepted = false; + + foreach(PluginInterface * iPlugin, m_mouseMoveHandlers) { + if (iPlugin->mouseMove(type, obj, event)) { + accepted = true; + } + } + + return accepted; +} + +bool PluginProxy::processKeyPress(const Qz::ObjectName &type, QObject* obj, QKeyEvent* event) +{ + bool accepted = false; + + foreach(PluginInterface * iPlugin, m_keyPressHandlers) { + if (iPlugin->keyPress(type, obj, event)) { + accepted = true; + } + } + + return accepted; +} + +bool PluginProxy::processKeyRelease(const Qz::ObjectName &type, QObject* obj, QKeyEvent* event) +{ + bool accepted = false; + + foreach(PluginInterface * iPlugin, m_keyReleaseHandlers) { + if (iPlugin->keyRelease(type, obj, event)) { + accepted = true; + } + } + + return accepted; +} + diff --git a/src/plugins/pluginproxy.h b/src/plugins/pluginproxy.h index 9187451f6..7acec433f 100644 --- a/src/plugins/pluginproxy.h +++ b/src/plugins/pluginproxy.h @@ -23,35 +23,39 @@ #include #include +#include "mainapplication.h" #include "plugins.h" #include "qz_namespace.h" -class SpeedDial; class PluginProxy : public Plugins { public: + enum EventHandlerType { MousePressHandler, MouseReleaseHandler, MouseMoveHandler, KeyPressHandler, KeyReleaseHandler }; + explicit PluginProxy(); - // Application API + void unloadPlugin(Plugin* plugin); + void registerAppEventHandler(const EventHandlerType &type, PluginInterface* obj); + void populateWebViewMenu(QMenu* menu, WebView* view, const QWebHitTestResult &r); - // CLick2Flash - void c2f_loadSettings(); - void c2f_saveSettings(); - void c2f_addWhitelist(QString page) { c2f_whitelist.append(page); } - void c2f_removeWhitelist(QString page) { c2f_whitelist.removeOne(page); } - void c2f_setEnabled(bool en) { c2f_enabled = en; } - bool c2f_isEnabled() { return c2f_enabled; } - QStringList c2f_getWhiteList() { return c2f_whitelist; } + bool processMousePress(const Qz::ObjectName &type, QObject* obj, QMouseEvent* event); + bool processMouseRelease(const Qz::ObjectName &object, QObject* obj, QMouseEvent* event); + bool processMouseMove(const Qz::ObjectName &object, QObject* obj, QMouseEvent* event); - // SpeedDial - SpeedDial* speedDial() { return m_speedDial; } + bool processKeyPress(const Qz::ObjectName &object, QObject* obj, QKeyEvent* event); + bool processKeyRelease(const Qz::ObjectName &object, QObject* obj, QKeyEvent* event); private: - QStringList c2f_whitelist; - bool c2f_enabled; + QList m_mousePressHandlers; + QList m_mouseReleaseHandlers; + QList m_mouseMoveHandlers; + + QList m_keyPressHandlers; + QList m_keyReleaseHandlers; - SpeedDial* m_speedDial; }; +#define QZ_REGISTER_EVENT_HANDLER(Type) mApp->plugins()->registerAppEventHandler(Type, this); + #endif // PLUGINPROXY_H diff --git a/src/plugins/plugins.cpp b/src/plugins/plugins.cpp index f47366d16..171febea2 100644 --- a/src/plugins/plugins.cpp +++ b/src/plugins/plugins.cpp @@ -18,6 +18,7 @@ #include "pluginproxy.h" #include "plugininterface.h" #include "mainapplication.h" +#include "speeddial.h" #include "settings.h" #ifdef PORTABLE_BUILD @@ -29,20 +30,21 @@ Plugins::Plugins(QObject* parent) : QObject(parent) , m_pluginsLoaded(false) + , m_speedDial(new SpeedDial(this)) { loadSettings(); } -void Plugins::loadPlugin(Plugins::Plugin* plugin) +bool Plugins::loadPlugin(Plugins::Plugin* plugin) { if (plugin->isLoaded()) { - return; + return true; } plugin->pluginLoader->setFileName(plugin->fullPath); PluginInterface* iPlugin = qobject_cast(plugin->pluginLoader->instance()); if (!iPlugin) { - return; + return false; } m_availablePlugins.removeOne(*plugin); @@ -50,6 +52,8 @@ void Plugins::loadPlugin(Plugins::Plugin* plugin) m_availablePlugins.append(*plugin); refreshLoadedPlugins(); + + return plugin->isLoaded(); } void Plugins::unloadPlugin(Plugins::Plugin* plugin) @@ -75,8 +79,29 @@ void Plugins::loadSettings() m_pluginsEnabled = settings.value("EnablePlugins", DEFAULT_ENABLE_PLUGINS).toBool(); m_allowedPluginFileNames = settings.value("AllowedPlugins", QStringList()).toStringList(); settings.endGroup(); + + c2f_loadSettings(); } +void Plugins::c2f_loadSettings() +{ + Settings settings; + settings.beginGroup("ClickToFlash"); + c2f_whitelist = settings.value("whitelist", QStringList()).toStringList(); + c2f_enabled = settings.value("Enabled", true).toBool(); + settings.endGroup(); +} + +void Plugins::c2f_saveSettings() +{ + Settings settings; + settings.beginGroup("ClickToFlash"); + settings.setValue("whitelist", c2f_whitelist); + settings.setValue("Enabled", c2f_enabled); + settings.endGroup(); +} + + void Plugins::loadPlugins() { if (!m_pluginsEnabled || m_pluginsLoaded) { diff --git a/src/plugins/plugins.h b/src/plugins/plugins.h index e05ac7b24..78cc25d21 100644 --- a/src/plugins/plugins.h +++ b/src/plugins/plugins.h @@ -27,6 +27,7 @@ #include #include "plugininterface.h" +class SpeedDial; class Plugins : public QObject { Q_OBJECT @@ -54,9 +55,21 @@ public: QList getAvailablePlugins() { return m_availablePlugins; } - void loadPlugin(Plugin* plugin); + bool loadPlugin(Plugin* plugin); void unloadPlugin(Plugin* plugin); + // CLick2Flash + void c2f_loadSettings(); + void c2f_saveSettings(); + void c2f_addWhitelist(QString page) { c2f_whitelist.append(page); } + void c2f_removeWhitelist(QString page) { c2f_whitelist.removeOne(page); } + void c2f_setEnabled(bool en) { c2f_enabled = en; } + bool c2f_isEnabled() { return c2f_enabled; } + QStringList c2f_getWhiteList() { return c2f_whitelist; } + + // SpeedDial + SpeedDial* speedDial() { return m_speedDial; } + public slots: void loadSettings(); void loadPlugins(); @@ -73,6 +86,10 @@ private: bool m_pluginsEnabled; bool m_pluginsLoaded; + + SpeedDial* m_speedDial; + QStringList c2f_whitelist; + bool c2f_enabled; }; Q_DECLARE_METATYPE(Plugins::Plugin) diff --git a/src/webview/webview.cpp b/src/webview/webview.cpp index 010239c41..c4ffd89af 100644 --- a/src/webview/webview.cpp +++ b/src/webview/webview.cpp @@ -768,6 +768,10 @@ void WebView::wheelEvent(QWheelEvent* event) void WebView::mousePressEvent(QMouseEvent* event) { + if (mApp->plugins()->processMousePress(Qz::ON_WebView, this, event)) { + return; + } + switch (event->button()) { case Qt::XButton1: back(); @@ -820,6 +824,10 @@ void WebView::mousePressEvent(QMouseEvent* event) void WebView::mouseReleaseEvent(QMouseEvent* event) { + if (mApp->plugins()->processMouseRelease(Qz::ON_WebView, this, event)) { + return; + } + switch (event->button()) { case Qt::MiddleButton: { QWebFrame* frame = page()->frameAt(event->pos()); @@ -842,8 +850,21 @@ void WebView::mouseReleaseEvent(QMouseEvent* event) QWebView::mouseReleaseEvent(event); } +void WebView::mouseMoveEvent(QMouseEvent* event) +{ + if (mApp->plugins()->processMouseMove(Qz::ON_WebView, this, event)) { + return; + } + + QWebView::mouseMoveEvent(event); +} + void WebView::keyPressEvent(QKeyEvent* event) { + if (mApp->plugins()->processKeyPress(Qz::ON_WebView, this, event)) { + return; + } + switch (event->key()) { case Qt::Key_C: if (event->modifiers() == Qt::ControlModifier) { @@ -868,6 +889,15 @@ void WebView::keyPressEvent(QKeyEvent* event) QWebView::keyPressEvent(event); } +void WebView::keyReleaseEvent(QKeyEvent* event) +{ + if (mApp->plugins()->processKeyRelease(Qz::ON_WebView, this, event)) { + return; + } + + QWebView::keyReleaseEvent(event); +} + void WebView::resizeEvent(QResizeEvent* event) { QWebView::resizeEvent(event); diff --git a/src/webview/webview.h b/src/webview/webview.h index 4d03a1ad2..5c6f4ebef 100644 --- a/src/webview/webview.h +++ b/src/webview/webview.h @@ -110,7 +110,9 @@ protected: void wheelEvent(QWheelEvent* event); void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); void keyPressEvent(QKeyEvent* event); + void keyReleaseEvent(QKeyEvent* event); void resizeEvent(QResizeEvent* event); void setZoom(int zoom);