Grantlee
0.4.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 #include <QtCore/QDateTime> 00034 00035 #include <deque> 00036 #include <list> 00037 #include <map> 00038 #include <vector> 00039 00041 00042 namespace Grantlee 00043 { 00044 00046 00047 #ifndef Q_QDOC 00048 00059 class GRANTLEE_CORE_EXPORT MetaType 00060 { 00061 public: 00065 typedef QVariant ( *LookupFunction )( const QVariant &, const QString & ); 00066 00070 typedef QVariantList ( *ToVariantListFunction )( const QVariant & ); 00071 00075 static void registerLookUpOperator( int id, LookupFunction f ); 00076 00080 static void registerToVariantListOperator( int id, ToVariantListFunction f ); 00081 00085 static void internalLock(); 00086 00090 static void internalUnlock(); 00091 00095 static QVariant lookup( const QVariant &object, const QString &property ); 00096 00100 static QVariantList toVariantList( const QVariant &obj ); 00101 00105 static bool lookupAlreadyRegistered( int id ); 00106 00110 static bool toListAlreadyRegistered( int id ); 00111 00115 static inline int init(); 00116 00120 static int initBuiltins() { return init(); } 00121 00122 private: 00123 MetaType(); 00124 }; 00125 #endif 00126 00127 namespace 00128 { 00129 00130 /* 00131 * This is a helper to select an appropriate overload of indexAccess 00132 */ 00133 template<typename RealType, typename HandleAs> 00134 struct LookupTrait 00135 { 00136 static QVariant doLookUp( const QVariant &object, const QString &property ); 00137 }; 00138 00139 template<typename T> 00140 struct IsQObjectStar 00141 { 00142 enum { Yes = false }; 00143 }; 00144 00145 template<typename T> 00146 struct IsQObjectStar<T*> 00147 { 00148 typedef int yes_type; 00149 typedef char no_type; 00150 00151 static yes_type check(QObject*); 00152 static no_type check(...); 00153 enum { Yes = sizeof(check(static_cast<T*>(0))) == sizeof(yes_type) }; 00154 }; 00155 00156 template<typename T, bool> 00157 struct LookupPointer 00158 { 00159 static QVariant doLookUp( const QVariant &object, const QString &property ) 00160 { 00161 typedef typename Grantlee::TypeAccessor<T> Accessor; 00162 return Accessor::lookUp( object.value<T>(), property ); 00163 } 00164 }; 00165 00166 template<typename T> 00167 struct LookupPointer<T, true> 00168 { 00169 static QVariant doLookUp( const QVariant &object, const QString &property ) 00170 { 00171 typedef typename Grantlee::TypeAccessor<QObject*> Accessor; 00172 return Accessor::lookUp( object.value<T>(), property ); 00173 } 00174 }; 00175 00176 template<typename RealType> 00177 struct LookupTrait<RealType*, RealType*> 00178 { 00179 static QVariant doLookUp( const QVariant &object, const QString &property ) 00180 { 00181 return LookupPointer<RealType*, IsQObjectStar<RealType*>::Yes>::doLookUp(object, property); 00182 } 00183 }; 00184 00185 template<typename RealType, typename HandleAs> 00186 struct LookupTrait<RealType&, HandleAs&> 00187 { 00188 static QVariant doLookUp( const QVariant &object, const QString &property ) 00189 { 00190 typedef typename Grantlee::TypeAccessor<HandleAs&> Accessor; 00191 return Accessor::lookUp( static_cast<HandleAs>( object.value<RealType>() ), property ); 00192 } 00193 }; 00194 00195 template<typename RealType, typename HandleAs> 00196 static int doRegister( int id ) 00197 { 00198 if ( MetaType::lookupAlreadyRegistered( id ) ) 00199 return id; 00200 00201 QVariant ( *lf )( const QVariant&, const QString& ) = LookupTrait<RealType, HandleAs>::doLookUp; 00202 00203 MetaType::registerLookUpOperator( id, reinterpret_cast<MetaType::LookupFunction>( lf ) ); 00204 00205 return id; 00206 } 00207 00208 /* 00209 * Register a type so grantlee knows how to handle it. 00210 */ 00211 template<typename RealType, typename HandleAs> 00212 struct InternalRegisterType 00213 { 00214 static int doReg() { 00215 const int id = qMetaTypeId<RealType>(); 00216 return doRegister<RealType&, HandleAs&>( id ); 00217 } 00218 }; 00219 00220 template<typename RealType, typename HandleAs> 00221 struct InternalRegisterType<RealType*, HandleAs*> 00222 { 00223 static int doReg() { 00224 const int id = qMetaTypeId<RealType*>(); 00225 return doRegister<RealType*, HandleAs*>( id ); 00226 } 00227 }; 00228 00229 template<typename Container, typename HandleAs> 00230 int registerSequentialContainer() 00231 { 00232 const int id = InternalRegisterType<Container, HandleAs>::doReg(); 00233 00234 if ( MetaType::toListAlreadyRegistered( id ) ) 00235 return id; 00236 00237 QVariantList ( *tlf )( const QVariant& ) = SequentialContainerAccessor<Container>::doToList; 00238 MetaType::registerToVariantListOperator( id, reinterpret_cast<MetaType::ToVariantListFunction>( tlf ) ); 00239 return id; 00240 } 00241 00242 template<typename Container> 00243 int registerSequentialContainer() 00244 { 00245 return registerSequentialContainer<Container, Container>(); 00246 } 00247 00248 template<typename Container, typename HandleAs> 00249 int registerAssociativeContainer() 00250 { 00251 const int id = InternalRegisterType<Container, HandleAs>::doReg(); 00252 00253 if ( MetaType::toListAlreadyRegistered( id ) ) 00254 return id; 00255 00256 QVariantList ( *tlf )( const QVariant& ) = AssociativeContainerAccessor<Container>::doToList; 00257 MetaType::registerToVariantListOperator( id, reinterpret_cast<MetaType::ToVariantListFunction>( tlf ) ); 00258 return id; 00259 } 00260 00261 template<typename Container> 00262 int registerAssociativeContainer() 00263 { 00264 return registerAssociativeContainer<Container, Container>(); 00265 } 00266 00267 } 00268 00269 #ifndef Q_QDOC 00270 00276 template<typename RealType, int n> 00277 struct RegisterTypeContainer 00278 { 00279 static void reg() 00280 { 00281 } 00282 }; 00283 #endif 00284 00290 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF(Container, Type) \ 00291 Grantlee::RegisterTypeContainer<Container<Type>, QMetaTypeId2<Container<Type> >::Defined>::reg(); \ 00292 00293 #ifndef Q_QDOC 00294 00297 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, Key, Type) \ 00298 Grantlee::RegisterTypeContainer<Container<Key, Type>, QMetaTypeId2<Container<Key, Type> >::Defined>::reg(); \ 00299 00300 #endif 00301 00317 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF(Container, Type) \ 00318 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, QString, Type) \ 00319 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint16, Type) \ 00320 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint32, Type) \ 00321 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint64, Type) \ 00322 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint16, Type) \ 00323 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint32, Type) \ 00324 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint64, Type) \ 00325 00326 namespace 00327 { 00328 00329 template<typename T> 00330 void registerContainers() 00331 { 00332 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QList, T ) 00333 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QQueue, T ) 00334 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QVector, T ) 00335 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QStack, T ) 00336 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QSet, T ) 00337 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QLinkedList, T ) 00338 00339 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF( QHash, T ) 00340 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF( QMap, T ) 00341 00342 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::deque, T ) 00343 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::vector, T ) 00344 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::list, T ) 00345 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF( std::map, T ) 00346 } 00347 00348 struct BuiltinRegister 00349 { 00350 void registerBuiltinContainers() const 00351 { 00352 Grantlee::MetaType::internalLock(); 00353 00354 registerContainers< bool >(); 00355 registerContainers< qint16 >(); 00356 registerContainers< qint32 >(); 00357 registerContainers< qint64 >(); 00358 registerContainers< quint16 >(); 00359 registerContainers< quint32 >(); 00360 registerContainers< quint64 >(); 00361 registerContainers< float >(); 00362 registerContainers< double >(); 00363 registerContainers< QString >(); 00364 registerContainers< QVariant >(); 00365 registerContainers< QDateTime >(); 00366 registerContainers< QObject* >(); 00367 00368 registerSequentialContainer<QStringList, QList<QString> >(); 00369 Grantlee::MetaType::internalUnlock(); 00370 } 00371 }; 00372 00373 Q_GLOBAL_STATIC( BuiltinRegister, builtinRegister ) 00374 00375 } 00376 00377 #ifndef Q_QDOC 00378 struct MetaTypeInitializer { 00379 static inline int initialize() 00380 { 00381 static const BuiltinRegister *br = builtinRegister(); 00382 br->registerBuiltinContainers(); 00383 return 0; 00384 } 00385 }; 00386 #endif 00387 00393 #define GRANTLEE_METATYPE_INITIALIZE static const int i = Grantlee::MetaTypeInitializer::initialize(); Q_UNUSED(i) 00394 00395 #ifndef Q_QDOC 00396 inline int MetaType::init() 00397 { 00398 GRANTLEE_METATYPE_INITIALIZE 00399 return 0; 00400 } 00401 #endif 00402 00438 template<typename RealType, typename HandleAs> 00439 int registerMetaType() 00440 { 00441 { 00442 GRANTLEE_METATYPE_INITIALIZE 00443 Q_UNUSED( i ) 00444 } 00445 MetaType::internalLock(); 00446 00447 const int id = InternalRegisterType<RealType, HandleAs>::doReg(); 00448 00449 registerContainers<RealType>(); 00450 00451 MetaType::internalUnlock(); 00452 00453 return id; 00454 } 00455 00456 #ifndef Q_QDOC 00457 00463 template<typename Type> 00464 int registerMetaType() 00465 { 00466 return registerMetaType<Type, Type>(); 00467 } 00468 00469 // http://catb.org/jargon/html/magic-story.html 00470 enum { 00471 Magic, 00472 MoreMagic 00473 }; 00474 00475 #endif 00476 } // namespace Grantlee 00477 00483 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER(Container) \ 00484 namespace Grantlee { \ 00485 template<typename T> \ 00486 struct RegisterTypeContainer<Container<T>, MoreMagic> \ 00487 { \ 00488 static int reg() \ 00489 { \ 00490 const int id = registerSequentialContainer<Container<T> >(); \ 00491 registerContainers<Container<T> >(); \ 00492 return id; \ 00493 } \ 00494 }; \ 00495 } \ 00496 00497 00502 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER(Container) \ 00503 namespace Grantlee { \ 00504 template<typename T, typename U> \ 00505 struct RegisterTypeContainer<Container<T, U>, MoreMagic> \ 00506 { \ 00507 static int reg() \ 00508 { \ 00509 const int id = registerAssociativeContainer<Container<T, U> >(); \ 00510 registerContainers<Container<T, U> >(); \ 00511 return id; \ 00512 } \ 00513 }; \ 00514 } \ 00515 00516 #ifndef Q_QDOC 00517 00520 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS(Container, As) \ 00521 namespace Grantlee { \ 00522 template<typename T> \ 00523 struct RegisterTypeContainer<Container<T>, MoreMagic> \ 00524 { \ 00525 static int reg() \ 00526 { \ 00527 return registerSequentialContainer<Container<T>, As<T> >(); \ 00528 } \ 00529 }; \ 00530 } \ 00531 00532 #endif 00533 00539 #define GRANTLEE_BEGIN_LOOKUP(Type) \ 00540 namespace Grantlee \ 00541 { \ 00542 template<> \ 00543 inline QVariant TypeAccessor<Type&>::lookUp( const Type &object, const QString &property ) \ 00544 { \ 00545 00546 00551 #define GRANTLEE_BEGIN_LOOKUP_PTR(Type) \ 00552 namespace Grantlee \ 00553 { \ 00554 template<> \ 00555 inline QVariant TypeAccessor<Type*>::lookUp( const Type * const object, const QString &property ) \ 00556 { \ 00557 00558 00563 #define GRANTLEE_END_LOOKUP \ 00564 return QVariant(); \ 00565 } \ 00566 } \ 00567 00568 00569 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QList) 00570 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QQueue, QList) 00571 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QVector) 00572 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QStack, QVector) 00573 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QSet) // Actually associative, but iterated as a sequential. 00574 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QLinkedList) 00575 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER (QHash) 00576 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER (QMap) 00577 00578 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (std::deque) 00579 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (std::vector) 00580 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (std::list) 00581 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER (std::map) 00582 00583 00584 #endif // #define GRANTLEE_METATYPE_H 00585