Grantlee  0.4.0
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 
290 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF(Container, Type) \
291  Grantlee::RegisterTypeContainer<Container<Type>, QMetaTypeId2<Container<Type> >::Defined>::reg(); \
292 
293 #ifndef Q_QDOC
294 
297 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, Key, Type) \
298  Grantlee::RegisterTypeContainer<Container<Key, Type>, QMetaTypeId2<Container<Key, Type> >::Defined>::reg(); \
299 
300 #endif
301 
317 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF(Container, Type) \
318  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, QString, Type) \
319  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint16, Type) \
320  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint32, Type) \
321  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint64, Type) \
322  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint16, Type) \
323  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint32, Type) \
324  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint64, Type) \
325 
326 namespace
327 {
328 
329 template<typename T>
330 void registerContainers()
331 {
338 
341 
346 }
347 
348 struct BuiltinRegister
349 {
350  void registerBuiltinContainers() const
351  {
352  Grantlee::MetaType::internalLock();
353 
354  registerContainers< bool >();
355  registerContainers< qint16 >();
356  registerContainers< qint32 >();
357  registerContainers< qint64 >();
358  registerContainers< quint16 >();
359  registerContainers< quint32 >();
360  registerContainers< quint64 >();
361  registerContainers< float >();
362  registerContainers< double >();
363  registerContainers< QString >();
364  registerContainers< QVariant >();
365  registerContainers< QDateTime >();
366  registerContainers< QObject* >();
367 
368  registerSequentialContainer<QStringList, QList<QString> >();
369  Grantlee::MetaType::internalUnlock();
370  }
371 };
372 
373 Q_GLOBAL_STATIC( BuiltinRegister, builtinRegister )
374 
375 }
376 
377 #ifndef Q_QDOC
378 struct MetaTypeInitializer {
379  static inline int initialize()
380  {
381  static const BuiltinRegister *br = builtinRegister();
382  br->registerBuiltinContainers();
383  return 0;
384  }
385 };
386 #endif
387 
393 #define GRANTLEE_METATYPE_INITIALIZE static const int i = Grantlee::MetaTypeInitializer::initialize(); Q_UNUSED(i)
394 
395 #ifndef Q_QDOC
396 inline int MetaType::init()
397 {
399  return 0;
400 }
401 #endif
402 
438 template<typename RealType, typename HandleAs>
440 {
441  {
443  Q_UNUSED( i )
444  }
445  MetaType::internalLock();
446 
447  const int id = InternalRegisterType<RealType, HandleAs>::doReg();
448 
449  registerContainers<RealType>();
450 
451  MetaType::internalUnlock();
452 
453  return id;
454 }
455 
456 #ifndef Q_QDOC
457 
463 template<typename Type>
464 int registerMetaType()
465 {
466  return registerMetaType<Type, Type>();
467 }
468 
469 // http://catb.org/jargon/html/magic-story.html
470 enum {
471  Magic,
472  MoreMagic
473 };
474 
475 #endif
476 } // namespace Grantlee
477 
483 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER(Container) \
484 namespace Grantlee { \
485 template<typename T> \
486 struct RegisterTypeContainer<Container<T>, MoreMagic> \
487 { \
488  static int reg() \
489  { \
490  const int id = registerSequentialContainer<Container<T> >(); \
491  registerContainers<Container<T> >(); \
492  return id; \
493  } \
494 }; \
495 } \
496 
497 
502 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER(Container) \
503 namespace Grantlee { \
504 template<typename T, typename U> \
505 struct RegisterTypeContainer<Container<T, U>, MoreMagic> \
506 { \
507  static int reg() \
508  { \
509  const int id = registerAssociativeContainer<Container<T, U> >(); \
510  registerContainers<Container<T, U> >(); \
511  return id; \
512  } \
513 }; \
514 } \
515 
516 #ifndef Q_QDOC
517 
520 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS(Container, As) \
521 namespace Grantlee { \
522 template<typename T> \
523 struct RegisterTypeContainer<Container<T>, MoreMagic> \
524 { \
525  static int reg() \
526  { \
527  return registerSequentialContainer<Container<T>, As<T> >(); \
528  } \
529 }; \
530 } \
531 
532 #endif
533 
539 #define GRANTLEE_BEGIN_LOOKUP(Type) \
540 namespace Grantlee \
541 { \
542 template<> \
543 inline QVariant TypeAccessor<Type&>::lookUp( const Type &object, const QString &property ) \
544 { \
545 
546 
551 #define GRANTLEE_BEGIN_LOOKUP_PTR(Type) \
552 namespace Grantlee \
553 { \
554 template<> \
555 inline QVariant TypeAccessor<Type*>::lookUp( const Type * const object, const QString &property ) \
556 { \
557 
558 
563 #define GRANTLEE_END_LOOKUP \
564  return QVariant(); \
565 } \
566 } \
567 
568 
570 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QQueue, QList)
572 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QStack, QVector)
573 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QSet) // Actually associative, but iterated as a sequential.
577 
582 
583 
584 #endif // #define GRANTLEE_METATYPE_H
585 
int registerMetaType()
Registers the type RealType with the metatype system.
Definition: metatype.h:439
#define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER(Container)
Definition: metatype.h:483
#define GRANTLEE_METATYPE_INITIALIZE
Definition: metatype.h:393
#define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF(Container, Type)
Definition: metatype.h:290
#define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER(Container)
Definition: metatype.h:502
#define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF(Container,Type)
Definition: metatype.h:317
The Grantlee namespace holds all public Grantlee API.
Definition: Mainpage.dox:7