Grantlee  0.4.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.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 #if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0))
00146   list.reserve( static_cast<int>( std::distance( it, end ) ) );
00147 #endif
00148   for ( ; it != end; ++it ) {
00149     list << QVariant::fromValue( Getter::get( it ) );
00150   }
00151   return list;
00152 }
00153 
00154 template<typename Container>
00155 struct SequentialContainerAccessor
00156 {
00157   static QVariantList doToList( const QVariant &obj )
00158   {
00159     return getList<ValueGetter<Container> >( obj );
00160   }
00161 };
00162 
00163 template<>
00164 struct SequentialContainerAccessor<QVariantList>
00165 {
00166   static QVariantList doToList( const QVariant &obj )
00167   {
00168     return obj.toList();
00169   }
00170 };
00171 
00172 template<typename Container>
00173 struct AssociativeContainerAccessor
00174 {
00175   static QVariantList doToList( const QVariant &obj )
00176   {
00177     return getList<KeyGetter<Container> >( obj );
00178   }
00179 };
00180 
00181 }
00182 
00183 }
00184 
00185 #endif