Grantlee  0.4.0
templates/lib/typeaccessor.h
Go to the documentation of this file.
00001 /*
00002   This file is part of the Grantlee template system.
00003 
00004   Copyright (c) 2010 Stephen Kelly <steveire@gmail.com>
00005 
00006   This library is free software; you can redistribute it and/or
00007   modify it under the terms of the GNU Lesser General Public
00008   License as published by the Free Software Foundation; either version
00009   2.1 of the Licence, or (at your option) any later version.
00010 
00011   This library is distributed in the hope that it will be useful,
00012   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   Lesser General Public License for more details.
00015 
00016   You should have received a copy of the GNU Lesser General Public
00017   License along with this library.  If not, see <http://www.gnu.org/licenses/>.
00018 
00019 */
00020 
00021 #ifndef GRANTLEE_TYPEACCESSOR_H
00022 #define GRANTLEE_TYPEACCESSOR_H
00023 
00024 #include "containeraccessor.h"
00025 #include "grantlee_core_export.h"
00026 
00027 #include <QtCore/QLinkedList>
00028 #include <QtCore/QSet>
00029 #include <QtCore/QSharedPointer>
00030 #include <QtCore/QVariant>
00031 
00032 #include <deque>
00033 #include <list>
00034 #include <vector>
00035 
00037 
00038 namespace Grantlee
00039 {
00040 
00041 #ifndef Q_QDOC
00042 template <typename T>
00043 struct TypeAccessor
00044 {
00045   static QVariant lookUp( const T object, const QString &property );
00046 };
00047 
00048 template <typename T>
00049 struct TypeAccessor<T*>
00050 {
00051   static QVariant lookUp( const T * const object, const QString &property );
00052 };
00053 
00054 template <typename T>
00055 struct TypeAccessor<T&>
00056 {
00057   static QVariant lookUp( const T &object, const QString &property );
00058 };
00059 #endif
00060 
00061 namespace
00062 {
00063 
00064 template<typename Container>
00065 struct SequentialContainerLookup
00066 {
00067   static QVariant doLookUp( const Container &container, const QString &property )
00068   {
00069     if ( property == QLatin1String( "size" ) || property == QLatin1String( "count" ) ) {
00070       return QVariant::fromValue<int>( std::distance( container.begin(), container.end() ) );
00071     }
00072 
00073     bool ok = false;
00074     const size_t listIndex = ( size_t )property.toInt( &ok );
00075 
00076     if ( !ok || listIndex >= ( size_t )container.size() ) {
00077       return QVariant();
00078     }
00079 
00080     return QVariant::fromValue( container[listIndex] );
00081   }
00082 };
00083 
00084 template<typename Container>
00085 QVariant doAssociativeContainerLookup( const Container &object, const QString &property )
00086 {
00087   {
00088     typename Container::const_iterator it = Finder<Container>::find( object, property );
00089     if ( it != object.end() )
00090       return QVariant::fromValue( MappedValueGetter<Container>::get( it ) );
00091   }
00092   if ( property == QLatin1String( "size" ) || property == QLatin1String( "count" ) ) {
00093       return QVariant::fromValue<int>( std::distance( object.begin(), object.end() ) );
00094   }
00095   if ( property == QLatin1String( "items" ) ) {
00096     typename Container::const_iterator it = object.begin();
00097     const typename Container::const_iterator end = object.end();
00098     QVariantList list;
00099     for ( ; it != end; ++it ) {
00100       QVariantList nested;
00101       nested.push_back( QVariant::fromValue( KeyGetter<Container>::get( it ) ) );
00102       nested.push_back( QVariant::fromValue( MappedValueGetter<Container>::get( it ) ) );
00103       list.push_back( nested );
00104     }
00105     return list;
00106   }
00107 
00108   if ( property == QLatin1String( "keys" ) ) {
00109     typename Container::const_iterator it = object.begin();
00110     const typename Container::const_iterator end = object.end();
00111     QVariantList list;
00112     for ( ; it != end; ++it ) {
00113       list.push_back( QVariant::fromValue( KeyGetter<Container>::get( it ) ) );
00114     }
00115     return list;
00116   }
00117 
00118   if ( property == QLatin1String( "values" ) ) {
00119     typename Container::const_iterator it = object.begin();
00120     const typename Container::const_iterator end = object.end();
00121     QVariantList list;
00122     for ( ; it != end; ++it ) {
00123       list.push_back( QVariant::fromValue( MappedValueGetter<Container>::get( it ) ) );
00124     }
00125     return list;
00126   }
00127 
00128   return QVariant();
00129 }
00130 
00131 }
00132 
00133 #ifndef Q_QDOC
00134 template <>
00135 QVariant GRANTLEE_CORE_EXPORT TypeAccessor<QObject*>::lookUp( const QObject * const object, const QString &property );
00136 
00140 QVariant GRANTLEE_CORE_EXPORT doQobjectLookUp( const QObject * const object, const QString& property );
00141 #endif
00142 }
00143 
00151 #define GRANTLEE_DISABLE_RANDOM_ACCESS(Container)                     \
00152 namespace Grantlee {                                                  \
00153 template<typename T>                                                  \
00154 struct TypeAccessor<Container<T>&>                                    \
00155 {                                                                     \
00156   static QVariant lookUp( const Container<T> &c, const QString &p)    \
00157   {                                                                   \
00158     if ( p == QLatin1String( "size" )                                 \
00159       || p == QLatin1String( "count" ) ) {                            \
00160       return QVariant::fromValue<int>(                                \
00161           std::distance( c.begin(), c.end() ) );                      \
00162     }                                                                 \
00163     return QVariant();                                                \
00164   }                                                                   \
00165 };                                                                    \
00166 }                                                                     \
00167 
00168 
00173 #define GRANTLEE_SEQUENTIAL_TYPE_CONTAINER_ACCESSOR(Container)                          \
00174 namespace Grantlee {                                                                    \
00175 template<typename T>                                                                    \
00176 struct TypeAccessor<Container<T>&>                                                      \
00177 {                                                                                       \
00178   static QVariant lookUp( const Container<T> &c, const QString &property )              \
00179   {                                                                                     \
00180     return SequentialContainerLookup<Container<T> >::doLookUp( c, property );           \
00181   }                                                                                     \
00182 };                                                                                      \
00183 }                                                                                       \
00184 
00185 
00192 #define GRANTLEE_ASSOCIATIVE_TYPE_CONTAINER_ACCESSOR(Container)                    \
00193 namespace Grantlee {                                                               \
00194 template<typename T, typename U>                                                   \
00195 struct TypeAccessor<Container<T, U>&>                                              \
00196 {                                                                                  \
00197   static QVariant lookUp( const Container<T, U> &c, const QString &property )      \
00198   {                                                                                \
00199     return doAssociativeContainerLookup( c, property );                            \
00200   }                                                                                \
00201 };                                                                                 \
00202 }                                                                                  \
00203 
00204 
00209 #define GRANTLEE_SMART_PTR_ACCESSOR(SmartPointer)                                  \
00210 namespace Grantlee {                                                               \
00211 template<typename T>                                                               \
00212 struct TypeAccessor<SmartPointer<T>&>                                              \
00213 {                                                                                  \
00214   static QVariant lookUp( const SmartPointer<T> &object, const QString &property ) \
00215   {                                                                                \
00216     return doQobjectLookUp( object.operator->(), property );                       \
00217   }                                                                                \
00218 };                                                                                 \
00219 }                                                                                  \
00220 
00221 GRANTLEE_SEQUENTIAL_TYPE_CONTAINER_ACCESSOR(QList)
00222 GRANTLEE_SEQUENTIAL_TYPE_CONTAINER_ACCESSOR(QVector)
00223 
00224 GRANTLEE_ASSOCIATIVE_TYPE_CONTAINER_ACCESSOR(QHash)
00225 GRANTLEE_ASSOCIATIVE_TYPE_CONTAINER_ACCESSOR(QMap)
00226 
00227 GRANTLEE_DISABLE_RANDOM_ACCESS(QSet)
00228 GRANTLEE_DISABLE_RANDOM_ACCESS(QLinkedList)
00229 GRANTLEE_DISABLE_RANDOM_ACCESS(std::list)
00230 
00231 GRANTLEE_SEQUENTIAL_TYPE_CONTAINER_ACCESSOR  (std::deque)
00232 GRANTLEE_SEQUENTIAL_TYPE_CONTAINER_ACCESSOR  (std::vector)
00233 GRANTLEE_ASSOCIATIVE_TYPE_CONTAINER_ACCESSOR (std::map)
00234 
00235 GRANTLEE_SMART_PTR_ACCESSOR(QSharedPointer)
00236 
00237 #endif