Grantlee
0.5.1
|
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 00285 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) 00286 00287 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF(Container, Type) 00288 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, Key, Type) 00289 00290 #else 00291 00297 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF(Container, Type) \ 00298 Grantlee::RegisterTypeContainer<Container<Type>, QMetaTypeId2<Container<Type> >::Defined>::reg(); \ 00299 00300 #ifndef Q_QDOC 00301 00304 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, Key, Type) \ 00305 Grantlee::RegisterTypeContainer<Container<Key, Type>, QMetaTypeId2<Container<Key, Type> >::Defined>::reg(); \ 00306 00307 #endif 00308 00309 #endif 00310 00326 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF(Container, Type) \ 00327 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, QString, Type) \ 00328 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint16, Type) \ 00329 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint32, Type) \ 00330 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint64, Type) \ 00331 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint16, Type) \ 00332 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint32, Type) \ 00333 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint64, Type) \ 00334 00335 namespace 00336 { 00337 00338 template<typename T> 00339 void registerContainers() 00340 { 00341 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QList, T ) 00342 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QQueue, T ) 00343 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QVector, T ) 00344 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QStack, T ) 00345 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QSet, T ) 00346 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QLinkedList, T ) 00347 00348 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF( QHash, T ) 00349 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF( QMap, T ) 00350 00351 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::deque, T ) 00352 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::vector, T ) 00353 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::list, T ) 00354 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF( std::map, T ) 00355 } 00356 00357 struct BuiltinRegister 00358 { 00359 void registerBuiltinContainers() const 00360 { 00361 Grantlee::MetaType::internalLock(); 00362 00363 registerContainers< bool >(); 00364 registerContainers< qint16 >(); 00365 registerContainers< qint32 >(); 00366 registerContainers< qint64 >(); 00367 registerContainers< quint16 >(); 00368 registerContainers< quint32 >(); 00369 registerContainers< quint64 >(); 00370 registerContainers< float >(); 00371 registerContainers< double >(); 00372 registerContainers< QString >(); 00373 registerContainers< QVariant >(); 00374 registerContainers< QDateTime >(); 00375 registerContainers< QObject* >(); 00376 00377 registerSequentialContainer<QStringList, QList<QString> >(); 00378 Grantlee::MetaType::internalUnlock(); 00379 } 00380 }; 00381 00382 Q_GLOBAL_STATIC( BuiltinRegister, builtinRegister ) 00383 00384 } 00385 00386 #ifndef Q_QDOC 00387 struct MetaTypeInitializer { 00388 static inline int initialize() 00389 { 00390 static const BuiltinRegister *br = builtinRegister(); 00391 br->registerBuiltinContainers(); 00392 return 0; 00393 } 00394 }; 00395 #endif 00396 00402 #define GRANTLEE_METATYPE_INITIALIZE static const int i = Grantlee::MetaTypeInitializer::initialize(); Q_UNUSED(i) 00403 00404 #ifndef Q_QDOC 00405 inline int MetaType::init() 00406 { 00407 GRANTLEE_METATYPE_INITIALIZE 00408 return 0; 00409 } 00410 #endif 00411 00447 template<typename RealType, typename HandleAs> 00448 int registerMetaType() 00449 { 00450 { 00451 GRANTLEE_METATYPE_INITIALIZE 00452 Q_UNUSED( i ) 00453 } 00454 MetaType::internalLock(); 00455 00456 const int id = InternalRegisterType<RealType, HandleAs>::doReg(); 00457 00458 registerContainers<RealType>(); 00459 00460 MetaType::internalUnlock(); 00461 00462 return id; 00463 } 00464 00465 #ifndef Q_QDOC 00466 00472 template<typename Type> 00473 int registerMetaType() 00474 { 00475 return registerMetaType<Type, Type>(); 00476 } 00477 00478 // http://catb.org/jargon/html/magic-story.html 00479 enum { 00480 Magic, 00481 MoreMagic 00482 }; 00483 00484 #endif 00485 } // namespace Grantlee 00486 00492 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER(Container) \ 00493 namespace Grantlee { \ 00494 template<typename T> \ 00495 struct RegisterTypeContainer<Container<T>, MoreMagic> \ 00496 { \ 00497 static int reg() \ 00498 { \ 00499 const int id = registerSequentialContainer<Container<T> >(); \ 00500 registerContainers<Container<T> >(); \ 00501 return id; \ 00502 } \ 00503 }; \ 00504 } \ 00505 00506 00511 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER(Container) \ 00512 namespace Grantlee { \ 00513 template<typename T, typename U> \ 00514 struct RegisterTypeContainer<Container<T, U>, MoreMagic> \ 00515 { \ 00516 static int reg() \ 00517 { \ 00518 const int id = registerAssociativeContainer<Container<T, U> >(); \ 00519 registerContainers<Container<T, U> >(); \ 00520 return id; \ 00521 } \ 00522 }; \ 00523 } \ 00524 00525 #ifndef Q_QDOC 00526 00529 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS(Container, As) \ 00530 namespace Grantlee { \ 00531 template<typename T> \ 00532 struct RegisterTypeContainer<Container<T>, MoreMagic> \ 00533 { \ 00534 static int reg() \ 00535 { \ 00536 return registerSequentialContainer<Container<T>, As<T> >(); \ 00537 } \ 00538 }; \ 00539 } \ 00540 00541 #endif 00542 00548 #define GRANTLEE_BEGIN_LOOKUP(Type) \ 00549 namespace Grantlee \ 00550 { \ 00551 template<> \ 00552 inline QVariant TypeAccessor<Type&>::lookUp( const Type &object, const QString &property ) \ 00553 { \ 00554 00555 00560 #define GRANTLEE_BEGIN_LOOKUP_PTR(Type) \ 00561 namespace Grantlee \ 00562 { \ 00563 template<> \ 00564 inline QVariant TypeAccessor<Type*>::lookUp( const Type * const object, const QString &property ) \ 00565 { \ 00566 00567 00572 #define GRANTLEE_END_LOOKUP \ 00573 return QVariant(); \ 00574 } \ 00575 } \ 00576 00577 00578 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QList) 00579 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QQueue, QList) 00580 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QVector) 00581 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QStack, QVector) 00582 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QSet) // Actually associative, but iterated as a sequential. 00583 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QLinkedList) 00584 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER (QHash) 00585 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER (QMap) 00586 00587 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (std::deque) 00588 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (std::vector) 00589 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (std::list) 00590 GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER (std::map) 00591 00592 00593 #endif // #define GRANTLEE_METATYPE_H