Grantlee  0.3.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 
34 #include <deque>
35 #include <list>
36 #include <map>
37 #include <vector>
38 
40 
41 namespace Grantlee
42 {
43 
45 
46 #ifndef Q_QDOC
47 
58 class GRANTLEE_CORE_EXPORT MetaType
59 {
60 public:
64  typedef QVariant ( *LookupFunction )( const QVariant &, const QString & );
65 
69  typedef QVariantList ( *ToVariantListFunction )( const QVariant & );
70 
74  static void registerLookUpOperator( int id, LookupFunction f );
75 
79  static void registerToVariantListOperator( int id, ToVariantListFunction f );
80 
84  static void internalLock();
85 
89  static void internalUnlock();
90 
94  static QVariant lookup( const QVariant &object, const QString &property );
95 
99  static QVariantList toVariantList( const QVariant &obj );
100 
104  static bool lookupAlreadyRegistered( int id );
105 
109  static bool toListAlreadyRegistered( int id );
110 
114  static inline int init();
115 
119  static int initBuiltins() { return init(); }
120 
121 private:
122  MetaType();
123 };
124 #endif
125 
126 namespace
127 {
128 
129 /*
130  * This is a helper to select an appropriate overload of indexAccess
131  */
132 template<typename RealType, typename HandleAs>
133 struct LookupTrait
134 {
135  static QVariant doLookUp( const QVariant &object, const QString &property );
136 };
137 
138 template<typename T>
139 struct IsQObjectStar
140 {
141  enum { Yes = false };
142 };
143 
144 template<typename T>
145 struct IsQObjectStar<T*>
146 {
147  typedef int yes_type;
148  typedef char no_type;
149 
150  static yes_type check(QObject*);
151  static no_type check(...);
152  enum { Yes = sizeof(check(static_cast<T*>(0))) == sizeof(yes_type) };
153 };
154 
155 template<typename T, bool>
156 struct LookupPointer
157 {
158  static QVariant doLookUp( const QVariant &object, const QString &property )
159  {
160  typedef typename Grantlee::TypeAccessor<T> Accessor;
161  return Accessor::lookUp( object.value<T>(), property );
162  }
163 };
164 
165 template<typename T>
166 struct LookupPointer<T, true>
167 {
168  static QVariant doLookUp( const QVariant &object, const QString &property )
169  {
170  typedef typename Grantlee::TypeAccessor<QObject*> Accessor;
171  return Accessor::lookUp( object.value<T>(), property );
172  }
173 };
174 
175 template<typename RealType>
176 struct LookupTrait<RealType*, RealType*>
177 {
178  static QVariant doLookUp( const QVariant &object, const QString &property )
179  {
180  return LookupPointer<RealType*, IsQObjectStar<RealType*>::Yes>::doLookUp(object, property);
181  }
182 };
183 
184 template<typename RealType, typename HandleAs>
185 struct LookupTrait<RealType&, HandleAs&>
186 {
187  static QVariant doLookUp( const QVariant &object, const QString &property )
188  {
189  typedef typename Grantlee::TypeAccessor<HandleAs&> Accessor;
190  return Accessor::lookUp( static_cast<HandleAs>( object.value<RealType>() ), property );
191  }
192 };
193 
194 template<typename RealType, typename HandleAs>
195 static int doRegister( int id )
196 {
197  if ( MetaType::lookupAlreadyRegistered( id ) )
198  return id;
199 
200  QVariant ( *lf )( const QVariant&, const QString& ) = LookupTrait<RealType, HandleAs>::doLookUp;
201 
202  MetaType::registerLookUpOperator( id, reinterpret_cast<MetaType::LookupFunction>( lf ) );
203 
204  return id;
205 }
206 
207 /*
208  * Register a type so grantlee knows how to handle it.
209  */
210 template<typename RealType, typename HandleAs>
211 struct InternalRegisterType
212 {
213  static int doReg() {
214  const int id = qMetaTypeId<RealType>();
215  return doRegister<RealType&, HandleAs&>( id );
216  }
217 };
218 
219 template<typename RealType, typename HandleAs>
220 struct InternalRegisterType<RealType*, HandleAs*>
221 {
222  static int doReg() {
223  const int id = qMetaTypeId<RealType*>();
224  return doRegister<RealType*, HandleAs*>( id );
225  }
226 };
227 
228 template<typename Container, typename HandleAs>
229 int registerSequentialContainer()
230 {
231  const int id = InternalRegisterType<Container, HandleAs>::doReg();
232 
233  if ( MetaType::toListAlreadyRegistered( id ) )
234  return id;
235 
236  QVariantList ( *tlf )( const QVariant& ) = SequentialContainerAccessor<Container>::doToList;
237  MetaType::registerToVariantListOperator( id, reinterpret_cast<MetaType::ToVariantListFunction>( tlf ) );
238  return id;
239 }
240 
241 template<typename Container>
242 int registerSequentialContainer()
243 {
244  return registerSequentialContainer<Container, Container>();
245 }
246 
247 template<typename Container, typename HandleAs>
248 int registerAssociativeContainer()
249 {
250  const int id = InternalRegisterType<Container, HandleAs>::doReg();
251 
252  if ( MetaType::toListAlreadyRegistered( id ) )
253  return id;
254 
255  QVariantList ( *tlf )( const QVariant& ) = AssociativeContainerAccessor<Container>::doToList;
256  MetaType::registerToVariantListOperator( id, reinterpret_cast<MetaType::ToVariantListFunction>( tlf ) );
257  return id;
258 }
259 
260 template<typename Container>
261 int registerAssociativeContainer()
262 {
263  return registerAssociativeContainer<Container, Container>();
264 }
265 
266 }
267 
268 #ifndef Q_QDOC
269 
275 template<typename RealType, int n>
276 struct RegisterTypeContainer
277 {
278  static void reg()
279  {
280  }
281 };
282 #endif
283 
289 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_IF(Container, Type) \
290  Grantlee::RegisterTypeContainer<Container<Type>, QMetaTypeId2<Container<Type> >::Defined>::reg(); \
291 
292 #ifndef Q_QDOC
293 
296 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, Key, Type) \
297  Grantlee::RegisterTypeContainer<Container<Key, Type>, QMetaTypeId2<Container<Key, Type> >::Defined>::reg(); \
298 
299 #endif
300 
316 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_IF(Container, Type) \
317  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, QString, Type) \
318  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint16, Type) \
319  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint32, Type) \
320  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, qint64, Type) \
321  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint16, Type) \
322  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint32, Type) \
323  GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER_KEY_IF(Container, quint64, Type) \
324 
325 namespace
326 {
327 
328 template<typename T>
329 void registerContainers()
330 {
337 
340 
345 }
346 
347 struct BuiltinRegister
348 {
349  void registerBuiltinContainers() const
350  {
351  Grantlee::MetaType::internalLock();
352 
353  registerContainers< bool >();
354  registerContainers< qint16 >();
355  registerContainers< qint32 >();
356  registerContainers< qint64 >();
357  registerContainers< quint16 >();
358  registerContainers< quint32 >();
359  registerContainers< quint64 >();
360  registerContainers< float >();
361  registerContainers< double >();
362  registerContainers< QString >();
363  registerContainers< QVariant >();
364  registerContainers< QDateTime >();
365  registerContainers< QObject* >();
366 
367  registerSequentialContainer<QStringList, QList<QString> >();
368  Grantlee::MetaType::internalUnlock();
369  }
370 };
371 
372 Q_GLOBAL_STATIC( BuiltinRegister, builtinRegister )
373 
374 }
375 
376 #ifndef Q_QDOC
377 struct MetaTypeInitializer {
378  static inline int initialize()
379  {
380  static const BuiltinRegister *br = builtinRegister();
381  br->registerBuiltinContainers();
382  return 0;
383  }
384 };
385 #endif
386 
392 #define GRANTLEE_METATYPE_INITIALIZE static const int i = Grantlee::MetaTypeInitializer::initialize(); Q_UNUSED(i)
393 
394 #ifndef Q_QDOC
395 inline int MetaType::init()
396 {
398  return 0;
399 }
400 #endif
401 
437 template<typename RealType, typename HandleAs>
439 {
440  {
442  Q_UNUSED( i )
443  }
444  MetaType::internalLock();
445 
446  const int id = InternalRegisterType<RealType, HandleAs>::doReg();
447 
448  registerContainers<RealType>();
449 
450  MetaType::internalUnlock();
451 
452  return id;
453 }
454 
455 #ifndef Q_QDOC
456 
462 template<typename Type>
463 int registerMetaType()
464 {
465  return registerMetaType<Type, Type>();
466 }
467 
468 // http://catb.org/jargon/html/magic-story.html
469 enum {
470  Magic,
471  MoreMagic
472 };
473 
474 #endif
475 } // namespace Grantlee
476 
482 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER(Container) \
483 namespace Grantlee { \
484 template<typename T> \
485 struct RegisterTypeContainer<Container<T>, MoreMagic> \
486 { \
487  static int reg() \
488  { \
489  const int id = registerSequentialContainer<Container<T> >(); \
490  registerContainers<Container<T> >(); \
491  return id; \
492  } \
493 }; \
494 } \
495 
496 
501 #define GRANTLEE_REGISTER_ASSOCIATIVE_CONTAINER(Container) \
502 namespace Grantlee { \
503 template<typename T, typename U> \
504 struct RegisterTypeContainer<Container<T, U>, MoreMagic> \
505 { \
506  static int reg() \
507  { \
508  const int id = registerAssociativeContainer<Container<T, U> >(); \
509  registerContainers<Container<T, U> >(); \
510  return id; \
511  } \
512 }; \
513 } \
514 
515 #ifndef Q_QDOC
516 
519 #define GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS(Container, As) \
520 namespace Grantlee { \
521 template<typename T> \
522 struct RegisterTypeContainer<Container<T>, MoreMagic> \
523 { \
524  static int reg() \
525  { \
526  return registerSequentialContainer<Container<T>, As<T> >(); \
527  } \
528 }; \
529 } \
530 
531 #endif
532 
538 #define GRANTLEE_BEGIN_LOOKUP(Type) \
539 namespace Grantlee \
540 { \
541 template<> \
542 inline QVariant TypeAccessor<Type&>::lookUp( const Type &object, const QString &property ) \
543 { \
544 
545 
550 #define GRANTLEE_BEGIN_LOOKUP_PTR(Type) \
551 namespace Grantlee \
552 { \
553 template<> \
554 inline QVariant TypeAccessor<Type*>::lookUp( const Type * const object, const QString &property ) \
555 { \
556 
557 
562 #define GRANTLEE_END_LOOKUP \
563  return QVariant(); \
564 } \
565 } \
566 
567 
569 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QQueue, QList)
571 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER_AS (QStack, QVector)
572 GRANTLEE_REGISTER_SEQUENTIAL_CONTAINER (QSet) // Actually associative, but iterated as a sequential.
576 
581 
582 
583 #endif // #define GRANTLEE_METATYPE_H
584