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 | |
28 | namespace Grantlee |
29 | { |
30 | |
31 | /// @headerfile containeraccessor.h grantlee/containeraccessor.h |
32 | /** |
33 | @internal Used as a convenience base class for container %iterator access. |
34 | */ |
35 | template<typename Container_> |
36 | struct 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 | */ |
52 | template<typename Container> |
53 | struct 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 | */ |
71 | template<typename Container> |
72 | struct 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 |
83 | template<typename T, typename U> |
84 | struct 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 | |
91 | template<typename T, typename U> |
92 | struct 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 | |
99 | template<typename Container> |
100 | struct ValueGetter : public Getter<Container> |
101 | { |
102 | static typename Container::value_type get( const typename Container::const_iterator it ) { |
103 | return *it; |
104 | } |
105 | }; |
106 | |
107 | template<typename Container, typename T = typename Container::key_type> |
108 | struct 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 | |
126 | template<typename Container> |
127 | struct 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 | |
136 | namespace { |
137 | |
138 | template<typename Getter> |
139 | QVariantList 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 | |
154 | template<typename Container> |
155 | struct SequentialContainerAccessor |
156 | { |
157 | static QVariantList doToList( const QVariant &obj ) |
158 | { |
159 | return getList<ValueGetter<Container> >( obj ); |
160 | } |
161 | }; |
162 | |
163 | template<> |
164 | struct SequentialContainerAccessor<QVariantList> |
165 | { |
166 | static QVariantList doToList( const QVariant &obj ) |
167 | { |
168 | return obj.toList(); |
169 | } |
170 | }; |
171 | |
172 | template<typename Container> |
173 | struct 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 | |