|
1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <cntview.h> |
|
17 #include "CNTSTD.H" |
|
18 #include <collate.h> |
|
19 |
|
20 |
|
21 |
|
22 //#define CNTVIEW_API_PROFILING |
|
23 |
|
24 |
|
25 // |
|
26 // CContactViewRangeBase |
|
27 // |
|
28 |
|
29 /** |
|
30 @internalComponent |
|
31 */ |
|
32 CContactViewRangeBase::CContactViewRangeBase(const CContactViewBase& aView) |
|
33 : iView(aView),iLow(KErrNotFound),iHigh(KErrNotFound) |
|
34 { |
|
35 } |
|
36 |
|
37 CContactViewRangeBase::~CContactViewRangeBase() |
|
38 { |
|
39 delete iCollateMethod; |
|
40 } |
|
41 |
|
42 void CContactViewRangeBase::ConstructL() |
|
43 /** Called by derived classes to set the collation method iCollateMethod to be |
|
44 the standard collation method for the current locale. |
|
45 @internalComponent |
|
46 */ |
|
47 { |
|
48 // Needed to ensure unicode sorting / inserting into sorted lists works the same as ER5, |
|
49 // i.e. that it encludes all spaces and punctuation. |
|
50 iCollateMethod = new(ELeave) TCollationMethod; |
|
51 *iCollateMethod = *Mem::CollationMethodByIndex(0); |
|
52 iCollateMethod->iFlags|=TCollationMethod::EIgnoreNone; |
|
53 } |
|
54 |
|
55 EXPORT_C TBool CContactViewRangeBase::IndicesValid() const |
|
56 /** Tests whether the lower and upper indexes are valid, i.e. not KErrNotFound. |
|
57 |
|
58 @return ETrue if the indexes are valid, EFalse if not. */ |
|
59 { |
|
60 if (iLow==KErrNotFound) |
|
61 { |
|
62 ASSERT(iHigh==KErrNotFound); |
|
63 return EFalse; |
|
64 } |
|
65 return ETrue; |
|
66 } |
|
67 |
|
68 TInt CContactViewRangeBase::FindIndexL(const TDesC& aMatch,TCriteria aCriteria) const |
|
69 // Binary search through iView to find the first contact that matches aMatch according to aCritera. |
|
70 /** Called by implementations of SetL() to search the sub view's underlying view |
|
71 for the index of the first item whose field content matches aMatch, using |
|
72 the specified search criteria. |
|
73 |
|
74 @internalComponent |
|
75 @param aMatch The text to search for. |
|
76 @param aCriteria The search criteria. |
|
77 @return The index of the first matching item in the view. KErrNotFound if the |
|
78 view is empty or if none match. */ |
|
79 { |
|
80 const TInt NumberOfCharsToCompare=1; |
|
81 TInt result=KErrNotFound; |
|
82 TInt min=0; |
|
83 TInt max=iView.CountL()-1; |
|
84 if (max<0) |
|
85 { |
|
86 // The parent view is empty. |
|
87 return KErrNotFound; |
|
88 } |
|
89 TBool finished=EFalse; |
|
90 |
|
91 HBufC* sortableText; |
|
92 while (!finished) |
|
93 { |
|
94 TInt guess; |
|
95 if (max==min) |
|
96 { |
|
97 finished=ETrue; |
|
98 } |
|
99 |
|
100 guess=(max-min)/2+min; |
|
101 sortableText = iView.AllFieldsLC(guess,KNullDesC); |
|
102 TInt compare=sortableText->Left(NumberOfCharsToCompare).CompareC(aMatch.Left(NumberOfCharsToCompare),3,iCollateMethod); |
|
103 CleanupStack::PopAndDestroy();//sortableText |
|
104 switch (aCriteria) |
|
105 { |
|
106 case ELessThan: |
|
107 { |
|
108 if (compare>0 || compare==0) |
|
109 { |
|
110 // String is greater than aMatch. |
|
111 max=guess-1; |
|
112 if (max<min) |
|
113 { |
|
114 finished=ETrue; |
|
115 } |
|
116 } |
|
117 else if (compare<0) |
|
118 { |
|
119 // String is less than aMatch - could be a hit. |
|
120 min=guess+1; |
|
121 if (min>max) |
|
122 { |
|
123 finished=ETrue; |
|
124 } |
|
125 if (result==KErrNotFound || guess>result) |
|
126 { |
|
127 // guess is a closer match, so overwrite result. |
|
128 result=guess; |
|
129 } |
|
130 } |
|
131 break; |
|
132 } |
|
133 case ELessThanOrEqualTo: |
|
134 { |
|
135 if (compare>0) |
|
136 { |
|
137 // String is greater than aMatch. |
|
138 max=guess-1; |
|
139 if (max<min) |
|
140 { |
|
141 finished=ETrue; |
|
142 } |
|
143 } |
|
144 else if (compare<=0) |
|
145 { |
|
146 // String is less than or equal to aMatch - possible hit. |
|
147 min=guess+1; |
|
148 if (min>max) |
|
149 { |
|
150 finished=ETrue; |
|
151 } |
|
152 if (result==KErrNotFound || guess>result) |
|
153 { |
|
154 // guess is a closer match, so overwrite result. |
|
155 result=guess; |
|
156 } |
|
157 } |
|
158 break; |
|
159 } |
|
160 case EGreaterThan: |
|
161 { |
|
162 if (compare<0 || compare==0) |
|
163 { |
|
164 // String is less than aMatch. |
|
165 min=guess+1; |
|
166 if (min>max) |
|
167 { |
|
168 finished=ETrue; |
|
169 } |
|
170 } |
|
171 else if (compare>0) |
|
172 { |
|
173 // String is greater than aMatch - possible hit. |
|
174 max=guess-1; |
|
175 if (max<min) |
|
176 { |
|
177 finished=ETrue; |
|
178 } |
|
179 if (result==KErrNotFound || guess<result) |
|
180 { |
|
181 // guess is a closer match, so overwrite result. |
|
182 result=guess; |
|
183 } |
|
184 } |
|
185 break; |
|
186 } |
|
187 case EGreaterThanOrEqualTo: |
|
188 { |
|
189 if (compare<0) |
|
190 { |
|
191 // String is less than aMatch. |
|
192 min=guess+1; |
|
193 if (min>max) |
|
194 { |
|
195 finished=ETrue; |
|
196 } |
|
197 } |
|
198 else if (compare>=0) |
|
199 { |
|
200 // String is >= aMatch - possible hit. |
|
201 max=guess-1; |
|
202 if (max<min) |
|
203 { |
|
204 finished=ETrue; |
|
205 } |
|
206 if (result==KErrNotFound || guess<result) |
|
207 { |
|
208 // guess is a closer match, so overwrite result. |
|
209 result=guess; |
|
210 } |
|
211 } |
|
212 break; |
|
213 } |
|
214 }; |
|
215 } |
|
216 return result; |
|
217 } |
|
218 |
|
219 /** |
|
220 @internalComponent |
|
221 */ |
|
222 TBool CContactViewRangeBase::MatchesCriteriaL(TCriteria aCriteria,const TDesC& aMatch,TInt aIndex) const |
|
223 { |
|
224 TBool match=EFalse; |
|
225 HBufC* sortableText=iView.AllFieldsLC(aIndex,KNullDesC); |
|
226 TInt compare=sortableText->CompareC(aMatch,3,iCollateMethod); |
|
227 |
|
228 switch(aCriteria) |
|
229 { |
|
230 case ELessThan: |
|
231 { |
|
232 if(compare<0) |
|
233 { |
|
234 //RDebug::Print(_L("Match of %S against < %S PASSED\x0D\x00\x0a\x00"),&sortableText,&aMatch); |
|
235 match=ETrue; |
|
236 } |
|
237 else |
|
238 { |
|
239 //RDebug::Print(_L("Match of %S against < %S FAILED\x0D\x00\x0a\x00"),&sortableText,&aMatch); |
|
240 } |
|
241 break; |
|
242 }; |
|
243 case ELessThanOrEqualTo: |
|
244 { |
|
245 if(compare<=0) |
|
246 match=ETrue; |
|
247 break; |
|
248 }; |
|
249 case EGreaterThan: |
|
250 { |
|
251 if(compare>0) |
|
252 match=ETrue; |
|
253 break; |
|
254 }; |
|
255 case EGreaterThanOrEqualTo: |
|
256 { |
|
257 if(compare>=0) |
|
258 { |
|
259 //RDebug::Print(_L("Match of %S against >= %S PASSED\x0D\x00\x0a\x00"),&sortableText,&aMatch); |
|
260 match=ETrue; |
|
261 } |
|
262 else |
|
263 { |
|
264 //RDebug::Print(_L("Match of %S against >= %S FAILED\x0D\x00\x0a\x00"),&sortableText,&aMatch); |
|
265 } |
|
266 break; |
|
267 }; |
|
268 }; |
|
269 |
|
270 return match; |
|
271 } |
|
272 |
|
273 void CContactViewRangeBase::ValidateIndices() |
|
274 /** Called by derived classes to validate the upper and lower indexes (iLow and |
|
275 iHigh). |
|
276 |
|
277 If either index is KErrNotFound, or iLow is greater than iHigh, then both |
|
278 are set to KErrNotFound. |
|
279 @internalComponent |
|
280 */ |
|
281 { |
|
282 // Check that range isn't inside out, and both ranges are valid. |
|
283 if (iLow>iHigh || iHigh==KErrNotFound || iLow==KErrNotFound) |
|
284 { |
|
285 // Invalidate both indicies. |
|
286 iLow=KErrNotFound; |
|
287 iHigh=KErrNotFound; |
|
288 } |
|
289 } |
|
290 |
|
291 // |
|
292 // CContactViewRange |
|
293 // |
|
294 |
|
295 |
|
296 CContactViewRange::CContactViewRange(const CContactViewBase& aView,const TDesC& aLowMatch,TCriteria aLowCriteria,const TDesC& aHighMatch,TCriteria aHighCriteria) |
|
297 :CContactViewRangeBase(aView),iLowMatch(aLowMatch),iLowCriteria(aLowCriteria),iHighMatch(aHighMatch),iHighCriteria(aHighCriteria) |
|
298 { |
|
299 } |
|
300 |
|
301 EXPORT_C CContactViewRange* CContactViewRange::NewL(const CContactViewBase& aView,const TDesC& aLowMatch,TCriteria aLowCriteria,const TDesC& aHighMatch,TCriteria aHighCriteria) |
|
302 /** Allocates and constructs a new sub view range. |
|
303 |
|
304 @param aView The sub view's underlying view. |
|
305 @param aLowMatch The match string for the bottom of the range. Only the first |
|
306 character in the string is used. |
|
307 @param aLowCriteria The query search condition for the bottom of the range; |
|
308 either CContactViewRangeBase::EGreaterThan or CContactViewRangeBase::EGreaterThanOrEqualTo. |
|
309 @param aHighMatch The match string for the top of the range. Only the first |
|
310 character in the string is used. |
|
311 @param aHighCriteria The query search condition for the top of the range; either |
|
312 CContactViewRangeBase::ELessThan or CContactViewRangeBase::ELessThanOrEqualTo. |
|
313 @return Pointer to a newly created sub view range object */ |
|
314 { |
|
315 #ifdef CNTVIEW_API_PROFILING |
|
316 RDebug::Print(_L("[CNTMODEL] CContactViewRange::NewL()\n")); |
|
317 #endif |
|
318 CContactViewRange* self=new(ELeave) CContactViewRange(aView,aLowMatch,aLowCriteria,aHighMatch,aHighCriteria); |
|
319 CleanupStack::PushL(self); |
|
320 self->ConstructL(); |
|
321 CleanupStack::Pop(); // self. |
|
322 return self; |
|
323 } |
|
324 |
|
325 CContactViewRange::~CContactViewRange() |
|
326 /** Destructor. */ |
|
327 { |
|
328 } |
|
329 |
|
330 void CContactViewRange::ConstructL() |
|
331 { |
|
332 CContactViewRangeBase::ConstructL(); |
|
333 } |
|
334 |
|
335 void CContactViewRange::SetL() |
|
336 { |
|
337 iLow=FindIndexL(iLowMatch,iLowCriteria); |
|
338 iHigh=FindIndexL(iHighMatch,iHighCriteria); |
|
339 ValidateIndices(); |
|
340 } |
|
341 |
|
342 |
|
343 // |
|
344 // CContactViewLowRange |
|
345 // |
|
346 |
|
347 CContactViewLowRange::CContactViewLowRange(const CContactViewBase& aView,const TDesC& aMatch,TCriteria aCriteria) |
|
348 : CContactViewRangeBase(aView),iMatch(aMatch),iCriteria(aCriteria) |
|
349 { |
|
350 } |
|
351 |
|
352 CContactViewLowRange::~CContactViewLowRange() |
|
353 { |
|
354 } |
|
355 |
|
356 EXPORT_C CContactViewLowRange* CContactViewLowRange::NewL(const CContactViewBase& aView,const TDesC& aMatch,TCriteria aCriteria) |
|
357 /** Allocates and constructs a CContactViewLowRange object. |
|
358 |
|
359 @param aView The sub view's underlying view. |
|
360 @param aMatch The string to match items against. Only the first character in |
|
361 the string is used. |
|
362 @param aCriteria The query search condition; either CContactViewRangeBase::ELessThanOrEqualTo |
|
363 or CContactViewRangeBase::ELessThan. |
|
364 @return Pointer to a newly created CContactViewLowRange object */ |
|
365 { |
|
366 #ifdef CNTVIEW_API_PROFILING |
|
367 RDebug::Print(_L("[CNTMODEL] CContactViewLowRange::NewL()\n")); |
|
368 #endif |
|
369 CContactViewLowRange* self=new(ELeave) CContactViewLowRange(aView,aMatch,aCriteria); |
|
370 CleanupStack::PushL(self); |
|
371 self->ConstructL(); |
|
372 CleanupStack::Pop(); // self. |
|
373 return self; |
|
374 } |
|
375 |
|
376 void CContactViewLowRange::SetL() |
|
377 { |
|
378 iHigh=FindIndexL(iMatch,iCriteria); |
|
379 if(iHigh!=KErrNotFound && iHigh >=0) |
|
380 { |
|
381 iLow=0; |
|
382 } |
|
383 ValidateIndices(); |
|
384 } |
|
385 |
|
386 |
|
387 // |
|
388 // CContactViewHighRange |
|
389 // |
|
390 |
|
391 CContactViewHighRange::CContactViewHighRange (const CContactViewBase& aView,const TDesC& aMatch,TCriteria aCriteria) |
|
392 : CContactViewRangeBase(aView),iMatch(aMatch),iCriteria(aCriteria) |
|
393 { |
|
394 } |
|
395 |
|
396 CContactViewHighRange::~CContactViewHighRange() |
|
397 { |
|
398 } |
|
399 |
|
400 EXPORT_C CContactViewHighRange * CContactViewHighRange::NewL(const CContactViewBase& aView,const TDesC& aMatch,TCriteria aCriteria) |
|
401 /** Allocates and constructs a CContactViewHighRange object. |
|
402 |
|
403 @param aView The sub view's underlying view. |
|
404 @param aMatch The string to match items against. Only the first character in |
|
405 the string is used. |
|
406 @param aCriteria The query search condition; either CContactViewRangeBase::EGreaterThan |
|
407 or CContactViewRangeBase::EGreaterThanOrEqualTo. |
|
408 @return Pointer to newly created CContactViewHighRange object */ |
|
409 { |
|
410 #ifdef CNTVIEW_API_PROFILING |
|
411 RDebug::Print(_L("[CNTMODEL] CContactViewHighRange::NewL()\n")); |
|
412 #endif |
|
413 CContactViewHighRange * self=new(ELeave) CContactViewHighRange (aView,aMatch,aCriteria); |
|
414 CleanupStack::PushL(self); |
|
415 self->ConstructL(); |
|
416 CleanupStack::Pop(); // self. |
|
417 return self; |
|
418 } |
|
419 |
|
420 void CContactViewHighRange::SetL() |
|
421 { |
|
422 iLow=FindIndexL(iMatch,iCriteria); |
|
423 if (iLow!=KErrNotFound) |
|
424 { |
|
425 iHigh=iView.CountL()-1; |
|
426 } |
|
427 ValidateIndices(); |
|
428 } |