From ce4a32fe52ef09d8f5ff1dd22c001110902b60a2 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kdecore/kgenericfactory.tcc | 272 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 kdecore/kgenericfactory.tcc (limited to 'kdecore/kgenericfactory.tcc') diff --git a/kdecore/kgenericfactory.tcc b/kdecore/kgenericfactory.tcc new file mode 100644 index 000000000..41cd77824 --- /dev/null +++ b/kdecore/kgenericfactory.tcc @@ -0,0 +1,272 @@ +/* + * The Type2Type template and the Inheritance Detector are from + * + * (c) Andrei Alexandrescu and + * free for any use. + * + * The rest is: + * Copyright (C) 2001 Simon Hausmann + * + * 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. + */ +// -*- mode: c++ -*- +// +// W A R N I N G +// ------------- +// +// This file is not part of the KDE API. It exists for the convenience +// of KGenericFactory. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef KGENERICFACTORY_TCC +#define KGENERICFACTORY_TCC + +#include +#include + +namespace KParts +{ + class Part; +} + +namespace KDEPrivate +{ + template + struct InheritanceDetector + { + typedef char ConversionExists; + struct ConversionDoesNotExist { char bleh[ 2 ]; }; + static ConversionExists test( Base * ); + static ConversionDoesNotExist test( ... ); + }; + + /* Simon: KCC doesn't eat the generic InheritanceDetector. + Instead we have to use concrete specializations :-( + + template + struct InheritanceTest + { + typedef Derived * DerivedPtr; + enum { Result = sizeof( InheritanceDetector::test( DerivedPtr() ) ) == + sizeof( InheritanceDetector::ConversionExists ) }; + }; + */ + + template + struct QWidgetInheritanceTest + { + typedef Derived * DerivedPtr; + enum { Result = sizeof( InheritanceDetector::test( DerivedPtr() ) ) == + sizeof( InheritanceDetector::ConversionExists ) }; + }; + + template + struct PartInheritanceTest + { + typedef Derived * DerivedPtr; + enum { Result = sizeof( InheritanceDetector::test( DerivedPtr() ) ) == + sizeof( InheritanceDetector::ConversionExists ) }; + }; + + + template + struct If + { + typedef Else Result; + }; + + template + struct If + { + typedef Then Result; + }; + + // a small helper template, to ease the overloading done in ConcreteFactory + // to choose the right constructor for the given class. + template + struct Type2Type + { + typedef T OriginalType; + }; + + // this template is called from the MultiFactory one. It instantiates + // the given class if the className matches. Instantiating is done by + // calling the right constructor (a parentwidget/widgetname/parent/name + // one for Parts, a parentwidget/widgetname one for widgets and last + // but not least the standard default constructor of parent/name . + // the choice of the right constructor is done using an ordered inheritance + // test. + template + class ConcreteFactory + { + public: + typedef typename If< PartInheritanceTest< Product >::Result, + KParts::Part, + typename If< QWidgetInheritanceTest< Product >::Result, + QWidget, QObject >::Result >::Result BaseType; + + static inline Product *create( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const char *className, const QStringList &args ) + { + QMetaObject *metaObject = Product::staticMetaObject(); + while ( metaObject ) + { + if ( !qstrcmp( className, metaObject->className() ) ) + return create( parentWidget, widgetName, + parent, name, args, Type2Type() ); + metaObject = metaObject->superClass(); + } + return 0; + } + private: + typedef typename If< QWidgetInheritanceTest::Result, + ParentType, QWidget >::Result WidgetParentType; + + static inline Product *create( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const QStringList &args, Type2Type ) + { + return new Product( parentWidget, widgetName, parent, name, args ); + } + + static inline Product *create( QWidget* /*parentWidget*/, const char* /*widgetName*/, + QObject *parent, const char *name, + const QStringList &args, Type2Type ) + { + + WidgetParentType *p = dynamic_cast( parent ); + if ( parent && !p ) + return 0; + return new Product( p, name, args ); + } + + static inline Product *create( QWidget* /*parentWidget*/, const char* /*widgetName*/, + QObject *parent, const char *name, + const QStringList &args, Type2Type ) + { + ParentType *p = dynamic_cast( parent ); + if ( parent && !p ) + return 0; + return new Product( p, name, args ); + } + }; + + // this template is used to iterate through the typelist and call the + // concrete factory for each type. the specializations of this template + // are the ones actually being responsible for iterating, in fact. + template + class MultiFactory + { + public: + inline static QObject *create( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const char *className, + const QStringList &args ) + { + return ConcreteFactory::create( parentWidget, widgetName, + parent, name, className, + args ); + } + + }; + + // this specialized template we 'reach' at the end of a typelist + // (the last item in a typelist is the NullType) + template <> + class MultiFactory + { + public: + inline static QObject *create( QWidget *, const char *, QObject *, + const char *, const char *, + const QStringList & ) + { return 0; } + }; + + // this specialized template we 'reach' at the end of a typelist + // (the last item in a typelist is the NullType) + template <> + class MultiFactory + { + public: + inline static QObject *create( QWidget *, const char *, QObject *, + const char *, const char *, + const QStringList & ) + { return 0; } + }; + + template + class MultiFactory< KTypeList, QObject > + { + public: + inline static QObject *create( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const char *className, + const QStringList &args ) + { + // try with the head of the typelist first. the head is always + // a concrete type. + QObject *object = MultiFactory::create( parentWidget, widgetName, + parent, name, className, + args ); + + if ( !object ) + object = MultiFactory::create( parentWidget, widgetName, + parent, name, className, + args ); + + return object; + } + }; + + template + class MultiFactory< KTypeList, + KTypeList > + { + public: + inline static QObject *create( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const char *className, + const QStringList &args ) + { + // try with the head of the typelist first. the head is always + // a concrete type. + QObject *object = MultiFactory + ::create( parentWidget, widgetName, + parent, name, className, args ); + + // if that failed continue by advancing the typelist, calling this + // template specialization recursively (with T2 being a typelist) . + // at the end we reach the nulltype specialization. + if ( !object ) + object = MultiFactory + ::create( parentWidget, widgetName, + parent, name, className, args ); + + return object; + } + }; +} + +#endif + +/* + * vim: et sw=4 + */ -- cgit v1.2.3