KParts

plugin.cpp
1 /*
2  This file is part of the KDE project
3  SPDX-FileCopyrightText: 1999 Simon Hausmann <[email protected]>
4  SPDX-FileCopyrightText: 1999 David Faure <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "plugin.h"
10 
11 #if KPARTS_BUILD_DEPRECATED_SINCE(5, 90)
12 
13 QT_WARNING_PUSH
14 QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
15 QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
16 
17 #include "part.h"
18 
19 #include <KConfigGroup>
20 #include <KDesktopFile>
21 #include <KLocalizedString>
22 #include <KPluginFactory>
23 #include <KPluginLoader>
24 #include <KPluginMetaData>
25 #include <KSharedConfig>
26 #include <KXMLGUIFactory>
27 #if !KPARTS_BUILD_DEPRECATED_SINCE(5, 77) || KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 76)
28 #include <KAboutData>
29 #endif
30 
31 #include <QDir>
32 #include <QFile>
33 #include <QFileInfo>
34 #include <QStandardPaths>
35 
36 using namespace KParts;
37 
38 class KParts::PluginPrivate
39 {
40 public:
41  QString m_parentInstance;
42  QString m_library; // filename of the library
43 };
44 
46  : QObject(parent)
47  , d(new PluginPrivate())
48 {
49  // qDebug() << className();
50 }
51 
52 Plugin::~Plugin() = default;
53 
55 {
57 
58  if (d->m_parentInstance.isEmpty() || (!path.isEmpty() && QDir::isAbsolutePath(path))) {
59  return path;
60  }
61 
62  QString absPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, d->m_parentInstance + QLatin1Char('/') + path);
63  Q_ASSERT(!absPath.isEmpty());
64  return absPath;
65 }
66 
68 {
70 
71  if (d->m_parentInstance.isEmpty() || (!path.isEmpty() && QDir::isAbsolutePath(path))) {
72  return path;
73  }
74 
75  QString absPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + d->m_parentInstance + QLatin1Char('/') + path;
76  return absPath;
77 }
78 
79 // static
80 QList<Plugin::PluginInfo> Plugin::pluginInfos(const QString &componentName)
81 {
82  QList<PluginInfo> plugins;
83 
84  QMap<QString, QStringList> sortedPlugins;
85 
86  const QStringList dirs =
88  for (const QString &dir : dirs) {
89  const auto rcfiles = QDir(dir).entryList(QStringList(QStringLiteral("*.rc")));
90  for (const QString &file : rcfiles) {
91  const QFileInfo fInfo(dir + QLatin1Char('/') + file);
92  QMap<QString, QStringList>::Iterator mapIt = sortedPlugins.find(fInfo.fileName());
93  if (mapIt == sortedPlugins.end()) {
94  mapIt = sortedPlugins.insert(fInfo.fileName(), QStringList());
95  }
96  mapIt.value().append(fInfo.absoluteFilePath());
97  }
98  }
99 
101  QMap<QString, QStringList>::ConstIterator mapEnd = sortedPlugins.constEnd();
102  for (; mapIt != mapEnd; ++mapIt) {
103  PluginInfo info;
104  QString doc;
105  info.m_absXMLFileName = KXMLGUIClient::findMostRecentXMLFile(mapIt.value(), doc);
106  if (info.m_absXMLFileName.isEmpty()) {
107  continue;
108  }
109 
110  // qDebug() << "found KParts Plugin : " << info.m_absXMLFileName;
111  info.m_relXMLFileName = QLatin1String("kpartplugins/") + mapIt.key();
112 
113  info.m_document.setContent(doc);
114  if (info.m_document.documentElement().isNull()) {
115  continue;
116  }
117 
118  plugins.append(info);
119  }
120 
121  return plugins;
122 }
123 
124 void Plugin::loadPlugins(QObject *parent, const QString &componentName)
125 {
127 }
128 
129 void Plugin::loadPlugins(QObject *parent, const QList<PluginInfo> &pluginInfos, const QString &componentName)
130 {
131  for (const auto &pluginInfo : pluginInfos) {
132  const QString library = pluginInfo.m_document.documentElement().attribute(QStringLiteral("library"));
133 
134  if (library.isEmpty() || hasPlugin(parent, library)) {
135  continue;
136  }
137 
138  Plugin *plugin = loadPlugin(parent, library, pluginInfo.m_document.documentElement().attribute(QStringLiteral("X-KDE-PluginKeyword")));
139 
140  if (plugin) {
141  plugin->d->m_parentInstance = componentName;
142  plugin->setXMLFile(pluginInfo.m_relXMLFileName, false, false);
143  plugin->setDOMDocument(pluginInfo.m_document);
144  }
145  }
146 }
147 
148 void Plugin::loadPlugins(QObject *parent, const QList<PluginInfo> &pluginInfos)
149 {
150  loadPlugins(parent, pluginInfos, QString());
151 }
152 
153 // static
154 Plugin *Plugin::loadPlugin(QObject *parent, const QString &libname, const QString &keyword)
155 {
156  KPluginLoader loader(libname);
157  KPluginFactory *factory = loader.factory();
158 
159  if (!factory) {
160  return nullptr;
161  }
162 
163  Plugin *plugin = factory->create<Plugin>(keyword, parent);
164  if (!plugin) {
165  return nullptr;
166  }
167  plugin->d->m_library = libname;
168  return plugin;
169 }
170 
172 {
173  QList<KParts::Plugin *> objects;
174 
175  if (!parent) {
176  return objects;
177  }
178 
180  return objects;
181 }
182 
183 bool Plugin::hasPlugin(QObject *parent, const QString &library)
184 {
185  const QObjectList plugins = parent->children();
186 
187  return std::any_of(plugins.begin(), plugins.end(), [&library](QObject *p) {
188  Plugin *plugin = qobject_cast<Plugin *>(p);
189  return (plugin && plugin->d->m_library == library);
190  });
191 }
192 
193 #if KPARTS_BUILD_DEPRECATED_SINCE(5, 77)
194 void Plugin::setComponentData(const KAboutData &pluginData)
195 {
196  // backward-compatible registration, usage deprecated
197 #if KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 76)
198  QT_WARNING_PUSH
199  QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
200  QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
201  KAboutData::registerPluginData(pluginData);
202  QT_WARNING_POP
203 #endif
204 
205  KXMLGUIClient::setComponentName(pluginData.componentName(), pluginData.displayName());
206 }
207 #endif
208 
210 {
211  // backward-compatible registration, usage deprecated
212 #if KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 76)
213  QT_WARNING_PUSH
214  QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
215  QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
217  QT_WARNING_POP
218 #endif
219 
220  KXMLGUIClient::setComponentName(metaData.pluginId(), metaData.name());
221 }
222 
224  KXMLGUIClient *parentGUIClient,
225  const QString &componentName,
226  bool enableNewPluginsByDefault,
227  int interfaceVersionRequired)
228 {
229  KConfigGroup cfgGroup(KSharedConfig::openConfig(componentName + QLatin1String("rc")), "KParts Plugins");
230  const QList<PluginInfo> plugins = pluginInfos(componentName);
231  for (const auto &pluginInfo : plugins) {
232  QDomElement docElem = pluginInfo.m_document.documentElement();
233  QString library = docElem.attribute(QStringLiteral("library"));
234  QString keyword;
235 
236  if (library.isEmpty()) {
237  continue;
238  }
239 
240  // Check configuration
241  const QString name = docElem.attribute(QStringLiteral("name"));
242 
243  bool pluginEnabled = enableNewPluginsByDefault;
244  if (cfgGroup.hasKey(name + QLatin1String("Enabled"))) {
245  pluginEnabled = cfgGroup.readEntry(name + QLatin1String("Enabled"), false);
246  } else { // no user-setting, load plugin default setting
247  QString relPath = componentName + QLatin1Char('/') + pluginInfo.m_relXMLFileName;
248  relPath.truncate(relPath.lastIndexOf(QLatin1Char('.'))); // remove extension
249  relPath += QLatin1String(".desktop");
250  // qDebug() << "looking for " << relPath;
252  if (!desktopfile.isEmpty()) {
253  // qDebug() << "loadPlugins found desktop file for " << name << ": " << desktopfile;
254  KDesktopFile _desktop(desktopfile);
255  const KConfigGroup desktop = _desktop.desktopGroup();
256  keyword = desktop.readEntry("X-KDE-PluginKeyword", "");
257  pluginEnabled = desktop.readEntry("X-KDE-PluginInfo-EnabledByDefault", enableNewPluginsByDefault);
258  if (interfaceVersionRequired != 0) {
259  const int version = desktop.readEntry("X-KDE-InterfaceVersion", 1);
260  if (version != interfaceVersionRequired) {
261  // qDebug() << "Discarding plugin " << name << ", interface version " << version << ", expected " << interfaceVersionRequired;
262  pluginEnabled = false;
263  }
264  }
265  } else {
266  // qDebug() << "loadPlugins no desktop file found in " << relPath;
267  }
268  }
269 
270  // search through already present plugins
271  const QObjectList pluginList = parent->children();
272 
273  bool pluginFound = false;
274  for (auto *p : pluginList) {
275  Plugin *plugin = qobject_cast<Plugin *>(p);
276  if (plugin && plugin->d->m_library == library) {
277  // delete and unload disabled plugins
278  if (!pluginEnabled) {
279  // qDebug() << "remove plugin " << name;
280  KXMLGUIFactory *factory = plugin->factory();
281  if (factory) {
282  factory->removeClient(plugin);
283  }
284  delete plugin;
285  }
286 
287  pluginFound = true;
288  break;
289  }
290  }
291 
292  // if the plugin is already loaded or if it's disabled in the
293  // configuration do nothing
294  if (pluginFound || !pluginEnabled) {
295  continue;
296  }
297 
298  // qDebug() << "load plugin " << name << " " << library << " " << keyword;
299  Plugin *plugin = loadPlugin(parent, library, keyword);
300 
301  if (plugin) {
302  plugin->d->m_parentInstance = componentName;
303  plugin->setXMLFile(pluginInfo.m_relXMLFileName, false, false);
304  plugin->setDOMDocument(pluginInfo.m_document);
305  parentGUIClient->insertChildClient(plugin);
306  }
307  }
308 }
309 #endif
void append(const T &value)
QMap::const_iterator constBegin() const const
QString readEntry(const char *key, const char *aDefault=nullptr) const
void truncate(int position)
void removeClient(KXMLGUIClient *client)
static void loadPlugins(QObject *parent, const QString &instance)
Load the plugin libraries from the directories appropriate to instance and make the Plugin objects ch...
Definition: plugin.cpp:124
const T value(const Key &key, const T &defaultValue) const const
typedef QObjectList
static QList< Plugin * > pluginObjects(QObject *parent)
Returns a list of plugin objects loaded for parent.
Definition: plugin.cpp:171
virtual void setDOMDocument(const QDomDocument &document, bool merge=false)
QString componentName() const
QString writableLocation(QStandardPaths::StandardLocation type)
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString locate(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
QString xmlFile() const override
Reimplemented for internal reasons.
Definition: plugin.cpp:54
QMap::iterator insert(const Key &key, const T &value)
QMap::iterator end()
void insertChildClient(KXMLGUIClient *child)
QString displayName() const
QMap::iterator find(const Key &key)
A plugin is the way to add actions to an existing KParts application, or to a Part.
Definition: plugin.h:51
virtual QString xmlFile() const
QMap::const_iterator constEnd() const const
virtual void setComponentName(const QString &componentName, const QString &componentDisplayName)
QString name() const
Plugin(QObject *parent=nullptr)
Construct a new KParts plugin.
Definition: plugin.cpp:45
void setMetaData(const KPluginMetaData &metaData)
Definition: plugin.cpp:209
virtual void setXMLFile(const QString &file, bool merge=false, bool setXMLDoc=true)
bool isEmpty() const const
QList< T > findChildren(const QString &name, Qt::FindChildOptions options) const const
FindDirectChildrenOnly
KXMLGUIFactory * factory() const
bool hasKey(const char *key) const
const Key key(const T &value, const Key &defaultKey) const const
bool isAbsolutePath(const QString &path)
virtual void setComponentData(const KAboutData &pluginData)
Definition: plugin.cpp:194
KConfigGroup desktopGroup() const
static void registerPluginData(const KAboutData &aboutData)
unsigned int version()
QStringList locateAll(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options)
~Plugin() override
Destructor.
QString attribute(const QString &name, const QString &defValue) const const
QStringList entryList(QDir::Filters filters, QDir::SortFlags sort) const const
QString pluginId() const
QObject * parent() const const
The KParts namespace,.
QString localXMLFile() const override
Reimplemented for internal reasons.
Definition: plugin.cpp:67
const QObjectList & children() const const
virtual QString componentName() const
static KAboutData fromPluginMetaData(const KPluginMetaData &plugin)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Aug 15 2022 03:59:46 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.