1
mirror of https://invent.kde.org/network/falkon.git synced 2024-12-20 02:36:34 +01:00

Plugins: Implement removing locally installed plugins

This commit is contained in:
David Rosca 2019-04-18 11:28:10 +02:00
parent a3e320fb47
commit 7a562a4847
No known key found for this signature in database
GPG Key ID: EBC3FC294452C6D8
8 changed files with 91 additions and 33 deletions

View File

@ -356,7 +356,7 @@ QString FalkonSchemeReply::configPage()
page.replace(QLatin1String("%USER-AGENT%"), mApp->webProfile()->httpUserAgent());
QString pluginsString;
const QList<Plugins::Plugin> &availablePlugins = mApp->plugins()->getAvailablePlugins();
const QList<Plugins::Plugin> &availablePlugins = mApp->plugins()->availablePlugins();
foreach (const Plugins::Plugin &plugin, availablePlugins) {
PluginSpec spec = plugin.pluginSpec;

View File

@ -28,10 +28,28 @@
#include "qml/qmlplugin.h"
#include <iostream>
#include <QPluginLoader>
#include <QDir>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QFileInfo>
bool Plugins::Plugin::isLoaded() const
{
return instance;
}
bool Plugins::Plugin::isRemovable() const
{
return !pluginPath.isEmpty() && QFileInfo(pluginPath).isWritable();
}
bool Plugins::Plugin::operator==(const Plugin &other) const
{
return type == other.type &&
pluginId == other.pluginId;
}
Plugins::Plugins(QObject* parent)
: QObject(parent)
@ -45,10 +63,9 @@ Plugins::Plugins(QObject* parent)
}
}
QList<Plugins::Plugin> Plugins::getAvailablePlugins()
QList<Plugins::Plugin> Plugins::availablePlugins()
{
loadAvailablePlugins();
return m_availablePlugins;
}
@ -88,24 +105,30 @@ void Plugins::unloadPlugin(Plugins::Plugin* plugin)
void Plugins::removePlugin(Plugins::Plugin *plugin)
{
if (plugin->type != Plugin::QmlPlugin) {
if (!plugin->isRemovable()) {
return;
}
if (plugin->isLoaded()) {
unloadPlugin(plugin);
}
// For QML plugins, pluginId is qml:<plugin-dir-name>
const QString dirName = plugin->pluginId.mid(4);
const QString dirPath = DataPaths::locate(DataPaths::Plugins, QSL("qml/") + dirName);
bool result = QDir(dirPath).removeRecursively();
bool result = false;
QFileInfo info(plugin->pluginPath);
if (info.isDir()) {
result = QDir(plugin->pluginPath).removeRecursively();
} else if (info.isFile()) {
result = QFile::remove(plugin->pluginPath);
}
if (!result) {
qWarning() << "Unable to remove" << plugin->pluginSpec.name;
qWarning() << "Failed to remove" << plugin->pluginSpec.name;
return;
}
m_availablePlugins.removeOne(*plugin);
refreshedLoadedPlugins();
emit availablePluginsChanged();
}
void Plugins::loadSettings()
@ -233,7 +256,7 @@ void Plugins::loadAvailablePlugins()
// QmlPlugin
for (QString dir : dirs) {
// qml plugins will be loaded from subdirectory qml
// Qml plugins will be loaded from subdirectory qml
dir.append(QSL("/qml"));
const auto qmlDirs = QDir(dir).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo &info : qmlDirs) {
@ -267,7 +290,7 @@ void Plugins::refreshLoadedPlugins()
}
}
emit refreshedLoadedPlugins();
emit availablePluginsChanged();
}
void Plugins::loadPythonSupport()
@ -369,7 +392,7 @@ Plugins::Plugin Plugins::loadSharedLibraryPlugin(const QString &name)
Plugin plugin;
plugin.type = Plugin::SharedLibraryPlugin;
plugin.pluginId = QSL("lib:%1").arg(QFileInfo(fullPath).fileName());
plugin.libraryPath = fullPath;
plugin.pluginPath = fullPath;
plugin.pluginLoader = loader;
plugin.pluginSpec = createSpec(iPlugin->metaData());
return plugin;

View File

@ -60,6 +60,7 @@ public:
};
Type type = Invalid;
QString pluginId;
QString pluginPath;
PluginSpec pluginSpec;
PluginInterface *instance = nullptr;
@ -67,25 +68,19 @@ public:
PluginInterface *internalInstance = nullptr;
// SharedLibraryPlugin
QString libraryPath;
QPluginLoader *pluginLoader = nullptr;
// Other
QVariant data;
bool isLoaded() const {
return instance;
}
bool operator==(const Plugin &other) const {
return this->type == other.type &&
this->pluginId == other.pluginId;
}
bool isLoaded() const;
bool isRemovable() const;
bool operator==(const Plugin &other) const;
};
explicit Plugins(QObject* parent = 0);
QList<Plugin> getAvailablePlugins();
QList<Plugin> availablePlugins();
bool loadPlugin(Plugin* plugin);
void unloadPlugin(Plugin* plugin);
@ -108,7 +103,7 @@ protected:
Q_SIGNALS:
void pluginUnloaded(PluginInterface* plugin);
void refreshedLoadedPlugins();
void availablePluginsChanged();
private:
void loadPythonSupport();

