Warning, /frameworks/kdelibs4support/src/kdecore/kgenericfactory.tcc is written in an unsupported language. File is not indexed.

0001 /*
0002  * The Type2Type template and the Inheritance Detector are from
0003  * <http://www.cuj.com/experts/1810/alexandr.htm>
0004  * (c) Andrei Alexandrescu <andrei@metalanguage.com> and
0005  * free for any use.
0006  *
0007  * The rest is:
0008  * Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
0009  *
0010  * This library is free software; you can redistribute it and/or
0011  * modify it under the terms of the GNU Library General Public
0012  * License as published by the Free Software Foundation; either
0013  * version 2 of the License, or (at your option) any later version.
0014  *
0015  * This library is distributed in the hope that it will be useful,
0016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0018  * Library General Public License for more details.
0019  *
0020  * You should have received a copy of the GNU Library General Public License
0021  * along with this library; see the file COPYING.LIB.  If not, write to
0022  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0023  * Boston, MA 02110-1301, USA.
0024  */
0025 // -*- mode: c++ -*-
0026 //
0027 //  W A R N I N G
0028 //  -------------
0029 //
0030 // This file is not part of the KDE API.  It exists for the convenience
0031 // of KGenericFactory. This header file may change from version to
0032 // version without notice, or even be removed.
0033 //
0034 // We mean it.
0035 //
0036 
0037 #ifndef KGENERICFACTORY_TCC
0038 #define KGENERICFACTORY_TCC
0039 
0040 #include <QMetaObject>
0041 #include <ktypelist.h>
0042 #include "kdebug.h"
0043 
0044 namespace KParts
0045 {
0046     class Part;
0047 }
0048 
0049 #ifndef KDELIBS4SUPPORT_NO_DEPRECATED
0050 namespace KDEPrivate
0051 {
0052     template <class Base>
0053     struct InheritanceDetector
0054     {
0055         typedef char ConversionExists;
0056         struct ConversionDoesNotExist { char bleh[ 2 ]; };
0057         static ConversionExists test( Base * );
0058         static ConversionDoesNotExist test( ... );
0059     };
0060 
0061     /* Simon: KCC doesn't eat the generic InheritanceDetector<Base>.
0062        Instead we have to use concrete specializations :-(
0063 
0064     template <class Base, class Derived>
0065     struct InheritanceTest
0066     {
0067         typedef Derived * DerivedPtr;
0068         enum { Result = sizeof( InheritanceDetector<Base>::test( DerivedPtr() ) ) ==
0069                         sizeof( InheritanceDetector<Base>::ConversionExists ) };
0070     };
0071     */
0072 
0073     template <class Derived>
0074     struct QWidgetInheritanceTest
0075     {
0076         typedef Derived * DerivedPtr;
0077         enum { Result = sizeof( InheritanceDetector<QWidget>::test( DerivedPtr() ) ) ==
0078                         sizeof( InheritanceDetector<QWidget>::ConversionExists ) };
0079     };
0080 
0081     template <class Derived>
0082     struct PartInheritanceTest
0083     {
0084         typedef Derived * DerivedPtr;
0085         enum { Result = sizeof( InheritanceDetector<KParts::Part>::test( DerivedPtr() ) ) ==
0086                         sizeof( InheritanceDetector<KParts::Part>::ConversionExists ) };
0087     };
0088 
0089 
0090     template <bool condition, typename Then, typename Else>
0091     struct If
0092     {
0093         typedef Else Result;
0094     };
0095 
0096     template <typename Then, typename Else>
0097     struct If<true, Then, Else>
0098     {
0099         typedef Then Result;
0100     };
0101 
0102     // a small helper template, to ease the overloading done in ConcreteFactory
0103     // to choose the right constructor for the given class.
0104     template <class T>
0105     struct Type2Type
0106     {
0107         typedef T OriginalType;
0108     };
0109 
0110 
0111     // this template is called from the MultiFactory one. It instantiates
0112     // the given class if the className matches. Instantiating is done by
0113     // calling the right constructor (a parentwidget/parent
0114     // one for Parts, a parentwidget one for widgets and last
0115     // but not least the standard default constructor with a parent .
0116     // the choice of the right constructor is done using an ordered inheritance
0117     // test.
0118     template <class Product, class ParentType = QObject>
0119     class ConcreteFactory
0120     {
0121     public:
0122         typedef typename If< PartInheritanceTest< Product >::Result,
0123                              KParts::Part,
0124                              typename If< QWidgetInheritanceTest< Product >::Result,
0125                                           QWidget, QObject >::Result >::Result BaseType;
0126 
0127         static inline Product *create( QWidget *parentWidget,
0128                                        QObject *parent,
0129                                        const char *className, const QStringList &args )
0130         {
0131             const QMetaObject* metaObject = &Product::staticMetaObject;
0132             while ( metaObject )
0133             {
0134                 //kDebug(150) << "className=" << className << " metaObject->className()=" << metaObject->className() << endl;
0135                 if ( !qstrcmp( className, metaObject->className() ) )
0136                     return create( parentWidget,
0137                                    parent, args, Type2Type<BaseType>() );
0138                 metaObject = metaObject->superClass();
0139             }
0140             //kDebug(150) << "error, returning 0" << endl;
0141             return 0;
0142         }
0143     private:
0144         typedef typename If< QWidgetInheritanceTest<ParentType>::Result,
0145                              ParentType, QWidget >::Result WidgetParentType;
0146 
0147         static inline Product *create( QWidget *parentWidget,
0148                                        QObject *parent,
0149                                        const QStringList &args, Type2Type<KParts::Part> )
0150         {
0151             //kDebug(150) << "create - 1" << endl;
0152             return new Product( parentWidget, parent, args );
0153         }
0154 
0155         static inline Product *create( QWidget* /*parentWidget*/,
0156                                        QObject *parent,
0157                                        const QStringList &args, Type2Type<QWidget> )
0158         {
0159             //kDebug(150) << "create - 2" << endl;
0160             WidgetParentType *p = dynamic_cast<WidgetParentType *>( parent );
0161             if ( parent && !p )
0162                 return 0;
0163             return new Product( p, args );
0164         }
0165 
0166         static inline Product *create( QWidget* /*parentWidget*/,
0167                                        QObject *parent,
0168                                        const QStringList &args, Type2Type<QObject> )
0169         {
0170             //kDebug(150) << "create - 3" << endl;
0171             ParentType *p = dynamic_cast<ParentType *>( parent );
0172             if ( parent && !p )
0173                 return 0;
0174             return new Product( p, args );
0175         }
0176     };
0177 
0178     // this template is used to iterate through the typelist and call the
0179     // concrete factory for each type. the specializations of this template
0180     // are the ones actually being responsible for iterating, in fact.
0181     template <class Product, class ParentType = QObject>
0182     class MultiFactory
0183     {
0184     public:
0185         inline static QObject *create( QWidget *parentWidget,
0186                                        QObject *parent,
0187                                        const char *className,
0188                                        const QStringList &args )
0189         {
0190             return ConcreteFactory<Product, ParentType>::create( parentWidget,
0191                                                                  parent, className,
0192                                                                  args );
0193         }
0194 
0195     };
0196 
0197     // this specialized template we 'reach' at the end of a typelist
0198     // (the last item in a typelist is the NullType)
0199     template <>
0200     class MultiFactory<KDE::NullType>
0201     {
0202     public:
0203         inline static QObject *create( QWidget *, QObject *,
0204                                        const char *,
0205                                        const QStringList & )
0206         { return nullptr; }
0207     };
0208 
0209      // this specialized template we 'reach' at the end of a typelist
0210     // (the last item in a typelist is the NullType)
0211     template <>
0212     class MultiFactory<KDE::NullType, KDE::NullType>
0213     {
0214     public:
0215         inline static QObject *create( QWidget *, QObject *,
0216                                        const char *,
0217                                        const QStringList & )
0218         { return nullptr; }
0219     };
0220 
0221     template <class Product, class ProductListTail>
0222     class MultiFactory< KTypeList<Product, ProductListTail>, QObject >
0223     {
0224     public:
0225         inline static QObject *create( QWidget *parentWidget,
0226                                        QObject *parent,
0227                                        const char *className,
0228                                        const QStringList &args )
0229         {
0230             // try with the head of the typelist first. the head is always
0231             // a concrete type.
0232             QObject *object = MultiFactory<Product>::create( parentWidget,
0233                                                              parent, className,
0234                                                              args );
0235 
0236             if ( !object )
0237                 object = MultiFactory<ProductListTail>::create( parentWidget,
0238                                                                 parent, className,
0239                                                                 args );
0240 
0241             return object;
0242         }
0243     };
0244 
0245     template <class Product, class ProductListTail,
0246               class ParentType, class ParentTypeListTail>
0247     class MultiFactory< KTypeList<Product, ProductListTail>,
0248                         KTypeList<ParentType, ParentTypeListTail> >
0249     {
0250     public:
0251         inline static QObject *create( QWidget *parentWidget,
0252                                        QObject *parent,
0253                                        const char *className,
0254                                        const QStringList &args )
0255         {
0256             // try with the head of the typelist first. the head is always
0257             // a concrete type.
0258             QObject *object = MultiFactory<Product, ParentType>
0259                                   ::create( parentWidget,
0260                                             parent, className, args );
0261 
0262             // if that failed continue by advancing the typelist, calling this
0263             // template specialization recursively (with T2 being a typelist) .
0264             // at the end we reach the nulltype specialization.
0265             if ( !object )
0266                 object = MultiFactory<ProductListTail, ParentTypeListTail>
0267                              ::create( parentWidget,
0268                                        parent, className, args );
0269 
0270             return object;
0271         }
0272     };
0273 }
0274 
0275 #endif
0276 
0277 #endif