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:
parent
a3e320fb47
commit
7a562a4847
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user