1 | /* |
2 | This file is part of libkabc. |
3 | Copyright (c) 2002 Jost Schenck <jost@schenck.de> |
4 | 2003 Tobias Koenig <tokoe@kde.org> |
5 | |
6 | This library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Library General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2 of the License, 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 | Library General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Library General Public License |
17 | along with this library; see the file COPYING.LIB. If not, write to |
18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | Boston, MA 02110-1301, USA. |
20 | */ |
21 | |
22 | #include "addresseelist.h" |
23 | #include "field.h" |
24 | #include "sortmode.h" |
25 | |
26 | #include <kdebug.h> |
27 | |
28 | #include <QtCore/QSharedData> |
29 | |
30 | using namespace KABC; |
31 | |
32 | // |
33 | // |
34 | // Traits |
35 | // |
36 | // |
37 | |
38 | SortingTraits::Uid::Uid() |
39 | : d( 0 ) |
40 | { |
41 | } |
42 | |
43 | SortingTraits::Uid::~Uid() |
44 | { |
45 | } |
46 | |
47 | bool SortingTraits::Uid::eq( const Addressee &a1, const Addressee &a2 ) |
48 | { |
49 | // locale awareness doesn't make sense sorting ids |
50 | return QString::compare( a1.uid(), a2.uid() ) == 0; |
51 | } |
52 | |
53 | bool SortingTraits::Uid::lt( const Addressee &a1, const Addressee &a2 ) |
54 | { |
55 | // locale awareness doesn't make sense sorting ids |
56 | return QString::compare( a1.uid(), a2.uid() ) < 0; |
57 | } |
58 | |
59 | SortingTraits::Name::Name() |
60 | : d( 0 ) |
61 | { |
62 | } |
63 | |
64 | SortingTraits::Name::~Name() |
65 | { |
66 | } |
67 | |
68 | bool SortingTraits::Name::eq( const Addressee &a1, const Addressee &a2 ) |
69 | { |
70 | return QString::localeAwareCompare( a1.name(), a2.name() ) == 0; |
71 | } |
72 | |
73 | bool SortingTraits::Name::lt( const Addressee &a1, const Addressee &a2 ) |
74 | { |
75 | return QString::localeAwareCompare( a1.name(), a2.name() ) < 0; |
76 | } |
77 | |
78 | SortingTraits::FormattedName::FormattedName() |
79 | : d( 0 ) |
80 | { |
81 | } |
82 | |
83 | SortingTraits::FormattedName::~FormattedName() |
84 | { |
85 | } |
86 | |
87 | bool SortingTraits::FormattedName::eq( const Addressee &a1, const Addressee &a2 ) |
88 | { |
89 | return QString::localeAwareCompare( a1.formattedName(), a2.formattedName() ) == 0; |
90 | } |
91 | |
92 | bool SortingTraits::FormattedName::lt( const Addressee &a1, const Addressee &a2 ) |
93 | { |
94 | return QString::localeAwareCompare( a1.formattedName(), a2.formattedName() ) < 0; |
95 | } |
96 | |
97 | SortingTraits::FamilyName::FamilyName() |
98 | : d( 0 ) |
99 | { |
100 | } |
101 | |
102 | SortingTraits::FamilyName::~FamilyName() |
103 | { |
104 | } |
105 | |
106 | bool SortingTraits::FamilyName::eq( const Addressee &a1, const Addressee &a2 ) |
107 | { |
108 | return |
109 | QString::localeAwareCompare( a1.familyName(), a2.familyName() ) == 0 && |
110 | QString::localeAwareCompare( a1.givenName(), a2.givenName() ) == 0; |
111 | } |
112 | |
113 | bool SortingTraits::FamilyName::lt( const Addressee &a1, const Addressee &a2 ) |
114 | { |
115 | int family = QString::localeAwareCompare( a1.familyName(), a2.familyName() ); |
116 | if ( 0 == family ) { |
117 | return QString::localeAwareCompare( a1.givenName(), a2.givenName() ) < 0; |
118 | } else { |
119 | return family < 0; |
120 | } |
121 | } |
122 | |
123 | SortingTraits::GivenName::GivenName() |
124 | : d( 0 ) |
125 | { |
126 | } |
127 | |
128 | SortingTraits::GivenName::~GivenName() |
129 | { |
130 | } |
131 | |
132 | bool SortingTraits::GivenName::eq( const Addressee &a1, const Addressee &a2 ) |
133 | { |
134 | return |
135 | QString::localeAwareCompare( a1.givenName(), a2.givenName() ) == 0 && |
136 | QString::localeAwareCompare( a1.familyName(), a2.familyName() ) == 0; |
137 | } |
138 | |
139 | bool SortingTraits::GivenName::lt( const Addressee &a1, const Addressee &a2 ) |
140 | { |
141 | int given = QString::localeAwareCompare( a1.givenName(), a2.givenName() ); |
142 | if ( 0 == given ) { |
143 | return QString::localeAwareCompare( a1.familyName(), a2.familyName() ) < 0; |
144 | } else { |
145 | return given < 0; |
146 | } |
147 | } |
148 | |
149 | // |
150 | // |
151 | // AddresseeList |
152 | // |
153 | // |
154 | |
155 | static Field *sActiveField=0; |
156 | |
157 | class AddresseeList::Private : public QSharedData |
158 | { |
159 | public: |
160 | Private() |
161 | : mReverseSorting( false ), mActiveSortingCriterion( FormattedName ) |
162 | { |
163 | } |
164 | |
165 | Private( const Private &other ) |
166 | : QSharedData( other ) |
167 | { |
168 | mReverseSorting = other.mReverseSorting; |
169 | mActiveSortingCriterion = other.mActiveSortingCriterion; |
170 | } |
171 | |
172 | bool mReverseSorting; |
173 | SortingCriterion mActiveSortingCriterion; |
174 | }; |
175 | |
176 | AddresseeList::AddresseeList() |
177 | : QList<Addressee>(), d( new Private ) |
178 | { |
179 | } |
180 | |
181 | AddresseeList::~AddresseeList() |
182 | { |
183 | } |
184 | |
185 | AddresseeList::AddresseeList( const AddresseeList &other ) |
186 | : QList<Addressee>( other ), d( other.d ) |
187 | { |
188 | } |
189 | |
190 | AddresseeList::AddresseeList( const QList<Addressee> &l ) |
191 | : QList<Addressee>( l ), d( new Private ) |
192 | { |
193 | } |
194 | |
195 | AddresseeList &AddresseeList::operator=( const AddresseeList &other ) |
196 | { |
197 | if ( this != &other ) { |
198 | QList<Addressee>::operator=( other ); |
199 | d = other.d; |
200 | } |
201 | |
202 | return *this; |
203 | } |
204 | |
205 | QString AddresseeList::toString() const |
206 | { |
207 | QString str; |
208 | |
209 | str += QLatin1String( "AddresseeList {\n" ); |
210 | str += QString::fromLatin1( " Reverse Order: %1\n" ).arg( d->mReverseSorting ? |
211 | QLatin1String( "true" ) : |
212 | QLatin1String( "false" ) ); |
213 | |
214 | QString crit; |
215 | if ( Uid == d->mActiveSortingCriterion ) { |
216 | crit = QLatin1String( "Uid" ); |
217 | } else if ( Name == d->mActiveSortingCriterion ) { |
218 | crit = QLatin1String( "Name" ); |
219 | } else if ( FormattedName == d->mActiveSortingCriterion ) { |
220 | crit = QLatin1String( "FormattedName" ); |
221 | } else if ( FamilyName == d->mActiveSortingCriterion ) { |
222 | crit = QLatin1String( "FamilyName" ); |
223 | } else if ( GivenName == d->mActiveSortingCriterion ) { |
224 | crit = QLatin1String( "GivenName" ); |
225 | } else { |
226 | crit = QLatin1String( "unknown -- update dump method" ); |
227 | } |
228 | |
229 | str += QString::fromLatin1( " Sorting criterion: %1\n" ).arg( crit ); |
230 | #if 0 //code commented in loop => comment it too |
231 | for ( const_iterator it = begin(); it != end(); ++it ) { |
232 | // str += (*it).toString(); |
233 | } |
234 | #endif |
235 | |
236 | str += QLatin1String( "}\n" ); |
237 | |
238 | return str; |
239 | } |
240 | |
241 | void AddresseeList::setReverseSorting( bool reverseSorting ) |
242 | { |
243 | d->mReverseSorting = reverseSorting; |
244 | } |
245 | |
246 | bool AddresseeList::reverseSorting() const |
247 | { |
248 | return d->mReverseSorting; |
249 | } |
250 | |
251 | void AddresseeList::sortBy( SortingCriterion c ) |
252 | { |
253 | d->mActiveSortingCriterion = c; |
254 | if ( Uid == c ) { |
255 | sortByTrait<SortingTraits::Uid>(); |
256 | } else if ( Name == c ) { |
257 | sortByTrait<SortingTraits::Name>(); |
258 | } else if ( FormattedName == c ) { |
259 | sortByTrait<SortingTraits::FormattedName>(); |
260 | } else if ( FamilyName == c ) { |
261 | sortByTrait<SortingTraits::FamilyName>(); |
262 | } else if ( GivenName == c ) { |
263 | sortByTrait<SortingTraits::GivenName>(); |
264 | } else { |
265 | kError( 5700 ) << "AddresseeList sorting criterion passed for which a trait is not known." |
266 | << "No sorting done." ; |
267 | } |
268 | } |
269 | |
270 | void AddresseeList::sort() |
271 | { |
272 | sortBy( d->mActiveSortingCriterion ); |
273 | } |
274 | |
275 | template<class Trait> |
276 | void AddresseeList::sortByTrait() |
277 | { |
278 | // FIXME: better sorting algorithm, bubblesort is not acceptable for larger lists. |
279 | // |
280 | // for i := 1 to n - 1 |
281 | // do for j := 1 to n - i |
282 | // do if A[j] > A[j+1] |
283 | // then temp := A[j] |
284 | // A[j] := A[j + 1] |
285 | // A[j + 1 ] := temp |
286 | |
287 | iterator i1 = begin(); |
288 | iterator endIt = end(); |
289 | --endIt; |
290 | if ( i1 == endIt ) { // don't need sorting |
291 | return; |
292 | } |
293 | |
294 | iterator i2 = endIt; |
295 | while ( i1 != endIt ) { |
296 | iterator j1 = begin(); |
297 | iterator j2 = j1; |
298 | ++j2; |
299 | while ( j1 != i2 ) { |
300 | if ( ( !d->mReverseSorting && Trait::lt( *j2, *j1 ) ) || |
301 | ( d->mReverseSorting && Trait::lt( *j1, *j2 ) ) ) { |
302 | qSwap( *j1, *j2 ); |
303 | } |
304 | ++j1; |
305 | ++j2; |
306 | } |
307 | ++i1; |
308 | --i2; |
309 | } |
310 | } |
311 | |
312 | void AddresseeList::sortByField( Field *field ) |
313 | { |
314 | if ( !field ) { |
315 | kWarning( 5700 ) << "sortByField called with no active sort field" ; |
316 | return; |
317 | } |
318 | |
319 | sActiveField = field; |
320 | |
321 | if ( count() == 0 ) { |
322 | return; |
323 | } |
324 | |
325 | KABC::FieldSortMode *mode = new KABC::FieldSortMode( sActiveField, !d->mReverseSorting ); |
326 | |
327 | KABC::Addressee::setSortMode( mode ); |
328 | qSort( *this ); |
329 | KABC::Addressee::setSortMode( 0 ); |
330 | |
331 | delete mode; |
332 | } |
333 | |
334 | void AddresseeList::sortByMode( SortMode *mode ) |
335 | { |
336 | if ( count() == 0 ) { |
337 | return; |
338 | } |
339 | |
340 | KABC::Addressee::setSortMode( mode ); |
341 | qSort( *this ); |
342 | KABC::Addressee::setSortMode( 0 ); |
343 | } |
344 | |
345 | SortingCriterion AddresseeList::sortingCriterion() const |
346 | { |
347 | return d->mActiveSortingCriterion; |
348 | } |
349 | |
350 | Field *AddresseeList::sortingField() const |
351 | { |
352 | return sActiveField; |
353 | } |
354 | |