This file is part of the KDE project
SPDX-FileCopyrightText: 2014 Alex Richardson <arichardson.kde@gmail.com>
SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KPLUGINMETADATA_H
#define KPLUGINMETADATA_H
#include "kcoreaddons_export.h"
#include <QExplicitlySharedDataPointer>
#include <QJsonObject>
#include <QMetaType>
#include <QString>
#include <QStringList>
#include <functional>
class QPluginLoader;
class QStaticPlugin;
class KPluginMetaDataPrivate;
class KAboutPerson;
* @class KPluginMetaData kpluginmetadata.h KPluginMetaData
*
* This class allows easily accessing some standardized values from the JSON metadata that
* can be embedded into Qt plugins. Additional plugin-specific metadata can be retrieved by
* directly reading from the QJsonObject returned by KPluginMetaData::rawData().
*
* For embedded metadata, you should not specify an id manually. Instead the id will
* be derived from the file basename.
*
* The following keys will be read from an object "KPlugin" inside the metadata JSON:
*
* Key | Accessor function | JSON Type
* -------------------| -------------------- | ---------------------
* Name | name() | string
* Description | description() | string
* Icon | iconName() | string
* Authors | authors() | object array (KAboutPerson)
* Category | category() | string
* License | license() | string
* Copyright | copyrightText() | string
* Id | pluginId() | string
* Version | version() | string
* Website | website() | string
* BugReportUrl | bugReportUrl() | string
* EnabledByDefault | isEnabledByDefault() | bool
* MimeTypes | mimeTypes() | string array
* FormFactors | formFactors() | string array
* Translators | translators() | object array (KAboutPerson)
* OtherContributors | otherContributors() | object array (KAboutPerson)
*
* The Authors, Translators and OtherContributors keys are expected to be
* list of objects that match the structure expected by KAboutPerson::fromJSON().
*
* An example metadata json file could look like this:
* @verbatim
{
"KPlugin": {
"Name": "Date and Time",
"Description": "Date and time by timezone",
"Icon": "preferences-system-time",
"Authors": [ { "Name": "Aaron Seigo", "Email": "aseigo@kde.org" } ],
"Category": "Date and Time",
"EnabledByDefault": "true",
"License": "LGPL",
"Version": "1.0",
"Website": "https://plasma.kde.org/"
}
}
@endverbatim
*
* @sa KAboutPerson::fromJSON()
* @since 5.1
*/
class KCOREADDONS_EXPORT KPluginMetaData
{
Q_GADGET
Q_PROPERTY(bool isValid READ isValid CONSTANT)
Q_PROPERTY(bool isHidden READ isHidden CONSTANT)
Q_PROPERTY(QString fileName READ fileName CONSTANT)
Q_PROPERTY(QJsonObject rawData READ rawData CONSTANT)
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QString description READ description CONSTANT)
Q_PROPERTY(QList<KAboutPerson> authors READ authors CONSTANT)
Q_PROPERTY(QList<KAboutPerson> translators READ translators CONSTANT)
Q_PROPERTY(QList<KAboutPerson> otherContributors READ otherContributors CONSTANT)
Q_PROPERTY(QString category READ category CONSTANT)
Q_PROPERTY(QString iconName READ iconName CONSTANT)
Q_PROPERTY(QString license READ license CONSTANT)
Q_PROPERTY(QString licenseText READ licenseText CONSTANT)
Q_PROPERTY(QString copyrightText READ copyrightText CONSTANT)
Q_PROPERTY(QString pluginId READ pluginId CONSTANT)
Q_PROPERTY(QString version READ version CONSTANT)
Q_PROPERTY(QString website READ website CONSTANT)
Q_PROPERTY(QString bugReportUrl READ bugReportUrl CONSTANT)
Q_PROPERTY(QStringList mimeTypes READ mimeTypes CONSTANT)
Q_PROPERTY(QStringList formFactors READ formFactors CONSTANT)
Q_PROPERTY(bool isEnabledByDefault READ isEnabledByDefault CONSTANT)
public:
* Options for creating a KPluginMetaData object.
* @since 5.91
*/
enum KPluginMetaDataOption {
AllowEmptyMetaData = 1,
* If KCoreAddons should keep metadata in cache. This makes querying the namespace again faster. Consider using this if you need revalidation of plugins
* @since 6.0
*/
CacheMetaData = 2,
};
Q_DECLARE_FLAGS(KPluginMetaDataOptions, KPluginMetaDataOption)
Q_FLAG(KPluginMetaDataOption)
KPluginMetaData();
* Reads the plugin metadata from a QPluginLoader instance. You must call QPluginLoader::setFileName()
* or use the appropriate constructor on @p loader before calling this.
* @param option Added in 6.0, see enum docs
*/
KPluginMetaData(const QPluginLoader &loader, KPluginMetaDataOptions options = {});
* Reads the plugin metadata from a plugin which can be loaded from @p file.
*
* Platform-specific library suffixes may be omitted since @p file will be resolved
* using the same logic as QPluginLoader.
*
* @see QPluginLoader::setFileName()
*/
KPluginMetaData(const QString &pluginFile, KPluginMetaDataOptions options = {});
* Creates a KPluginMetaData from a QJsonObject holding the metadata and a file name
* This can be used if the data is not retrieved from a Qt C++ plugin library but from some
* other source.
*
* @param metaData the JSON metadata to use for this object
* @param pluginFile the file that the plugin can be loaded from
*
* @since 6.0
*/
KPluginMetaData(const QJsonObject &metaData, const QString &fileName);
* Copy contructor
*/
KPluginMetaData(const KPluginMetaData &);
* Copy assignment
*/
KPluginMetaData &operator=(const KPluginMetaData &);
* Destructor
*/
~KPluginMetaData();
* Load a KPluginMetaData instance from a .json file. Unlike the constructor with a single file argument,
* this ensure that only JSON format plugins are loaded and any other type is rejected.
*
* @param jsonFile the .json file to load
* @since 5.91
*/
static KPluginMetaData fromJsonFile(const QString &jsonFile);
* @param directory The directory to search for plugins. If a relative path is given for @p directory,
* all entries of QCoreApplication::libraryPaths() will be checked with @p directory appended as a
* subdirectory. If an absolute path is given only that directory will be searched.
* @note Check if the returned KPluginMetaData is valid before continuing to use it.
*
* @param pluginId The Id of the plugin. The id should be the same as the filename, see KPluginMetaData::pluginId()
* @param option Added in 6.0, see enum docs
* @since 5.84
*/
static KPluginMetaData findPluginById(const QString &directory, const QString &pluginId, KPluginMetaDataOptions options = {});
* Find all plugins inside @p directory. Only plugins which have JSON metadata will be considered.
*
* @param directory The directory to search for plugins. If a relative path is given for @p directory,
* all entries of QCoreApplication::libraryPaths() will be checked with @p directory appended as a
* subdirectory. If an absolute path is given only that directory will be searched.
*
* @param filter a callback function that returns @c true if the found plugin should be loaded
* and @c false if it should be skipped. If this argument is omitted all plugins will be loaded
* @param option Weather or not allow plugins with empty metadata to be considered valid
*
* @return all plugins found in @p directory that fulfil the constraints of @p filter
* @since 5.86
*/
static QList<KPluginMetaData>
findPlugins(const QString &directory, std::function<bool(const KPluginMetaData &)> filter = {}, KPluginMetaDataOptions options = {});
* @return whether this object holds valid information about a plugin.
* If this is @c true pluginId() will return a non-empty string.
*/
bool isValid() const;
* @return whether this object should be hidden
*
* @since 5.8
*/
bool isHidden() const;
* @return the path to the plugin.
* When the KPluginMetaData(QJsonObject, QString) constructor is used, the string is not modified.
* Otherwise, the path is resolved using QPluginLoader.
* For static plugins the fileName is the namespace and pluginId concatenated
*
* @note It is not guaranteed that this is a valid path to a shared library (i.e. loadable
* by QPluginLoader) since the metadata could also refer to a non-C++ plugin.
*/
QString fileName() const;
* @return the full metadata stored inside the plugin file.
*/
QJsonObject rawData() const;
* @return the user visible name of the plugin.
*/
QString name() const;
* @return a short description of the plugin.
*/
QString description() const;
* @return the author(s) of this plugin.
*/
QList<KAboutPerson> authors() const;
* @return the translator(s) of this plugin.
*
* @since 5.18
*/
QList<KAboutPerson> translators() const;
* @return a list of people that contributed to this plugin (other than the authors and translators).
*
* @since 5.18
*/
QList<KAboutPerson> otherContributors() const;
* @return the categories of this plugin (e.g. "playlist/skin").
*/
QString category() const;
* @return the icon name for this plugin
* @see QIcon::fromTheme()
*/
QString iconName() const;
* @return the short license identifier (e.g. LGPL).
* @see KAboutLicense::byKeyword() for retrieving the full license information
*/
QString license() const;
* @return the text of the license, equivalent to KAboutLicense::byKeyword(license()).text()
* @since 5.73
*/
QString licenseText() const;
* @return a short copyright statement
*
* @since 5.18
*/
QString copyrightText() const;
* @return the unique identifier within the namespace of the plugin
*
* For C++ plugins, this ID is derived from the filename.
* It should not be set in the metadata explicitly.
*
* When using @ref KPluginMetaData::fromJsonFile or @ref KPluginMetaData(QJsonObject, QString),
* the "Id" of the "KPlugin" object will be used. If unset, it will be derived
* from the filename.
*/
QString pluginId() const;
* @return the version of the plugin.
*/
QString version() const;
* @return the website of the plugin.
*/
QString website() const;
* @return the website where people can report a bug found in this plugin
* @since 5.99
*/
QString bugReportUrl() const;
* @return a list of MIME types this plugin can handle (e.g. "application/pdf", "image/png", etc.)
* @since 5.16
*/
QStringList mimeTypes() const;
* @return true if this plugin can handle the given mimetype
* This is more accurate than mimeTypes().contains(mimeType) because it also
* takes MIME type inheritance into account.
* @since 5.66
*/
bool supportsMimeType(const QString &mimeType) const;
* @return A string list of formfactors this plugin is useful for, e.g. desktop, handset or mediacenter.
* The keys for this are not formally defined, though the above-mentioned values should be used when applicable.
*
* @since 5.12
*/
QStringList formFactors() const;
* @return whether the plugin should be enabled by default.
* This is only a recommendation, applications can ignore this value if they want to.
*/
bool isEnabledByDefault() const;
* Returns @c true if the plugin is enabled in @p config, otherwise returns isEnabledByDefault().
* This can be used in conjunction with KPluginWidget.
*
* The @p config param should be a KConfigGroup object, because KCoreAddons can not depend
* on KConfig directly, this parameter is a template.
* @param config KConfigGroup where the enabled state is stored
* @since 5.89
*/
template<typename T>
bool isEnabled(const T &config) const
{
Q_ASSERT(config.isValid());
return config.readEntry(pluginId() + QLatin1String("Enabled"), isEnabledByDefault());
}
* @return the string value for @p key from the metadata or @p defaultValue if the key does not exist
*
* if QString is not the correct type for @p key you should use the other overloads or @ref KPluginMetaData::rawData
*/
QString value(QStringView key, const QString &defaultValue = QString()) const;
QString value(const QString &key, const QString &defaultValue = QString()) const;
QString value(const QString &key, const char *ch) const = delete;
* @overload
* @since 5.88
*/
bool value(QStringView key, bool defaultValue) const;
bool value(const QString &key, bool defaultValue) const;
* @overload
* @since 5.88
*/
int value(QStringView key, int defaultValue) const;
int value(const QString &key, int defaultValue) const;
* If the type of @p key is string, a list containing just that string will be returned.
* If the type is array, the list will contain one entry for each array member.
* @overload
* @since 5.88
*/
QStringList value(QStringView key, const QStringList &defaultValue) const;
QStringList value(const QString &key, const QStringList &defaultValue) const;
* @return @c true if this object is equal to @p other, otherwise @c false
*/
bool operator==(const KPluginMetaData &other) const;
* @return @c true if this object is not equal to @p other, otherwise @c false.
*/
inline bool operator!=(const KPluginMetaData &other) const
{
return !(*this == other);
}
* @note for loading plugin the plugin independently of it being static/dynamic
* use @ref KPluginFactory::loadFactory or @ref KPluginFactory::instantiatePlugin.
* @return true if the instance represents a static plugin
* @since 5.89
*/
bool isStaticPlugin() const;
private:
KCOREADDONS_NO_EXPORT QStaticPlugin staticPlugin() const;
KCOREADDONS_NO_EXPORT QString requestedFileName() const;
QExplicitlySharedDataPointer<KPluginMetaDataPrivate> d;
friend class KPluginFactory;
friend class KPluginMetaDataPrivate;
};
inline size_t qHash(const KPluginMetaData &md, size_t seed)
{
return qHash(md.pluginId(), seed);
}
KCOREADDONS_EXPORT QDebug operator<<(QDebug debug, const KPluginMetaData &metaData);
Q_DECLARE_TYPEINFO(KPluginMetaData, Q_RELOCATABLE_TYPE);
Q_DECLARE_OPERATORS_FOR_FLAGS(KPluginMetaData::KPluginMetaDataOptions)
#endif