File indexing completed on 2024-05-12 05:37:12
0001 /* 0002 SPDX-FileCopyrightText: 2015 Martin Klapetek <mklapetek@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "eventpluginsmanager.h" 0008 0009 #include <QAbstractListModel> 0010 #include <QCoreApplication> 0011 #include <QDebug> 0012 #include <QDir> 0013 #include <QJsonObject> 0014 #include <QPluginLoader> 0015 0016 #include <KPluginMetaData> 0017 0018 class EventPluginsManagerPrivate 0019 { 0020 public: 0021 explicit EventPluginsManagerPrivate(); 0022 ~EventPluginsManagerPrivate(); 0023 0024 friend class EventPluginsModel; 0025 struct PluginData { 0026 QString name; 0027 QString desc; 0028 QString icon; 0029 QString configUi; 0030 }; 0031 0032 std::unique_ptr<EventPluginsModel> model; 0033 QList<CalendarEvents::CalendarEventsPlugin *> plugins; 0034 QMap<QString, PluginData> availablePlugins; 0035 QStringList enabledPlugins; 0036 }; 0037 0038 class EventPluginsModel : public QAbstractListModel 0039 { 0040 Q_OBJECT 0041 public: 0042 EventPluginsModel(EventPluginsManagerPrivate *d) 0043 : d(d) 0044 , m_roles(QAbstractListModel::roleNames()) 0045 { 0046 m_roles.insert(Qt::EditRole, QByteArrayLiteral("checked")); 0047 m_roles.insert(Qt::UserRole, QByteArrayLiteral("configUi")); 0048 m_roles.insert(Qt::UserRole + 1, QByteArrayLiteral("pluginId")); 0049 } 0050 0051 // make these two available to the manager 0052 void beginResetModel() 0053 { 0054 QAbstractListModel::beginResetModel(); 0055 } 0056 0057 void endResetModel() 0058 { 0059 QAbstractListModel::endResetModel(); 0060 } 0061 0062 QHash<int, QByteArray> roleNames() const override 0063 { 0064 return m_roles; 0065 } 0066 0067 Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const override 0068 { 0069 Q_UNUSED(parent); 0070 return d->availablePlugins.size(); 0071 } 0072 0073 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override 0074 { 0075 if (!index.isValid() || !d) { 0076 return QVariant(); 0077 } 0078 0079 const auto it = std::next(d->availablePlugins.cbegin(), index.row()); 0080 const QString currentPlugin = it.key(); 0081 const EventPluginsManagerPrivate::PluginData metadata = it.value(); 0082 0083 switch (role) { 0084 case Qt::DisplayRole: 0085 return metadata.name; 0086 case Qt::ToolTipRole: 0087 return metadata.desc; 0088 case Qt::DecorationRole: 0089 return metadata.icon; 0090 case Qt::UserRole: { 0091 return metadata.configUi; 0092 } 0093 case Qt::UserRole + 1: 0094 return currentPlugin; 0095 case Qt::EditRole: 0096 return d->enabledPlugins.contains(currentPlugin); 0097 } 0098 0099 return QVariant(); 0100 } 0101 0102 bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override 0103 { 0104 if (role != Qt::EditRole || !index.isValid()) { 0105 return false; 0106 } 0107 0108 bool enabled = value.toBool(); 0109 const QString pluginId = d->availablePlugins.keys().at(index.row()); 0110 0111 if (enabled) { 0112 if (!d->enabledPlugins.contains(pluginId)) { 0113 d->enabledPlugins << pluginId; 0114 } 0115 } else { 0116 d->enabledPlugins.removeOne(pluginId); 0117 } 0118 0119 Q_EMIT dataChanged(index, index); 0120 0121 return true; 0122 } 0123 0124 Q_INVOKABLE QVariant get(int row, const QByteArray &role) 0125 { 0126 return data(createIndex(row, 0), roleNames().key(role)); 0127 } 0128 0129 private: 0130 EventPluginsManagerPrivate *d; 0131 QHash<int, QByteArray> m_roles; 0132 }; 0133 0134 EventPluginsManagerPrivate::EventPluginsManagerPrivate() 0135 : model(std::make_unique<EventPluginsModel>(this)) 0136 { 0137 const auto plugins = KPluginMetaData::findPlugins(QStringLiteral("plasmacalendarplugins")); 0138 for (const KPluginMetaData &plugin : plugins) { 0139 const QString prefix = plugin.fileName().left(plugin.fileName().lastIndexOf(QLatin1Char('/'))); 0140 const QString configName = plugin.value(QStringLiteral("X-KDE-PlasmaCalendar-ConfigUi")); 0141 0142 availablePlugins.insert(plugin.pluginId(), {plugin.name(), plugin.description(), plugin.iconName(), prefix + QLatin1Char('/') + configName}); 0143 } 0144 } 0145 0146 EventPluginsManagerPrivate::~EventPluginsManagerPrivate() 0147 { 0148 qDeleteAll(plugins); 0149 } 0150 0151 EventPluginsManager::EventPluginsManager(QObject *parent) 0152 : QObject(parent) 0153 , d(new EventPluginsManagerPrivate) 0154 { 0155 } 0156 0157 EventPluginsManager::~EventPluginsManager() 0158 { 0159 delete d; 0160 } 0161 0162 void EventPluginsManager::populateEnabledPluginsList(const QStringList &pluginsList) 0163 { 0164 d->model->beginResetModel(); 0165 d->enabledPlugins = pluginsList; 0166 d->model->endResetModel(); 0167 } 0168 0169 void EventPluginsManager::setEnabledPlugins(QStringList &pluginsList) 0170 { 0171 d->model->beginResetModel(); 0172 d->enabledPlugins = pluginsList; 0173 0174 // Remove all already loaded plugins from the pluginsList 0175 // and unload those plugins that are not in the pluginsList 0176 auto i = d->plugins.begin(); 0177 while (i != d->plugins.end()) { 0178 const QString pluginId = (*i)->property("pluginId").toString(); 0179 if (pluginsList.contains(pluginId)) { 0180 pluginsList.removeAll(pluginId); 0181 ++i; 0182 } else { 0183 (*i)->deleteLater(); 0184 i = d->plugins.erase(i); 0185 } 0186 } 0187 0188 // Now load all the plugins left in pluginsList 0189 for (const QString &pluginId : std::as_const(pluginsList)) { 0190 loadPlugin(pluginId); 0191 } 0192 0193 d->model->endResetModel(); 0194 Q_EMIT pluginsChanged(); 0195 } 0196 0197 QStringList EventPluginsManager::enabledPlugins() const 0198 { 0199 return d->enabledPlugins; 0200 } 0201 0202 void EventPluginsManager::loadPlugin(const QString &pluginId) 0203 { 0204 QPluginLoader loader("plasmacalendarplugins/" + QDir::cleanPath(pluginId)); 0205 0206 if (!loader.load()) { 0207 qWarning() << "Could not create Plasma Calendar Plugin: " << pluginId; 0208 qWarning() << loader.errorString(); 0209 return; 0210 } 0211 0212 QObject *obj = loader.instance(); 0213 if (obj) { 0214 CalendarEvents::CalendarEventsPlugin *eventsPlugin = qobject_cast<CalendarEvents::CalendarEventsPlugin *>(obj); 0215 if (eventsPlugin) { 0216 qDebug() << "Loading Calendar plugin" << eventsPlugin; 0217 eventsPlugin->setProperty("pluginId", pluginId); 0218 d->plugins << eventsPlugin; 0219 0220 // Connect the relay signals 0221 connect(eventsPlugin, &CalendarEvents::CalendarEventsPlugin::dataReady, this, &EventPluginsManager::dataReady); 0222 connect(eventsPlugin, &CalendarEvents::CalendarEventsPlugin::eventModified, this, &EventPluginsManager::eventModified); 0223 connect(eventsPlugin, &CalendarEvents::CalendarEventsPlugin::eventRemoved, this, &EventPluginsManager::eventRemoved); 0224 connect(eventsPlugin, &CalendarEvents::CalendarEventsPlugin::alternateCalendarDateReady, this, &EventPluginsManager::alternateCalendarDateReady); 0225 connect(eventsPlugin, &CalendarEvents::CalendarEventsPlugin::subLabelReady, this, &EventPluginsManager::subLabelReady); 0226 } else { 0227 // not our/valid plugin, so unload it 0228 loader.unload(); 0229 } 0230 } else { 0231 loader.unload(); 0232 } 0233 } 0234 0235 QList<CalendarEvents::CalendarEventsPlugin *> EventPluginsManager::plugins() const 0236 { 0237 return d->plugins; 0238 } 0239 0240 QAbstractListModel *EventPluginsManager::pluginsModel() const 0241 { 0242 return d->model.get(); 0243 } 0244 0245 #include "eventpluginsmanager.moc"