fix logic
[personal-kdelibs.git] / kdecore / util / kgenericfactory.tcc
blobb959a0e6aeb704086673958de3e1ffda335fc9cc
1 /*
2  * The Type2Type template and the Inheritance Detector are from
3  * <http://www.cuj.com/experts/1810/alexandr.htm>
4  * (c) Andrei Alexandrescu <andrei@metalanguage.com> and
5  * free for any use.
6  *
7  * The rest is:
8  * Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25 // -*- mode: c++ -*-
27 //  W A R N I N G
28 //  -------------
30 // This file is not part of the KDE API.  It exists for the convenience
31 // of KGenericFactory. This header file may change from version to
32 // version without notice, or even be removed.
34 // We mean it.
37 #ifndef KGENERICFACTORY_TCC
38 #define KGENERICFACTORY_TCC
40 #include <QtCore/QMetaObject>
41 #include <ktypelist.h>
42 #include "kdebug.h"
44 namespace KParts
46     class Part;
49 namespace KDEPrivate
51     template <class Base>
52     struct InheritanceDetector
53     {
54         typedef char ConversionExists;
55         struct ConversionDoesNotExist { char bleh[ 2 ]; };
56         static ConversionExists test( Base * );
57         static ConversionDoesNotExist test( ... );
58     };
60     /* Simon: KCC doesn't eat the generic InheritanceDetector<Base>.
61        Instead we have to use concrete specializations :-(
63     template <class Base, class Derived>
64     struct InheritanceTest
65     {
66         typedef Derived * DerivedPtr;
67         enum { Result = sizeof( InheritanceDetector<Base>::test( DerivedPtr() ) ) ==
68                         sizeof( InheritanceDetector<Base>::ConversionExists ) };
69     };
70     */
72     template <class Derived>
73     struct QWidgetInheritanceTest
74     {
75         typedef Derived * DerivedPtr;
76         enum { Result = sizeof( InheritanceDetector<QWidget>::test( DerivedPtr() ) ) ==
77                         sizeof( InheritanceDetector<QWidget>::ConversionExists ) };
78     };
80     template <class Derived>
81     struct PartInheritanceTest
82     {
83         typedef Derived * DerivedPtr;
84         enum { Result = sizeof( InheritanceDetector<KParts::Part>::test( DerivedPtr() ) ) ==
85                         sizeof( InheritanceDetector<KParts::Part>::ConversionExists ) };
86     };
89     template <bool condition, typename Then, typename Else>
90     struct If
91     {
92         typedef Else Result;
93     };
95     template <typename Then, typename Else>
96     struct If<true, Then, Else>
97     {
98         typedef Then Result;
99     };
101     // a small helper template, to ease the overloading done in ConcreteFactory
102     // to choose the right constructor for the given class.
103     template <class T>
104     struct Type2Type
105     {
106         typedef T OriginalType;
107     };
110     // this template is called from the MultiFactory one. It instantiates
111     // the given class if the className matches. Instantiating is done by
112     // calling the right constructor (a parentwidget/parent
113     // one for Parts, a parentwidget one for widgets and last
114     // but not least the standard default constructor with a parent .
115     // the choice of the right constructor is done using an ordered inheritance
116     // test.
117     template <class Product, class ParentType = QObject>
118     class ConcreteFactory
119     {
120     public:
121         typedef typename If< PartInheritanceTest< Product >::Result,
122                              KParts::Part,
123                              typename If< QWidgetInheritanceTest< Product >::Result,
124                                           QWidget, QObject >::Result >::Result BaseType;
126         static inline Product *create( QWidget *parentWidget,
127                                        QObject *parent,
128                                        const char *className, const QStringList &args )
129         {
130             const QMetaObject* metaObject = &Product::staticMetaObject;
131             while ( metaObject )
132             {
133                 //kDebug(150) << "className=" << className << " metaObject->className()=" << metaObject->className() << endl;
134                 if ( !qstrcmp( className, metaObject->className() ) )
135                     return create( parentWidget,
136                                    parent, args, Type2Type<BaseType>() );
137                 metaObject = metaObject->superClass();
138             }
139             //kDebug(150) << "error, returning 0" << endl;
140             return 0;
141         }
142     private:
143         typedef typename If< QWidgetInheritanceTest<ParentType>::Result,
144                              ParentType, QWidget >::Result WidgetParentType;
146         static inline Product *create( QWidget *parentWidget,
147                                        QObject *parent,
148                                        const QStringList &args, Type2Type<KParts::Part> )
149         {
150             //kDebug(150) << "create - 1" << endl;
151             return new Product( parentWidget, parent, args );
152         }
154         static inline Product *create( QWidget* /*parentWidget*/,
155                                        QObject *parent,
156                                        const QStringList &args, Type2Type<QWidget> )
157         {
158             //kDebug(150) << "create - 2" << endl;
159             WidgetParentType *p = dynamic_cast<WidgetParentType *>( parent );
160             if ( parent && !p )
161                 return 0;
162             return new Product( p, args );
163         }
165         static inline Product *create( QWidget* /*parentWidget*/,
166                                        QObject *parent,
167                                        const QStringList &args, Type2Type<QObject> )
168         {
169             //kDebug(150) << "create - 3" << endl;
170             ParentType *p = dynamic_cast<ParentType *>( parent );
171             if ( parent && !p )
172                 return 0;
173             return new Product( p, args );
174         }
175     };
177     // this template is used to iterate through the typelist and call the
178     // concrete factory for each type. the specializations of this template
179     // are the ones actually being responsible for iterating, in fact.
180     template <class Product, class ParentType = QObject>
181     class MultiFactory
182     {
183     public:
184         inline static QObject *create( QWidget *parentWidget,
185                                        QObject *parent,
186                                        const char *className,
187                                        const QStringList &args )
188         {
189             return ConcreteFactory<Product, ParentType>::create( parentWidget,
190                                                                  parent, className,
191                                                                  args );
192         }
194     };
196     // this specialized template we 'reach' at the end of a typelist
197     // (the last item in a typelist is the NullType)
198     template <>
199     class MultiFactory<KDE::NullType>
200     {
201     public:
202         inline static QObject *create( QWidget *, QObject *,
203                                        const char *,
204                                        const QStringList & )
205         { return 0; }
206     };
208      // this specialized template we 'reach' at the end of a typelist
209     // (the last item in a typelist is the NullType)
210     template <>
211     class MultiFactory<KDE::NullType, KDE::NullType>
212     {
213     public:
214         inline static QObject *create( QWidget *, QObject *,
215                                        const char *,
216                                        const QStringList & )
217         { return 0; }
218     };
220     template <class Product, class ProductListTail>
221     class MultiFactory< KTypeList<Product, ProductListTail>, QObject >
222     {
223     public:
224         inline static QObject *create( QWidget *parentWidget,
225                                        QObject *parent,
226                                        const char *className,
227                                        const QStringList &args )
228         {
229             // try with the head of the typelist first. the head is always
230             // a concrete type.
231             QObject *object = MultiFactory<Product>::create( parentWidget,
232                                                              parent, className,
233                                                              args );
235             if ( !object )
236                 object = MultiFactory<ProductListTail>::create( parentWidget,
237                                                                 parent, className,
238                                                                 args );
240             return object;
241         }
242     };
244     template <class Product, class ProductListTail,
245               class ParentType, class ParentTypeListTail>
246     class MultiFactory< KTypeList<Product, ProductListTail>,
247                         KTypeList<ParentType, ParentTypeListTail> >
248     {
249     public:
250         inline static QObject *create( QWidget *parentWidget,
251                                        QObject *parent,
252                                        const char *className,
253                                        const QStringList &args )
254         {
255             // try with the head of the typelist first. the head is always
256             // a concrete type.
257             QObject *object = MultiFactory<Product, ParentType>
258                                   ::create( parentWidget,
259                                             parent, className, args );
261             // if that failed continue by advancing the typelist, calling this
262             // template specialization recursively (with T2 being a typelist) .
263             // at the end we reach the nulltype specialization.
264             if ( !object )
265                 object = MultiFactory<ProductListTail, ParentTypeListTail>
266                              ::create( parentWidget,
267                                        parent, className, args );
269             return object;
270         }
271     };
274 #endif
277  * vim: et sw=4
278  */