1/*
2 This file is part of the Grantlee template system.
3
4 Copyright (c) 2010 Stephen Kelly <steveire@gmail.com>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either version
9 2.1 of the Licence, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library. If not, see <http://www.gnu.org/licenses/>.
18
19*/
20
21#ifndef CONTAINERACCESSOR_H
22#define CONTAINERACCESSOR_H
23
24#include <QtCore/QVariant>
25
26#include <map>
27
28namespace Grantlee
29{
30
31/// @headerfile containeraccessor.h grantlee/containeraccessor.h
32/**
33 @internal Used as a convenience base class for container %iterator access.
34*/
35template<typename Container_>
36struct Getter
37{
38 /**
39 * @internal Used to extract a list from the container.
40 */
41 typedef Container_ Container;
42};
43
44/// @headerfile containeraccessor.h grantlee/containeraccessor.h
45/**
46 Trait for retrieving a key from a container %iterator.
47
48 This can be trivially specialized in rare cases if supporting a third party container.
49
50 @see @ref third_party_containers
51 */
52template<typename Container>
53struct KeyGetter : public Getter<Container>
54{
55 /**
56 Returns the key available through the container %iterator @p it.
57 */
58 static typename Container::key_type get( const typename Container::const_iterator it ) {
59 return it.key();
60 }
61};
62
63/// @headerfile containeraccessor.h grantlee/containeraccessor.h
64/**
65 Trait for retrieving a mapped value from a container %iterator.
66
67 This can be trivially specialized in rare cases if supporting a third party container.
68
69 @see @ref third_party_containers
70 */
71template<typename Container>
72struct MappedValueGetter : public Getter<Container>
73{
74 /**
75 Returns the key available through the container %iterator @p it.
76 */
77 static typename Container::mapped_type get( const typename Container::const_iterator it ) {
78 return *it;
79 }
80};
81
82#ifndef Q_QDOC
83template<typename T, typename U>
84struct KeyGetter<std::map<T, U> > : public Getter<std::map<T, U> >
85{
86 static T get( typename std::map<T, U>::const_iterator it ) {
87 return it->first;
88 }
89};
90
91template<typename T, typename U>
92struct MappedValueGetter<std::map<T, U> > : public Getter<std::map<T, U> >
93{
94 static U get( typename std::map<T, U>::const_iterator it ) {
95 return it->second;
96 }
97};
98
99template<typename Container>
100struct ValueGetter : public Getter<Container>
101{
102 static typename Container::value_type get( const typename Container::const_iterator it ) {
103 return *it;
104 }
105};
106
107template<typename Container, typename T = typename Container::key_type>
108struct Finder
109{
110 static typename Container::const_iterator find( const Container &container, const QString &nextPart )
111 {
112 {
113 // Compile error if key_type is not a number.
114 static const QString s = QString::number( T() );
115 Q_UNUSED( s )
116 }
117
118 QVariant v = nextPart;
119 if ( !v.convert( QVariant::Double ) )
120 return container.end();
121 typename Container::key_type key = v.value<typename Container::key_type>();
122 return container.find( key );
123 }
124};
125
126template<typename Container>
127struct Finder<Container, QString>
128{
129 static typename Container::const_iterator find( const Container &container, const QString &nextPart )
130 {
131 return container.find( nextPart );
132 }
133};
134#endif
135
136namespace {
137
138template<typename Getter>
139QVariantList getList( const QVariant &obj )
140{
141 const typename Getter::Container c = obj.value<typename Getter::Container>();
142 typename Getter::Container::const_iterator it = c.begin();
143 const typename Getter::Container::const_iterator end = c.end();
144 QVariantList list;
145#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0))
146 list.reserve( static_cast<int>( std::distance( it, end ) ) );
147#endif
148 for ( ; it != end; ++it ) {
149 list << QVariant::fromValue( Getter::get( it ) );
150 }
151 return list;
152}
153
154template<typename Container>
155struct SequentialContainerAccessor
156{
157 static QVariantList doToList( const QVariant &obj )
158 {
159 return getList<ValueGetter<Container> >( obj );
160 }
161};
162
163template<>
164struct SequentialContainerAccessor<QVariantList>
165{
166 static QVariantList doToList( const QVariant &obj )
167 {
168 return obj.toList();
169 }
170};
171
172template<typename Container>
173struct AssociativeContainerAccessor
174{
175 static QVariantList doToList( const QVariant &obj )
176 {
177 return getList<KeyGetter<Container> >( obj );
178 }
179};
180
181}
182
183}
184
185#endif
186