KCoreAddons

kpluginmetadata.h
1 /*
2  This file is part of the KDE project
3 
4  SPDX-FileCopyrightText: 2014 Alex Richardson <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-only
7 */
8 
9 #ifndef KPLUGINMETADATA_H
10 #define KPLUGINMETADATA_H
11 
12 #include "kcoreaddons_export.h"
13 
14 #include <QExplicitlySharedDataPointer>
15 #include <QJsonObject>
16 #include <QMetaType>
17 #include <QString>
18 #include <QStringList>
19 
20 #include <functional>
21 
22 class KPluginLoader;
23 class QPluginLoader;
24 class KPluginMetaDataPrivate;
25 class KAboutPerson;
26 class QObject;
27 
28 /**
29  * @class KPluginMetaData kpluginmetadata.h KPluginMetaData
30  *
31  * This class allows easily accessing some standardized values from the JSON metadata that
32  * can be embedded into Qt plugins. Additional plugin-specific metadata can be retrieved by
33  * directly reading from the QJsonObject returned by KPluginMetaData::rawData().
34  *
35  * This class can be used instead of KPluginInfo from KService for applications that only load
36  * Qt C++ plugins.
37  *
38  * The following keys will be read from an object "KPlugin" inside the metadata JSON:
39  *
40  * Key | Accessor function | JSON Type
41  * -------------------| -------------------- | ---------------------
42  * Name | name() | string
43  * Description | description() | string
44  * ExtraInformation | extraInformation() | string
45  * Icon | iconName() | string
46  * Authors | authors() | object array (KAboutPerson)
47  * Category | category() | string
48  * License | license() | string
49  * Copyright | copyrightText() | string
50  * Id | pluginId() | string
51  * Version | version() | string
52  * Website | website() | string
53  * EnabledByDefault | isEnabledByDefault() | bool
54  * ServiceTypes | serviceTypes() | string array
55  * MimeTypes | mimeTypes() | string array
56  * FormFactors | formFactors() | string array
57  * Translators | translators() | object array (KAboutPerson)
58  * OtherContributors | otherContributors() | object array (KAboutPerson)
59  *
60  * The Authors, Translators and OtherContributors keys are expected to be
61  * list of objects that match the structure expected by KAboutPerson::fromJSON().
62  *
63  * An example metadata json file could look like this:
64  * @verbatim
65  {
66  "KPlugin": {
67  "Name": "Date and Time",
68  "Description": "Date and time by timezone",
69  "Icon": "preferences-system-time",
70  "Authors": { "Name": "Aaron Seigo", "Email": "[email protected]" },
71  "Category": "Date and Time",
72  "EnabledByDefault": "true",
73  "License": "LGPL",
74  "Id": "time",
75  "Version": "1.0",
76  "Website": "https://plasma.kde.org/",
77  "ServiceTypes": ["Plasma/DataEngine"]
78  }
79  }
80  @endverbatim
81  *
82  * @sa KAboutPerson::fromJSON()
83  * @since 5.1
84  */
85 class KCOREADDONS_EXPORT KPluginMetaData
86 {
87  Q_GADGET
88  Q_PROPERTY(bool isValid READ isValid CONSTANT)
89  Q_PROPERTY(bool isHidden READ isHidden CONSTANT)
90  Q_PROPERTY(QString fileName READ fileName CONSTANT)
91  Q_PROPERTY(QString metaDataFileName READ metaDataFileName CONSTANT)
92  Q_PROPERTY(QJsonObject rawData READ rawData CONSTANT)
93  Q_PROPERTY(QString name READ name CONSTANT)
94  Q_PROPERTY(QString description READ description CONSTANT)
95  Q_PROPERTY(QString extraInformation READ extraInformation CONSTANT)
96  Q_PROPERTY(QVariantList authors READ authorsVariant CONSTANT)
97  Q_PROPERTY(QVariantList translators READ translatorsVariant CONSTANT)
98  Q_PROPERTY(QVariantList otherContributors READ otherContributorsVariant CONSTANT)
99  Q_PROPERTY(QString category READ category CONSTANT)
100  Q_PROPERTY(QString iconName READ iconName CONSTANT)
101  Q_PROPERTY(QString license READ license CONSTANT)
102  Q_PROPERTY(QString licenseText READ licenseText CONSTANT)
103  Q_PROPERTY(QString copyrightText READ copyrightText CONSTANT)
104  Q_PROPERTY(QString pluginId READ pluginId CONSTANT)
105  Q_PROPERTY(QString version READ version CONSTANT)
106  Q_PROPERTY(QString website READ website CONSTANT)
107 #if KCOREADDONS_ENABLE_DEPRECATED_SINCE(5, 79)
108  Q_PROPERTY(QStringList dependencies READ dependencies CONSTANT)
109 #endif
110  Q_PROPERTY(QStringList serviceTypes READ serviceTypes CONSTANT)
111  Q_PROPERTY(QStringList mimeTypes READ mimeTypes CONSTANT)
112  Q_PROPERTY(QStringList formFactors READ formFactors CONSTANT)
113  Q_PROPERTY(bool isEnabledByDefault READ isEnabledByDefault CONSTANT)
114  Q_PROPERTY(int initialPreference READ isEnabledByDefault CONSTANT)
115 
116 public:
117  /** Creates an invalid KPluginMetaData instance */
118  KPluginMetaData();
119 
120  /**
121  * Reads the plugin metadata from a KPluginLoader instance. You must call KPluginLoader::setFileName()
122  * or use the appropriate constructor on @p loader before calling this.
123  */
124  KPluginMetaData(const KPluginLoader &loader);
125 
126  /**
127  * Reads the plugin metadata from a QPluginLoader instance. You must call QPluginLoader::setFileName()
128  * or use the appropriate constructor on @p loader before calling this.
129  */
130  KPluginMetaData(const QPluginLoader &loader);
131 
132  /**
133  * Reads the plugin metadata from a plugin or .desktop which can be loaded from @p file.
134  *
135  * For plugins, platform-specific library suffixes may be omitted since @p file will be resolved
136  * using the same logic as QPluginLoader.
137  *
138  * If the file name ends with ".desktop", the .desktop file will be parsed instead of
139  * reading the metadata from the QPluginLoader. This is the same as calling
140  * KPluginMetaData::fromDesktopFile() without the serviceTypes parameter.
141  *
142  * If @p file ends with .json, the file will be loaded as the QJsonObject metadata.
143  *
144  * @see QPluginLoader::setFileName()
145  * @see KPluginMetaData::fromDesktopFile()
146  */
147  KPluginMetaData(const QString &file);
148 
149  /**
150  * Creates a KPluginMetaData from a QJsonObject holding the metadata and a file name
151  * This can be used if the data is not retrieved from a Qt C++ plugin library but from some
152  * other source.
153  * @see KPluginMetaData(const QJsonObject &, const QString &, const QString &)
154  */
155  KPluginMetaData(const QJsonObject &metaData, const QString &file);
156 
157  // TODO: KF6: merge with the above and make metaDataFile default to QString()
158  /**
159  * Creates a KPluginMetaData
160  * @param metaData the JSON metadata to use for this object
161  * @param pluginFile the file that the plugin can be loaded from
162  * @param metaDataFile the file that the JSON metadata was read from
163  *
164  * This can be used if the data is not retrieved from a Qt C++ plugin library but from some
165  * other source.
166  *
167  * @since 5.5
168  */
169  KPluginMetaData(const QJsonObject &metaData, const QString &pluginFile, const QString &metaDataFile);
170 
171  /**
172  * Copy contructor
173  */
175  /**
176  * Copy assignment
177  */
178  KPluginMetaData &operator=(const KPluginMetaData &);
179  /**
180  * Destructor
181  */
182  ~KPluginMetaData();
183 
184  /**
185  * Load a KPluginMetaData instace from a .desktop file. Unlike the constructor which takes
186  * a single file parameter this method allows you to specify which service type files should
187  * be parsed to determine the correct type for a given .desktop property.
188  * This ensures that a e.g. comma-separated string list field in the .desktop file will correctly
189  * be converted to a JSON string array.
190  *
191  * @note This function mostly exists for backwards-compatibility. It is recommended
192  * that new applications load JSON files directly instead of using .desktop files for plugin metadata.
193  *
194  * @param file the .desktop file to load
195  * @param serviceTypes a list of files to parse If one of these paths is a relative path it
196  * will be resolved relative to the "kservicetypes5" subdirectory in QStandardPaths::GenericDataLocation.
197  * If the list is empty only the default set of properties will be treated specially and all other entries
198  * will be read as the JSON string type.
199  *
200  * @since 5.16
201  */
202  static KPluginMetaData fromDesktopFile(const QString &file, const QStringList &serviceTypes = QStringList());
203 
204  /**
205  * @return whether this object holds valid information about a plugin.
206  * If this is @c true pluginId() will return a non-empty string.
207  */
208  bool isValid() const;
209 
210  /**
211  * @return whether this object should be hidden, this is usually not used for binary
212  * plugins, when loading a KPluginMetaData from a .desktop file, this will reflect
213  * the value of the "Hidden" key.
214  *
215  * @since 5.8
216  */
217  bool isHidden() const;
218 
219  /**
220  * @return the path to the plugin. This string can be passed to the KPluginLoader
221  * or QPluginLoader constructors in order to attempt to load this plugin.
222  * @note It is not guaranteed that this is a valid path to a shared library (i.e. loadable
223  * by QPluginLoader) since the metadata could also refer to a non-C++ plugin.
224  */
225  QString fileName() const;
226 
227  /**
228  * @return the file that the metadata was read from. This is not necessarily the same as
229  * fileName(), since not all plugins have the metadata embedded. The metadata could also be
230  * stored in a separate .desktop file.
231  *
232  * @since 5.5
233  */
234  QString metaDataFileName() const;
235 
236  /**
237  * @return the full metadata stored inside the plugin file.
238  */
239  QJsonObject rawData() const;
240 
241  /**
242  * Tries to instantiate this plugin using KPluginMetaData::fileName().
243  * @note The value of KPluginMetaData::dependencies() is not used here, dependencies must be
244  * resolved manually.
245  *
246  * @return The plugin root object or @c nullptr if it could not be loaded
247  * @see QPluginLoader::instance(), KPluginLoader::instance()
248  */
249  QObject *instantiate() const;
250 
251  /**
252  * @return the user visible name of the plugin.
253  */
254  QString name() const;
255 
256  /**
257  * @return a short description of the plugin.
258  */
259  QString description() const;
260 
261  /**
262  * @return additional information about this plugin (e.g. for use in an "about plugin" dialog)
263  *
264  * @since 5.18
265  */
266  QString extraInformation() const;
267 
268  /**
269  * @return the author(s) of this plugin.
270  */
271  QList<KAboutPerson> authors() const;
272 
273  /**
274  * @return the translator(s) of this plugin.
275  *
276  * @since 5.18
277  */
278  QList<KAboutPerson> translators() const;
279 
280  /**
281  * @return a list of people that contributed to this plugin (other than the authors and translators).
282  *
283  * @since 5.18
284  */
285  QList<KAboutPerson> otherContributors() const;
286 
287  /**
288  * @return the categories of this plugin (e.g. "playlist/skin").
289  */
290  QString category() const;
291 
292  /**
293  * @return the icon name for this plugin
294  * @see QIcon::fromTheme()
295  */
296  QString iconName() const;
297 
298  /**
299  * @return the short license identifier (e.g. LGPL).
300  * @see KAboutLicense::byKeyword() for retrieving the full license information
301  */
302  QString license() const;
303 
304  /**
305  * @return the text of the license, equivalent to KAboutLicense::byKeyword(license()).text()
306  * @since 5.73
307  */
308  QString licenseText() const;
309 
310  /**
311  * @return a short copyright statement
312  *
313  * @since 5.18
314  */
315  QString copyrightText() const;
316 
317  /**
318  * @return the internal name of the plugin
319  * If the Id property is not set in the metadata, this will return the
320  * plugin file name without the file extension.
321  */
322  QString pluginId() const;
323 
324  /**
325  * @return the version of the plugin.
326  */
327  QString version() const;
328 
329  /**
330  * @return the website of the plugin.
331  */
332  QString website() const;
333 
334 #if KCOREADDONS_ENABLE_DEPRECATED_SINCE(5, 79)
335  /**
336  * @return a list of plugins that this plugin depends on so that it can function properly
337  * @see KJsonPluginInfo::pluginId()
338  * @deprecated Since 5.79, plugin dependencies are deprecated and will be removed in KF6
339  */
340  KCOREADDONS_DEPRECATED_VERSION(5, 79, "Plugin dependencies are deprecated and will be removed in KF6")
341  QStringList dependencies() const;
342 #endif
343 
344  /**
345  * Returns the service types that this plugin implements.
346  *
347  * This is mostly for historical / compatibility purposes.
348  * As a general rule, instead of opening many plugins to then filter by servicetype,
349  * put all plugins of the same type in a subdirectory, that you can pass to findPlugins directly.
350  * No point in opening 20 plugins to pick out only 3, when the filesystem can do that filtering for you.
351  *
352  * @note Unlike KService this does not contain the MIME types. To get the handled MIME types
353  * use the KPluginMetaData::mimeTypes() function.
354  * @return a list of service types this plugin implements (e.g. "Plasma/DataEngine")
355  */
356  QStringList serviceTypes() const;
357 
358  /**
359  * @return a list of MIME types this plugin can handle (e.g. "application/pdf", "image/png", etc.)
360  * @since 5.16
361  */
362  QStringList mimeTypes() const;
363 
364  /**
365  * @return true if this plugin can handle the given mimetype
366  * This is more accurate than mimeTypes().contains(mimeType) because it also
367  * takes MIME type inheritance into account.
368  * @since 5.66
369  */
370  bool supportsMimeType(const QString &mimeType) const;
371 
372  /**
373  * @return A string list of formfactors this plugin is useful for, e.g. desktop, tablet,
374  * handset, mediacenter, etc.
375  * The keys for this are not formally defined.
376  *
377  * @since 5.12
378  */
379  QStringList formFactors() const;
380 
381  /**
382  * @return whether the plugin should be enabled by default.
383  * This is only a recommendation, applications can ignore this value if they want to.
384  */
385  bool isEnabledByDefault() const;
386 
387  /**
388  * @return the initial preference of the plugin.
389  * This is the preference to associate with this plugin initially (before
390  * the user has had any chance to define preferences for it).
391  * Higher values indicate stronger preference.
392  * @since 5.67
393  */
394  int initialPreference() const;
395 
396  /**
397  * @return the value for @p key from the metadata or @p defaultValue if the key does not exist
398  * or the value for @p key is not of type string
399  *
400  * @see KPluginMetaData::rawData() if QString is not the correct type for @p key
401  */
402  QString value(const QString &key, const QString &defaultValue = QString()) const;
403 
404  /** @return the value for @p key inside @p jo as a string list. If the type of @p key is string, a list with containing
405  * just that string will be returned, if it is an array the list will contain one entry for each array member.
406  * If the key cannot be found an empty list will be returned.
407  */
408  static QStringList readStringList(const QJsonObject &jo, const QString &key);
409 
410  /**
411  * Reads a value from @p jo but unlike QJsonObject::value() it allows different entries for each locale
412  * This is done by appending the locale identifier in brackets to the key (e.g. "[de_DE]" or "[es]")
413  * When looking for a key "foo" with German (Germany) locale we will first attempt to read "foo[de_DE]",
414  * if that does not exist "foo[de]", finally falling back to "foo" if that also doesn't exist.
415  * @return the translated value for @p key from @p jo or @p defaultValue if @p key was not found
416  */
417  static QJsonValue readTranslatedValue(const QJsonObject &jo, const QString &key, const QJsonValue &defaultValue = QJsonValue());
418 
419  /**
420  * @return the translated value of @p key from @p jo as a string or @p defaultValue if @p key was not found
421  * or the value for @p key is not of type string
422  * @see KPluginMetaData::readTranslatedValue(const QJsonObject &jo, const QString &key)
423  */
424  static QString readTranslatedString(const QJsonObject &jo, const QString &key, const QString &defaultValue = QString());
425 
426  /**
427  * @return @c true if this object is equal to @p other, otherwise @c false
428  */
429  bool operator==(const KPluginMetaData &other) const;
430 
431  /**
432  * @return @c true if this object is not equal to @p other, otherwise @c false.
433  */
434  inline bool operator!=(const KPluginMetaData &other) const
435  {
436  return !(*this == other);
437  }
438 
439 private:
440  QJsonObject rootObject() const;
441  void loadFromDesktopFile(const QString &file, const QStringList &serviceTypes);
442 
443 private:
444  QVariantList authorsVariant() const;
445  QVariantList translatorsVariant() const;
446  QVariantList otherContributorsVariant() const;
447 
448  QJsonObject m_metaData;
449  QString m_fileName;
450  QExplicitlySharedDataPointer<KPluginMetaDataPrivate> d; // for future binary compatible extensions
451 };
452 
453 inline uint qHash(const KPluginMetaData &md, uint seed)
454 {
455  return qHash(md.pluginId(), seed);
456 }
457 
458 Q_DECLARE_METATYPE(KPluginMetaData)
459 
460 #endif // KPLUGINMETADATA_H
This class behaves largely like QPluginLoader (and, indeed, uses it internally), but additionally rea...
Definition: kpluginloader.h:61
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
This class is used to store information about a person or developer.
Definition: kaboutdata.h:56
bool operator!=(const KPluginMetaData &other) const
This class allows easily accessing some standardized values from the JSON metadata that can be embedd...
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Thu May 13 2021 23:01:38 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.