diff --git a/src/lib/plugins/plugins.cpp b/src/lib/plugins/plugins.cpp index ae3ea7f6..335e4149 100644 --- a/src/lib/plugins/plugins.cpp +++ b/src/lib/plugins/plugins.cpp @@ -1,242 +1,237 @@ /* ============================================================ * Falkon - Qt web browser * Copyright (C) 2010-2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #include "pluginproxy.h" #include "plugininterface.h" #include "mainapplication.h" #include "speeddial.h" #include "settings.h" #include "datapaths.h" #include "adblock/adblockplugin.h" #include #include #include Plugins::Plugins(QObject* parent) : QObject(parent) , m_pluginsLoaded(false) , m_speedDial(new SpeedDial(this)) { loadSettings(); } QList Plugins::getAvailablePlugins() { loadAvailablePlugins(); return m_availablePlugins; } bool Plugins::loadPlugin(Plugins::Plugin* plugin) { if (plugin->isLoaded()) { return true; } plugin->pluginLoader->setFileName(plugin->fullPath); PluginInterface* iPlugin = qobject_cast(plugin->pluginLoader->instance()); if (!iPlugin) { return false; } m_availablePlugins.removeOne(*plugin); plugin->instance = initPlugin(PluginInterface::LateInitState, iPlugin, plugin->pluginLoader); m_availablePlugins.prepend(*plugin); refreshLoadedPlugins(); return plugin->isLoaded(); } void Plugins::unloadPlugin(Plugins::Plugin* plugin) { if (!plugin->isLoaded()) { return; } plugin->instance->unload(); plugin->pluginLoader->unload(); emit pluginUnloaded(plugin->instance); m_availablePlugins.removeOne(*plugin); plugin->instance = 0; m_availablePlugins.append(*plugin); refreshLoadedPlugins(); } void Plugins::loadSettings() { Settings settings; settings.beginGroup("Plugin-Settings"); - m_pluginsEnabled = settings.value("EnablePlugins", true).toBool(); m_allowedPlugins = settings.value("AllowedPlugins", QStringList()).toStringList(); settings.endGroup(); // Plugins are saved with relative path in portable mode #ifdef NO_SYSTEM_DATAPATH if (true) { #else if (mApp->isPortable()) { #endif QDir dir(DataPaths::path(DataPaths::Plugins)); for (int i = 0; i < m_allowedPlugins.count(); ++i) m_allowedPlugins[i] = dir.absoluteFilePath(QFileInfo(m_allowedPlugins[i]).fileName()); } } void Plugins::shutdown() { foreach (PluginInterface* iPlugin, m_loadedPlugins) { iPlugin->unload(); } } void Plugins::loadPlugins() { - if (!m_pluginsEnabled) { - return; - } - QDir settingsDir(DataPaths::currentProfilePath() + "/extensions/"); if (!settingsDir.exists()) { settingsDir.mkdir(settingsDir.absolutePath()); } foreach (const QString &fullPath, m_allowedPlugins) { QPluginLoader* loader = new QPluginLoader(fullPath); PluginInterface* iPlugin = qobject_cast(loader->instance()); if (!iPlugin) { qWarning() << "Plugins::loadPlugins Loading" << fullPath << "failed:" << loader->errorString(); continue; } Plugin plugin; plugin.fileName = QFileInfo(fullPath).fileName(); plugin.fullPath = fullPath; plugin.pluginLoader = loader; plugin.instance = initPlugin(PluginInterface::StartupInitState, iPlugin, loader); if (plugin.isLoaded()) { plugin.pluginSpec = iPlugin->pluginSpec(); m_availablePlugins.append(plugin); } } // Internal plugins AdBlockPlugin *adBlock = new AdBlockPlugin(); if (initPlugin(PluginInterface::StartupInitState, adBlock, nullptr)) { m_internalPlugins.append(adBlock); } refreshLoadedPlugins(); std::cout << "Falkon: " << (m_loadedPlugins.count() - m_internalPlugins.count()) << " extensions loaded" << std::endl; } void Plugins::loadAvailablePlugins() { if (m_pluginsLoaded) { return; } m_pluginsLoaded = true; QStringList dirs = DataPaths::allPaths(DataPaths::Plugins); // Portable build: Load only plugins from DATADIR/plugins/ directory. #ifndef NO_SYSTEM_DATAPATH if (mApp->isPortable()) #endif dirs = QStringList(DataPaths::path(DataPaths::Plugins)); foreach (const QString &dir, dirs) { QDir pluginsDir = QDir(dir); foreach (const QString &fileName, pluginsDir.entryList(QDir::Files)) { const QString absolutePath = pluginsDir.absoluteFilePath(fileName); QPluginLoader* loader = new QPluginLoader(absolutePath); PluginInterface* iPlugin = qobject_cast(loader->instance()); if (!iPlugin) { qWarning() << "Plugins::loadAvailablePlugins" << loader->errorString(); continue; } Plugin plugin; plugin.fileName = fileName; plugin.fullPath = absolutePath; plugin.pluginSpec = iPlugin->pluginSpec(); plugin.pluginLoader = loader; plugin.instance = 0; loader->unload(); if (!alreadySpecInAvailable(plugin.pluginSpec)) { m_availablePlugins.append(plugin); } } } } PluginInterface* Plugins::initPlugin(PluginInterface::InitState state, PluginInterface* pluginInterface, QPluginLoader* loader) { if (!pluginInterface) { return 0; } pluginInterface->init(state, DataPaths::currentProfilePath() + QL1S("/extensions")); if (!pluginInterface->testPlugin()) { pluginInterface->unload(); if (loader) { loader->unload(); } emit pluginUnloaded(pluginInterface); return 0; } qApp->installTranslator(pluginInterface->getTranslator(mApp->currentLanguageFile())); return pluginInterface; } void Plugins::refreshLoadedPlugins() { m_loadedPlugins = m_internalPlugins; foreach (const Plugin &plugin, m_availablePlugins) { if (plugin.isLoaded()) { m_loadedPlugins.append(plugin.instance); } } } bool Plugins::alreadySpecInAvailable(const PluginSpec &spec) { foreach (const Plugin &plugin, m_availablePlugins) { if (plugin.pluginSpec == spec) { return true; } } return false; } diff --git a/src/lib/plugins/plugins.h b/src/lib/plugins/plugins.h index d4ad5025..4e20d637 100644 --- a/src/lib/plugins/plugins.h +++ b/src/lib/plugins/plugins.h @@ -1,102 +1,101 @@ /* ============================================================ * Falkon - Qt web browser * Copyright (C) 2010-2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #ifndef PLUGINLOADER_H #define PLUGINLOADER_H #include #include #include #include "qzcommon.h" #include "plugininterface.h" class QPluginLoader; class SpeedDial; class FALKON_EXPORT Plugins : public QObject { Q_OBJECT public: struct Plugin { QString fileName; QString fullPath; PluginSpec pluginSpec; QPluginLoader* pluginLoader; PluginInterface* instance; Plugin() { pluginLoader = 0; instance = 0; } bool isLoaded() const { return instance; } bool operator==(const Plugin &other) const { return (this->fileName == other.fileName && this->fullPath == other.fullPath && this->pluginSpec == other.pluginSpec && this->instance == other.instance); } }; explicit Plugins(QObject* parent = 0); QList getAvailablePlugins(); bool loadPlugin(Plugin* plugin); void unloadPlugin(Plugin* plugin); void shutdown(); // SpeedDial SpeedDial* speedDial() { return m_speedDial; } public slots: void loadSettings(); void loadPlugins(); protected: QList m_loadedPlugins; signals: void pluginUnloaded(PluginInterface* plugin); private: bool alreadySpecInAvailable(const PluginSpec &spec); PluginInterface* initPlugin(PluginInterface::InitState state , PluginInterface* pluginInterface, QPluginLoader* loader); void refreshLoadedPlugins(); void loadAvailablePlugins(); QList m_availablePlugins; QStringList m_allowedPlugins; - bool m_pluginsEnabled; bool m_pluginsLoaded; SpeedDial* m_speedDial; QList m_internalPlugins; }; Q_DECLARE_METATYPE(Plugins::Plugin) #endif // PLUGINLOADER_H diff --git a/src/lib/preferences/pluginslist.ui b/src/lib/preferences/pluginslist.ui index bc23e292..b9e0e441 100644 --- a/src/lib/preferences/pluginslist.ui +++ b/src/lib/preferences/pluginslist.ui @@ -1,86 +1,79 @@ PluginsList 0 0 623 462 0 0 0 0 - - - - Allow Application Extensions to be loaded - - - true QAbstractItemView::ScrollPerPixel true true false 0 0 Settings Qt::Horizontal 40 20 diff --git a/src/lib/preferences/pluginsmanager.cpp b/src/lib/preferences/pluginsmanager.cpp index 8b11aac5..b03c0a71 100644 --- a/src/lib/preferences/pluginsmanager.cpp +++ b/src/lib/preferences/pluginsmanager.cpp @@ -1,250 +1,226 @@ /* ============================================================ * Falkon - Qt web browser * Copyright (C) 2010-2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #include "pluginsmanager.h" #include "ui_pluginslist.h" #include "pluginproxy.h" #include "mainapplication.h" #include "plugininterface.h" #include "pluginlistdelegate.h" #include "qztools.h" #include "settings.h" #include "iconprovider.h" #include #include #include PluginsManager::PluginsManager(QWidget* parent) : QWidget(parent) , ui(new Ui::PluginsList) , m_loaded(false) { ui->setupUi(this); ui->list->setLayoutDirection(Qt::LeftToRight); ui->butSettings->setIcon(IconProvider::settingsIcon()); //Application Extensions Settings settings; settings.beginGroup("Plugin-Settings"); bool appPluginsEnabled = settings.value("EnablePlugins", true).toBool(); settings.endGroup(); - ui->allowAppPlugins->setChecked(appPluginsEnabled); ui->list->setEnabled(appPluginsEnabled); 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))); ui->list->setItemDelegate(new PluginListDelegate(ui->list)); } void PluginsManager::load() { if (!m_loaded) { refresh(); m_loaded = true; } } void PluginsManager::save() { if (!m_loaded) { return; } 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(); // Save plugins with relative path in portable mode #ifdef NO_SYSTEM_DATAPATH if (true) #else if (mApp->isPortable()) #endif allowedPlugins.append(plugin.fileName); else allowedPlugins.append(plugin.fullPath); } } Settings settings; settings.beginGroup("Plugin-Settings"); - settings.setValue("EnablePlugins", ui->allowAppPlugins->isChecked()); settings.setValue("AllowedPlugins", allowedPlugins); settings.endGroup(); } -void PluginsManager::allowAppPluginsChanged(bool state) -{ - ui->list->setEnabled(state); - - if (!state) { - for (int i = 0; i < ui->list->count(); i++) { - QListWidgetItem* item = ui->list->item(i); - - if (item->checkState() == Qt::Checked) { - item->setCheckState(Qt::Unchecked); - } - } - } - - refresh(); -} - void PluginsManager::refresh() { - if (!ui->allowAppPlugins->isChecked()) { - return; - } - ui->list->clear(); ui->butSettings->setEnabled(false); disconnect(ui->list, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); const QList &allPlugins = mApp->plugins()->getAvailablePlugins(); foreach (const Plugins::Plugin &plugin, allPlugins) { PluginSpec spec = plugin.pluginSpec; QListWidgetItem* item = new QListWidgetItem(ui->list); QIcon icon = QIcon(spec.icon); if (icon.isNull()) { icon = QIcon(QSL(":/icons/preferences/extensions.svg")); } item->setIcon(icon); QString pluginInfo = QString("%1 %2
%3
%4").arg(spec.name, spec.version, spec.author.toHtmlEscaped(), spec.info); item->setToolTip(pluginInfo); item->setText(spec.name); item->setData(Qt::UserRole, spec.version); item->setData(Qt::UserRole + 1, spec.info); item->setData(Qt::UserRole + 2, spec.description); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(plugin.isLoaded() ? Qt::Checked : Qt::Unchecked); item->setData(Qt::UserRole + 10, QVariant::fromValue(plugin)); ui->list->addItem(item); } sortItems(); connect(ui->list, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); } void PluginsManager::sortItems() { ui->list->sortItems(); bool itemMoved; do { itemMoved = false; for (int i = 0; i < ui->list->count(); ++i) { QListWidgetItem* topItem = ui->list->item(i); QListWidgetItem* bottomItem = ui->list->item(i + 1); if (!topItem || !bottomItem) { continue; } if (topItem->checkState() == Qt::Unchecked && bottomItem->checkState() == Qt::Checked) { QListWidgetItem* item = ui->list->takeItem(i + 1); ui->list->insertItem(i, item); itemMoved = true; } } } while (itemMoved); } void PluginsManager::currentChanged(QListWidgetItem* item) { if (!item) { return; } 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 PluginsManager::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 { mApp->plugins()->unloadPlugin(&plugin); } 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 extension!")); } item->setData(Qt::UserRole + 10, QVariant::fromValue(plugin)); connect(ui->list, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); currentChanged(ui->list->currentItem()); } void PluginsManager::settingsClicked() { QListWidgetItem* item = ui->list->currentItem(); if (!item || item->checkState() == Qt::Unchecked) { return; } Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value(); if (!plugin.isLoaded()) { mApp->plugins()->loadPlugin(&plugin); item->setData(Qt::UserRole + 10, QVariant::fromValue(plugin)); } if (plugin.isLoaded() && plugin.pluginSpec.hasSettings) { plugin.instance->showSettings(this); } } PluginsManager::~PluginsManager() { delete ui; } diff --git a/src/lib/preferences/pluginsmanager.h b/src/lib/preferences/pluginsmanager.h index 904f6ed3..2a9a37ee 100644 --- a/src/lib/preferences/pluginsmanager.h +++ b/src/lib/preferences/pluginsmanager.h @@ -1,58 +1,57 @@ /* ============================================================ * Falkon - Qt web browser -* Copyright (C) 2010-2014 David Rosca +* Copyright (C) 2010-2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #ifndef PLUGINSMANAGER_H #define PLUGINSMANAGER_H #include #include "qzcommon.h" namespace Ui { class PluginsList; } class QListWidgetItem; class FALKON_EXPORT PluginsManager : public QWidget { Q_OBJECT public: explicit PluginsManager(QWidget* parent = 0); ~PluginsManager(); void load(); void save(); private slots: void settingsClicked(); void currentChanged(QListWidgetItem* item); void itemChanged(QListWidgetItem* item); - void allowAppPluginsChanged(bool state); void refresh(); private: void sortItems(); Ui::PluginsList* ui; bool m_loaded; }; #endif // PLUGINSMANAGER_H