View File

@ -50,6 +50,7 @@ Plugins::Plugin QmlPlugin::loadPlugin(const QString &name)
Plugins::Plugin plugin;
plugin.type = Plugins::Plugin::QmlPlugin;
plugin.pluginId = QSL("qml:%1").arg(QFileInfo(name).fileName());
plugin.pluginPath = fullPath;
DesktopFile desktopFile(fullPath + QSL("/metadata.desktop"));
plugin.pluginSpec = Plugins::createSpec(desktopFile);
QString entryPoint = desktopFile.value(QSL("X-Falkon-EntryPoint")).toString();

View File

@ -70,6 +70,16 @@
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="butRemove">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@ -38,6 +38,7 @@ PluginsManager::PluginsManager(QWidget* parent)
ui->setupUi(this);
ui->list->setLayoutDirection(Qt::LeftToRight);
ui->butSettings->setIcon(IconProvider::settingsIcon());
ui->butRemove->setIcon(QIcon::fromTheme(QSL("edit-delete")));
//Application Extensions
Settings settings;
@ -48,8 +49,10 @@ PluginsManager::PluginsManager(QWidget* parent)
ui->list->setEnabled(appPluginsEnabled);
connect(ui->butSettings, &QAbstractButton::clicked, this, &PluginsManager::settingsClicked);
connect(ui->butRemove, &QAbstractButton::clicked, this, &PluginsManager::removeClicked);
connect(ui->list, &QListWidget::currentItemChanged, this, &PluginsManager::currentChanged);
connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
connect(mApp->plugins(), &Plugins::availablePluginsChanged, this, &PluginsManager::refresh);
ui->list->setItemDelegate(new PluginListDelegate(ui->list));
}
@ -86,11 +89,17 @@ void PluginsManager::save()
void PluginsManager::refresh()
{
if (m_blockRefresh) {
return;
}
const int oldCurrentRow = ui->list->currentRow();
ui->list->clear();
ui->butSettings->setEnabled(false);
disconnect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
const QList<Plugins::Plugin> &allPlugins = mApp->plugins()->getAvailablePlugins();
const QList<Plugins::Plugin> &allPlugins = mApp->plugins()->availablePlugins();
foreach (const Plugins::Plugin &plugin, allPlugins) {
PluginSpec spec = plugin.pluginSpec;
@ -119,6 +128,11 @@ void PluginsManager::refresh()
sortItems();
if (oldCurrentRow >= 0) {
ui->list->setCurrentRow(qMax(0, oldCurrentRow - 1));
ui->list->setFocus();
}
connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
}
@ -153,13 +167,8 @@ void PluginsManager::currentChanged(QListWidgetItem* item)
}
const Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value<Plugins::Plugin>();
bool showSettings = plugin.pluginSpec.hasSettings;
if (!plugin.isLoaded()) {
showSettings = false;
}
ui->butSettings->setEnabled(showSettings);
ui->butSettings->setEnabled(plugin.isLoaded() && plugin.pluginSpec.hasSettings);
ui->butRemove->setEnabled(plugin.isRemovable());
}
void PluginsManager::itemChanged(QListWidgetItem* item)
@ -170,6 +179,8 @@ void PluginsManager::itemChanged(QListWidgetItem* item)
Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value<Plugins::Plugin>();
m_blockRefresh = true;
if (item->checkState() == Qt::Checked) {
mApp->plugins()->loadPlugin(&plugin);
}
@ -177,6 +188,8 @@ void PluginsManager::itemChanged(QListWidgetItem* item)
mApp->plugins()->unloadPlugin(&plugin);
}
m_blockRefresh = false;
disconnect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
if (item->checkState() == Qt::Checked && !plugin.isLoaded()) {
@ -188,7 +201,6 @@ void PluginsManager::itemChanged(QListWidgetItem* item)
connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
currentChanged(ui->list->currentItem());
}
@ -212,6 +224,20 @@ void PluginsManager::settingsClicked()
}
}
void PluginsManager::removeClicked()
{
QListWidgetItem* item = ui->list->currentItem();
if (!item) {
return;
}
Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value<Plugins::Plugin>();
if (plugin.isRemovable()) {
mApp->plugins()->removePlugin(&plugin);
}
}
PluginsManager::~PluginsManager()
{
delete ui;

View File

@ -42,6 +42,7 @@ public:
private Q_SLOTS:
void settingsClicked();
void removeClicked();
void currentChanged(QListWidgetItem* item);
void itemChanged(QListWidgetItem* item);
@ -52,6 +53,7 @@ private:
Ui::PluginsList* ui;
bool m_loaded;
bool m_blockRefresh = false;
};
#endif // PLUGINSMANAGER_H

View File

@ -107,6 +107,7 @@ Plugins::Plugin pyfalkon_load_plugin(const QString &name)
Plugins::Plugin plugin;
plugin.type = Plugins::Plugin::PythonPlugin;
plugin.pluginId = QSL("python:%1").arg(QFileInfo(name).fileName());
plugin.pluginPath = fullPath;
plugin.pluginSpec = Plugins::createSpec(DesktopFile(fullPath + QSL("/metadata.desktop")));
return plugin;
}