From b6615f409f452af5ccb095333dd19054d02dffeb Mon Sep 17 00:00:00 2001 From: nowrep Date: Sun, 19 Feb 2012 16:01:51 +0100 Subject: [PATCH] Edited build config to build libqupzilla and link to it afterwards. - edited plugins system - proper plugin loading / unloading - edited plugins interface --- .gitignore | 3 +- QupZilla.pro | 3 +- defines.pri | 16 ++++ install.pri | 13 ++- main/main.pro | 18 ++++ plugins.pri | 10 +- plugins/TestPlugin/testplugin.cpp | 62 +++++++++--- plugins/TestPlugin/testplugin.h | 22 ++--- plugins/libqupzilla/libqupzilla.pro | 17 ---- plugins/plugins.pro | 7 +- src/main.cpp | 1 - src/network/qupzillaschemehandler.cpp | 12 +-- src/plugins/plugininterface.h | 41 +++++--- src/plugins/pluginproxy.cpp | 14 +-- src/plugins/plugins.cpp | 123 +++++++++++++++++------- src/plugins/plugins.h | 43 +++++++-- src/preferences/pluginslist.cpp | 130 ++++++++++++++++---------- src/preferences/pluginslist.h | 7 +- src/preferences/pluginslist.ui | 17 ---- src/src.pro | 9 +- 20 files changed, 356 insertions(+), 212 deletions(-) create mode 100644 main/main.pro delete mode 100644 plugins/libqupzilla/libqupzilla.pro diff --git a/.gitignore b/.gitignore index aab97cad5..f09b0027d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,8 @@ TestPlugin-build search_* src-* bin/qupzilla -bin/plugins/libExamplePlugin.so +*.so +libqupzilla.* bin/core qupzilla.sh git_revision diff --git a/QupZilla.pro b/QupZilla.pro index 220a53531..ac11f4fdb 100644 --- a/QupZilla.pro +++ b/QupZilla.pro @@ -11,5 +11,6 @@ lessThan(QT_VERSION, 4.7) { } TEMPLATE = subdirs -SUBDIRS = src +SUBDIRS = src main build_plugins: SUBDIRS += plugins +CONFIG += ordered diff --git a/defines.pri b/defines.pri index e384671d2..8e4a77b46 100644 --- a/defines.pri +++ b/defines.pri @@ -3,6 +3,7 @@ OBJECTS_DIR = $$PWD/build MOC_DIR = $$PWD/build RCC_DIR = $$PWD/build UI_DIR = $$PWD/build +VERSION = 1.1.8 # Please read BUILD information # #DEFINES += NO_SYSTEM_DATAPATH @@ -30,3 +31,18 @@ equals(d_use_webgl, "true") { DEFINES += USE_WEBGL } equals(d_w7api, "true") { DEFINES += W7API } equals(d_kde, "true") { DEFINES += KDE } equals(d_portable, "true") { DEFINES += PORTABLE_BUILD } + +!mac:unix { + d_prefix = $$(QUPZILLA_PREFIX) + data_folder = /usr/share/qupzilla + + !equals(d_prefix, "") { + data_folder = "$$d_prefix"share/qupzilla + } + + DEFINES += USE_DATADIR=\\\"""$$data_folder/"\\\"" + + #Git revision + rev = $$system(sh $$PWD/scripts/getrevision.sh) + !equals(rev, ""): DEFINES += GIT_REVISION=\\\"""$$rev"\\\"" +} diff --git a/install.pri b/install.pri index 5897a84ab..d6cb4b6d4 100644 --- a/install.pri +++ b/install.pri @@ -12,6 +12,7 @@ mac { !mac:unix { d_prefix = $$(QUPZILLA_PREFIX) binary_folder = /usr/bin + library_folder = /usr/lib data_folder = /usr/share/qupzilla launcher_folder = /usr/share/applications icon_folder = /usr/share/pixmaps @@ -19,16 +20,18 @@ mac { !equals(d_prefix, "") { binary_folder = "$$d_prefix"bin + library_folder = "$$d_prefix"lib data_folder = "$$d_prefix"share/qupzilla launcher_folder = "$$d_prefix"share/applications icon_folder = "$$d_prefix"share/pixmaps hicolor_folder = "$$d_prefix"share/icons/hicolor } - DEFINES += USE_DATADIR=\\\"""$$data_folder/"\\\"" - target.path = $$binary_folder + targetlib.files = $$PWD/bin/libqupzilla* + targetlib.path = $$library_folder + target1.files += $$PWD/bin/locale target1.files += $$PWD/bin/themes target1.path = $$data_folder @@ -57,10 +60,6 @@ mac { ico256.files = $$PWD/linux/hicolor/256x256/apps/qupzilla.png ico256.path = $$hicolor_folder/256x256/apps - INSTALLS += target target1 target2 target3 + INSTALLS += target targetlib target1 target2 target3 INSTALLS += ico16 ico32 ico48 ico64 ico128 ico256 - - #Git revision - rev = $$system(sh $$PWD/scripts/getrevision.sh) - !equals(rev, ""): DEFINES += GIT_REVISION=\\\"""$$rev"\\\"" } diff --git a/main/main.pro b/main/main.pro new file mode 100644 index 000000000..9c44100ef --- /dev/null +++ b/main/main.pro @@ -0,0 +1,18 @@ +QT += core gui webkit sql network script +unix: QT += dbus + +TARGET = qupzilla +TEMPLATE = app +LIBS += -L../bin -lqupzilla + +include(../install.pri) +include(../defines.pri) +include(../translations.pri) +include(../src/3rdparty/qtsingleapplication.pri) + +INCLUDEPATH += ../src/app +SOURCES = ../src/main.cpp + +unix:contains(DEFINES, "NO_SYSTEM_DATAPATH"): QMAKE_RPATHDIR += $$PWD/../bin + +message(========== Building qupzilla binary ==========) diff --git a/plugins.pri b/plugins.pri index 7fac5c4e7..03d1a046b 100644 --- a/plugins.pri +++ b/plugins.pri @@ -26,9 +26,9 @@ TEMPLATE = lib CONFIG += plugin DESTDIR = $$PWD/bin/plugins -OBJECTS_DIR = $$TARGET-build -MOC_DIR = $$TARGET-build -RCC_DIR = $$TARGET-build -UI_DIR = $$TARGET-build +OBJECTS_DIR = build +MOC_DIR = build +RCC_DIR = build +UI_DIR = build -LIBS += $$PWD/plugins/libqupzilla/libqupzilla.a +LIBS += -L $$PWD/bin -lqupzilla diff --git a/plugins/TestPlugin/testplugin.cpp b/plugins/TestPlugin/testplugin.cpp index c0745a5ed..9322bb0e6 100644 --- a/plugins/TestPlugin/testplugin.cpp +++ b/plugins/TestPlugin/testplugin.cpp @@ -1,10 +1,37 @@ #include "testplugin.h" +#include "qupzilla.h" -void TestPlugin::init(QString sPath) +PluginSpec TestPlugin::pluginSpec() +{ + PluginSpec spec; + spec.name = tr("Example Plugin"); + spec.info = tr("Example minimal plugin"); + spec.description = tr("Very simple minimal plugin example"); + spec.version = "0.0.1"; + spec.author = "David Rosca "; + spec.icon = QIcon(":qupzilla.png"); + spec.hasSettings = true; + + return spec; +} + +void TestPlugin::init(const QString &sPath) { - settingsPath = sPath; - //This function is called right after plugin is loaded qDebug() << __FUNCTION__ << "called"; + + // This function is called right after plugin is loaded + // it will be called even if we return false from testPlugin() + // so it is recommended not to call any QupZilla function here + + settingsPath = sPath; +} + +void TestPlugin::unload() +{ + qDebug() << __FUNCTION__ << "called"; + + // This function will be called when unloading plugin + // it will be also called if we return false from testPlugin() } bool TestPlugin::testPlugin() @@ -13,29 +40,34 @@ bool TestPlugin::testPlugin() //There should be some testing if plugin is loaded correctly //If this function returns false, plugin is automatically unloaded - return true; + return (QupZilla::VERSION == "1.1.8"); } -QTranslator* TestPlugin::getTranslator(QString locale) +QTranslator* TestPlugin::getTranslator(const QString &locale) { QTranslator* translator = new QTranslator(); translator->load(":/" + locale); return translator; } -void TestPlugin::showSettings() +void TestPlugin::showSettings(QWidget *parent) { - QWidget* widget = new QWidget(); - new QLabel("Example Plugin v0.0.1", widget); - widget->resize(200, 200); - widget->setAttribute(Qt::WA_DeleteOnClose); - widget->setWindowModality(Qt::WindowModal); //As the preferences window is modal too - widget->setWindowTitle("Example Plugin Settings"); - widget->setWindowIcon(pluginIcon()); - widget->show(); + QDialog* dialog = new QDialog(parent); + QPushButton* b = new QPushButton("Example Plugin v0.0.1"); + + QHBoxLayout* l = new QHBoxLayout(dialog); + l->addWidget(b); + dialog->setLayout(l); + + dialog->resize(200, 200); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->setWindowTitle("Example Plugin Settings"); + dialog->setWindowIcon(QIcon(":/qupzilla.png")); + + dialog->show(); } -void TestPlugin::populateWebViewMenu(QMenu* menu, QWebView* view, QWebHitTestResult r) +void TestPlugin::populateWebViewMenu(QMenu* menu, QWebView* view, const QWebHitTestResult &r) { Q_UNUSED(view) QString title; diff --git a/plugins/TestPlugin/testplugin.h b/plugins/TestPlugin/testplugin.h index e8621ee5c..6c1d6d2aa 100644 --- a/plugins/TestPlugin/testplugin.h +++ b/plugins/TestPlugin/testplugin.h @@ -5,8 +5,6 @@ //This file is available to download at QupZilla website #include "plugininterface.h" -#include "historymodel.h" - //For clean plugin directory, please build necessary files into //plugin in .qrc data files @@ -15,6 +13,7 @@ #include #include #include +#include class TestPlugin : public QObject, public PluginInterface { @@ -22,25 +21,22 @@ class TestPlugin : public QObject, public PluginInterface Q_INTERFACES(PluginInterface) public: - QString pluginName() { return tr("Example Plugin"); } - QString pluginInfo() { return tr("Example minimal plugin"); } - QString pluginDescription() { return tr("Very simple minimal plugin example"); } - QString pluginVersion() { return "0.0.1"; } - QString pluginAuthor() { return "David Rosca "; } - void init(QString sPath); + PluginSpec pluginSpec(); + + void init(const QString &sPath); + void unload(); bool testPlugin(); - QTranslator* getTranslator(QString locale); - QIcon pluginIcon() { return QIcon(":/qupzilla.png"); } - bool hasSettings() { return true; } - void showSettings(); + QTranslator* getTranslator(const QString &locale); + void showSettings(QWidget* parent = 0); - void populateWebViewMenu(QMenu* menu, QWebView* view, QWebHitTestResult r); + void populateWebViewMenu(QMenu* menu, QWebView* view, const QWebHitTestResult &r); void populateHelpMenu(QMenu* menu); void populateToolsMenu(QMenu* menu); private slots: void actionSlot(); + private: QString settingsPath; }; diff --git a/plugins/libqupzilla/libqupzilla.pro b/plugins/libqupzilla/libqupzilla.pro deleted file mode 100644 index 099f3e488..000000000 --- a/plugins/libqupzilla/libqupzilla.pro +++ /dev/null @@ -1,17 +0,0 @@ -include(../../src/3rdparty/qtsingleapplication.pri) -include(../../defines.pri) -include(../../install.pri) -include(../../src/src.pri) - -QT += core gui webkit sql network script -unix:QT += dbus - -TARGET = qupzilla -TEMPLATE = lib -CONFIG -= shared -CONFIG += static - -DESTDIR = $$PWD -OBJECTS_DIR = $$PWD/build -RESOURCES = -win32|os2:RC_FILE = diff --git a/plugins/plugins.pro b/plugins/plugins.pro index 6ff22166f..fe7f4d449 100644 --- a/plugins/plugins.pro +++ b/plugins/plugins.pro @@ -1,7 +1,2 @@ TEMPLATE = subdirs - -sub_lib.subdir = libqupzilla -sub_testplugin.subdir = TestPlugin -sub_testplugin.depends = sub_lib - -SUBDIRS = sub_lib sub_testplugin +SUBDIRS = TestPlugin diff --git a/src/main.cpp b/src/main.cpp index a15092d53..64e2a0c5e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,7 +40,6 @@ void sigpipe_handler(int s) int main(int argc, char* argv[]) { - Q_INIT_RESOURCE(data); Q_INIT_RESOURCE(icons); Q_INIT_RESOURCE(html); diff --git a/src/network/qupzillaschemehandler.cpp b/src/network/qupzillaschemehandler.cpp index 72acbd21a..deb97aadd 100644 --- a/src/network/qupzillaschemehandler.cpp +++ b/src/network/qupzillaschemehandler.cpp @@ -328,16 +328,12 @@ QString QupZillaSchemeReply::configPage() QString("
%1
%2
").arg(tr("Platform"), qz_buildSystem())); QString pluginsString; - QStringList availablePlugins = mApp->plugins()->getAvailablePlugins(); + const QList &availablePlugins = mApp->plugins()->getAvailablePlugins(); - foreach(const QString & fileName, availablePlugins) { - PluginInterface* plugin = mApp->plugins()->getPlugin(fileName); - if (!plugin) { - continue; - } + foreach(const Plugins::Plugin & plugin, availablePlugins) { + PluginSpec spec = plugin.pluginSpec; pluginsString.append(QString("%1%2%3%4").arg( - plugin->pluginName(), plugin->pluginVersion(), - Qt::escape(plugin->pluginAuthor()), plugin->pluginDescription())); + spec.name, spec.version, Qt::escape(spec.author), spec.description)); } if (pluginsString.isEmpty()) { diff --git a/src/plugins/plugininterface.h b/src/plugins/plugininterface.h index d3757161e..9b447be76 100644 --- a/src/plugins/plugininterface.h +++ b/src/plugins/plugininterface.h @@ -26,29 +26,42 @@ #include #include +struct PluginSpec { + QString name; + QString info; + QString description; + QString author; + QString version; + QIcon icon; + bool hasSettings; + + bool operator==(const PluginSpec &other) { + return (this->name == other.name && + this->info == other.info && + this->description == other.description && + this->author == other.author && + this->version == other.version); + } +}; + class PluginInterface { public: //Plugin Necessary Init Functions - //You have to reimplement those functions, otherwise QupZilla crash - virtual ~PluginInterface() { } - virtual QString pluginName() = 0; - virtual QString pluginInfo() = 0; - virtual QString pluginDescription() = 0; - virtual QString pluginVersion() = 0; - virtual QString pluginAuthor() = 0; - virtual void init(QString settingsPath) = 0; + virtual PluginSpec pluginSpec() = 0; + + virtual void init(const QString &settingsPath) = 0; + virtual void unload() = 0; virtual bool testPlugin() = 0; //End Plugin Necessary Init Functions - virtual QTranslator* getTranslator(QString locale) { Q_UNUSED(locale) return 0; } - virtual QIcon pluginIcon() { return QIcon(); } - virtual bool hasSettings() { return false; } - virtual void showSettings() { } + virtual ~PluginInterface() { } + virtual QTranslator* getTranslator(const QString &locale) { Q_UNUSED(locale) return 0; } + virtual void showSettings(QWidget* parent = 0) { Q_UNUSED(parent) } virtual void populateToolsMenu(QMenu* menu) { Q_UNUSED(menu) } virtual void populateHelpMenu(QMenu* menu) { Q_UNUSED(menu) } - virtual void populateWebViewMenu(QMenu* menu, QWebView* view, QWebHitTestResult r) { Q_UNUSED(menu) Q_UNUSED(view) Q_UNUSED(r) } + virtual void populateWebViewMenu(QMenu* menu, QWebView* view, const QWebHitTestResult &r) { Q_UNUSED(menu) Q_UNUSED(view) Q_UNUSED(r) } virtual void formSent(const QNetworkRequest &request, const QByteArray &outgoingData) { Q_UNUSED(request) Q_UNUSED(outgoingData)} virtual void pageLoaded(QWebView* view) { Q_UNUSED(view) } @@ -57,7 +70,7 @@ public: { Q_UNUSED(op) Q_UNUSED(request) Q_UNUSED(outgoingData) return 0; } }; -Q_DECLARE_INTERFACE(PluginInterface, "Qupzilla.Browser.PluginInterface/1.0") +Q_DECLARE_INTERFACE(PluginInterface, "QupZilla.Browser.PluginInterface/1.1") #endif // PLUGININTERFACE_H diff --git a/src/plugins/pluginproxy.cpp b/src/plugins/pluginproxy.cpp index 23182aef4..14773c47f 100644 --- a/src/plugins/pluginproxy.cpp +++ b/src/plugins/pluginproxy.cpp @@ -30,14 +30,14 @@ PluginProxy::PluginProxy() void PluginProxy::populateWebViewMenu(QMenu* menu, QWebView* view, QWebHitTestResult r) { - if (!menu || !view || loadedPlugins.count() == 0) { + if (!menu || !view || m_loadedPlugins.count() == 0) { return; } menu->addSeparator(); int count = menu->actions().count(); - foreach(PluginInterface * iPlugin, loadedPlugins) + foreach(PluginInterface * iPlugin, m_loadedPlugins) iPlugin->populateWebViewMenu(menu, view, r); if (menu->actions().count() == count) { @@ -47,13 +47,13 @@ void PluginProxy::populateWebViewMenu(QMenu* menu, QWebView* view, QWebHitTestRe void PluginProxy::populateToolsMenu(QMenu* menu) { - if (!menu || loadedPlugins.count() == 0) { + if (!menu || m_loadedPlugins.count() == 0) { return; } int count = menu->actions().count(); - foreach(PluginInterface * iPlugin, loadedPlugins) + foreach(PluginInterface * iPlugin, m_loadedPlugins) iPlugin->populateToolsMenu(menu); if (menu->actions().count() != count) { @@ -63,13 +63,13 @@ void PluginProxy::populateToolsMenu(QMenu* menu) void PluginProxy::populateHelpMenu(QMenu* menu) { - if (!menu || loadedPlugins.count() == 0) { + if (!menu || m_loadedPlugins.count() == 0) { return; } int count = menu->actions().count(); - foreach(PluginInterface * iPlugin, loadedPlugins) + foreach(PluginInterface * iPlugin, m_loadedPlugins) iPlugin->populateHelpMenu(menu); if (menu->actions().count() != count) { @@ -80,7 +80,7 @@ void PluginProxy::populateHelpMenu(QMenu* menu) QNetworkReply* PluginProxy::createNetworkRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice* outgoingData) { QNetworkReply* reply = 0; - foreach(PluginInterface * iPlugin, loadedPlugins) { + foreach(PluginInterface * iPlugin, m_loadedPlugins) { reply = iPlugin->createNetworkRequest(op, request, outgoingData); if (reply) { break; diff --git a/src/plugins/plugins.cpp b/src/plugins/plugins.cpp index 5b4a5086d..204e0c1ec 100644 --- a/src/plugins/plugins.cpp +++ b/src/plugins/plugins.cpp @@ -28,14 +28,48 @@ Plugins::Plugins(QObject* parent) : QObject(parent) + , m_pluginsLoaded(false) { loadSettings(); } +void Plugins::loadPlugin(Plugins::Plugin* plugin) +{ + if (plugin->isLoaded()) { + return; + } + + plugin->pluginLoader->setFileName(plugin->fullPath); + PluginInterface* iPlugin = qobject_cast(plugin->pluginLoader->instance()); + if (!iPlugin) { + return; + } + + m_availablePlugins.removeOne(*plugin); + plugin->instance = initPlugin(iPlugin, plugin->pluginLoader); + m_availablePlugins.append(*plugin); + + refreshLoadedPlugins(); +} + +void Plugins::unloadPlugin(Plugins::Plugin *plugin) +{ + if (!plugin->isLoaded()) { + return; + } + + plugin->instance->unload(); + plugin->pluginLoader->unload(); + + m_availablePlugins.removeOne(*plugin); + plugin->instance = 0; + m_availablePlugins.append(*plugin); + + refreshLoadedPlugins(); +} + void Plugins::loadSettings() { - m_allowedPluginFileNames.clear(); - Settings settings; settings.beginGroup("Plugin-Settings"); m_pluginsEnabled = settings.value("EnablePlugins", DEFAULT_ENABLE_PLUGINS).toBool(); @@ -45,55 +79,76 @@ void Plugins::loadSettings() void Plugins::loadPlugins() { - if (!m_pluginsEnabled) { + if (!m_pluginsEnabled || m_pluginsLoaded) { return; } - m_availablePluginFileNames.clear(); - loadedPlugins.clear(); + m_pluginsLoaded = true; - QDir pluginsDir = QDir(mApp->PLUGINSDIR); + QStringList dirs; + dirs << mApp->PLUGINSDIR +#ifdef Q_WS_X11 + << "/usr/lib/qupzilla/" +#endif + << mApp->PROFILEDIR + "plugins/"; - foreach(const QString & fileName, pluginsDir.entryList(QDir::Files)) { - m_availablePluginFileNames.append(fileName); - - if (!m_allowedPluginFileNames.contains(fileName)) { - continue; - } - - QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); - QObject* plugin = loader.instance(); - if (plugin) { - PluginInterface* iPlugin = qobject_cast(plugin); - iPlugin->init(mApp->getActiveProfilPath() + "plugins.ini"); - if (!iPlugin->testPlugin()) { - loader.unload(); + foreach(const QString & dir, dirs) { + QDir pluginsDir = QDir(dir); + foreach(const QString & fileName, pluginsDir.entryList(QDir::Files)) { + QPluginLoader* loader = new QPluginLoader(pluginsDir.absoluteFilePath(fileName)); + PluginInterface* iPlugin = qobject_cast(loader->instance()); + if (!iPlugin) { continue; } - qApp->installTranslator(iPlugin->getTranslator(mApp->getActiveLanguage())); - loadedPlugins.append(iPlugin); - m_loadedPluginFileNames.append(fileName); + Plugin plugin; + plugin.fileName = fileName; + plugin.fullPath = pluginsDir.absoluteFilePath(fileName); + plugin.pluginSpec = iPlugin->pluginSpec(); + plugin.pluginLoader = loader; + plugin.instance = 0; + + if (m_allowedPluginFileNames.contains(fileName)) { + plugin.instance = initPlugin(iPlugin, loader); + } + else { + loader->unload(); + } + + m_availablePlugins.append(plugin); } } - std::cout << loadedPlugins.count() << " plugins loaded" << std::endl; + refreshLoadedPlugins(); + + std::cout << m_loadedPlugins.count() << " plugins loaded" << std::endl; } -PluginInterface* Plugins::getPlugin(QString pluginFileName) +PluginInterface* Plugins::initPlugin(PluginInterface* interface, QPluginLoader* loader) { - QString path = mApp->PLUGINSDIR + pluginFileName; - if (!QFile::exists(path)) { + if (!interface) { return 0; } - QPluginLoader loader(path); - QObject* plugin = loader.instance(); - if (plugin) { - PluginInterface* iPlugin = qobject_cast(plugin); - return iPlugin; - } - else { + interface->init(mApp->getActiveProfilPath() + "plugins.ini"); + + if (!interface->testPlugin()) { + interface->unload(); + loader->unload(); return 0; } + + qApp->installTranslator(interface->getTranslator(mApp->getActiveLanguage())); + return interface; +} + +void Plugins::refreshLoadedPlugins() +{ + m_loadedPlugins.clear(); + + foreach(const Plugin &plugin, m_availablePlugins) { + if (plugin.isLoaded()) { + m_loadedPlugins.append(plugin.instance); + } + } } diff --git a/src/plugins/plugins.h b/src/plugins/plugins.h index 48c75eda8..f5cd768a5 100644 --- a/src/plugins/plugins.h +++ b/src/plugins/plugins.h @@ -22,34 +22,59 @@ #include #include #include +#include -#include #include +#include "plugininterface.h" -class PluginInterface; class Plugins : public QObject { Q_OBJECT public: + struct Plugin { + QString fileName; + QString fullPath; + PluginSpec pluginSpec; + QPluginLoader* pluginLoader; + PluginInterface* instance; + + bool isLoaded() const { + return instance; + } + + bool operator==(const Plugin &other) { + return (this->fileName == other.fileName && + this->fullPath == other.fullPath && + this->pluginSpec == other.pluginSpec && + this->instance == other.instance); + } + }; + explicit Plugins(QObject* parent = 0); - QStringList getAvailablePlugins() { return m_availablePluginFileNames; } - QStringList getAllowedPlugins() { return m_allowedPluginFileNames; } - PluginInterface* getPlugin(QString pluginFileName); - //void setPluginsAllowed(bool state) { pluginsEnabled = state; qDebug() << state;} + QList getAvailablePlugins() { return m_availablePlugins; } + + void loadPlugin(Plugin* plugin); + void unloadPlugin(Plugin *plugin); public slots: void loadSettings(); void loadPlugins(); protected: - QList loadedPlugins; + QList m_loadedPlugins; private: - QStringList m_availablePluginFileNames; + PluginInterface* initPlugin(PluginInterface* interface, QPluginLoader* loader); + void refreshLoadedPlugins(); + + QList m_availablePlugins; QStringList m_allowedPluginFileNames; - QStringList m_loadedPluginFileNames; + bool m_pluginsEnabled; + bool m_pluginsLoaded; }; +Q_DECLARE_METATYPE(Plugins::Plugin) + #endif // PLUGINLOADER_H diff --git a/src/preferences/pluginslist.cpp b/src/preferences/pluginslist.cpp index 9f5fc0cd8..725c3da40 100644 --- a/src/preferences/pluginslist.cpp +++ b/src/preferences/pluginslist.cpp @@ -35,18 +35,17 @@ PluginsList::PluginsList(QWidget* parent) ui->setupUi(this); //Application Extensions - refresh(); - connect(ui->butSettings, SIGNAL(clicked()), this, SLOT(settingsClicked())); - connect(ui->list, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT(currentChanged(QListWidgetItem*))); - connect(ui->butLoad, SIGNAL(clicked()), this, SLOT(reloadPlugins())); - connect(ui->allowAppPlugins, SIGNAL(clicked(bool)), this, SLOT(allowAppPluginsChanged(bool))); - Settings settings; settings.beginGroup("Plugin-Settings"); ui->allowAppPlugins->setChecked(settings.value("EnablePlugins", DEFAULT_ENABLE_PLUGINS).toBool()); settings.endGroup(); allowAppPluginsChanged(ui->allowAppPlugins->isChecked()); + connect(ui->butSettings, SIGNAL(clicked()), this, SLOT(settingsClicked())); + connect(ui->list, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT(currentChanged(QListWidgetItem*))); + connect(ui->list, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); + connect(ui->allowAppPlugins, SIGNAL(clicked(bool)), this, SLOT(allowAppPluginsChanged(bool))); + //WebKit Plugins connect(ui->add, SIGNAL(clicked()), this, SLOT(addWhitelist())); connect(ui->remove, SIGNAL(clicked()), this, SLOT(removeWhitelist())); @@ -60,6 +59,7 @@ PluginsList::PluginsList(QWidget* parent) QTreeWidgetItem* item = new QTreeWidgetItem(ui->whitelist); item->setText(0, site); } + allowC2FChanged(ui->allowClick2Flash->isChecked()); } @@ -87,12 +87,22 @@ void PluginsList::removeWhitelist() void PluginsList::save() { + QStringList allowedPlugins; + for (int i = 0; i < ui->list->count(); i++) { + QListWidgetItem* item = ui->list->item(i); + + if (item->checkState() == Qt::Checked) { + const Plugins::Plugin &plugin = item->data(Qt::UserRole + 10).value(); + + allowedPlugins.append(plugin.fileName); + } + } + Settings settings; settings.beginGroup("Plugin-Settings"); settings.setValue("EnablePlugins", ui->allowAppPlugins->isChecked()); + settings.setValue("AllowedPlugins", allowedPlugins); settings.endGroup(); - - reloadPlugins(); } void PluginsList::allowAppPluginsChanged(bool state) @@ -102,7 +112,14 @@ void PluginsList::allowAppPluginsChanged(bool state) settings.setValue("EnablePlugins", state); settings.endGroup(); - ui->verticalFrame->setEnabled(state); + mApp->plugins()->loadSettings(); + mApp->plugins()->loadPlugins(); + + ui->list->setEnabled(state); + + if (state) { + refresh(); + } } void PluginsList::allowC2FChanged(bool state) @@ -123,32 +140,31 @@ void PluginsList::refresh() { ui->list->clear(); ui->butSettings->setEnabled(false); + disconnect(ui->list, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); - QStringList availablePlugins = mApp->plugins()->getAvailablePlugins(); - QStringList allowedPlugins = mApp->plugins()->getAllowedPlugins(); - foreach(const QString & fileName, availablePlugins) { - PluginInterface* plugin = mApp->plugins()->getPlugin(fileName); - if (!plugin) { - continue; - } + const QList &allPlugins = mApp->plugins()->getAvailablePlugins(); + + foreach(const Plugins::Plugin & plugin, allPlugins) { + PluginSpec spec = plugin.pluginSpec; QListWidgetItem* item = new QListWidgetItem(ui->list); - item->setText("" + plugin->pluginName() + " (" + plugin->pluginVersion() + ") by " + plugin->pluginAuthor() + "\n" - + plugin->pluginInfo() + "\n" + plugin->pluginDescription()); + QString pluginInfo = tr("%1 (%2)\nAuthor: %3\n%4\n%5").arg(spec.name, spec.version, spec.author, spec.info, spec.description); + item->setText(pluginInfo); - QIcon icon = plugin->pluginIcon(); + QIcon icon = spec.icon; if (icon.isNull()) { icon = QIcon(":/icons/preferences/extension.png"); } item->setIcon(icon); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - item->setCheckState((allowedPlugins.contains(fileName)) ? Qt::Checked : Qt::Unchecked); - item->setWhatsThis(plugin->hasSettings() ? "1" : "0"); - item->setToolTip(fileName); + item->setCheckState(plugin.isLoaded() ? Qt::Checked : Qt::Unchecked); + item->setData(Qt::UserRole + 10, qVariantFromValue(plugin)); ui->list->addItem(item); } + + connect(ui->list, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); } void PluginsList::currentChanged(QListWidgetItem* item) @@ -157,50 +173,64 @@ void PluginsList::currentChanged(QListWidgetItem* item) return; } - QString has = item->whatsThis(); - bool show; - if (has == "1") { - show = true; + const Plugins::Plugin &plugin = item->data(Qt::UserRole + 10).value(); + bool showSettings = plugin.pluginSpec.hasSettings; + + if (!plugin.isLoaded()) { + showSettings = false; + } + + ui->butSettings->setEnabled(showSettings); +} + +void PluginsList::itemChanged(QListWidgetItem *item) +{ + if (!item) { + return; + } + + Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value(); + + if (item->checkState() == Qt::Checked) { + mApp->plugins()->loadPlugin(&plugin); } else { - show = false; + mApp->plugins()->unloadPlugin(&plugin); } - if (item->checkState() == Qt::Unchecked) { - show = false; + disconnect(ui->list, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); + + if (item->checkState() == Qt::Checked && !plugin.isLoaded()) { + item->setCheckState(Qt::Unchecked); + QMessageBox::critical(this, tr("Error!"), tr("Cannot load plugin!")); } - ui->butSettings->setEnabled(show); + item->setData(Qt::UserRole + 10, qVariantFromValue(plugin)); + + connect(ui->list, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); + + + currentChanged(ui->list->currentItem()); } void PluginsList::settingsClicked() { - if (!ui->list->currentItem()) { + QListWidgetItem* item = ui->list->currentItem(); + if (!item) { return; } - QString name = ui->list->currentItem()->toolTip(); - PluginInterface* plugin = mApp->plugins()->getPlugin(name); - plugin->showSettings(); -} + Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value(); -void PluginsList::reloadPlugins() -{ - QStringList allowedPlugins; - for (int i = 0; i < ui->list->count(); i++) { - if (ui->list->item(i)->checkState() == Qt::Checked) { - allowedPlugins.append(ui->list->item(i)->toolTip()); - } + if (!plugin.isLoaded()) { + mApp->plugins()->loadPlugin(&plugin); + + item->setData(Qt::UserRole + 10, qVariantFromValue(plugin)); } - Settings settings; - settings.beginGroup("Plugin-Settings"); - settings.setValue("AllowedPlugins", allowedPlugins); - settings.endGroup(); - mApp->plugins()->loadSettings(); - mApp->plugins()->loadPlugins(); - - refresh(); + if (plugin.isLoaded()) { + plugin.instance->showSettings(this); + } } PluginsList::~PluginsList() diff --git a/src/preferences/pluginslist.h b/src/preferences/pluginslist.h index fcd78e38e..9e7ae021d 100644 --- a/src/preferences/pluginslist.h +++ b/src/preferences/pluginslist.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace Ui { @@ -36,14 +37,13 @@ public: ~PluginsList(); void save(); -public slots: - void reloadPlugins(); - private slots: //App extension void settingsClicked(); void currentChanged(QListWidgetItem* item); + void itemChanged(QListWidgetItem* item); void allowAppPluginsChanged(bool state); + //WebKit plugins void addWhitelist(); void removeWhitelist(); @@ -51,6 +51,7 @@ private slots: private: void refresh(); + Ui::PluginsList* ui; }; diff --git a/src/preferences/pluginslist.ui b/src/preferences/pluginslist.ui index 25524043b..a534f3871 100644 --- a/src/preferences/pluginslist.ui +++ b/src/preferences/pluginslist.ui @@ -79,23 +79,6 @@ - - - - - 0 - 0 - - - - Load Plugins - - - - :/icons/faenza/reload.png:/icons/faenza/reload.png - - - diff --git a/src/src.pro b/src/src.pro index 927de3495..a0eee8e02 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,13 +1,14 @@ QT += core gui webkit sql network script unix:QT += dbus TARGET = qupzilla -TEMPLATE = app +TEMPLATE = lib include(3rdparty/qtsingleapplication.pri) include(src.pri) -include(../install.pri) include(../defines.pri) -include(../translations.pri) -message(Using following defines) +SOURCES -= main.cpp + +message(========== Building libqupzilla ==========) +message( Using following defines:) message($$DEFINES)