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