[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    KPluginFactory/-Loader as KLibFactory replacement and KDE enhanced
From:       Matthias Kretz <kretz () kde ! org>
Date:       2007-08-24 8:19:27
Message-ID: 200708241019.32498.kretz () kde ! org
[Download RAW message or body]

[Attachment #2 (multipart/mixed)]


Hi,

Bernhard, probably better known as PutHuhn, has been continuing the work I 
started on KPluginFactory the last days. He also added KPluginLoader, which 
is a subclass of QPluginLoader and therefore does the Qt library version 
check when loading a plugin. In addition KPluginLoader does the same kind of 
check for the kdelibs version. That way plugins compiled against a newer 
version of Qt or kdelibs will refuse to load.

Most of the work on completing KPluginFactory was to make it compatible enough 
to be a drop in replacement for KLibFactory, but I'm confident that it'll 
work out quite well with what we got now.

Attached you'll find his patch. I'll comment in a separate mail.

-- 
________________________________________________________
Matthias Kretz (Germany)                            <><
http://Vir.homelinux.org/
MatthiasKretz@gmx.net, kretz@kde.org,
Matthias.Kretz@urz.uni-heidelberg.de

["kpluginfactoryloader.patch" (text/x-diff)]

Index: kernel/kcomponentdata.cpp
===================================================================
--- kernel/kcomponentdata.cpp	(revision 704027)
+++ kernel/kcomponentdata.cpp	(working copy)
@@ -78,7 +78,7 @@
     }
 }
 
-KComponentData::KComponentData(const KAboutData *aboutData)
+KComponentData::KComponentData(const KAboutData *aboutData, \
MainComponentRegistration registerAsMain)  : d(new KComponentDataPrivate)
 {
     d->name = aboutData->appName();
@@ -88,7 +88,9 @@
 
     Q_ASSERT(!d->name.isEmpty());
 
-    KGlobal::newComponentData(*this);
+    if (registerAsMain == RegisterAsMainComponent) {
+        KGlobal::newComponentData(*this);
+    }
 }
 
 void KComponentData::_checkConfig() // called by KSharedConfigPtr
Index: kernel/kcomponentdata.h
===================================================================
--- kernel/kcomponentdata.h	(revision 704027)
+++ kernel/kcomponentdata.h	(working copy)
@@ -113,7 +113,7 @@
      *
      * @see KAboutData
      */
-    explicit KComponentData(const KAboutData *aboutData);
+    explicit KComponentData(const KAboutData *aboutData, MainComponentRegistration = \
RegisterAsMainComponent);  
     /**
      * Destructor.
Index: util/kgenericfactory.h
===================================================================
--- util/kgenericfactory.h	(revision 704027)
+++ util/kgenericfactory.h	(working copy)
@@ -19,14 +19,15 @@
 #ifndef kgenericfactory_h
 #define kgenericfactory_h
 
-#include <klibloader.h>
+#include <kpluginfactory.h>
+#include <kpluginloader.h>
 #include <ktypelist.h>
 #include <kcomponentdata.h>
 #include <kgenericfactory.tcc>
 #include <kglobal.h>
 #include <klocale.h>
 #include <kdebug.h>
-
+#if 0
 /* @internal */
 template <class T>
 class KGenericFactoryBase
@@ -75,7 +76,7 @@
     virtual void setupTranslations( void )
     {
         if (componentData().isValid()) {
-            KGlobal::locale()->insertCatalog(s_componentData->catalogName());
+            KGlobal::locale() s_componentData->catalogName());
         }
     }
 
@@ -118,7 +119,7 @@
     }
     return *s_componentData;
 }
-
+#endif
 /**
  * This template provides a generic implementation of a KLibFactory ,
  * for use with shared library components. It implements the pure virtual
@@ -178,15 +179,15 @@
  * \endcode
  */
 template <class Product, class ParentType = QObject>
-class KGenericFactory : public KLibFactory, public KGenericFactoryBase<Product>
+class KDE_DEPRECATED KGenericFactory : public KLibFactory
 {
 public:
     explicit KGenericFactory( const char *componentName = 0, const char *catalogName \
                = 0 )
-        : KGenericFactoryBase<Product>( componentName, catalogName )
+        : KLibFactory(componentName, catalogName)
     {}
 
     explicit KGenericFactory( const KAboutData *data )
-        : KGenericFactoryBase<Product>( data )
+        : KLibFactory(data)
     {}
 
 
@@ -194,12 +195,11 @@
     virtual QObject *createObject( QObject *parent,
                                    const char *className, const QStringList &args )
     {
-        KGenericFactoryBase<Product>::initializeMessageCatalog();
         return KDEPrivate::ConcreteFactory<Product, ParentType>
             ::create( 0, parent, className, args );
     }
 };
