Grantlee
0.2.0
|
00001 /* 00002 This file is part of the Grantlee template system. 00003 00004 Copyright (c) 2010 Michael Jansen <kde@michael-jansen.biz> 00005 Copyright (c) 2010 Stephen Kelly <steveire@gmail.com> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Lesser General Public 00009 License as published by the Free Software Foundation; either version 00010 2.1 of the Licence, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public 00018 License along with this library. If not, see <http://www.gnu.org/licenses/>. 00019 00020 */ 00021 00022 #ifndef GRANTLEE_METATYPE_H 00023 #define GRANTLEE_METATYPE_H 00024 00025 #include "grantlee_core_export.h" 00026 00027 #include "typeaccessor.h" 00028 00029 #include <QtCore/QVariant> 00030 #include <QtCore/QStringList> 00031 #include <QtCore/QStack> 00032 #include <QtCore/QQueue> 00033 00034 #include <deque> 00035 #include <list> 00036 #include <map> 00037 #include <vector> 00038 00040 00041 namespace Grantlee 00042 { 00043 00045 00046 #ifndef Q_QDOC 00047 00058 class GRANTLEE_CORE_EXPORT MetaType 00059 { 00060 public: 00064 typedef QVariant ( *LookupFunction )( const QVariant &, const QString & ); 00065 00069 typedef QVariantList ( *ToVariantListFunction )( const QVariant & ); 00070 00074 static void registerLookUpOperator( int id, LookupFunction f ); 00075 00079 static void registerToVariantListOperator( int id, ToVariantListFunction f ); 00080 00084 static void internalLock(); 00085 00089 static void internalUnlock(); 00090 00094 static QVariant lookup( const QVariant &object, const QString &property ); 00095 00099 static QVariantList toVariantList( const QVariant &obj ); 00100 00104 static bool lookupAlreadyRegistered( int id ); 00105 00109 static bool toListAlreadyRegistered( int id ); 00110 00114 static inline int init(); 00115 00119 static int initBuiltins() { return init(); } 00120 00121 private: 00122 MetaType(); 00123 }; 00124 #endif 00125 00126 namespace 00127 { 00128 00129 /* 00130 * This is a helper to select an appropriate overload of indexAccess 00131 */ 00132 template<typename RealType, typename HandleAs> 00133 struct LookupTrait 00134 { 00135 static QVariant doLookUp( const QVariant &object, const QString &property ) 00136 { 00137 typedef typename Grantlee::TypeAccessor<HandleAs> Accessor; 00138 return Accessor::lookUp( static_cast<HandleAs>( object.value<RealType>() ), property ); 00139 } 00140 }; 00141 00142 template<typename T> 00143 struct IsQObjectStar 00144 { 00145 enum { Yes = false }; 00146 }; 00147 00148 template<typename T> 00149 struct IsQObjectStar<T*> 00150 { 00151 typedef int yes_type; 00152 typedef char no_type; 00153 00154 static yes_type check(QObject*); 00155 static no_type check(...); 00156 enum { Yes = sizeof(check(static_cast<T*>(0))) == sizeof(yes_type) }; 00157 }; 00158 00159 template<typename T, bool> 00160 struct LookupPointer 00161 { 00162 static QVariant doLookUp( const QVariant &object, const QString &property ) 00163 { 00164 typedef typename Grantlee::TypeAccessor<T> Accessor; 00165 return Accessor::lookUp( object.value<T>(), property ); 00166 } 00167 }; 00168 00169 template<typename T> 00170 struct LookupPointer<T, true> 00171 { 00172 static QVariant doLookUp( const QVariant &object, const QString &property ) 00173 { 00174 typedef typename Grantlee::TypeAccessor<QObject*> Accessor; 00175 return Accessor::lookUp( object.value<T>(), property ); 00176 } 00177 }; 00178 00179 template<typename RealType> 00180 struct LookupTrait<RealType*, RealType*> 00181 { 00182 static QVariant doLookUp( const QVariant &object, const QString &property ) 00183 { 00184 return LookupPointer<RealType*, IsQObjectStar<RealType*>::Yes>::doLookUp(object, property); 00185 } 00186 }; 00187 00188 template<typename RealType, typename HandleAs> 00189 struct LookupTrait<RealType&, HandleAs&> 00190 { 00191 static QVariant doLookUp( const QVariant &object, const QString &property ) 00192 { 00193 typedef typename Grantlee::TypeAccessor<HandleAs&> Accessor; 00194 return Accessor::lookUp( static_cast<HandleAs>( object.value<RealType>() ), property ); 00195 } 00196 }; 00197 00198 template<typename RealType, typename HandleAs> 00199 static int doRegister( int id ) 00200 { 00201 if ( MetaType::lookupAlreadyRegistered( id ) ) 00202 return id; 00203 00204 QVariant ( *lf )( const QVariant&, const QString& ) = LookupTrait<RealType, HandleAs>::doLookUp; 00205 00206 MetaType::registerLookUpOperator( id, reinterpret_cast<MetaType::LookupFunction>( lf ) ); 00207 00208 return id; 00209 } 00210 00211 /* 00212 * Register a type so grantlee knows how to handle it. 00213 */ 00214 template<typename RealType, typename HandleAs> 00215 struct InternalRegisterType 00216 { 00217 static int doReg() { 00218 const int id = qMetaTypeId<RealType>(); 00219 return doRegister<RealType&, HandleAs&>( id ); 00220 } 00221 }; 00222 00223 template<typename RealType, typename HandleAs> 00224 struct InternalRegisterType<RealType*, HandleAs*> 00225 { 00226 static int doReg() { 00227 const int id = qMetaTypeId<RealType*>(); 00228 return doRegister<RealType*, HandleAs*>( id ); 00229 } 00230 }; 00231 00232 template<typename Container, typename HandleAs> 00233 int registerSequentialContainer() 00234 { 00235 const int id = InternalRegisterType<Container, HandleAs>::doReg(); 00236 00237 if ( MetaType::toListAlreadyRegistered( id ) ) 00238 return id; 00239 00240 QVariantList ( *tlf )( const QVariant& ) = SequentialContainerAccessor<Container>::doToList; 00241 MetaType::registerToVariantListOperator( id, reinterpret_cast<MetaType::ToVariantListFunction>( tlf ) ); 00242 return id; 00243 } 00244 00245 template<typename Container> 00246 int registerSequentialContainer() 00247 { 00248 return registerSequentialContainer<Container, Container>(); 00249 } 00250 00251 template<typename Container, typename HandleAs> 00252 int registerAssociativeContainer() 00253 { 00254 const int id = InternalRegisterType<Container, HandleAs>::doReg(); 00255 00256 if ( MetaType::toListAlreadyRegistered( id ) ) 00257 return id; 00258 00259 QVariantList ( *tlf )( const QVariant& ) = AssociativeContainerAccessor<Container>::doToList; 00260 MetaType::registerToVariantListOperator( id, reinterpret_cast<MetaType::ToVariantListFunction>( tlf ) ); 00261 return id; 00262 } 00263 00264 template<typename Container> 00265 int registerAssociativeContainer() 00266 { 00267 return registerAssociativeContainer<Container, Container>(); 00268 } 00269 00270 } 00271 00272 #ifndef Q_QDOC 00273 00279 template<typename RealType, int n> 00280 struct RegisterTypeContainer 00281 { 00282 static void reg() 00283 { 00284 } 00285 }; 00286 #endif 00287 00293 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF(Container, Type) \ 00294 Grantlee::RegisterTypeContainer<Container<Type>, QMetaTypeId2<Container<Type> >::Defined>::reg(); \ 00295 00296 #ifndef Q_QDOC 00297 00300 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, Key, Type) \ 00301 Grantlee::RegisterTypeContainer<Container<Key, Type>, QMetaTypeId2<Container<Key, Type> >::Defined>::reg(); \ 00302 00303 #endif 00304 00320 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF(Container, Type) \ 00321 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, QString, Type) \ 00322 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint16, Type) \ 00323 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint32, Type) \ 00324 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint64, Type) \ 00325 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint16, Type) \ 00326 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint32, Type) \ 00327 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint64, Type) \ 00328 00329 namespace 00330 { 00331 00332 template<typename T> 00333 void registerContainers() 00334 { 00335 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QList, T ) 00336 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QQueue, T ) 00337 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QVector, T ) 00338 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QStack, T ) 00339 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QSet, T ) 00340 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QLinkedList, T ) 00341 00342 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF( QHash, T ) 00343 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF( QMap, T ) 00344 00345 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::deque, T ) 00346 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::vector, T ) 00347 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::list, T ) 00348 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF( std::map, T ) 00349 } 00350 00351 struct BuiltinRegister 00352 { 00353 void registerBuiltinContainers() const 00354 { 00355 Grantlee::MetaType::internalLock(); 00356 00357 registerContainers< bool >(); 00358 registerContainers< qint16 >(); 00359 registerContainers< qint32 >(); 00360 registerContainers< qint64 >(); 00361 registerContainers< quint16 >(); 00362 registerContainers< quint32 >(); 00363 registerContainers< quint64 >(); 00364 registerContainers< float >(); 00365 registerContainers< double >(); 00366 registerContainers< QString >(); 00367 registerContainers< QVariant >(); 00368 registerContainers< QDateTime >(); 00369 registerContainers< QObject* >(); 00370 00371 registerSequentialContainer<QStringList, QList<QString> >(); 00372 Grantlee::MetaType::internalUnlock(); 00373 } 00374 }; 00375 00376 Q_GLOBAL_STATIC( BuiltinRegister, builtinRegister ) 00377 00378 } 00379 00380 #ifndef Q_QDOC 00381 struct MetaTypeInitializer { 00382 static inline int initialize() 00383 { 00384 static const BuiltinRegister *br = builtinRegister(); 00385 br->registerBuiltinContainers(); 00386 return 0; 00387 } 00388 }; 00389 #endif 00390 00396 #define GRANTLEE_METATYPE_INITIALIZE static const int i = Grantlee::MetaTypeInitializer::initialize(); Q_UNUSED(i) 00397 00398 #ifndef Q_QDOC 00399 inline int MetaType::init() 00400 { 00401 GRANTLEE_METATYPE_INITIALIZE 00402 return 0; 00403 } 00404 #endif 00405 00441 template<typename RealType, typename HandleAs> 00442 int registerMetaType() 00443 { 00444 { 00445 GRANTLEE_METATYPE_INITIALIZE 00446 Q_UNUSED( i ) 00447 } 00448 MetaType::internalLock(); 00449 00450 const int id = InternalRegisterType<RealType, HandleAs>::doReg(); 00451 00452 registerContainers<RealType>(); 00453 00454 MetaType::internalUnlock(); 00455 00456 return id; 00457 } 00458 00459 #ifndef Q_QDOC 00460 00466 template<typename Type> 00467 int registerMetaType() 00468 { 00469 return registerMetaType<Type, Type>(); 00470 } 00471 00472 // http://catb.org/jargon/html/magic-story.html 00473 enum { 00474 Magic, 00475 MoreMagic 00476 }; 00477 00478 #endif 00479 } // namespace Grantlee 00480 00486 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER(Container) \ 00487 namespace Grantlee { \ 00488 template<typename T> \ 00489 struct RegisterTypeContainer<Container<T>, MoreMagic> \ 00490 { \ 00491 static int reg() \ 00492 { \ 00493 const int id = registerSequentialContainer<Container<T> >(); \ 00494 registerContainers<Container<T> >(); \ 00495 return id; \ 00496 } \ 00497 }; \ 00498 } \ 00499 00500 00505 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER(Container) \ 00506 namespace Grantlee { \ 00507 template<typename T, typename U> \ 00508 struct RegisterTypeContainer<Container<T, U>, MoreMagic> \ 00509 { \ 00510 static int reg() \ 00511 { \ 00512 const int id = registerAssociativeContainer<Container<T, U> >(); \ 00513 registerContainers<Container<T, U> >(); \ 00514 return id; \ 00515 } \ 00516 }; \ 00517 } \ 00518 00519 #ifndef Q_QDOC 00520 00523 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS(Container, As) \ 00524 namespace Grantlee { \ 00525 template<typename T> \ 00526 struct RegisterTypeContainer<Container<T>, MoreMagic> \ 00527 { \ 00528 static int reg() \ 00529 { \ 00530 return registerSequentialContainer<Container<T>, As<T> >(); \ 00531 } \ 00532 }; \ 00533 } \ 00534 00535 #endif 00536 00542 #define GRANTLEE_BEGIN_LOOKUP(Type) \ 00543 namespace Grantlee \ 00544 { \ 00545 template<> \ 00546 inline QVariant TypeAccessor<Type&>::lookUp( const Type &object, const QString &property ) \ 00547 { \ 00548 00549 00554 #define GRANTLEE_BEGIN_LOOKUP_PTR(Type) \ 00555 namespace Grantlee \ 00556 { \ 00557 template<> \ 00558 inline QVariant TypeAccessor<Type*>::lookUp( const Type * const object, const QString &property ) \ 00559 { \ 00560 00561 00566 #define GRANTLEE_END_LOOKUP \ 00567 return QVariant(); \ 00568 } \ 00569 } \ 00570 00571 00572 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QList) 00573 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QQueue, QList) 00574 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QVector) 00575 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QStack, QVector) 00576 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QSet) // Actually associative, but iterated as a sequential. 00577 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QLinkedList) 00578 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER (QHash) 00579 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER (QMap) 00580 00581 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (std::deque) 00582 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (std::vector) 00583 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (std::list) 00584 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER (std::map) 00585 00586 00587 #endif // #define GRANTLEE_METATYPE_H 00588