File indexing completed on 2024-05-19 04:59:01
0001 /* ============================================================ 0002 * Falkon - Qt web browser 0003 * Copyright (C) 2010-2018 David Rosca <nowrep@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 "pluginsmanager.h" 0019 #include "ui_pluginslist.h" 0020 #include "pluginproxy.h" 0021 #include "mainapplication.h" 0022 #include "plugininterface.h" 0023 #include "pluginlistdelegate.h" 0024 #include "qztools.h" 0025 #include "settings.h" 0026 #include "iconprovider.h" 0027 #include "../config.h" 0028 0029 #include <QInputDialog> 0030 #include <QMessageBox> 0031 #include <QTimer> 0032 0033 PluginsManager::PluginsManager(QWidget* parent) 0034 : QWidget(parent) 0035 , ui(new Ui::PluginsList) 0036 , m_loaded(false) 0037 { 0038 ui->setupUi(this); 0039 ui->list->setLayoutDirection(Qt::LeftToRight); 0040 ui->butSettings->setIcon(IconProvider::settingsIcon()); 0041 ui->butRemove->setIcon(QIcon::fromTheme(QSL("edit-delete"))); 0042 0043 //Application Extensions 0044 Settings settings; 0045 settings.beginGroup(QSL("Plugin-Settings")); 0046 bool appPluginsEnabled = settings.value(QSL("EnablePlugins"), true).toBool(); 0047 settings.endGroup(); 0048 0049 ui->list->setEnabled(appPluginsEnabled); 0050 0051 connect(ui->butSettings, &QAbstractButton::clicked, this, &PluginsManager::settingsClicked); 0052 connect(ui->butRemove, &QAbstractButton::clicked, this, &PluginsManager::removeClicked); 0053 connect(ui->list, &QListWidget::currentItemChanged, this, &PluginsManager::currentChanged); 0054 connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged); 0055 connect(ui->search, &QLineEdit::textChanged, this, &PluginsManager::addFilter); 0056 connect(mApp->plugins(), &Plugins::availablePluginsChanged, this, &PluginsManager::refresh); 0057 0058 ui->list->setItemDelegate(new PluginListDelegate(ui->list)); 0059 } 0060 0061 void PluginsManager::load() 0062 { 0063 if (!m_loaded) { 0064 refresh(); 0065 m_loaded = true; 0066 } 0067 } 0068 0069 void PluginsManager::save() 0070 { 0071 if (!m_loaded) { 0072 return; 0073 } 0074 0075 QStringList allowedPlugins; 0076 for (int i = 0; i < ui->list->count(); i++) { 0077 QListWidgetItem* item = ui->list->item(i); 0078 0079 if (item->checkState() == Qt::Checked) { 0080 const Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value<Plugins::Plugin>(); 0081 allowedPlugins.append(plugin.pluginId); 0082 } 0083 } 0084 0085 Settings settings; 0086 settings.beginGroup(QSL("Plugin-Settings")); 0087 settings.setValue(QSL("AllowedPlugins"), allowedPlugins); 0088 settings.endGroup(); 0089 } 0090 0091 void PluginsManager::refresh() 0092 { 0093 if (m_blockRefresh) { 0094 return; 0095 } 0096 0097 const int oldCurrentRow = ui->list->currentRow(); 0098 0099 ui->list->clear(); 0100 ui->butSettings->setEnabled(false); 0101 disconnect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged); 0102 0103 const QList<Plugins::Plugin> &allPlugins = mApp->plugins()->availablePlugins(); 0104 0105 for (const Plugins::Plugin &plugin : allPlugins) { 0106 PluginSpec spec = plugin.pluginSpec; 0107 0108 auto* item = new QListWidgetItem(ui->list); 0109 QIcon icon = QIcon(spec.icon); 0110 if (icon.isNull()) { 0111 icon = QIcon(QSL(":/icons/preferences/extensions.svg")); 0112 } 0113 item->setIcon(icon); 0114 0115 const QString pluginInfo = QStringLiteral("<b>%1</b> %2<br/><i>%3</i><br/>").arg(spec.name, spec.version, spec.author.toHtmlEscaped()); 0116 item->setToolTip(pluginInfo); 0117 0118 item->setText(spec.name); 0119 item->setData(Qt::UserRole, spec.version); 0120 item->setData(Qt::UserRole + 1, spec.author); 0121 item->setData(Qt::UserRole + 2, spec.description); 0122 0123 item->setFlags(item->flags() | Qt::ItemIsUserCheckable); 0124 item->setCheckState(plugin.isLoaded() ? Qt::Checked : Qt::Unchecked); 0125 item->setData(Qt::UserRole + 10, QVariant::fromValue(plugin)); 0126 0127 ui->list->addItem(item); 0128 } 0129 0130 sortItems(); 0131 0132 if (oldCurrentRow >= 0) { 0133 ui->list->setCurrentRow(qMax(0, oldCurrentRow - 1)); 0134 ui->list->setFocus(); 0135 } 0136 0137 connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged); 0138 } 0139 0140 void PluginsManager::sortItems() 0141 { 0142 ui->list->sortItems(); 0143 0144 bool itemMoved; 0145 do { 0146 itemMoved = false; 0147 for (int i = 0; i < ui->list->count(); ++i) { 0148 QListWidgetItem* topItem = ui->list->item(i); 0149 QListWidgetItem* bottomItem = ui->list->item(i + 1); 0150 if (!topItem || !bottomItem) { 0151 continue; 0152 } 0153 0154 if (topItem->checkState() == Qt::Unchecked && bottomItem->checkState() == Qt::Checked) { 0155 QListWidgetItem* item = ui->list->takeItem(i + 1); 0156 ui->list->insertItem(i, item); 0157 itemMoved = true; 0158 } 0159 } 0160 } 0161 while (itemMoved); 0162 } 0163 0164 void PluginsManager::currentChanged(QListWidgetItem* item) 0165 { 0166 if (!item) { 0167 return; 0168 } 0169 0170 const Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value<Plugins::Plugin>(); 0171 ui->butSettings->setEnabled(plugin.isLoaded() && plugin.pluginSpec.hasSettings); 0172 ui->butRemove->setEnabled(plugin.isRemovable()); 0173 } 0174 0175 void PluginsManager::itemChanged(QListWidgetItem* item) 0176 { 0177 if (!item) { 0178 return; 0179 } 0180 0181 Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value<Plugins::Plugin>(); 0182 0183 m_blockRefresh = true; 0184 0185 if (item->checkState() == Qt::Checked) { 0186 mApp->plugins()->loadPlugin(&plugin); 0187 } 0188 else { 0189 mApp->plugins()->unloadPlugin(&plugin); 0190 } 0191 0192 m_blockRefresh = false; 0193 0194 disconnect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged); 0195 0196 if (item->checkState() == Qt::Checked && !plugin.isLoaded()) { 0197 item->setCheckState(Qt::Unchecked); 0198 QMessageBox::critical(this, tr("Error!"), tr("Cannot load extension!")); 0199 } 0200 0201 item->setData(Qt::UserRole + 10, QVariant::fromValue(plugin)); 0202 0203 connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged); 0204 0205 currentChanged(ui->list->currentItem()); 0206 } 0207 0208 void PluginsManager::settingsClicked() 0209 { 0210 QListWidgetItem* item = ui->list->currentItem(); 0211 if (!item || item->checkState() == Qt::Unchecked) { 0212 return; 0213 } 0214 0215 Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value<Plugins::Plugin>(); 0216 0217 if (!plugin.isLoaded()) { 0218 mApp->plugins()->loadPlugin(&plugin); 0219 0220 item->setData(Qt::UserRole + 10, QVariant::fromValue(plugin)); 0221 } 0222 0223 if (plugin.isLoaded() && plugin.pluginSpec.hasSettings) { 0224 plugin.instance->showSettings(this); 0225 } 0226 } 0227 0228 void PluginsManager::removeClicked() 0229 { 0230 QListWidgetItem* item = ui->list->currentItem(); 0231 if (!item) { 0232 return; 0233 } 0234 0235 Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value<Plugins::Plugin>(); 0236 0237 const auto button = QMessageBox::warning(this, tr("Confirmation"), 0238 tr("Are you sure you want to remove '%1'?").arg(plugin.pluginSpec.name), 0239 QMessageBox::Yes | QMessageBox::No); 0240 if (button != QMessageBox::Yes) { 0241 return; 0242 } 0243 0244 mApp->plugins()->removePlugin(&plugin); 0245 } 0246 0247 void PluginsManager::addFilter(const QString& filter) { 0248 for (int i = 0; i < ui->list->count(); ++i) { 0249 const QString& pluginName = ui->list->item(i)->text(); 0250 0251 if (pluginName.contains(filter,Qt::CaseInsensitive) || !filter.size()) { 0252 ui->list->item(i)->setHidden(false); 0253 } 0254 else { 0255 ui->list->item(i)->setHidden(true); 0256 } 0257 } 0258 } 0259 0260 PluginsManager::~PluginsManager() 0261 { 0262 delete ui; 0263 }