-
+#if 0
 /**
  * This template provides a generic implementation of a KLibFactory ,
  * for use with shared library components. It implements the pure virtual
@@ -274,11 +274,11 @@
 {
 public:
     explicit KGenericFactory( const char *componentName  = 0, const char \
                *catalogName  = 0 )
-        : KGenericFactoryBase< KTypeList<Product, ProductListTail> >( componentName, \
catalogName ) +        : KLibFactory(componentName, catalogName), \
KGenericFactoryBase<KTypeList<Product, ProductListTail> >(componentName, catalogName) \
{}  
     explicit KGenericFactory( const KAboutData *data )
-        : KGenericFactoryBase< KTypeList<Product, ProductListTail> >( data )
+        : KLibFactory(data), KGenericFactoryBase<KTypeList<Product, ProductListTail> \
>(data)  {}
 
 
@@ -368,10 +368,10 @@
 {
 public:
     explicit KGenericFactory( const char *componentName  = 0, const char \
                *catalogName  = 0 )
-        : KGenericFactoryBase< KTypeList<Product, ProductListTail> >( componentName, \
catalogName ) +        : KLibFactory(componentName, catalogName), \
KGenericFactoryBase<KTypeList<Product, ProductListTail> >(componentName, catalogName) \
{}  explicit KGenericFactory( const KAboutData *data )
-        : KGenericFactoryBase< KTypeList<Product, ProductListTail> >( data )
+        : KLibFactory(data), KGenericFactoryBase<KTypeList<Product, ProductListTail> \
>(data)  {}
 
 
@@ -387,10 +387,11 @@
     }
 };
 
-
+#endif
 /*
  * vim: et sw=4
  */
 
 #endif
 
+
Index: util/klibloader.cpp
===================================================================
--- util/klibloader.cpp	(revision 704027)
+++ util/klibloader.cpp	(working copy)
@@ -95,14 +95,22 @@
 
 // -------------------------------------------------------------------------
 
+#if 0
 KLibFactory::KLibFactory( QObject* _parent )
-    : QObject( _parent ), d(0)
+    : QObject( _parent ), d_ptr(0)
 {
 }
 
+KLibFactory::KLibFactory(KLibFactoryPrivate &dd, QObject *parent)
+    : QObject(parent), d_ptr(&dd)
+{
+    d_ptr->q_ptr = this;
+}
+
 KLibFactory::~KLibFactory()
 {
 //    kDebug(150) << "Deleting KLibFactory " << this;
+    delete d_ptr;
 }
 
 QObject* KLibFactory::create( QObject* _parent, const char* classname, const \
QStringList &args ) @@ -112,8 +120,8 @@
 	emit objectCreated( obj );
     return obj;
 }
+#endif
 
-
 // -----------------------------------------------
 
 class KLibraryPrivate
@@ -123,13 +131,13 @@
     KLibrary *q;
     QString libname;
     QString filename;
-    QHash<QByteArray, KLibFactory*> factories;
+    QHash<QByteArray, KPluginFactory*> factories;
     QLibrary* handle;
     QList<QObject*> objs;
     QTimer* timer;
 
-    KLibFactory *kde3Factory(const QByteArray &factoryname);
-    KLibFactory *kde4Factory();
+    KPluginFactory *kde3Factory(const QByteArray &factoryname);
+    KPluginFactory *kde4Factory();
 };
 
 KLibrary::KLibrary( const QString& libname, const QString& filename, QLibrary * \
handle ) @@ -177,7 +185,7 @@
     return d->filename;
 }
 
