Grantlee  0.5.1
metatype.h
Go to the documentation of this file.
1 /*
2  This file is part of the Grantlee template system.
3 
4  Copyright (c) 2010 Michael Jansen <kde@michael-jansen.biz>
5  Copyright (c) 2010 Stephen Kelly <steveire@gmail.com>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public
9  License as published by the Free Software Foundation; either version
10  2.1 of the Licence, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 
20 */
21 
22 #ifndef GRANTLEE_METATYPE_H
23 #define GRANTLEE_METATYPE_H
24 
25 #include "grantlee_core_export.h"
26 
27 #include "typeaccessor.h"
28 
29 #include <QtCore/QVariant>
30 #include <QtCore/QStringList>
31 #include <QtCore/QStack>
32 #include <QtCore/QQueue>
33 #include <QtCore/QDateTime>
34 
35 #include <deque>
36 #include <list>
37 #include <map>
38 #include <vector>
39 
41 
42 namespace Grantlee
43 {
44 
46 
47 #ifndef Q_QDOC
48 
59 class GRANTLEE_CORE_EXPORT MetaType
60 {
61 public:
65  typedef QVariant ( *LookupFunction )( const QVariant &, const QString & );
66 
70  typedef QVariantList ( *ToVariantListFunction )( const QVariant & );
71 
75  static void registerLookUpOperator( int id, LookupFunction f );
76 
80  static void registerToVariantListOperator( int id, ToVariantListFunction f );
81 
85  static void internalLock();
86 
90  static void internalUnlock();
91 
95  static QVariant lookup( const QVariant &object, const QString &property );
96 
100  static QVariantList toVariantList( const QVariant &obj );
101 
105  static bool lookupAlreadyRegistered( int id );
106 
110  static bool toListAlreadyRegistered( int id );
111 
115  static inline int init();
116 
120  static int initBuiltins() { return init(); }
121 
122 private:
123  MetaType();
124 };
125 #endif
126 
127 namespace
128 {
129 
130 /*
131  * This is a helper to select an appropriate overload of indexAccess
132  */
133 template<typename RealType, typename HandleAs>
134 struct LookupTrait
135 {
136  static QVariant doLookUp( const QVariant &object, const QString &property );
137 };
138 
139 template<typename T>
140 struct IsQObjectStar
141 {
142  enum { Yes = false };
143 };
144 
145 template<typename T>
146 struct IsQObjectStar<T*>
147 {
148  typedef int yes_type;
149  typedef char no_type;
150 
151  static yes_type check(QObject*);
152  static no_type check(...);
153  enum { Yes = sizeof(check(static_cast<T*>(0))) == sizeof(yes_type) };
154 };
155 
156 template<typename T, bool>
157 struct LookupPointer
158 {
159  static QVariant doLookUp( const QVariant &object, const QString &property )
160  {
161  typedef typename Grantlee::TypeAccessor<T> Accessor;
162  return Accessor::lookUp( object.value<T>(), property );
163  }
164 };
165 
166 template<typename T>
167 struct LookupPointer<T, true>
168 {
169  static QVariant doLookUp( const QVariant &object, const QString &property )
170  {
171  typedef typename Grantlee::TypeAccessor<QObject*> Accessor;
172  return Accessor::lookUp( object.value<T>(), property );
173  }
174 };
175 
176 template<typename RealType>
177 struct LookupTrait<RealType*, RealType*>
178 {
179  static QVariant doLookUp( const QVariant &object, const QString &property )
180  {
181  return LookupPointer<RealType*, IsQObjectStar<RealType*>::Yes>::doLookUp(object, property);
182  }
183 };
184 
185 template<typename RealType, typename HandleAs>
186 struct LookupTrait<RealType&, HandleAs&>
187 {
188  static QVariant doLookUp( const QVariant &object, const QString &property )
189  {
190  typedef typename Grantlee::TypeAccessor<HandleAs&> Accessor;
191  return Accessor::lookUp( static_cast<HandleAs>( object.value<RealType>() ), property );
192  }
193 };
194 
195 template<typename RealType, typename HandleAs>
196 static int doRegister( int id )
197 {
198  if ( MetaType::lookupAlreadyRegistered( id ) )
199  return id;
200 
201  QVariant ( *lf )( const QVariant&, const QString& ) = LookupTrait<RealType, HandleAs>::doLookUp;
202 
203  MetaType::registerLookUpOperator( id, reinterpret_cast<MetaType::LookupFunction>( lf ) );
204 
205  return id;
206 }
207 
208 /*
209  * Register a type so grantlee knows how to handle it.
210  */
211 template<typename RealType, typename HandleAs>
212 struct InternalRegisterType
213 {
214  static int doReg() {
215  const int id = qMetaTypeId<RealType>();
216  return doRegister<RealType&, HandleAs&>( id );
217  }
218 };
219 
220 template<typename RealType, typename HandleAs>
221 struct InternalRegisterType<RealType*, HandleAs*>
222 {
223  static int doReg() {
224  const int id = qMetaTypeId<RealType*>();
225  return doRegister<RealType*, HandleAs*>( id );
226  }
227 };
228 
229 template<typename Container, typename HandleAs>
230 int registerSequentialContainer()
231 {
232  const int id = InternalRegisterType<Container, HandleAs>::doReg();
233 
234  if ( MetaType::toListAlreadyRegistered( id ) )
235  return id;
236 
237  QVariantList ( *tlf )( const QVariant& ) = SequentialContainerAccessor<Container>::doToList;
238  MetaType::registerToVariantListOperator( id, reinterpret_cast<MetaType::ToVariantListFunction>( tlf ) );
239  return id;
240 }
241 
242 template<typename Container>
243 int registerSequentialContainer()
244 {
245  return registerSequentialContainer<Container, Container>();
246 }
247 
248 template<typename Container, typename HandleAs>
249 int registerAssociativeContainer()
250 {
251  const int id = InternalRegisterType<Container, HandleAs>::doReg();
252 
253  if ( MetaType::toListAlreadyRegistered( id ) )
254  return id;
255 
256  QVariantList ( *tlf )( const QVariant& ) = AssociativeContainerAccessor<Container>::doToList;
257  MetaType::registerToVariantListOperator( id, reinterpret_cast<MetaType::ToVariantListFunction>( tlf ) );
258  return id;
259 }
260 
261 template<typename Container>
262 int registerAssociativeContainer()
263 {
264  return registerAssociativeContainer<Container, Container>();
265 }
266 
267 }
268 
269 #ifndef Q_QDOC
270 
276 template<typename RealType, int n>
277 struct RegisterTypeContainer
278 {
279  static void reg()
280  {
281  }
282 };
283 #endif
284 
285 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
286 
287 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF(Container, Type)
288 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, Key, Type)
289 
290 #else
291 
297 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF(Container, Type) \
298  Grantlee::RegisterTypeContainer<Container<Type>, QMetaTypeId2<Container<Type> >::Defined>::reg(); \
299 
300 #ifndef Q_QDOC
301 
304 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, Key, Type) \
305  Grantlee::RegisterTypeContainer<Container<Key, Type>, QMetaTypeId2<Container<Key, Type> >::Defined>::reg(); \
306 
307 #endif
308 
309 #endif
310 
326 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF(Container, Type) \
327  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, QString, Type) \
328  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint16, Type) \
329  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint32, Type) \
330  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint64, Type) \
331  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint16, Type) \
332  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint32, Type) \
333  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint64, Type) \
334 
335 namespace
336 {
337 
338 template<typename T>
339 void registerContainers()
340 {
341  GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QList, T )
342  GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QQueue, T )
343  GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QVector, T )
344  GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QStack, T )
345  GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QSet, T )
346  GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( QLinkedList, T )
347 
350 
351  GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::deque, T )
352  GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::vector, T )
353  GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF( std::list, T )
355 }
356 
357 struct BuiltinRegister
358 {
359  void registerBuiltinContainers() const
360  {
361  Grantlee::MetaType::internalLock();
362 
363  registerContainers< bool >();
364  registerContainers< qint16 >();
365  registerContainers< qint32 >();
366  registerContainers< qint64 >();
367  registerContainers< quint16 >();
368  registerContainers< quint32 >();
369  registerContainers< quint64 >();
370  registerContainers< float >();
371  registerContainers< double >();
372  registerContainers< QString >();
373  registerContainers< QVariant >();
374  registerContainers< QDateTime >();
375  registerContainers< QObject* >();
376 
377  registerSequentialContainer<QStringList, QList<QString> >();
378  Grantlee::MetaType::internalUnlock();
379  }
380 };
381 
382 Q_GLOBAL_STATIC( BuiltinRegister, builtinRegister )
383 
384 }
385 
386 #ifndef Q_QDOC
387 struct MetaTypeInitializer {
388  static inline int initialize()
389  {
390  static const BuiltinRegister *br = builtinRegister();
391  br->registerBuiltinContainers();
392  return 0;
393  }
394 };
395 #endif
396 
402 #define GRANTLEE_METATYPE_INITIALIZE static const int i = Grantlee::MetaTypeInitializer::initialize(); Q_UNUSED(i)
403 
404 #ifndef Q_QDOC
405 inline int MetaType::init()
406 {
408  return 0;
409 }
410 #endif
411 
447 template<typename RealType, typename HandleAs>
449 {
450  {
452  Q_UNUSED( i )
453  }
454  MetaType::internalLock();
455 
456  const int id = InternalRegisterType<RealType, HandleAs>::doReg();
457 
458  registerContainers<RealType>();
459 
460  MetaType::internalUnlock();
461 
462  return id;
463 }
464 
465 #ifndef Q_QDOC
466 
472 template<typename Type>
473 int registerMetaType()
474 {
475  return registerMetaType<Type, Type>();
476 }
477 
478 // http://catb.org/jargon/html/magic-story.html
479 enum {
480  Magic,
481  MoreMagic
482 };
483 
484 #endif
485 } // namespace Grantlee
486 
492 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER(Container) \
493 namespace Grantlee { \
494 template<typename T> \
495 struct RegisterTypeContainer<Container<T>, MoreMagic> \
496 { \
497  static int reg() \
498  { \
499  const int id = registerSequentialContainer<Container<T> >(); \
500  registerContainers<Container<T> >(); \
501  return id; \
502  } \
503 }; \
504 } \
505 
506 
511 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER(Container) \
512 namespace Grantlee { \
513 template<typename T, typename U> \
514 struct RegisterTypeContainer<Container<T, U>, MoreMagic> \
515 { \
516  static int reg() \
517  { \
518  const int id = registerAssociativeContainer<Container<T, U> >(); \
519  registerContainers<Container<T, U> >(); \
520  return id; \
521  } \
522 }; \
523 } \
524 
525 #ifndef Q_QDOC
526 
529 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS(Container, As) \
530 namespace Grantlee { \
531 template<typename T> \
532 struct RegisterTypeContainer<Container<T>, MoreMagic> \
533 { \
534  static int reg() \
535  { \
536  return registerSequentialContainer<Container<T>, As<T> >(); \
537  } \
538 }; \
539 } \
540 
541 #endif
542 
548 #define GRANTLEE_BEGIN_LOOKUP(Type) \
549 namespace Grantlee \
550 { \
551 template<> \
552 inline QVariant TypeAccessor<Type&>::lookUp( const Type &object, const QString &property ) \
553 { \
554 
555 
560 #define GRANTLEE_BEGIN_LOOKUP_PTR(Type) \
561 namespace Grantlee \
562 { \
563 template<> \
564 inline QVariant TypeAccessor<Type*>::lookUp( const Type * const object, const QString &property ) \
565 { \
566 
567 
572 #define GRANTLEE_END_LOOKUP \
573  return QVariant(); \
574 } \
575 } \
576 
577 
579 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QQueue, QList)
581 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QStack, QVector)
582 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QSet) // Actually associative, but iterated as a sequential.
586 
591 
592 
593 #endif // #define GRANTLEE_METATYPE_H
int registerMetaType()
Registers the type RealType with the metatype system.
Definition: metatype.h:448
#define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER(Container)
Definition: metatype.h:492
#define GRANTLEE_METATYPE_INITIALIZE
Definition: metatype.h:402
#define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER(Container)
Definition: metatype.h:511
#define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF(Container,Type)
Definition: metatype.h:326
The Grantlee namespace holds all public Grantlee API.
Definition: Mainpage.dox:7