mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00

already done by KComponentDataPrivate, when the component is created and deleted Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
485 lines
19 KiB
C++
485 lines
19 KiB
C++
/* This file is part of the KDE project
|
|
Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
|
|
Copyright (C) 2007 Bernhard Loos <nhuh.put@web.de>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
#ifndef KDECORE_KPLUGINFACTORY_H
|
|
#define KDECORE_KPLUGINFACTORY_H
|
|
|
|
#include "kdecore_export.h"
|
|
|
|
#include <QtCore/QObject>
|
|
#include <QtCore/QVariant>
|
|
#include <QtCore/QStringList>
|
|
#include <QtCore/qplugin.h>
|
|
#include <kcomponentdata.h>
|
|
#include <kglobal.h>
|
|
|
|
class KPluginFactoryPrivate;
|
|
namespace KParts { class Part; }
|
|
|
|
#define K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, baseFactory) \
|
|
class name : public baseFactory \
|
|
{ \
|
|
public: \
|
|
explicit name(const char * = 0, const char * = 0, QObject * = 0); \
|
|
explicit name(const KAboutData &, QObject * = 0); \
|
|
~name(); \
|
|
static KComponentData componentData(); \
|
|
private: \
|
|
void init(); \
|
|
};
|
|
|
|
#define K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) \
|
|
K_GLOBAL_STATIC(KComponentData, name##factorycomponentdata) \
|
|
name::name(const char *componentName, const char *catalogName, QObject *parent) \
|
|
: baseFactory(componentName, catalogName, parent) { init(); } \
|
|
name::name(const KAboutData &aboutData, QObject *parent) \
|
|
: baseFactory(aboutData, parent) { init(); } \
|
|
void name::init() \
|
|
{ \
|
|
if (name##factorycomponentdata->isValid()) \
|
|
setComponentData(*name##factorycomponentdata); \
|
|
else \
|
|
*name##factorycomponentdata = KPluginFactory::componentData(); \
|
|
pluginRegistrations \
|
|
} \
|
|
name::~name() {} \
|
|
KComponentData name::componentData() \
|
|
{ \
|
|
return *name##factorycomponentdata; \
|
|
}
|
|
|
|
#define K_PLUGIN_FACTORY_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) \
|
|
K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, baseFactory) \
|
|
K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations)
|
|
|
|
/**
|
|
* \relates KPluginLoader
|
|
* This macro exports the main object of the plugin. Most times, this will be a KPluginFactory
|
|
* or derived class, but any QObject derived class can be used.
|
|
* Take a look at the documentation of Q_EXPORT_PLUGIN for some details.
|
|
*
|
|
* @ingroup KDEMacros
|
|
*/
|
|
#define K_EXPORT_PLUGIN(factory) \
|
|
Q_EXPORT_PLUGIN(factory)
|
|
|
|
/**
|
|
* \relates KPluginFactory
|
|
* Defines a KPluginFactory subclass with two constructors and a static componentData function.
|
|
*
|
|
* The first constructor takes the arguments (const char *componentName, const char *catalogName,
|
|
* QObject *parent).
|
|
* The second constructor takes (const KAboutData *aboutData, QObject *parent).
|
|
*
|
|
* The static componentData method returns the same KComponentData object as the
|
|
* KPluginFactory::componentData function returns. As you normally don't have a pointer to the
|
|
* factory object in the plugin code the static componentData function is a convenient way to access
|
|
* the KComponentData.
|
|
*
|
|
* \param name The name of the KPluginFactory derived class. This is the name you'll need for
|
|
* K_EXPORT_PLUGIN
|
|
*
|
|
* \param pluginRegistrations This is code inserted into the constructors the class. You'll want to
|
|
* call registerPlugin from there.
|
|
*
|
|
* Example:
|
|
* \code
|
|
* #include <KPluginFactory>
|
|
* #include <KPluginLoader>
|
|
* #include <plugininterface.h>
|
|
*
|
|
* class MyPlugin;
|
|
*
|
|
* K_PLUGIN_FACTORY(MyPluginFactory,
|
|
* registerPlugin<MyPlugin>();
|
|
* )
|
|
* K_EXPORT_PLUGIN(MyPluginFactory("componentName", "catalogName"))
|
|
*
|
|
* // or:
|
|
* static KAboutData createAboutData()
|
|
* {
|
|
* KAboutData aboutData("myplugin", "myplugin", ki18n("MyPlugin"), "0.1",
|
|
* ki18n("a description of the plugin"), KAboutData::License_LGPL,
|
|
* ki18n("Copyright (C) 2007 Your Name"));
|
|
* aboutData.addAuthor(ki18n("Your Name"), ...);
|
|
* return aboutData;
|
|
* }
|
|
* K_EXPORT_PLUGIN(MyPluginFactory(createAboutData()))
|
|
*
|
|
* class MyPlugin : public PluginInterface
|
|
* {
|
|
* ...
|
|
* KComponentData kcd = MyPluginFactory::componentData();
|
|
* ...
|
|
* };
|
|
* \endcode
|
|
*
|
|
* \see K_PLUGIN_FACTORY_DECLARATION
|
|
* \see K_PLUGIN_FACTORY_DEFINITION
|
|
*/
|
|
#define K_PLUGIN_FACTORY(name, pluginRegistrations) K_PLUGIN_FACTORY_WITH_BASEFACTORY(name, KPluginFactory, pluginRegistrations)
|
|
|
|
/**
|
|
* \relates KPluginFactory
|
|
* K_PLUGIN_FACTORY_DECLARATION declares the KPluginFactory subclass. This macro can be used in a
|
|
* header file.
|
|
*
|
|
* \param name The name of the KPluginFactory derived class. This is the name you'll need for
|
|
* K_EXPORT_PLUGIN
|
|
*
|
|
* \see K_PLUGIN_FACTORY
|
|
* \see K_PLUGIN_FACTORY_DEFINITION
|
|
*/
|
|
#define K_PLUGIN_FACTORY_DECLARATION(name) K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, KPluginFactory)
|
|
|
|
/**
|
|
* \relates KPluginFactory
|
|
* K_PLUGIN_FACTORY_DEFINITION defines the KPluginFactory subclass. This macro can <b>not</b> be used in a
|
|
* header file.
|
|
*
|
|
* \param name The name of the KPluginFactory derived class. This is the name you'll need for
|
|
* K_EXPORT_PLUGIN
|
|
*
|
|
* \param pluginRegistrations This is code inserted into the constructors the class. You'll want to
|
|
* call registerPlugin from there.
|
|
*
|
|
* \see K_PLUGIN_FACTORY
|
|
* \see K_PLUGIN_FACTORY_DECLARATION
|
|
*/
|
|
#define K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, KPluginFactory, pluginRegistrations)
|
|
|
|
/**
|
|
* \class KPluginFactory kpluginfactory.h <KPluginFactory>
|
|
*
|
|
* If you develop a library that is to be loaded dynamically at runtime, then
|
|
* you should return a pointer to a KPluginFactory.
|
|
*
|
|
* For most cases it is enough to use the K_PLUGIN_FACTORY macro to create the factory.
|
|
*
|
|
* Example:
|
|
* \code
|
|
* #include <KPluginFactory>
|
|
* #include <KPluginLoader>
|
|
* #include <plugininterface.h>
|
|
*
|
|
* class MyPlugin;
|
|
*
|
|
* K_PLUGIN_FACTORY(MyPluginFactory,
|
|
* registerPlugin<MyPlugin>();
|
|
* )
|
|
* K_EXPORT_PLUGIN(MyPluginFactory("componentName"))
|
|
*
|
|
* class MyPlugin : public PluginInterface
|
|
* {
|
|
* ...
|
|
* KComponentData kcd = MyPluginFactory::componentData();
|
|
* ...
|
|
* };
|
|
* \endcode
|
|
*
|
|
* K_PLUGIN_FACTORY is a convenient macro that expands to a class derived from KPluginFactory
|
|
* providing two constructors and a static componentData() function. The second argument to
|
|
* K_PLUGIN_FACTORY is code that is called from the constructors. There you can use registerPlugin
|
|
* to register as many plugins for the factory as you want to.
|
|
*
|
|
* If you want to write a custom KPluginFactory not using the standard macro(s) you can reimplement
|
|
* the create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword)
|
|
* function.
|
|
*
|
|
* Example:
|
|
* \code
|
|
* class SomeScriptLanguageFactory : public KPluginFactory
|
|
* {
|
|
* Q_OBJECT
|
|
* public:
|
|
* SomeScriptLanguageFactory()
|
|
* : KPluginFactory("SomeScriptLanguageComponent")
|
|
* {}
|
|
*
|
|
* protected:
|
|
* virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword)
|
|
* {
|
|
* const QString identifier = QLatin1String(iface) + QLatin1Char('_') + keyword;
|
|
* // load scripting language module from the information in identifier
|
|
* // and return it:
|
|
* return object;
|
|
* }
|
|
* };
|
|
* \endcode
|
|
*
|
|
* If you want to load a library use KPluginLoader.
|
|
* The application that wants to instantiate plugin classes can do the following:
|
|
* \code
|
|
* KPluginFactory *factory = KPluginLoader("libraryname").factory();
|
|
* if (factory) {
|
|
* PluginInterface *p1 = factory->create<PluginInterface>(parent);
|
|
* OtherInterface *p2 = factory->create<OtherInterface>(parent);
|
|
* NextInterface *p3 = factory->create<NextInterface>("keyword1", parent);
|
|
* NextInterface *p3 = factory->create<NextInterface>("keyword2", parent);
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \author Matthias Kretz <kretz@kde.org>
|
|
* \author Bernhard Loos <nhuh.put@web.de>
|
|
*/
|
|
class KDECORE_EXPORT KPluginFactory : public QObject
|
|
{
|
|
Q_OBJECT
|
|
Q_DECLARE_PRIVATE(KPluginFactory)
|
|
public:
|
|
/**
|
|
* This constructor creates a factory for a plugin with the given \p componentName and
|
|
* \p catalogName. Those values are used to initialize a KComponentData object for the plugin.
|
|
* You can later access it with componentData(). If \p componentName is 0, an invalid KComponentData
|
|
* object will be created.
|
|
*
|
|
* \param componentName the component name of the plugin
|
|
* \param catalogName the translation catalog to use
|
|
* \param parent a parent object
|
|
*/
|
|
explicit KPluginFactory(const char *componentName = 0, const char *catalogName = 0, QObject *parent = 0);
|
|
|
|
/**
|
|
* This constructor creates a factory for a plugin with the given KAboutData object. This object is
|
|
* used to initialize a KComponentData object for the plugin. You can later access it with
|
|
* componentData().
|
|
* KPluginFactory takes ownership of the \p aboutData object, so don't delete it yourself!
|
|
*
|
|
* \param aboutData the KAboutData for the plugin
|
|
* \param parent a parent object
|
|
*/
|
|
explicit KPluginFactory(const KAboutData &aboutData, QObject *parent = 0);
|
|
|
|
/**
|
|
* This destroys the PluginFactory. It will remove the translation catalog for the plugin,
|
|
* if it was initialized.
|
|
*/
|
|
virtual ~KPluginFactory();
|
|
|
|
/**
|
|
* You can use this method to get the component data of the plugin. It is filled with the
|
|
* information given to the constructor of KPluginFactory.
|
|
* The K_PLUGIN_FACTORY macros provide a static version of this method, this can be used from
|
|
* any place within the plugin.
|
|
*
|
|
* Only use this method if you specified a componentData name or instance to the factory
|
|
* constructor or to setComponentData.
|
|
* Otherwise you get an invalid KComponentData, which will crash if used.
|
|
*
|
|
* \returns The KComponentData for the plugin
|
|
*/
|
|
KComponentData componentData() const;
|
|
|
|
/**
|
|
* Use this method to create an object. It will try to create an object which inherits
|
|
* \p T. If it has multiple choices, you will get a fatal error (kFatal()), so be careful
|
|
* to request a unique interface or use keywords.
|
|
*
|
|
* \tparam T The interface for which an object should be created. The object will inherit \p T.
|
|
* \param parent The parent of the object. If \p parent is a widget type, it will also passed
|
|
* to the parentWidget argument of the CreateInstanceFunction for the object.
|
|
* \param args Additional arguments which will be passed to the object.
|
|
* \returns A pointer to the created object is returned, or 0 if an error occurred.
|
|
*/
|
|
template<typename T>
|
|
T *create(QObject *parent = 0, const QVariantList &args = QVariantList());
|
|
|
|
/**
|
|
* Use this method to create an object. It will try to create an object which inherits
|
|
* \p T and was registered with \p keyword.
|
|
*
|
|
* \tparam T The interface for which an object should be created. The object will inherit \p T.
|
|
* \param keyword The keyword of the object.
|
|
* \param parent The parent of the object. If \p parent is a widget type, it will also passed
|
|
* to the parentWidget argument of the CreateInstanceFunction for the object.
|
|
* \param args Additional arguments which will be passed to the object.
|
|
* \returns A pointer to the created object is returned, or 0 if an error occurred.
|
|
*/
|
|
template<typename T>
|
|
T *create(const QString &keyword, QObject *parent = 0, const QVariantList &args = QVariantList());
|
|
|
|
/**
|
|
* Use this method to create an object. It will try to create an object which inherits
|
|
* \p T and was registered with \p keyword.
|
|
* This overload has an additional \p parentWidget argument, which is used by some plugins (e.g. Parts).
|
|
|
|
* \tparam T The interface for which an object should be created. The object will inherit \p T.
|
|
* \param parentWidget An additional parent widget.
|
|
* \param parent The parent of the object. If \p parent is a widget type, it will also passed
|
|
* to the parentWidget argument of the CreateInstanceFunction for the object.
|
|
* \param keyword The keyword of the object.
|
|
* \param args Additional arguments which will be passed to the object.
|
|
* \returns A pointer to the created object is returned, or 0 if an error occurred.
|
|
*/
|
|
template<typename T>
|
|
T *create(QWidget *parentWidget, QObject *parent, const QString &keyword = QString(), const QVariantList &args = QVariantList());
|
|
|
|
Q_SIGNALS:
|
|
void objectCreated(QObject *object);
|
|
|
|
protected:
|
|
/**
|
|
* Function pointer type to a function that instantiates a plugin.
|
|
*/
|
|
typedef QObject *(*CreateInstanceFunction)(QWidget *, QObject *, const QVariantList &);
|
|
|
|
explicit KPluginFactory(KPluginFactoryPrivate &dd, QObject *parent = 0);
|
|
|
|
/**
|
|
* Registers a plugin with the factory. Call this function from the constructor of the
|
|
* KPluginFactory subclass to make the create function able to instantiate the plugin when asked
|
|
* for an interface the plugin implements.
|
|
*
|
|
* You can register as many plugin classes as you want as long as either the plugin interface or
|
|
* the \p keyword makes it unique. E.g. it is possible to register a KCModule and a
|
|
* KParts::Part without having to specify keywords since their interfaces differ.
|
|
*
|
|
* \tparam T the name of the plugin class
|
|
*
|
|
* \param keyword An optional keyword as unique identifier for the plugin. This allows you to
|
|
* put more than one plugin with the same interface into the same library using the same
|
|
* factory. X-KDE-PluginKeyword is a convenient way to specify the keyword in a desktop file.
|
|
*
|
|
* \param instanceFunction A function pointer to a function that creates an instance of the
|
|
* plugin. The default function that will be used depends on the type of interface. If the
|
|
* interface inherits from
|
|
* \li \c KParts::Part the function will call
|
|
* \code
|
|
* new T(QWidget *parentWidget, QObject *parent, const QVariantList &args)
|
|
* \endcode
|
|
* \li \c QWidget the function will call
|
|
* \code
|
|
* new T(QWidget *parent, const QVariantList &args)
|
|
* \endcode
|
|
* \li else the function will call
|
|
* \code
|
|
* new T(QObject *parent, const QVariantList &args)
|
|
* \endcode
|
|
*/
|
|
template<class T>
|
|
void registerPlugin(const QString &keyword = QString(), CreateInstanceFunction instanceFunction
|
|
= InheritanceChecker<T>().createInstanceFunction(reinterpret_cast<T *>(0)))
|
|
{
|
|
registerPlugin(keyword, &T::staticMetaObject, instanceFunction);
|
|
}
|
|
|
|
KPluginFactoryPrivate *const d_ptr;
|
|
|
|
/**
|
|
* This method sets the component data of the plugin. You can access the component data object
|
|
* later with componentData().
|
|
* Normally you don't have to call this, because the factory constructs a component data object
|
|
* from the information given to the constructor.
|
|
* The object is destroyed, when the module containing the plugin is unloaded. Normally this happens
|
|
* only on application shutdown.
|
|
*
|
|
* \param componentData the new KComponentData object
|
|
*/
|
|
|
|
void setComponentData(const KComponentData &componentData);
|
|
|
|
/**
|
|
* This function is called when the factory asked to create an Object.
|
|
*
|
|
* You may reimplement it to provide a very flexible factory. This is especially useful to
|
|
* provide generic factories for plugins implemeted using a scripting language.
|
|
*
|
|
* \param iface The staticMetaObject::className() string identifying the plugin interface that
|
|
* was requested. E.g. for KCModule plugins this string will be "KCModule".
|
|
* \param parentWidget Only used if the requested plugin is a KPart.
|
|
* \param parent The parent object for the plugin object.
|
|
* \param args A plugin specific list of arbitrary arguments.
|
|
* \param keyword A string that uniquely identifies the plugin. If a KService is used this
|
|
* keyword is read from the X-KDE-PluginKeyword entry in the .desktop file.
|
|
*/
|
|
virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword);
|
|
|
|
template<class impl, class ParentType>
|
|
static QObject *createInstance(QWidget *parentWidget, QObject *parent, const QVariantList &args)
|
|
{
|
|
Q_UNUSED(parentWidget);
|
|
ParentType *p = 0;
|
|
if (parent) {
|
|
p = qobject_cast<ParentType *>(parent);
|
|
Q_ASSERT(p);
|
|
}
|
|
return new impl(p, args);
|
|
}
|
|
|
|
template<class impl>
|
|
static QObject *createPartInstance(QWidget *parentWidget, QObject *parent, const QVariantList &args)
|
|
{
|
|
return new impl(parentWidget, parent, args);
|
|
}
|
|
|
|
/**
|
|
* This is used to detect the arguments need for the constructor of plugin classes.
|
|
* You can inherit it, if you want to add new classes and still keep support for the old ones.
|
|
*/
|
|
template<class impl>
|
|
struct InheritanceChecker
|
|
{
|
|
CreateInstanceFunction createInstanceFunction(KParts::Part *) { return &createPartInstance<impl>; }
|
|
CreateInstanceFunction createInstanceFunction(QWidget *) { return &createInstance<impl, QWidget>; }
|
|
CreateInstanceFunction createInstanceFunction(...) { return &createInstance<impl, QObject>; }
|
|
};
|
|
|
|
private:
|
|
void registerPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceFunction instanceFunction);
|
|
};
|
|
|
|
template<typename T>
|
|
inline T *KPluginFactory::create(QObject *parent, const QVariantList &args)
|
|
{
|
|
QObject *o = create(T::staticMetaObject.className(), parent && parent->isWidgetType() ? reinterpret_cast<QWidget *>(parent): 0, parent, args, QString());
|
|
|
|
T *t = qobject_cast<T *>(o);
|
|
if (!t) {
|
|
delete o;
|
|
}
|
|
return t;
|
|
}
|
|
|
|
template<typename T>
|
|
inline T *KPluginFactory::create(const QString &keyword, QObject *parent, const QVariantList &args)
|
|
{
|
|
QObject *o = create(T::staticMetaObject.className(), parent && parent->isWidgetType() ? reinterpret_cast<QWidget *>(parent): 0, parent, args, keyword);
|
|
|
|
T *t = qobject_cast<T *>(o);
|
|
if (!t) {
|
|
delete o;
|
|
}
|
|
return t;
|
|
}
|
|
|
|
template<typename T>
|
|
inline T *KPluginFactory::create(QWidget *parentWidget, QObject *parent, const QString &keyword, const QVariantList &args)
|
|
{
|
|
QObject *o = create(T::staticMetaObject.className(), parentWidget, parent, args, keyword);
|
|
|
|
T *t = qobject_cast<T *>(o);
|
|
if (!t) {
|
|
delete o;
|
|
}
|
|
return t;
|
|
}
|
|
|
|
#endif // KDECORE_KPLUGINFACTORY_H
|