File indexing completed on 2024-05-12 03:54:57
0001 /* 0002 This file is part of the KDE project 0003 0004 SPDX-FileCopyrightText: 2014 Alex Richardson <arichardson.kde@gmail.com> 0005 SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #ifndef KPLUGINMETADATA_H 0011 #define KPLUGINMETADATA_H 0012 0013 #include "kcoreaddons_export.h" 0014 0015 #include <QExplicitlySharedDataPointer> 0016 #include <QJsonObject> 0017 #include <QMetaType> 0018 #include <QString> 0019 #include <QStringList> 0020 0021 #include <functional> 0022 0023 class QPluginLoader; 0024 class QStaticPlugin; 0025 class KPluginMetaDataPrivate; 0026 class KAboutPerson; 0027 /** 0028 * @class KPluginMetaData kpluginmetadata.h KPluginMetaData 0029 * 0030 * This class allows easily accessing some standardized values from the JSON metadata that 0031 * can be embedded into Qt plugins. Additional plugin-specific metadata can be retrieved by 0032 * directly reading from the QJsonObject returned by KPluginMetaData::rawData(). 0033 * 0034 * For embedded metadata, you should not specify an id manually. Instead the id will 0035 * be derived from the file basename. 0036 * 0037 * The following keys will be read from an object "KPlugin" inside the metadata JSON: 0038 * 0039 * Key | Accessor function | JSON Type 0040 * -------------------| -------------------- | --------------------- 0041 * Name | name() | string 0042 * Description | description() | string 0043 * Icon | iconName() | string 0044 * Authors | authors() | object array (KAboutPerson) 0045 * Category | category() | string 0046 * License | license() | string 0047 * Copyright | copyrightText() | string 0048 * Id | pluginId() | string 0049 * Version | version() | string 0050 * Website | website() | string 0051 * BugReportUrl | bugReportUrl() | string 0052 * EnabledByDefault | isEnabledByDefault() | bool 0053 * MimeTypes | mimeTypes() | string array 0054 * FormFactors | formFactors() | string array 0055 * Translators | translators() | object array (KAboutPerson) 0056 * OtherContributors | otherContributors() | object array (KAboutPerson) 0057 * 0058 * The Authors, Translators and OtherContributors keys are expected to be 0059 * list of objects that match the structure expected by KAboutPerson::fromJSON(). 0060 * 0061 * An example metadata json file could look like this: 0062 * @verbatim 0063 { 0064 "KPlugin": { 0065 "Name": "Date and Time", 0066 "Description": "Date and time by timezone", 0067 "Icon": "preferences-system-time", 0068 "Authors": [ { "Name": "Aaron Seigo", "Email": "aseigo@kde.org" } ], 0069 "Category": "Date and Time", 0070 "EnabledByDefault": "true", 0071 "License": "LGPL", 0072 "Version": "1.0", 0073 "Website": "https://plasma.kde.org/" 0074 } 0075 } 0076 @endverbatim 0077 * 0078 * @sa KAboutPerson::fromJSON() 0079 * @since 5.1 0080 */ 0081 class KCOREADDONS_EXPORT KPluginMetaData 0082 { 0083 Q_GADGET 0084 Q_PROPERTY(bool isValid READ isValid CONSTANT) 0085 Q_PROPERTY(bool isHidden READ isHidden CONSTANT) 0086 Q_PROPERTY(QString fileName READ fileName CONSTANT) 0087 Q_PROPERTY(QJsonObject rawData READ rawData CONSTANT) 0088 Q_PROPERTY(QString name READ name CONSTANT) 0089 Q_PROPERTY(QString description READ description CONSTANT) 0090 Q_PROPERTY(QList<KAboutPerson> authors READ authors CONSTANT) 0091 Q_PROPERTY(QList<KAboutPerson> translators READ translators CONSTANT) 0092 Q_PROPERTY(QList<KAboutPerson> otherContributors READ otherContributors CONSTANT) 0093 Q_PROPERTY(QString category READ category CONSTANT) 0094 Q_PROPERTY(QString iconName READ iconName CONSTANT) 0095 Q_PROPERTY(QString license READ license CONSTANT) 0096 Q_PROPERTY(QString licenseText READ licenseText CONSTANT) 0097 Q_PROPERTY(QString copyrightText READ copyrightText CONSTANT) 0098 Q_PROPERTY(QString pluginId READ pluginId CONSTANT) 0099 Q_PROPERTY(QString version READ version CONSTANT) 0100 Q_PROPERTY(QString website READ website CONSTANT) 0101 Q_PROPERTY(QString bugReportUrl READ bugReportUrl CONSTANT) 0102 Q_PROPERTY(QStringList mimeTypes READ mimeTypes CONSTANT) 0103 Q_PROPERTY(QStringList formFactors READ formFactors CONSTANT) 0104 Q_PROPERTY(bool isEnabledByDefault READ isEnabledByDefault CONSTANT) 0105 0106 public: 0107 /** 0108 * Options for creating a KPluginMetaData object. 0109 * @since 5.91 0110 */ 0111 enum KPluginMetaDataOption { 0112 AllowEmptyMetaData = 1, ///< Plugins with empty metaData are considered valid 0113 /** 0114 * If KCoreAddons should keep metadata in cache. This makes querying the namespace again faster. Consider using this if you need revalidation of plugins 0115 * @since 6.0 0116 */ 0117 CacheMetaData = 2, 0118 }; 0119 Q_DECLARE_FLAGS(KPluginMetaDataOptions, KPluginMetaDataOption) 0120 Q_FLAG(KPluginMetaDataOption) 0121 0122 /** Creates an invalid KPluginMetaData instance */ 0123 KPluginMetaData(); 0124 0125 /** 0126 * Reads the plugin metadata from a QPluginLoader instance. You must call QPluginLoader::setFileName() 0127 * or use the appropriate constructor on @p loader before calling this. 0128 * @param option Added in 6.0, see enum docs 0129 */ 0130 KPluginMetaData(const QPluginLoader &loader, KPluginMetaDataOptions options = {}); 0131 0132 /** 0133 * Reads the plugin metadata from a plugin which can be loaded from @p file. 0134 * 0135 * Platform-specific library suffixes may be omitted since @p file will be resolved 0136 * using the same logic as QPluginLoader. 0137 * 0138 * @see QPluginLoader::setFileName() 0139 */ 0140 KPluginMetaData(const QString &pluginFile, KPluginMetaDataOptions options = {}); 0141 0142 /** 0143 * Creates a KPluginMetaData from a QJsonObject holding the metadata and a file name 0144 * This can be used if the data is not retrieved from a Qt C++ plugin library but from some 0145 * other source. 0146 * 0147 * @param metaData the JSON metadata to use for this object 0148 * @param pluginFile the file that the plugin can be loaded from 0149 * 0150 * @since 6.0 0151 */ 0152 KPluginMetaData(const QJsonObject &metaData, const QString &fileName); 0153 0154 /** 0155 * Copy contructor 0156 */ 0157 KPluginMetaData(const KPluginMetaData &); 0158 /** 0159 * Copy assignment 0160 */ 0161 KPluginMetaData &operator=(const KPluginMetaData &); 0162 /** 0163 * Destructor 0164 */ 0165 ~KPluginMetaData(); 0166 0167 /** 0168 * Load a KPluginMetaData instance from a .json file. Unlike the constructor with a single file argument, 0169 * this ensure that only JSON format plugins are loaded and any other type is rejected. 0170 * 0171 * @param jsonFile the .json file to load 0172 * @since 5.91 0173 */ 0174 static KPluginMetaData fromJsonFile(const QString &jsonFile); 0175 0176 /** 0177 * @param directory The directory to search for plugins. If a relative path is given for @p directory, 0178 * all entries of QCoreApplication::libraryPaths() will be checked with @p directory appended as a 0179 * subdirectory. If an absolute path is given only that directory will be searched. 0180 * @note Check if the returned KPluginMetaData is valid before continuing to use it. 0181 * 0182 * @param pluginId The Id of the plugin. The id should be the same as the filename, see KPluginMetaData::pluginId() 0183 * @param option Added in 6.0, see enum docs 0184 * @since 5.84 0185 */ 0186 static KPluginMetaData findPluginById(const QString &directory, const QString &pluginId, KPluginMetaDataOptions options = {}); 0187 0188 /** 0189 * Find all plugins inside @p directory. Only plugins which have JSON metadata will be considered. 0190 * 0191 * @param directory The directory to search for plugins. If a relative path is given for @p directory, 0192 * all entries of QCoreApplication::libraryPaths() will be checked with @p directory appended as a 0193 * subdirectory. If an absolute path is given only that directory will be searched. 0194 * 0195 * @param filter a callback function that returns @c true if the found plugin should be loaded 0196 * and @c false if it should be skipped. If this argument is omitted all plugins will be loaded 0197 * @param option Weather or not allow plugins with empty metadata to be considered valid 0198 * 0199 * @return all plugins found in @p directory that fulfil the constraints of @p filter 0200 * @since 5.86 0201 */ 0202 static QList<KPluginMetaData> 0203 findPlugins(const QString &directory, std::function<bool(const KPluginMetaData &)> filter = {}, KPluginMetaDataOptions options = {}); 0204 0205 /** 0206 * @return whether this object holds valid information about a plugin. 0207 * If this is @c true pluginId() will return a non-empty string. 0208 */ 0209 bool isValid() const; 0210 0211 /** 0212 * @return whether this object should be hidden 0213 * 0214 * @since 5.8 0215 */ 0216 bool isHidden() const; 0217 0218 /** 0219 * @return the path to the plugin. 0220 * When the KPluginMetaData(QJsonObject, QString) constructor is used, the string is not modified. 0221 * Otherwise, the path is resolved using QPluginLoader. 0222 * For static plugins the fileName is the namespace and pluginId concatenated 0223 * 0224 * @note It is not guaranteed that this is a valid path to a shared library (i.e. loadable 0225 * by QPluginLoader) since the metadata could also refer to a non-C++ plugin. 0226 */ 0227 QString fileName() const; 0228 0229 /** 0230 * @return the full metadata stored inside the plugin file. 0231 */ 0232 QJsonObject rawData() const; 0233 0234 /** 0235 * @return the user visible name of the plugin. 0236 */ 0237 QString name() const; 0238 0239 /** 0240 * @return a short description of the plugin. 0241 */ 0242 QString description() const; 0243 0244 /** 0245 * @return the author(s) of this plugin. 0246 */ 0247 QList<KAboutPerson> authors() const; 0248 0249 /** 0250 * @return the translator(s) of this plugin. 0251 * 0252 * @since 5.18 0253 */ 0254 QList<KAboutPerson> translators() const; 0255 0256 /** 0257 * @return a list of people that contributed to this plugin (other than the authors and translators). 0258 * 0259 * @since 5.18 0260 */ 0261 QList<KAboutPerson> otherContributors() const; 0262 0263 /** 0264 * @return the categories of this plugin (e.g. "playlist/skin"). 0265 */ 0266 QString category() const; 0267 0268 /** 0269 * @return the icon name for this plugin 0270 * @see QIcon::fromTheme() 0271 */ 0272 QString iconName() const; 0273 0274 /** 0275 * @return the short license identifier (e.g. LGPL). 0276 * @see KAboutLicense::byKeyword() for retrieving the full license information 0277 */ 0278 QString license() const; 0279 0280 /** 0281 * @return the text of the license, equivalent to KAboutLicense::byKeyword(license()).text() 0282 * @since 5.73 0283 */ 0284 QString licenseText() const; 0285 0286 /** 0287 * @return a short copyright statement 0288 * 0289 * @since 5.18 0290 */ 0291 QString copyrightText() const; 0292 0293 /** 0294 * @return the unique identifier within the namespace of the plugin 0295 * 0296 * For C++ plugins, this ID is derived from the filename. 0297 * It should not be set in the metadata explicitly. 0298 * 0299 * When using @ref KPluginMetaData::fromJsonFile or @ref KPluginMetaData(QJsonObject, QString), 0300 * the "Id" of the "KPlugin" object will be used. If unset, it will be derived 0301 * from the filename. 0302 */ 0303 QString pluginId() const; 0304 0305 /** 0306 * @return the version of the plugin. 0307 */ 0308 QString version() const; 0309 0310 /** 0311 * @return the website of the plugin. 0312 */ 0313 QString website() const; 0314 0315 /** 0316 * @return the website where people can report a bug found in this plugin 0317 * @since 5.99 0318 */ 0319 QString bugReportUrl() const; 0320 0321 /** 0322 * @return a list of MIME types this plugin can handle (e.g. "application/pdf", "image/png", etc.) 0323 * @since 5.16 0324 */ 0325 QStringList mimeTypes() const; 0326 0327 /** 0328 * @return true if this plugin can handle the given mimetype 0329 * This is more accurate than mimeTypes().contains(mimeType) because it also 0330 * takes MIME type inheritance into account. 0331 * @since 5.66 0332 */ 0333 bool supportsMimeType(const QString &mimeType) const; 0334 0335 /** 0336 * @return A string list of formfactors this plugin is useful for, e.g. desktop, handset or mediacenter. 0337 * The keys for this are not formally defined, though the above-mentioned values should be used when applicable. 0338 * 0339 * @since 5.12 0340 */ 0341 QStringList formFactors() const; 0342 0343 /** 0344 * @return whether the plugin should be enabled by default. 0345 * This is only a recommendation, applications can ignore this value if they want to. 0346 */ 0347 bool isEnabledByDefault() const; 0348 0349 /** 0350 * Returns @c true if the plugin is enabled in @p config, otherwise returns isEnabledByDefault(). 0351 * This can be used in conjunction with KPluginWidget. 0352 * 0353 * The @p config param should be a KConfigGroup object, because KCoreAddons can not depend 0354 * on KConfig directly, this parameter is a template. 0355 * @param config KConfigGroup where the enabled state is stored 0356 * @since 5.89 0357 */ 0358 template<typename T> 0359 bool isEnabled(const T &config) const 0360 { 0361 Q_ASSERT(config.isValid()); 0362 return config.readEntry(pluginId() + QLatin1String("Enabled"), isEnabledByDefault()); 0363 } 0364 0365 /** 0366 * @return the string value for @p key from the metadata or @p defaultValue if the key does not exist 0367 * 0368 * if QString is not the correct type for @p key you should use the other overloads or @ref KPluginMetaData::rawData 0369 */ 0370 QString value(const QString &key, const QString &defaultValue = QString()) const; 0371 QString value(const QString &key, const char *ch) const = delete; 0372 0373 /** 0374 * @overload 0375 * @since 5.88 0376 */ 0377 bool value(const QString &key, bool defaultValue) const; 0378 0379 /** 0380 * @overload 0381 * @since 5.88 0382 */ 0383 int value(const QString &key, int defaultValue) const; 0384 0385 /** @return the value for @p key from the metadata or @p defaultValue if the key does not exist. 0386 * If the type of @p key is string, a list containing just that string will be returned. 0387 * If the type is array, the list will contain one entry for each array member. 0388 * @overload 0389 * @since 5.88 0390 */ 0391 QStringList value(const QString &key, const QStringList &defaultValue) const; 0392 0393 /** 0394 * @return @c true if this object is equal to @p other, otherwise @c false 0395 */ 0396 bool operator==(const KPluginMetaData &other) const; 0397 0398 /** 0399 * @return @c true if this object is not equal to @p other, otherwise @c false. 0400 */ 0401 inline bool operator!=(const KPluginMetaData &other) const 0402 { 0403 return !(*this == other); 0404 } 0405 0406 /** 0407 * @note for loading plugin the plugin independently of it being static/dynamic 0408 * use @ref KPluginFactory::loadFactory or @ref KPluginFactory::instantiatePlugin. 0409 * @return true if the instance represents a static plugin 0410 * @since 5.89 0411 */ 0412 bool isStaticPlugin() const; 0413 0414 private: 0415 KCOREADDONS_NO_EXPORT QStaticPlugin staticPlugin() const; 0416 KCOREADDONS_NO_EXPORT QString requestedFileName() const; 0417 0418 QExplicitlySharedDataPointer<KPluginMetaDataPrivate> d; 0419 friend class KPluginFactory; 0420 friend class KPluginMetaDataPrivate; 0421 }; 0422 0423 inline size_t qHash(const KPluginMetaData &md, size_t seed) 0424 { 0425 return qHash(md.pluginId(), seed); 0426 } 0427 0428 /// @since 6.0 0429 KCOREADDONS_EXPORT QDebug operator<<(QDebug debug, const KPluginMetaData &metaData); 0430 0431 Q_DECLARE_TYPEINFO(KPluginMetaData, Q_RELOCATABLE_TYPE); 0432 Q_DECLARE_OPERATORS_FOR_FLAGS(KPluginMetaData::KPluginMetaDataOptions) 0433 0434 #endif // KPLUGINMETADATA_H