File indexing completed on 2024-04-28 04:58:11
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org> 0004 SPDX-FileCopyrightText: 1999 David Faure <faure@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "konq_kpart_plugin.h" 0010 0011 #include <KConfigGroup> 0012 #include <KPluginFactory> 0013 #include <KPluginMetaData> 0014 #include <KService> 0015 #include <KSharedConfig> 0016 #include <KXMLGUIFactory> 0017 0018 #include <QDir> 0019 #include <QFile> 0020 #include <QFileInfo> 0021 #include <QStandardPaths> 0022 0023 namespace KonqParts 0024 { 0025 0026 class PluginPrivate 0027 { 0028 public: 0029 QString m_parentInstance; 0030 QString m_pluginId; 0031 }; 0032 0033 Plugin::Plugin(QObject *parent) 0034 : QObject(parent) 0035 , d(new PluginPrivate()) 0036 { 0037 } 0038 0039 Plugin::~Plugin() = default; 0040 0041 QString Plugin::xmlFile() const 0042 { 0043 QString path = KXMLGUIClient::xmlFile(); 0044 0045 if (d->m_parentInstance.isEmpty() || (!path.isEmpty() && QDir::isAbsolutePath(path))) { 0046 return path; 0047 } 0048 0049 QString absPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, d->m_parentInstance + QLatin1Char('/') + path); 0050 Q_ASSERT(!absPath.isEmpty()); 0051 return absPath; 0052 } 0053 0054 QString Plugin::localXMLFile() const 0055 { 0056 QString path = KXMLGUIClient::xmlFile(); 0057 0058 if (d->m_parentInstance.isEmpty() || (!path.isEmpty() && QDir::isAbsolutePath(path))) { 0059 return path; 0060 } 0061 0062 QString absPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + d->m_parentInstance + QLatin1Char('/') + path; 0063 return absPath; 0064 } 0065 0066 // static 0067 QList<Plugin::PluginInfo> Plugin::pluginInfos(const QString &componentName) 0068 { 0069 QList<PluginInfo> plugins; 0070 0071 QVector<KPluginMetaData> metaDataList = KPluginMetaData::findPlugins(componentName + QStringLiteral("/kpartplugins")); 0072 std::sort(metaDataList.begin(), metaDataList.end(), [](const KPluginMetaData &d1, const KPluginMetaData &d2) { 0073 return d1.pluginId() < d2.pluginId(); 0074 }); 0075 0076 for (const KPluginMetaData &data : metaDataList) { 0077 PluginInfo info; 0078 info.m_metaData = data; 0079 QString doc; 0080 const QString fullComponentName = QStringLiteral("konqueror/partsrcfiles/") + QFileInfo(data.fileName()).baseName(); 0081 const auto files = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, fullComponentName + QLatin1String(".rc")); 0082 info.m_absXMLFileName = KXMLGUIClient::findMostRecentXMLFile(files, doc); 0083 doc = KXMLGUIFactory::readConfigFile(info.m_absXMLFileName); 0084 if (info.m_absXMLFileName.isEmpty()) { 0085 continue; 0086 } 0087 0088 info.m_document.setContent(doc); 0089 if (info.m_document.documentElement().isNull()) { 0090 continue; 0091 } 0092 0093 const QString tryExec = data.value(QStringLiteral("TryExec")); 0094 if (!tryExec.isEmpty() && QStandardPaths::findExecutable(tryExec).isEmpty()) { 0095 continue; 0096 } 0097 0098 plugins.append(info); 0099 } 0100 0101 return plugins; 0102 } 0103 0104 void Plugin::loadPlugins(QObject *parent, const QList<PluginInfo> &pluginInfos, const QString &componentName) 0105 { 0106 for (const auto &pluginInfo : pluginInfos) { 0107 if (hasPlugin(parent, pluginInfo.m_metaData.pluginId())) { 0108 continue; 0109 } 0110 0111 Plugin *plugin = loadPlugin(parent, pluginInfo.m_metaData); 0112 0113 if (plugin) { 0114 plugin->d->m_parentInstance = componentName; 0115 plugin->setXMLFile(pluginInfo.m_absXMLFileName, false, false); 0116 plugin->setDOMDocument(pluginInfo.m_document); 0117 } 0118 } 0119 } 0120 0121 // static 0122 Plugin *Plugin::loadPlugin(QObject *parent, const KPluginMetaData &data) 0123 { 0124 auto pluginResult = KPluginFactory::instantiatePlugin<Plugin>(data, parent); 0125 if (pluginResult) { 0126 pluginResult.plugin->d->m_pluginId = data.pluginId(); 0127 } 0128 return pluginResult.plugin; 0129 } 0130 0131 QList<KonqParts::Plugin *> Plugin::pluginObjects(QObject *parent) 0132 { 0133 QList<KonqParts::Plugin *> objects; 0134 0135 if (!parent) { 0136 return objects; 0137 } 0138 0139 objects = parent->findChildren<Plugin *>(QString(), Qt::FindDirectChildrenOnly); 0140 return objects; 0141 } 0142 0143 bool Plugin::hasPlugin(QObject *parent, const QString &pluginId) 0144 { 0145 const QObjectList plugins = parent->children(); 0146 0147 return std::any_of(plugins.begin(), plugins.end(), [&pluginId](QObject *p) { 0148 Plugin *plugin = qobject_cast<Plugin *>(p); 0149 return (plugin && plugin->d->m_pluginId == pluginId); 0150 }); 0151 } 0152 0153 0154 void Plugin::setMetaData(const KPluginMetaData &metaData) 0155 { 0156 // backward-compatible registration, usage deprecated 0157 KXMLGUIClient::setComponentName(metaData.pluginId(), metaData.name()); 0158 } 0159 0160 void Plugin::loadPlugins(QObject *parent, KXMLGUIClient *parentGUIClient, const QString &componentName) 0161 { 0162 KConfigGroup cfgGroup(KSharedConfig::openConfig(componentName + QLatin1String("rc")), "KParts Plugins"); 0163 const QList<PluginInfo> plugins = pluginInfos(componentName) << pluginInfos("konqueror"); 0164 for (const auto &pluginInfo : plugins) { 0165 QDomElement docElem = pluginInfo.m_document.documentElement(); 0166 0167 bool pluginEnabled = pluginInfo.m_metaData.isEnabled(cfgGroup); 0168 // search through already present plugins 0169 const QObjectList pluginList = parent->children(); 0170 0171 bool pluginFound = false; 0172 for (auto *p : pluginList) { 0173 Plugin *plugin = qobject_cast<Plugin *>(p); 0174 if (plugin && plugin->d->m_pluginId == pluginInfo.m_metaData.pluginId()) { 0175 // delete and unload disabled plugins 0176 if (!pluginEnabled) { 0177 // qDebug() << "remove plugin " << name; 0178 KXMLGUIFactory *factory = plugin->factory(); 0179 if (factory) { 0180 factory->removeClient(plugin); 0181 } 0182 delete plugin; 0183 } 0184 0185 pluginFound = true; 0186 break; 0187 } 0188 } 0189 0190 // if the plugin is already loaded or if it's disabled in the 0191 // configuration do nothing 0192 if (pluginFound || !pluginEnabled) { 0193 continue; 0194 } 0195 0196 // qDebug() << "load plugin " << name << " " << library << " " << keyword; 0197 Plugin *plugin = loadPlugin(parent, pluginInfo.m_metaData); 0198 0199 if (plugin) { 0200 plugin->d->m_parentInstance = componentName; 0201 plugin->setXMLFile(pluginInfo.m_absXMLFileName, false, false); 0202 plugin->setDOMDocument(pluginInfo.m_document); 0203 parentGUIClient->insertChildClient(plugin); 0204 } 0205 } 0206 } 0207 } 0208