summaryrefslogtreecommitdiffstats
path: root/kdecore/kgenericfactory.tcc
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /kdecore/kgenericfactory.tcc
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
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
Diffstat (limited to 'kdecore/kgenericfactory.tcc')
-rw-r--r--kdecore/kgenericfactory.tcc272
1 files changed, 272 insertions, 0 deletions
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
+ * <http://www.cuj.com/experts/1810/alexandr.htm>
+ * (c) Andrei Alexandrescu <andrei@metalanguage.com> and
+ * free for any use.
+ *
+ * The rest is:
+ * Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
+ *
+ * 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 <qmetaobject.h>
+#include <ktypelist.h>
+
+namespace KParts
+{
+ class Part;
+}
+
+namespace KDEPrivate
+{
+ template <class Base>
+ 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<Base>.
+ Instead we have to use concrete specializations :-(
+
+ template <class Base, class Derived>
+ struct InheritanceTest
+ {
+ typedef Derived * DerivedPtr;
+ enum { Result = sizeof( InheritanceDetector<Base>::test( DerivedPtr() ) ) ==
+ sizeof( InheritanceDetector<Base>::ConversionExists ) };
+ };
+ */
+
+ template <class Derived>
+ struct QWidgetInheritanceTest
+ {
+ typedef Derived * DerivedPtr;
+ enum { Result = sizeof( InheritanceDetector<QWidget>::test( DerivedPtr() ) ) ==
+ sizeof( InheritanceDetector<QWidget>::ConversionExists ) };
+ };
+
+ template <class Derived>
+ struct PartInheritanceTest
+ {
+ typedef Derived * DerivedPtr;
+ enum { Result = sizeof( InheritanceDetector<KParts::Part>::test( DerivedPtr() ) ) ==
+ sizeof( InheritanceDetector<KParts::Part>::ConversionExists ) };
+ };
+
+
+ template <bool condition, typename Then, typename Else>
+ struct If
+ {
+ typedef Else Result;
+ };
+
+ template <typename Then, typename Else>
+ struct If<true, Then, Else>
+ {
+ typedef Then Result;
+ };
+
+ // a small helper template, to ease the overloading done in ConcreteFactory
+ // to choose the right constructor for the given class.
+ template <class T>
+ 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 Product, class ParentType = QObject>
+ 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<BaseType>() );
+ metaObject = metaObject->superClass();
+ }
+ return 0;
+ }
+ private:
+ typedef typename If< QWidgetInheritanceTest<ParentType>::Result,
+ ParentType, QWidget >::Result WidgetParentType;
+
+ static inline Product *create( QWidget *parentWidget, const char *widgetName,
+ QObject *parent, const char *name,
+ const QStringList &args, Type2Type<KParts::Part> )
+ {
+ 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<QWidget> )
+ {
+
+ WidgetParentType *p = dynamic_cast<WidgetParentType *>( 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<QObject> )
+ {
+ ParentType *p = dynamic_cast<ParentType *>( 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 Product, class ParentType = QObject>
+ 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<Product, ParentType>::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<KDE::NullType>
+ {
+ 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<KDE::NullType, KDE::NullType>
+ {
+ public:
+ inline static QObject *create( QWidget *, const char *, QObject *,
+ const char *, const char *,
+ const QStringList & )
+ { return 0; }
+ };
+
+ template <class Product, class ProductListTail>
+ class MultiFactory< KTypeList<Product, ProductListTail>, 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<Product>::create( parentWidget, widgetName,
+ parent, name, className,
+ args );
+
+ if ( !object )
+ object = MultiFactory<ProductListTail>::create( parentWidget, widgetName,
+ parent, name, className,
+ args );
+
+ return object;
+ }
+ };
+
+ template <class Product, class ProductListTail,
+ class ParentType, class ParentTypeListTail>
+ class MultiFactory< KTypeList<Product, ProductListTail>,
+ KTypeList<ParentType, ParentTypeListTail> >
+ {
+ 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<Product, ParentType>
+ ::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<ProductListTail, ParentTypeListTail>
+ ::create( parentWidget, widgetName,
+ parent, name, className, args );
+
+ return object;
+ }
+ };
+}
+
+#endif
+
+/*
+ * vim: et sw=4
+ */