-KLibFactory* KLibraryPrivate::kde3Factory(const QByteArray &factoryname)
+KPluginFactory* KLibraryPrivate::kde3Factory(const QByteArray &factoryname)
 {
     QByteArray symname = "init_";
     if(!factoryname.isEmpty()) {
@@ -198,12 +206,12 @@
         return 0;
     }
 
-    typedef KLibFactory* (*t_func)();
+    typedef KPluginFactory* (*t_func)();
     // Cast the void* to non-pointer type first - it's not legal to
     // cast a pointer-to-object directly to a pointer-to-function.
     ptrdiff_t tmp = reinterpret_cast<ptrdiff_t>(sym);
     t_func func = reinterpret_cast<t_func>(tmp);
-    KLibFactory* factory = func();
+    KPluginFactory* factory = func();
 
     if( !factory )
     {
@@ -216,7 +224,7 @@
     return factory;
 }
 
-KLibFactory *KLibraryPrivate::kde4Factory()
+KPluginFactory *KLibraryPrivate::kde4Factory()
 {
     const QByteArray symname("qt_plugin_instance");
     if ( factories.contains( symname ) )
@@ -236,7 +244,7 @@
     ptrdiff_t tmp = reinterpret_cast<ptrdiff_t>(sym);
     t_func func = reinterpret_cast<t_func>(tmp);
     QObject* instance = func();
-    KLibFactory *factory = qobject_cast<KLibFactory *>(instance);
+    KPluginFactory *factory = qobject_cast<KPluginFactory *>(instance);
 
     if( !factory )
     {
@@ -250,9 +258,9 @@
 
 }
 
-KLibFactory* KLibrary::factory(const char* factoryname)
+KPluginFactory* KLibrary::factory(const char* factoryname)
 {
-    KLibFactory *factory = d->kde4Factory();
+    KPluginFactory *factory = d->kde4Factory();
     if (!factory)
         factory = d->kde3Factory(factoryname);
 
@@ -552,7 +560,7 @@
   d->close_pending( wrap );
 }
 
-KLibFactory* KLibLoader::factory( const QString &_name, QLibrary::LoadHints hint )
+KPluginFactory* KLibLoader::factory( const QString &_name, QLibrary::LoadHints hint \
)  {
     KLibrary* lib = library( _name, hint );
     if ( !lib )
Index: util/klibloader.h
===================================================================
--- util/klibloader.h	(revision 704027)
+++ util/klibloader.h	(working copy)
@@ -24,17 +24,14 @@
 #include <QtCore/QStringList>
 #include <QtCore/QHash>
 #include <QtCore/QLibrary>
-#include <QtCore/qplugin.h>
+#include <QtCore/QtPlugin>
 
+#include "kpluginfactory.h"
+
 class QString;
-class KLibFactory;
-class KLibFactoryPrivate;
 class KLibraryPrivate;
 class KLibLoaderPrivate;
 
-# define K_EXPORT_COMPONENT_FACTORY( libname, factory ) \
-    extern "C" { KDE_EXPORT KLibFactory *init_##libname() { return new factory; } }
-
 /**
  * @short Represents a dynamically loaded library.
  *
@@ -76,7 +73,7 @@
      * K_EXPORT_COMPONENT_FACTORY.
      * @return The factory of the library if there is any, otherwise 0
      */
-    KLibFactory* factory( const char* factoryname = 0 );
+    KPluginFactory* factory( const char* factoryname = 0 );
 
     /**
      * Looks up a symbol from the library. This is a very low level
@@ -118,7 +115,7 @@
 };
 
 
-
+#if 0
 /**
  * If you develop a library that is to be loaded dynamically at runtime, then
  * you should return a pointer to your factory. The K_EXPORT_COMPONENT_FACTORY
@@ -160,6 +157,7 @@
 class KDECORE_EXPORT KLibFactory : public QObject
 {
     Q_OBJECT
+    Q_DECLARE_PRIVATE(KLibFactory)
 public:
     /**
      * Create a new factory.
@@ -248,10 +246,10 @@
                                    const char* className = "QObject",
                                    const QStringList &args = QStringList() ) = 0;
 
-
-private:
-    KLibFactoryPrivate *const d;
+    KLibFactory(KLibFactoryPrivate &dd, QObject *parent);
+    KLibFactoryPrivate *const d_ptr;
 };
+#endif
 
 /**
  * The KLibLoader allows you to load libraries dynamically at runtime.
@@ -287,11 +285,11 @@
      *                 You can, however, give a library name ending in ".so"
      *                 (or whatever is used on your platform), and the library
      *                 will be loaded without resolving dependencies. Use with \
                caution.
-     * @return the KLibFactory, or 0 if the library does not exist or it does
+     * @return the KPluginFactory, or 0 if the library does not exist or it does
      *         not have a factory
      * @see library
      */
-    KLibFactory* factory( const QString &libname, QLibrary::LoadHints loadHint = 0);
+    KPluginFactory* factory( const QString &libname, QLibrary::LoadHints loadHint = \
0);  
     /**
      * Loads and initializes a library. Loading a library multiple times is
@@ -399,16 +397,57 @@
      * @param libraryName The library to open
      * @param parent The parent object (see QObject constructor)
      * @param args A list of string arguments, passed to the factory and possibly
-     *             to the component (see KLibFactory)
+     *             to the component (see KPluginFactory)
      * @param error
      * @return A pointer to the newly created object or a null pointer if the
      *         factory was unable to create an object of the given type.
      */
     template <typename T>
+    static T *createInstance(const QString &keyword, const QString &libname, QObject \
*parent = 0, +                              const QVariantList &args = \
QVariantList(), +                              int *error = 0 )
+    {
+        KLibrary *library = KLibLoader::self()->library( libname );
+        if ( !library )
+        {
+            if ( error )
+                *error = ErrNoLibrary;
+            return 0;
+        }
+        KPluginFactory *factory = library->factory();
+        if ( !factory )
+        {
+            library->unload();
+            if ( error )
+                *error = ErrNoFactory;
+            return 0;
+        }
+        QObject *object = factory->create<T>(keyword, parent, args);
+        T *res = qobject_cast<T *>( object );
+        if ( !res )
+        {
+            delete object;
+            library->unload();
+            if ( error )
+                *error = ErrNoComponent;
+        }
+        return res;
+    }
+
+    template <typename T>
     static T *createInstance( const QString &libname, QObject *parent = 0,
-                              const QStringList &args = QStringList(),
+                              const QVariantList &args = QVariantList(),
                               int *error = 0 )
     {
+        return createInstance<T>(QString(), libname, parent, args, error);
+    }
+
+    template <typename T>
+    KDE_DEPRECATED
+    static T *createInstance( const QString &libname, QObject *parent,
+                              const QStringList &args,
+                              int *error = 0 )
+    {
         KLibrary *library = KLibLoader::self()->library( libname );
         if ( !library )
         {
@@ -416,7 +455,7 @@
                 *error = ErrNoLibrary;
             return 0;
         }
-        KLibFactory *factory = library->factory();
+        KPluginFactory *factory = library->factory();
         if ( !factory )
         {
             library->unload();
@@ -424,7 +463,7 @@
                 *error = ErrNoFactory;
             return 0;
         }
-        QObject *object = factory->create( parent, T::staticMetaObject.className(), \
args ); +        QObject *object = factory->create<T>(parent, QVariantList() << \
args);  T *res = qobject_cast<T *>( object );
         if ( !res )
         {
Index: util/klibloader_p.h
===================================================================
--- util/klibloader_p.h	(revision 0)
+++ util/klibloader_p.h	(revision 0)
@@ -0,0 +1,32 @@
+/*  This file is part of the KDE project
+    Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License version 2 as published by the Free Software Foundation.
+
+    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_KLIBLOADER_P_H
+#define KDECORE_KLIBLOADER_P_H
+
+#include "klibloader.h"
+
+class KLibFactoryPrivate
+{
+    Q_DECLARE_PUBLIC(KLibFactory)
+    protected:
+        KLibFactory *q_ptr;
+};
+
+#endif // KDECORE_KLIBLOADER_P_H
Index: util/kpluginfactory.cpp
===================================================================
--- util/kpluginfactory.cpp	(revision 0)
+++ util/kpluginfactory.cpp	(revision 0)
@@ -0,0 +1,174 @@
+/*  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.
+
+*/
+
+#include "kpluginfactory.h"
+#include "kpluginfactory_p.h"
+
+#include <kaboutdata.h>
+
+
+KPluginFactory::KPluginFactory(const char *componentName, const char *catalogName, \
QObject *parent) +    : QObject(parent), d_ptr(new KPluginFactoryPrivate)
+{
+    Q_D(KPluginFactory);
+    d->componentData = *createComponentData();
+    if (!d->componentData.isValid()) {
+        d->aboutData = new KAboutData(componentName, catalogName, \
KLocalizedString(), "", KLocalizedString()); +        d->componentData = \
createComponentData(d->aboutData); +    }
+}
+
+KPluginFactory::KPluginFactory(const KAboutData *aboutData, QObject *parent)
+    : QObject(parent), d_ptr(new KPluginFactoryPrivate)
+{
+    Q_D(KPluginFactory);
+    d->componentData = *createComponentData();
+    d->aboutData = aboutData;
+    if (!d->componentData.isValid()) {
+        d->componentData = createComponentData(d->aboutData);
+    }
+}
+
+KPluginFactory::KPluginFactory(QObject *parent)
+    : QObject(parent), d_ptr(new KPluginFactoryPrivate())
+{
+}
+
+
+KPluginFactory::KPluginFactory(KPluginFactoryPrivate &d, QObject *parent)
+    : QObject(parent), d_ptr(&d)
+{
+}
+
+KPluginFactory::~KPluginFactory()
+{
+    Q_D(KPluginFactory);
+
+    if (d->catalogInitialized && d->componentData.isValid()) {
+        KGlobal::locale()->removeCatalog(d->componentData.catalogName());
+    }
+    
+    delete d_ptr;
+}
+
+KComponentData KPluginFactory::componentData() const
+{
+    Q_D(const KPluginFactory);
+    return d->componentData;
+}
+
+void KPluginFactory::registerPlugin(const char *iface, CreateInstanceFunction \
instanceFunction, const QString &keyword) +{
+    Q_D(KPluginFactory);
+    QString ident(iface);
+    ident.append(keyword);
+    Q_ASSERT(!d->createInstanceHash.contains(ident));
+    d->createInstanceHash.insert(ident, instanceFunction);
+}
+
+QObject *KPluginFactory::createObject(QObject *parent, const char *className, const \
QStringList &args) +{
+    return 0;
+}
+
+QObject *KPluginFactory::create(const char *iface, QObject *parent, const \
QVariantList &args, const QString &keyword) +{
+    Q_D(KPluginFactory);
+
+    QObject *obj = 0;
+
+    initializeMessageCatalog();
+
+    if (keyword.isEmpty() && (obj = createObject(parent, iface, \
variantListToStringList(args)))) { +        objectCreated(obj);
+        return obj;
+    }
+
+    QString ident(iface);
+    ident.append(keyword);
+
+    QHash<QString, KPluginFactory::CreateInstanceFunction>::ConstIterator \
factoryMethode; +    factoryMethode = d->createInstanceHash.find(ident);
+
+    if (factoryMethode == d->createInstanceHash.end())
+        return 0;
+
+    obj = (*factoryMethode)(parent, args);
+
+    if (obj) {
+        emit objectCreated(obj);
+    }
+    return obj;
+}
+
+void KPluginFactory::initializeMessageCatalog()
+{
+    Q_D(KPluginFactory);
+    
+    if (!d->catalogInitialized) {
+        d->catalogInitialized = true;
+        setupTranslations();
+    }
+}
+
+void KPluginFactory::setupTranslations()
+{
+    Q_D(KPluginFactory);
+
+    if (!d->componentData.isValid())
+        return;
+
+    KGlobal::locale()->insertCatalog(d->componentData.catalogName());
+}
+
+KComponentData KPluginFactory::createComponentData(const KAboutData *aboutData)
+{
+    return KComponentData(aboutData, KComponentData::SkipMainComponentRegistration);
+}
+
+QStringList KPluginFactory::variantListToStringList(const QVariantList &list)
+{
+    QVariantList copy(list);
+    QStringList stringlist;
+
+    while (!copy.isEmpty()) 
+        stringlist << copy.takeFirst().toString();
+
+    return stringlist;
+}
+
+QVariantList KPluginFactory::stringListToVariantList(const QStringList &list)
+{
+    QStringList copy(list);
+    QVariantList variantlist;
+
+    while (!copy.isEmpty()) 
+        variantlist << QVariant(copy.takeFirst());
+
+    return variantlist;
+}
+
+KComponentData *KPluginFactory::createComponentData()
+{
+    return new KComponentData();
+}
+
+#include "kpluginfactory.moc"
Index: util/kpluginfactory.h
===================================================================
--- util/kpluginfactory.h	(revision 0)
+++ util/kpluginfactory.h	(revision 0)
@@ -0,0 +1,170 @@
+/*  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 <kcomponentdata.h>
+
+class KPluginFactoryPrivate;
+
+#define K_REGISTER_PLUGIN_WITH_KEYWORD(impl, iface, keyword) \
+registerPlugin(iface::staticMetaObject.className(), &createInstance<impl>, keyword);
+
+#define K_REGISTER_PLUGIN(impl, iface) K_REGISTER_PLUGIN_WITH_KEYWORD(impl, iface, \
QString()) +
+#define K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, baseFactory) \
+class name : public baseFactory \
+{ \
+    public: \
+        name(const char *, const char * = 0, QObject * = 0); \
+        name(const KAboutData *, QObject * = 0); \
+        static KComponentData componentData(); \
+    private: \
+        static KPluginFactory *s_instance; \
+};
+
+#define K_PLUGIN_FACTORY_DECLARATION(name) \
K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, KPluginFactory) +
+#define K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, baseFactory, \
pluginRegistrations) \ +KPluginFactory *name::s_instance = 0; \
+name::name(const char *componentName, const char *catalogName, QObject *parent) \
+    : baseFactory(componentName, catalogName, parent) \
+{ \
+    s_instance = this; \
+    pluginRegistrations \
+} \
+name::name(const KAboutData *aboutData, QObject *parent) \
+    : baseFactory(aboutData, parent) \
+{ \
+    pluginRegistrations \
+} \
+KComponentData name::componentData() \
+{ \
+    Q_ASSERT(s_instance); \
+    return s_instance->componentData(); \
+}
+
+#define K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) \
K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, KPluginFactory, \
pluginRegistrations) +
+#define K_PLUGIN_FACTORY_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) \
+    K_PLUGIN_FACTORY_DECLARATION(name, baseFactory) \
+    K_PLUGIN_FACTORY_DEFINITION(name, baseFactory, pluginRegistrations)
+
+#define K_PLUGIN_FACTORY(name, pluginRegistrations) \
K_PLUGIN_FACTORY_WITH_BASEFACTORY(name, KPluginFactory, pluginRegistrations) +
+class KDECORE_EXPORT KPluginFactory : public QObject
+{
+    Q_OBJECT
+    Q_DECLARE_PRIVATE(KPluginFactory)
+public:
+    explicit KPluginFactory(const char *componentName, const char *catalogName = 0, \
QObject *parent = 0); +    explicit KPluginFactory(const KAboutData *aboutData, \
QObject *parent = 0); +    explicit KDE_CONSTRUCTOR_DEPRECATED KPluginFactory(QObject \
*parent); +    virtual ~KPluginFactory();
+
+    KComponentData componentData() const;
+
+    template<typename T>
+    T *create(QObject *parent = 0, const QVariantList &args = QVariantList());
+
+    template<typename T>
+    T *create(const QString &keyword, QObject *parent, const QVariantList &args = \
QVariantList()); +
+    template<typename T>
+    KDE_DEPRECATED
+    T *create(QObject *parent, const QStringList &args)
+    {
+        return create<T>(parent, stringListToVariantList(args));
+    }
+
+    KDE_DEPRECATED QObject *create(QObject *parent = 0, const char *classname = \
"QObject", const QStringList &args = QStringList()) +    {
+            return create(classname, parent, stringListToVariantList(args), \
QString()); +    }
+
+Q_SIGNALS:
+    void objectCreated(QObject *object);
+
+protected:
+    typedef QObject *(*CreateInstanceFunction)(QObject *,const QVariantList &);
+
+    explicit KPluginFactory(KPluginFactoryPrivate &dd, QObject *parent = 0);
+
+    template<class impl>
+    static QObject *createInstance(QObject *parent, const QVariantList &args)
+    {
+        return new impl(parent, args);
+    }
+
+    void registerPlugin(const char *iface, CreateInstanceFunction instanceFunction, \
const QString &keyword); +
+    virtual KComponentData createComponentData(const KAboutData *aboutData);
+
+    virtual KDE_DEPRECATED KComponentData *createComponentData();
+
+    QVariantList stringListToVariantList(const QStringList &list);
+
+    QStringList variantListToStringList(const QVariantList &list);
+
+    virtual void setupTranslations();
+
+    void initializeMessageCatalog();
+
+    KPluginFactoryPrivate *const d_ptr;
+
+    virtual KDE_DEPRECATED QObject *createObject(QObject *parent, const char \
*className, const QStringList &args); +
+private:
+    QObject *create(const char *iface, QObject *parent, const QVariantList &args, \
const QString &keyword); +};
+
+KDE_DEPRECATED typedef KPluginFactory KLibFactory;
+
+template<typename T>
+T *KPluginFactory::create(QObject *parent, const QVariantList &args)
+{
+    QObject *o = create(T::staticMetaObject.className(), parent, args, QString());
+    T *t = qobject_cast<T *>(o);
+    if (!t) {
+        delete o;
+    }
+    return t;
+}
+
+template<typename T>
+T *KPluginFactory::create(const QString &keyword, QObject *parent, const \
QVariantList &args) +{
+    QObject *o = create(T::staticMetaObject.className(), parent, args, keyword);
+    T *t = qobject_cast<T *>(o);
+    if (!t) {
+        delete o;
+    }
+    return t;
+}
+
+
+#endif // KDECORE_KPLUGINFACTORY_H
Index: util/kpluginfactory_p.h
===================================================================
--- util/kpluginfactory_p.h	(revision 0)
+++ util/kpluginfactory_p.h	(revision 0)
@@ -0,0 +1,47 @@
+/*  This file is part of the KDE project
+    Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+    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_P_H
+#define KDECORE_KPLUGINFACTORY_P_H
+
+#include "kpluginfactory.h"
+
+#include <QtCore/QHash>
+
+#include <kaboutdata.h>
+
+class KAboutData;
+
+class KPluginFactoryPrivate
+{
+public:
+    KPluginFactoryPrivate() : catalogInitialized(false), aboutData(0) {}
+    ~KPluginFactoryPrivate()
+    {
+        delete aboutData;
+    }
+
+    QHash<QString, KPluginFactory::CreateInstanceFunction> createInstanceHash;
+    KComponentData componentData;
+    bool catalogInitialized;
+    const KAboutData *aboutData;
+};
+
+#endif // KDECORE_KPLUGINFACTORY_P_H
Index: util/kpluginloader.cpp
===================================================================
--- util/kpluginloader.cpp	(revision 0)
+++ util/kpluginloader.cpp	(revision 0)
@@ -0,0 +1,173 @@
+/*  This file is part of the KDE project
+    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 version 2 as published by the Free Software Foundation.
+
+    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.
+*/
+
+#include "kpluginloader.h"
+
+#include <kcomponentdata.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+#include "kpluginfactory.h"
+#include <kservice.h>
+
+#include <QtCore/QLibrary>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+
+
+class KPluginLoader::Private
+{
+public:
+    Private(const QString &libname)
+        : name(libname), pluginVersion(-1), verificationData(0)
+    {}
+    
+    const QString name;
+    quint32 pluginVersion;
+    KDEPluginVerificationData *verificationData;
+    QString errorString;
+};
+
+static inline QString makeLibName( const QString &libname )
+{
+#ifdef Q_OS_WIN
+    if (!libname.endsWith(".dll"))
+        return libname + ".dll";
+    return libname;
+#else
+    int pos = libname.lastIndexOf('/');
+    if (pos < 0)
+      pos = 0;
+    if (libname.indexOf('.', pos) < 0) {
+        const char* const extList[] = { ".so", ".dylib", ".bundle", ".sl" };
+        for (uint i = 0; i < sizeof(extList) / sizeof(*extList); ++i) {
+           if (QLibrary::isLibrary(libname + extList[i]))
+               return libname + extList[i];
+        }
+    }
+    return libname;
+#endif
+}
+
+static inline QString findLibraryInternal(const QString &name, const KComponentData \
&cData) +{
+    QString libname = makeLibName(name);
+
+    if (QFileInfo(name).fileName().startsWith("lib"))
+        kDebug(150) << "plugins shouldn't have a 'lib' suffix:" << libname;
+
+    QString libfile;
+    if (QDir::isRelativePath(libname)) {
+        libfile = cData.dirs()->findResource("module", libname);
+        if ( libfile.isEmpty() )
+        {
+            libfile = cData.dirs()->findResource("lib", libname);
+            if (!libfile.isEmpty())
+                kDebug(150) << "library" << libname << "not found under 'module' but \
under 'lib'"; +        }
+    }
+    else {
+        libfile = libname;
+    }
+    return libfile;
+}
+
+KPluginLoader::KPluginLoader(const QString &plugin, const KComponentData \
&componentdata, QObject *parent) +    : QPluginLoader(findLibraryInternal(plugin, \
componentdata), parent), d(new Private(plugin)) +{
+    load();
+}
+
+KPluginLoader::KPluginLoader(const KService &service, const KComponentData \
&componentdata, QObject *parent) +: \
QPluginLoader(findLibraryInternal(service.library(), componentdata), parent), d(new \
Private(service.library())) +{
+    Q_ASSERT(service.isValid());
+
+    if (service.isApplication()) {
+        d->errorString = i18n("The service provides no library, the Library key is \
missing in the .desktop file"); +        return;
+    }
+    load();
+}
+
+KPluginFactory *KPluginLoader::factory()
+{
+    if (!isLoaded())
+        return 0;
+
+    QObject *obj = instance();
+
+    if (!obj)
+        return 0;
+    
+    KPluginFactory *factory = qobject_cast<KPluginFactory *>(obj);
+
+    if (factory == 0) {
+        delete obj;
+        d->errorString = i18n("The library %1 does not offer a KDE 4 compatible \
factory." , d->name); +    }
+
+    return factory;
+}
+
+bool KPluginLoader::load()
+{
+    if (!QPluginLoader::load())
+        return false;
+
+    QLibrary lib(fileName());
+    lib.load();
+    Q_ASSERT(lib.isLoaded());
+
+    d->verificationData = (KDEPluginVerificationData *) \
lib.resolve("kde_plugin_verification_data");    +    if (d->verificationData) {
+        if ((d->verificationData->KDEVersion > KDE_VERSION) || (KDE_VERSION_MAJOR << \
16 != (d->verificationData->KDEVersion & 0xFF0000))) { +            d->errorString = \
i18n("The plugin '%1' uses incompatible KDE library. (%2)", d->name, \
d->verificationData->KDEVersionString); +            lib.unload();
+            unload();
+            return false;
+        }
+    }
+    else {
+        kDebug(150) << "The plugin" << d->name << "doesn't contain a \
kde_plugin_verification_data structure"; +    }
+
+    quint32 *version = (quint32 *) lib.resolve("kde_plugin_version");
+    if (version)
+        d->pluginVersion = *version;
+    else
+        d->pluginVersion = -1;
+
+    lib.unload();
+
+    return true;
+}
+
+QString KPluginLoader::errorString() const
+{
+    if (!d->errorString.isEmpty())
+        return d->errorString;
+
+    return QPluginLoader::errorString();
+}
+
+quint32 KPluginLoader::pluginVersion() const
+{
+    return d->pluginVersion;
+}
+
+#include "kpluginloader.moc"
\ No newline at end of file
Index: util/kpluginloader.h
===================================================================
--- util/kpluginloader.h	(revision 0)
+++ util/kpluginloader.h	(revision 0)
@@ -0,0 +1,86 @@
+/*  This file is part of the KDE project
+    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 version 2 as published by the Free Software Foundation.
+
+    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_KPLUGINLOADER_H
+#define KDECORE_KPLUGINLOADER_H
+
+#include <kglobal.h>
+#include <kdeversion.h>
+
+#include <QtCore/QPluginLoader>
+#include <QtCore/qplugin.h>
+
+struct KDEPluginVerificationData
+{
+    quint8 dataVersion;
+    quint32 KDEVersion;
+    const char *KDEVersionString;
+};
+
+#define K_PLUGIN_VERIFICATION_DATA \
+extern "C" KDE_EXPORT KDEPluginVerificationData kde_plugin_verification_data = \
+{ 1, KDE_VERSION, KDE_VERSION_STRING };
+
+#define K_EXPORT_PLUGIN_VERSION(version) \
+extern "C" KDE_EXPORT quint32 kde_plugin_version = version;
+
+#define K_EXPORT_PLUGIN2(library, factory) \
+Q_EXPORT_PLUGIN2(library, factory) \
+K_PLUGIN_VERIFICATION_DATA
+
+#define K_EXPORT_PLUGIN(factory) K_EXPORT_PLUGIN2(factory, factory)
+
+#define K_EXPORT_COMPONENT_FACTORY(library, factory) K_EXPORT_PLUGIN2(library, \
factory) +
+
+class KComponentData;
+class KPluginFactory;
+class KService;
+
+class KDECORE_EXPORT KPluginLoader : public QPluginLoader
+{
+    Q_OBJECT
+    Q_PROPERTY(QString fileName READ fileName)
+    Q_PROPERTY(QString pluginName READ fileName)
+public:
+    explicit KPluginLoader(const QString &plugin, const KComponentData \
&componentdata = KGlobal::mainComponent(), QObject *parent = 0); +    explicit \
KPluginLoader(const KService &service, const KComponentData &componentdata = \
KGlobal::mainComponent(), QObject *parent = 0); +    ~KPluginLoader();
+
+    KPluginFactory *factory();
+
+    QString pluginName() const;
+
+    bool isLoaded() const;
+
+    bool load();
+
+    quint32 pluginVersion() const;
+
+    QString errorString() const;
+
+private:
+    Q_DISABLE_COPY(KPluginLoader)
+
+    using QPluginLoader::setFileName;
+
+    class Private;
+    Private *const d;
+};
+
+
+#endif


[Attachment #6 (application/pgp-signature)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic