mirror of
https://invent.kde.org/network/falkon.git
synced 2024-12-20 18:56: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());
|
page.replace(QLatin1String("%USER-AGENT%"), mApp->webProfile()->httpUserAgent());
|
||||||
|
|
||||||
QString pluginsString;
|
QString pluginsString;
|
||||||
const QList<Plugins::Plugin> &availablePlugins = mApp->plugins()->getAvailablePlugins();
|
const QList<Plugins::Plugin> &availablePlugins = mApp->plugins()->availablePlugins();
|
||||||
|
|
||||||
foreach (const Plugins::Plugin &plugin, availablePlugins) {
|
foreach (const Plugins::Plugin &plugin, availablePlugins) {
|
||||||
PluginSpec spec = plugin.pluginSpec;
|
PluginSpec spec = plugin.pluginSpec;
|
||||||
|
@ -28,10 +28,28 @@
|
|||||||
#include "qml/qmlplugin.h"
|
#include "qml/qmlplugin.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <QPluginLoader>
|
#include <QPluginLoader>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
#include <QQmlComponent>
|
#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)
|
Plugins::Plugins(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
@ -45,10 +63,9 @@ Plugins::Plugins(QObject* parent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Plugins::Plugin> Plugins::getAvailablePlugins()
|
QList<Plugins::Plugin> Plugins::availablePlugins()
|
||||||
{
|
{
|
||||||
loadAvailablePlugins();
|
loadAvailablePlugins();
|
||||||
|
|
||||||
return m_availablePlugins;
|
return m_availablePlugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,24 +105,30 @@ void Plugins::unloadPlugin(Plugins::Plugin* plugin)
|
|||||||
|
|
||||||
void Plugins::removePlugin(Plugins::Plugin *plugin)
|
void Plugins::removePlugin(Plugins::Plugin *plugin)
|
||||||
{
|
{
|
||||||
if (plugin->type != Plugin::QmlPlugin) {
|
if (!plugin->isRemovable()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugin->isLoaded()) {
|
if (plugin->isLoaded()) {
|
||||||
unloadPlugin(plugin);
|
unloadPlugin(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For QML plugins, pluginId is qml:<plugin-dir-name>
|
bool result = false;
|
||||||
const QString dirName = plugin->pluginId.mid(4);
|
|
||||||
const QString dirPath = DataPaths::locate(DataPaths::Plugins, QSL("qml/") + dirName);
|
QFileInfo info(plugin->pluginPath);
|
||||||
bool result = QDir(dirPath).removeRecursively();
|
if (info.isDir()) {
|
||||||
|
result = QDir(plugin->pluginPath).removeRecursively();
|
||||||
|
} else if (info.isFile()) {
|
||||||
|
result = QFile::remove(plugin->pluginPath);
|
||||||
|
}
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
qWarning() << "Unable to remove" << plugin->pluginSpec.name;
|
qWarning() << "Failed to remove" << plugin->pluginSpec.name;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_availablePlugins.removeOne(*plugin);
|
m_availablePlugins.removeOne(*plugin);
|
||||||
refreshedLoadedPlugins();
|
emit availablePluginsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plugins::loadSettings()
|
void Plugins::loadSettings()
|
||||||
@ -233,7 +256,7 @@ void Plugins::loadAvailablePlugins()
|
|||||||
|
|
||||||
// QmlPlugin
|
// QmlPlugin
|
||||||
for (QString dir : dirs) {
|
for (QString dir : dirs) {
|
||||||
// qml plugins will be loaded from subdirectory qml
|
// Qml plugins will be loaded from subdirectory qml
|
||||||
dir.append(QSL("/qml"));
|
dir.append(QSL("/qml"));
|
||||||
const auto qmlDirs = QDir(dir).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
const auto qmlDirs = QDir(dir).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
for (const QFileInfo &info : qmlDirs) {
|
for (const QFileInfo &info : qmlDirs) {
|
||||||
@ -267,7 +290,7 @@ void Plugins::refreshLoadedPlugins()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit refreshedLoadedPlugins();
|
emit availablePluginsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plugins::loadPythonSupport()
|
void Plugins::loadPythonSupport()
|
||||||
@ -369,7 +392,7 @@ Plugins::Plugin Plugins::loadSharedLibraryPlugin(const QString &name)
|
|||||||
Plugin plugin;
|
Plugin plugin;
|
||||||
plugin.type = Plugin::SharedLibraryPlugin;
|
plugin.type = Plugin::SharedLibraryPlugin;
|
||||||
plugin.pluginId = QSL("lib:%1").arg(QFileInfo(fullPath).fileName());
|
plugin.pluginId = QSL("lib:%1").arg(QFileInfo(fullPath).fileName());
|
||||||
plugin.libraryPath = fullPath;
|
plugin.pluginPath = fullPath;
|
||||||
plugin.pluginLoader = loader;
|
plugin.pluginLoader = loader;
|
||||||
plugin.pluginSpec = createSpec(iPlugin->metaData());
|
plugin.pluginSpec = createSpec(iPlugin->metaData());
|
||||||
return plugin;
|
return plugin;
|
||||||
|
@ -60,6 +60,7 @@ public:
|
|||||||
};
|
};
|
||||||
Type type = Invalid;
|
Type type = Invalid;
|
||||||
QString pluginId;
|
QString pluginId;
|
||||||
|
QString pluginPath;
|
||||||
PluginSpec pluginSpec;
|
PluginSpec pluginSpec;
|
||||||
PluginInterface *instance = nullptr;
|
PluginInterface *instance = nullptr;
|
||||||
|
|
||||||
@ -67,25 +68,19 @@ public:
|
|||||||
PluginInterface *internalInstance = nullptr;
|
PluginInterface *internalInstance = nullptr;
|
||||||
|
|
||||||
// SharedLibraryPlugin
|
// SharedLibraryPlugin
|
||||||
QString libraryPath;
|
|
||||||
QPluginLoader *pluginLoader = nullptr;
|
QPluginLoader *pluginLoader = nullptr;
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
QVariant data;
|
QVariant data;
|
||||||
|
|
||||||
bool isLoaded() const {
|
bool isLoaded() const;
|
||||||
return instance;
|
bool isRemovable() const;
|
||||||
}
|
bool operator==(const Plugin &other) const;
|
||||||
|
|
||||||
bool operator==(const Plugin &other) const {
|
|
||||||
return this->type == other.type &&
|
|
||||||
this->pluginId == other.pluginId;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Plugins(QObject* parent = 0);
|
explicit Plugins(QObject* parent = 0);
|
||||||
|
|
||||||
QList<Plugin> getAvailablePlugins();
|
QList<Plugin> availablePlugins();
|
||||||
|
|
||||||
bool loadPlugin(Plugin* plugin);
|
bool loadPlugin(Plugin* plugin);
|
||||||
void unloadPlugin(Plugin* plugin);
|
void unloadPlugin(Plugin* plugin);
|
||||||
@ -108,7 +103,7 @@ protected:
|
|||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void pluginUnloaded(PluginInterface* plugin);
|
void pluginUnloaded(PluginInterface* plugin);
|
||||||
void refreshedLoadedPlugins();
|
void availablePluginsChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadPythonSupport();
|
void loadPythonSupport();
|
||||||
|
@ -50,6 +50,7 @@ Plugins::Plugin QmlPlugin::loadPlugin(const QString &name)
|
|||||||
Plugins::Plugin plugin;
|
Plugins::Plugin plugin;
|
||||||
plugin.type = Plugins::Plugin::QmlPlugin;
|
plugin.type = Plugins::Plugin::QmlPlugin;
|
||||||
plugin.pluginId = QSL("qml:%1").arg(QFileInfo(name).fileName());
|
plugin.pluginId = QSL("qml:%1").arg(QFileInfo(name).fileName());
|
||||||
|
plugin.pluginPath = fullPath;
|
||||||
DesktopFile desktopFile(fullPath + QSL("/metadata.desktop"));
|
DesktopFile desktopFile(fullPath + QSL("/metadata.desktop"));
|
||||||
plugin.pluginSpec = Plugins::createSpec(desktopFile);
|
plugin.pluginSpec = Plugins::createSpec(desktopFile);
|
||||||
QString entryPoint = desktopFile.value(QSL("X-Falkon-EntryPoint")).toString();
|
QString entryPoint = desktopFile.value(QSL("X-Falkon-EntryPoint")).toString();
|
||||||
|
@ -70,6 +70,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="butRemove">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -38,6 +38,7 @@ PluginsManager::PluginsManager(QWidget* parent)
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->list->setLayoutDirection(Qt::LeftToRight);
|
ui->list->setLayoutDirection(Qt::LeftToRight);
|
||||||
ui->butSettings->setIcon(IconProvider::settingsIcon());
|
ui->butSettings->setIcon(IconProvider::settingsIcon());
|
||||||
|
ui->butRemove->setIcon(QIcon::fromTheme(QSL("edit-delete")));
|
||||||
|
|
||||||
//Application Extensions
|
//Application Extensions
|
||||||
Settings settings;
|
Settings settings;
|
||||||
@ -48,8 +49,10 @@ PluginsManager::PluginsManager(QWidget* parent)
|
|||||||
ui->list->setEnabled(appPluginsEnabled);
|
ui->list->setEnabled(appPluginsEnabled);
|
||||||
|
|
||||||
connect(ui->butSettings, &QAbstractButton::clicked, this, &PluginsManager::settingsClicked);
|
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::currentItemChanged, this, &PluginsManager::currentChanged);
|
||||||
connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
|
connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
|
||||||
|
connect(mApp->plugins(), &Plugins::availablePluginsChanged, this, &PluginsManager::refresh);
|
||||||
|
|
||||||
ui->list->setItemDelegate(new PluginListDelegate(ui->list));
|
ui->list->setItemDelegate(new PluginListDelegate(ui->list));
|
||||||
}
|
}
|
||||||
@ -86,11 +89,17 @@ void PluginsManager::save()
|
|||||||
|
|
||||||
void PluginsManager::refresh()
|
void PluginsManager::refresh()
|
||||||
{
|
{
|
||||||
|
if (m_blockRefresh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int oldCurrentRow = ui->list->currentRow();
|
||||||
|
|
||||||
ui->list->clear();
|
ui->list->clear();
|
||||||
ui->butSettings->setEnabled(false);
|
ui->butSettings->setEnabled(false);
|
||||||
disconnect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
|
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) {
|
foreach (const Plugins::Plugin &plugin, allPlugins) {
|
||||||
PluginSpec spec = plugin.pluginSpec;
|
PluginSpec spec = plugin.pluginSpec;
|
||||||
@ -119,6 +128,11 @@ void PluginsManager::refresh()
|
|||||||
|
|
||||||
sortItems();
|
sortItems();
|
||||||
|
|
||||||
|
if (oldCurrentRow >= 0) {
|
||||||
|
ui->list->setCurrentRow(qMax(0, oldCurrentRow - 1));
|
||||||
|
ui->list->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
|
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>();
|
const Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value<Plugins::Plugin>();
|
||||||
bool showSettings = plugin.pluginSpec.hasSettings;
|
ui->butSettings->setEnabled(plugin.isLoaded() && plugin.pluginSpec.hasSettings);
|
||||||
|
ui->butRemove->setEnabled(plugin.isRemovable());
|
||||||
if (!plugin.isLoaded()) {
|
|
||||||
showSettings = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->butSettings->setEnabled(showSettings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginsManager::itemChanged(QListWidgetItem* item)
|
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>();
|
Plugins::Plugin plugin = item->data(Qt::UserRole + 10).value<Plugins::Plugin>();
|
||||||
|
|
||||||
|
m_blockRefresh = true;
|
||||||
|
|
||||||
if (item->checkState() == Qt::Checked) {
|
if (item->checkState() == Qt::Checked) {
|
||||||
mApp->plugins()->loadPlugin(&plugin);
|
mApp->plugins()->loadPlugin(&plugin);
|
||||||
}
|
}
|
||||||
@ -177,6 +188,8 @@ void PluginsManager::itemChanged(QListWidgetItem* item)
|
|||||||
mApp->plugins()->unloadPlugin(&plugin);
|
mApp->plugins()->unloadPlugin(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_blockRefresh = false;
|
||||||
|
|
||||||
disconnect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
|
disconnect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
|
||||||
|
|
||||||
if (item->checkState() == Qt::Checked && !plugin.isLoaded()) {
|
if (item->checkState() == Qt::Checked && !plugin.isLoaded()) {
|
||||||
@ -188,7 +201,6 @@ void PluginsManager::itemChanged(QListWidgetItem* item)
|
|||||||
|
|
||||||
connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
|
connect(ui->list, &QListWidget::itemChanged, this, &PluginsManager::itemChanged);
|
||||||
|
|
||||||
|
|
||||||
currentChanged(ui->list->currentItem());
|
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()
|
PluginsManager::~PluginsManager()
|
||||||
{
|
{
|
||||||
delete ui;
|
delete ui;
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void settingsClicked();
|
void settingsClicked();
|
||||||
|
void removeClicked();
|
||||||
void currentChanged(QListWidgetItem* item);
|
void currentChanged(QListWidgetItem* item);
|
||||||
void itemChanged(QListWidgetItem* item);
|
void itemChanged(QListWidgetItem* item);
|
||||||
|
|
||||||
@ -52,6 +53,7 @@ private:
|
|||||||
|
|
||||||
Ui::PluginsList* ui;
|
Ui::PluginsList* ui;
|
||||||
bool m_loaded;
|
bool m_loaded;
|
||||||
|
bool m_blockRefresh = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PLUGINSMANAGER_H
|
#endif // PLUGINSMANAGER_H
|
||||||
|
@ -107,6 +107,7 @@ Plugins::Plugin pyfalkon_load_plugin(const QString &name)
|
|||||||
Plugins::Plugin plugin;
|
Plugins::Plugin plugin;
|
||||||
plugin.type = Plugins::Plugin::PythonPlugin;
|
plugin.type = Plugins::Plugin::PythonPlugin;
|
||||||
plugin.pluginId = QSL("python:%1").arg(QFileInfo(name).fileName());
|
plugin.pluginId = QSL("python:%1").arg(QFileInfo(name).fileName());
|
||||||
|
plugin.pluginPath = fullPath;
|
||||||
plugin.pluginSpec = Plugins::createSpec(DesktopFile(fullPath + QSL("/metadata.desktop")));
|
plugin.pluginSpec = Plugins::createSpec(DesktopFile(fullPath + QSL("/metadata.desktop")));
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user