c0274df69a
NO_CHANGELOG
254 lines
8.0 KiB
C++
254 lines
8.0 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2015 Martin Klapetek <mklapetek@kde.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "eventpluginsmanager.h"
|
|
|
|
#include <CalendarEvents/CalendarEventsPlugin>
|
|
|
|
#include <QAbstractListModel>
|
|
#include <QCoreApplication>
|
|
#include <QDebug>
|
|
#include <QDir>
|
|
#include <QJsonObject>
|
|
#include <QPluginLoader>
|
|
|
|
#include <KPluginLoader>
|
|
#include <KPluginMetaData>
|
|
|
|
class EventPluginsModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
EventPluginsModel(EventPluginsManager *manager)
|
|
: QAbstractListModel(manager)
|
|
{
|
|
m_manager = manager;
|
|
m_roles = QAbstractListModel::roleNames();
|
|
m_roles.insert(Qt::EditRole, QByteArrayLiteral("checked"));
|
|
m_roles.insert(Qt::UserRole, QByteArrayLiteral("configUi"));
|
|
m_roles.insert(Qt::UserRole + 1, QByteArrayLiteral("pluginPath"));
|
|
}
|
|
|
|
// make these two available to the manager
|
|
void beginResetModel()
|
|
{
|
|
QAbstractListModel::beginResetModel();
|
|
}
|
|
|
|
void endResetModel()
|
|
{
|
|
QAbstractListModel::endResetModel();
|
|
}
|
|
|
|
QHash<int, QByteArray> roleNames() const override
|
|
{
|
|
return m_roles;
|
|
}
|
|
|
|
Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
|
{
|
|
Q_UNUSED(parent);
|
|
return m_manager->m_availablePlugins.size();
|
|
}
|
|
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
|
|
{
|
|
if (!index.isValid() && !m_manager) {
|
|
return QVariant();
|
|
}
|
|
|
|
const auto it = m_manager->m_availablePlugins.cbegin() + index.row();
|
|
const QString currentPlugin = it.key();
|
|
const EventPluginsManager::PluginData metadata = it.value();
|
|
|
|
switch (role) {
|
|
case Qt::DisplayRole:
|
|
return metadata.name;
|
|
case Qt::ToolTipRole:
|
|
return metadata.desc;
|
|
case Qt::DecorationRole:
|
|
return metadata.icon;
|
|
case Qt::UserRole: {
|
|
// The currentPlugin path contains the full path including
|
|
// the plugin filename, so it needs to be cut off from the last '/'
|
|
const QStringRef pathRef = currentPlugin.leftRef(currentPlugin.lastIndexOf(QLatin1Char('/')));
|
|
const QString qmlFilePath = metadata.configUi;
|
|
return QString(pathRef % QLatin1Char('/') % qmlFilePath);
|
|
}
|
|
case Qt::UserRole + 1:
|
|
return currentPlugin;
|
|
case Qt::EditRole:
|
|
return m_manager->m_enabledPlugins.contains(currentPlugin);
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
|
|
{
|
|
if (role != Qt::EditRole || !index.isValid()) {
|
|
return false;
|
|
}
|
|
|
|
bool enabled = value.toBool();
|
|
const QString pluginPath = m_manager->m_availablePlugins.keys().at(index.row());
|
|
|
|
if (enabled) {
|
|
if (!m_manager->m_enabledPlugins.contains(pluginPath)) {
|
|
m_manager->m_enabledPlugins << pluginPath;
|
|
}
|
|
} else {
|
|
m_manager->m_enabledPlugins.removeOne(pluginPath);
|
|
}
|
|
|
|
Q_EMIT dataChanged(index, index);
|
|
|
|
return true;
|
|
}
|
|
|
|
Q_INVOKABLE QVariant get(int row, const QByteArray &role)
|
|
{
|
|
return data(createIndex(row, 0), roleNames().key(role));
|
|
}
|
|
|
|
private:
|
|
EventPluginsManager *m_manager;
|
|
QHash<int, QByteArray> m_roles;
|
|
};
|
|
|
|
EventPluginsManager::EventPluginsManager(QObject *parent)
|
|
: QObject(parent)
|
|
{
|
|
auto plugins = KPluginLoader::findPlugins(QStringLiteral("plasmacalendarplugins"), [](const KPluginMetaData &md) {
|
|
return md.serviceTypes().contains(QLatin1String("PlasmaCalendar/Plugin"));
|
|
});
|
|
for (const KPluginMetaData &plugin : qAsConst(plugins)) {
|
|
m_availablePlugins.insert(plugin.fileName(),
|
|
{plugin.name(), plugin.description(), plugin.iconName(), plugin.value(QStringLiteral("X-KDE-PlasmaCalendar-ConfigUi"))});
|
|
}
|
|
|
|
// Fallback for legacy pre-KPlugin plugins so we can still load them
|
|
const QStringList paths = QCoreApplication::libraryPaths();
|
|
for (const QString &libraryPath : paths) {
|
|
const QString path(libraryPath + QStringLiteral("/plasmacalendarplugins"));
|
|
QDir dir(path);
|
|
|
|
if (!dir.exists()) {
|
|
continue;
|
|
}
|
|
|
|
const QStringList entryList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
|
|
|
|
for (const QString &fileName : entryList) {
|
|
const QString absolutePath = dir.absoluteFilePath(fileName);
|
|
if (m_availablePlugins.contains(absolutePath)) {
|
|
continue;
|
|
}
|
|
|
|
QPluginLoader loader(absolutePath);
|
|
// Load only our own plugins
|
|
if (loader.metaData().value(QStringLiteral("IID")) == QLatin1String("org.kde.CalendarEventsPlugin")) {
|
|
const auto md = loader.metaData().value(QStringLiteral("MetaData")).toObject();
|
|
m_availablePlugins.insert(absolutePath,
|
|
{md.value(QStringLiteral("Name")).toString(),
|
|
md.value(QStringLiteral("Description")).toString(),
|
|
md.value(QStringLiteral("Icon")).toString(),
|
|
md.value(QStringLiteral("ConfigUi")).toString()});
|
|
}
|
|
}
|
|
}
|
|
|
|
m_model = new EventPluginsModel(this);
|
|
}
|
|
|
|
EventPluginsManager::~EventPluginsManager()
|
|
{
|
|
qDeleteAll(m_plugins);
|
|
}
|
|
|
|
void EventPluginsManager::populateEnabledPluginsList(const QStringList &pluginsList)
|
|
{
|
|
m_model->beginResetModel();
|
|
m_enabledPlugins = pluginsList;
|
|
m_model->endResetModel();
|
|
}
|
|
|
|
void EventPluginsManager::setEnabledPlugins(QStringList &pluginsList)
|
|
{
|
|
m_model->beginResetModel();
|
|
m_enabledPlugins = pluginsList;
|
|
|
|
// Remove all already loaded plugins from the pluginsList
|
|
// and unload those plugins that are not in the pluginsList
|
|
auto i = m_plugins.begin();
|
|
while (i != m_plugins.end()) {
|
|
const QString pluginPath = (*i)->property("pluginPath").toString();
|
|
if (pluginsList.contains(pluginPath)) {
|
|
pluginsList.removeAll(pluginPath);
|
|
++i;
|
|
} else {
|
|
(*i)->deleteLater();
|
|
i = m_plugins.erase(i);
|
|
}
|
|
}
|
|
|
|
// Now load all the plugins left in pluginsList
|
|
for (const QString &pluginPath : qAsConst(pluginsList)) {
|
|
loadPlugin(pluginPath);
|
|
}
|
|
|
|
m_model->endResetModel();
|
|
Q_EMIT pluginsChanged();
|
|
}
|
|
|
|
QStringList EventPluginsManager::enabledPlugins() const
|
|
{
|
|
return m_enabledPlugins;
|
|
}
|
|
|
|
void EventPluginsManager::loadPlugin(const QString &absolutePath)
|
|
{
|
|
QPluginLoader loader(absolutePath);
|
|
|
|
if (!loader.load()) {
|
|
qWarning() << "Could not create Plasma Calendar Plugin: " << absolutePath;
|
|
qWarning() << loader.errorString();
|
|
return;
|
|
}
|
|
|
|
QObject *obj = loader.instance();
|
|
if (obj) {
|
|
CalendarEvents::CalendarEventsPlugin *eventsPlugin = qobject_cast<CalendarEvents::CalendarEventsPlugin *>(obj);
|
|
if (eventsPlugin) {
|
|
qDebug() << "Loading Calendar plugin" << eventsPlugin;
|
|
eventsPlugin->setProperty("pluginPath", absolutePath);
|
|
m_plugins << eventsPlugin;
|
|
|
|
// Connect the relay signals
|
|
connect(eventsPlugin, &CalendarEvents::CalendarEventsPlugin::dataReady, this, &EventPluginsManager::dataReady);
|
|
connect(eventsPlugin, &CalendarEvents::CalendarEventsPlugin::eventModified, this, &EventPluginsManager::eventModified);
|
|
connect(eventsPlugin, &CalendarEvents::CalendarEventsPlugin::eventRemoved, this, &EventPluginsManager::eventRemoved);
|
|
} else {
|
|
// not our/valid plugin, so unload it
|
|
loader.unload();
|
|
}
|
|
} else {
|
|
loader.unload();
|
|
}
|
|
}
|
|
|
|
QList<CalendarEvents::CalendarEventsPlugin *> EventPluginsManager::plugins() const
|
|
{
|
|
return m_plugins;
|
|
}
|
|
|
|
QAbstractListModel *EventPluginsManager::pluginsModel() const
|
|
{
|
|
return m_model;
|
|
}
|
|
|
|
#include "eventpluginsmanager.moc"
|