Grantlee  0.2.0
templates/lib/containeraccessor.h
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 CONTAINERACCESSOR_H
00022 #define CONTAINERACCESSOR_H
00023 
00024 #include <QtCore/QVariant>
00025 
00026 #include <map>
00027 
00028 namespace Grantlee
00029 {
00030 
00032 
00035 template<typename Container_>
00036 struct Getter
00037 {
00041   typedef Container_ Container;
00042 };
00043 
00045 
00052 template<typename Container>
00053 struct KeyGetter : public Getter<Container>
00054 {
00058   static typename Container::key_type get( const typename Container::const_iterator it ) {
00059     return it.key();
00060   }
00061 };
00062 
00064 
00071 template<typename Container>
00072 struct MappedValueGetter : public Getter<Container>
00073 {
00077   static typename Container::mapped_type get( const typename Container::const_iterator it ) {
00078     return *it;
00079   }
00080 };
00081 
00082 #ifndef Q_QDOC
00083 template<typename T, typename U>
00084 struct KeyGetter<std::map<T, U> > : public Getter<std::map<T, U> >
00085 {
00086   static T get( typename std::map<T, U>::const_iterator it ) {
00087     return it->first;
00088   }
00089 };
00090 
00091 template<typename T, typename U>
00092 struct MappedValueGetter<std::map<T, U> > : public Getter<std::map<T, U> >
00093 {
00094   static U get( typename std::map<T, U>::const_iterator it ) {
00095     return it->second;
00096   }
00097 };
00098 
00099 template<typename Container>
00100 struct ValueGetter : public Getter<Container>
00101 {
00102   static typename Container::value_type get( const typename Container::const_iterator it ) {
00103     return *it;
00104   }
00105 };
00106 
00107 template<typename Container, typename T = typename Container::key_type>
00108 struct Finder
00109 {
00110   static typename Container::const_iterator find( const Container &container, const QString &nextPart )
00111   {
00112     {
00113       // Compile error if key_type is not a number.
00114       static const QString s = QString::number( T() );
00115       Q_UNUSED( s )
00116     }
00117 
00118     QVariant v = nextPart;
00119     if ( !v.canConvert<typename Container::key_type>() || !v.convert( QVariant::Double ) )
00120       return container.end();
00121     typename Container::key_type key = v.value<typename Container::key_type>();
00122     return container.find( key );
00123   }
00124 };
00125 
00126 template<typename Container>
00127 struct Finder<Container, QString>
00128 {
00129   static typename Container::const_iterator find( const Container &container, const QString &nextPart )
00130   {
00131     return container.find( nextPart );
00132   }
00133 };
00134 #endif
00135 
00136 namespace {
00137 
00138 template<typename Getter>
00139 QVariantList getList( const QVariant &obj )
00140 {
00141   const typename Getter::Container c = obj.value<typename Getter::Container>();
00142   typename Getter::Container::const_iterator it = c.begin();
00143   const typename Getter::Container::const_iterator end = c.end();
00144   QVariantList list;
00145   for ( ; it != end; ++it ) {
00146     list << QVariant::fromValue( Getter::get( it ) );
00147   }
00148   return list;
00149 }
00150 
00151 template<typename Container>
00152 struct SequentialContainerAccessor
00153 {
00154   static QVariantList doToList( const QVariant &obj )
00155   {
00156     return getList<ValueGetter<Container> >( obj );
00157   }
00158 };
00159 
00160 template<>
00161 struct SequentialContainerAccessor<QVariantList>
00162 {
00163   static QVariantList doToList( const QVariant &obj )
00164   {
00165     return obj.toList();
00166   }
00167 };
00168 
00169 template<typename Container>
00170 struct AssociativeContainerAccessor
00171 {
00172   static QVariantList doToList( const QVariant &obj )
00173   {
00174     return getList<KeyGetter<Container> >( obj );
00175   }
00176 };
00177 
00178 }
00179 
00180 }
00181 
00182 #endif