home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / SLAX 6.0.8 / slax-6.0.8.iso / slax / base / 006-devel.lzm / usr / include / kgenericfactory.tcc < prev    next >
Encoding:
Text File  |  2005-10-10  |  10.2 KB  |  273 lines

  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++ -*-
  26. //
  27. //  W A R N I N G
  28. //  -------------
  29. //
  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.
  33. //
  34. // We mean it.
  35. //
  36.  
  37. #ifndef KGENERICFACTORY_TCC
  38. #define KGENERICFACTORY_TCC
  39.  
  40. #include <qmetaobject.h>
  41. #include <ktypelist.h>
  42.  
  43. namespace KParts
  44. {
  45.     class Part;
  46. }
  47.  
  48. namespace KDEPrivate
  49. {
  50.     template <class Base>
  51.     struct InheritanceDetector
  52.     {
  53.         typedef char ConversionExists;
  54.         struct ConversionDoesNotExist { char bleh[ 2 ]; };
  55.         static ConversionExists test( Base * );
  56.         static ConversionDoesNotExist test( ... );
  57.     };
  58.  
  59.     /* Simon: KCC doesn't eat the generic InheritanceDetector<Base>. 
  60.        Instead we have to use concrete specializations :-(
  61.  
  62.     template <class Base, class Derived>
  63.     struct InheritanceTest
  64.     {
  65.         typedef Derived * DerivedPtr;
  66.         enum { Result = sizeof( InheritanceDetector<Base>::test( DerivedPtr() ) ) ==
  67.                         sizeof( InheritanceDetector<Base>::ConversionExists ) };
  68.     };
  69.     */
  70.  
  71.     template <class Derived>
  72.     struct QWidgetInheritanceTest
  73.     {
  74.         typedef Derived * DerivedPtr;
  75.         enum { Result = sizeof( InheritanceDetector<QWidget>::test( DerivedPtr() ) ) ==
  76.                         sizeof( InheritanceDetector<QWidget>::ConversionExists ) };
  77.     };
  78.  
  79.     template <class Derived>
  80.     struct PartInheritanceTest
  81.     {
  82.         typedef Derived * DerivedPtr;
  83.         enum { Result = sizeof( InheritanceDetector<KParts::Part>::test( DerivedPtr() ) ) ==
  84.                         sizeof( InheritanceDetector<KParts::Part>::ConversionExists ) };
  85.     };
  86.  
  87.  
  88.     template <bool condition, typename Then, typename Else>
  89.     struct If
  90.     {
  91.         typedef Else Result;
  92.     };
  93.  
  94.     template <typename Then, typename Else>
  95.     struct If<true, Then, Else>
  96.     {
  97.         typedef Then Result;
  98.     };
  99.  
  100.     // a small helper template, to ease the overloading done in ConcreteFactory
  101.     // to choose the right constructor for the given class.
  102.     template <class T>
  103.     struct Type2Type
  104.     {
  105.         typedef T OriginalType;
  106.     };
  107.  
  108.     // this template is called from the MultiFactory one. It instantiates
  109.     // the given class if the className matches. Instantiating is done by 
  110.     // calling the right constructor (a parentwidget/widgetname/parent/name 
  111.     // one for Parts, a parentwidget/widgetname one for widgets and last
  112.     // but not least the standard default constructor of parent/name .
  113.     // the choice of the right constructor is done using an ordered inheritance
  114.     // test.
  115.     template <class Product, class ParentType = QObject>
  116.     class ConcreteFactory
  117.     {
  118.     public:
  119.         typedef typename If< PartInheritanceTest< Product >::Result,
  120.                              KParts::Part,
  121.                              typename If< QWidgetInheritanceTest< Product >::Result,
  122.                                           QWidget, QObject >::Result >::Result BaseType;
  123.  
  124.         static inline Product *create( QWidget *parentWidget, const char *widgetName,
  125.                                        QObject *parent, const char *name, 
  126.                                        const char *className, const QStringList &args )
  127.         {
  128.             QMetaObject *metaObject = Product::staticMetaObject();
  129.             while ( metaObject )
  130.             {
  131.                 if ( !qstrcmp( className, metaObject->className() ) )
  132.                     return create( parentWidget, widgetName,
  133.                                    parent, name, args, Type2Type<BaseType>() );
  134.                 metaObject = metaObject->superClass();
  135.             }
  136.             return 0;
  137.         }
  138.     private:
  139.         typedef typename If< QWidgetInheritanceTest<ParentType>::Result,
  140.                              ParentType, QWidget >::Result WidgetParentType;
  141.  
  142.         static inline Product *create( QWidget *parentWidget, const char *widgetName,
  143.                                        QObject *parent, const char *name,
  144.                                        const QStringList &args, Type2Type<KParts::Part> )
  145.         { 
  146.             return new Product( parentWidget, widgetName, parent, name, args ); 
  147.         }
  148.  
  149.         static inline Product *create( QWidget* /*parentWidget*/, const char* /*widgetName*/,
  150.                                        QObject *parent, const char *name,
  151.                                        const QStringList &args, Type2Type<QWidget> )
  152.         {
  153.  
  154.             WidgetParentType *p = dynamic_cast<WidgetParentType *>( parent );
  155.             if ( parent && !p ) 
  156.                 return 0;
  157.             return new Product( p, name, args );
  158.         }
  159.  
  160.         static inline Product *create( QWidget* /*parentWidget*/, const char* /*widgetName*/,
  161.                                        QObject *parent, const char *name,
  162.                                        const QStringList &args, Type2Type<QObject> )
  163.         { 
  164.             ParentType *p = dynamic_cast<ParentType *>( parent );
  165.             if ( parent && !p )
  166.                 return 0;
  167.             return new Product( p, name, args ); 
  168.         }
  169.     };
  170.  
  171.     // this template is used to iterate through the typelist and call the
  172.     // concrete factory for each type. the specializations of this template
  173.     // are the ones actually being responsible for iterating, in fact.
  174.     template <class Product, class ParentType = QObject>
  175.     class MultiFactory
  176.     {
  177.     public:
  178.         inline static QObject *create( QWidget *parentWidget, const char *widgetName,
  179.                                        QObject *parent, const char *name,
  180.                                        const char *className, 
  181.                                        const QStringList &args )
  182.         {
  183.             return ConcreteFactory<Product, ParentType>::create( parentWidget, widgetName,
  184.                                                                  parent, name, className, 
  185.                                                                  args );
  186.         }
  187.  
  188.     };
  189.  
  190.     // this specialized template we 'reach' at the end of a typelist
  191.     // (the last item in a typelist is the NullType)
  192.     template <>
  193.     class MultiFactory<KDE::NullType>
  194.     {
  195.     public:
  196.         inline static QObject *create( QWidget *, const char *, QObject *, 
  197.                                        const char *, const char *, 
  198.                                        const QStringList & )
  199.         { return 0; }
  200.     };
  201.  
  202.      // this specialized template we 'reach' at the end of a typelist
  203.     // (the last item in a typelist is the NullType)
  204.     template <>
  205.     class MultiFactory<KDE::NullType, KDE::NullType>
  206.     {
  207.     public:
  208.         inline static QObject *create( QWidget *, const char *, QObject *, 
  209.                                        const char *, const char *, 
  210.                                        const QStringList & )
  211.         { return 0; }
  212.     };
  213.  
  214.     template <class Product, class ProductListTail>
  215.     class MultiFactory< KTypeList<Product, ProductListTail>, QObject >
  216.     {
  217.     public:
  218.         inline static QObject *create( QWidget *parentWidget, const char *widgetName,
  219.                                        QObject *parent, const char *name,
  220.                                        const char *className, 
  221.                                        const QStringList &args )
  222.         {
  223.             // try with the head of the typelist first. the head is always
  224.             // a concrete type.
  225.             QObject *object = MultiFactory<Product>::create( parentWidget, widgetName,
  226.                                                              parent, name, className, 
  227.                                                              args );
  228.  
  229.             if ( !object )
  230.                 object = MultiFactory<ProductListTail>::create( parentWidget, widgetName,
  231.                                                                 parent, name, className, 
  232.                                                                 args );
  233.  
  234.             return object;
  235.         }
  236.     };
  237.  
  238.     template <class Product, class ProductListTail,
  239.               class ParentType, class ParentTypeListTail>
  240.     class MultiFactory< KTypeList<Product, ProductListTail>,
  241.                         KTypeList<ParentType, ParentTypeListTail> >
  242.     {
  243.     public:
  244.         inline static QObject *create( QWidget *parentWidget, const char *widgetName,
  245.                                        QObject *parent, const char *name,
  246.                                        const char *className, 
  247.                                        const QStringList &args )
  248.         {
  249.             // try with the head of the typelist first. the head is always
  250.             // a concrete type.
  251.             QObject *object = MultiFactory<Product, ParentType>
  252.                                   ::create( parentWidget, widgetName,
  253.                                             parent, name, className, args );
  254.  
  255.             // if that failed continue by advancing the typelist, calling this
  256.             // template specialization recursively (with T2 being a typelist) .
  257.             // at the end we reach the nulltype specialization.
  258.             if ( !object )
  259.                 object = MultiFactory<ProductListTail, ParentTypeListTail>
  260.                              ::create( parentWidget, widgetName,
  261.                                        parent, name, className, args );
  262.  
  263.             return object;
  264.         }
  265.     };
  266. }
  267.  
  268. #endif
  269.  
  270. /*
  271.  * vim: et sw=4
  272.  */
  273.