|
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 // System includess |
|
17 #include "ecom/ecom.h" // For REComSession |
|
18 #include <ecom/ecomresolverparams.h> |
|
19 |
|
20 // User includes |
|
21 #include <cntviewbase.h> |
|
22 #include "CNTSTD.H" |
|
23 #include <cntviewfindconfig.h> |
|
24 #include "CVIEWCONTACTEXTENSION.h" |
|
25 #include <cntviewsortplugin.h> |
|
26 #include "cntviewprivate.h" |
|
27 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
28 #include <cntviewsortpluginbase.h> |
|
29 #endif |
|
30 |
|
31 extern void DebugLogViewNotification(const TDesC& aMethod, const TContactViewEvent& aEvent); |
|
32 |
|
33 //uncomment in conjunction with LocalView and T_Cnt_ViewSortProfiling |
|
34 //#define __PROFILE_SORT__ |
|
35 |
|
36 |
|
37 EXPORT_C RContactViewSortOrder::RContactViewSortOrder() : iSpare(KErrNone), iSpare2(0), iSpare3(0) |
|
38 /** Default C++ constructor. */ |
|
39 { |
|
40 } |
|
41 |
|
42 EXPORT_C void RContactViewSortOrder::Close() |
|
43 /** Closes the sort order array and frees all memory allocated to it. */ |
|
44 { |
|
45 iFields.Close(); |
|
46 } |
|
47 |
|
48 EXPORT_C void RContactViewSortOrder::CopyL(const RContactViewSortOrder& aSortOrder) |
|
49 /** Copies the field types contained in the specified sort order object into this |
|
50 object. |
|
51 |
|
52 Any existing field types in this object are replaced. |
|
53 |
|
54 @param aSortOrder The sort order to be copied. */ |
|
55 { |
|
56 iFields.Reset(); |
|
57 const TInt numFields=aSortOrder.iFields.Count(); |
|
58 for (TInt ii=0;ii<numFields;++ii) |
|
59 { |
|
60 TFieldType field = aSortOrder.iFields[ii]; |
|
61 AppendL(field); |
|
62 } |
|
63 } |
|
64 |
|
65 EXPORT_C void RContactViewSortOrder::InternalizeL(RReadStream& aStream) |
|
66 /** Internalises a sort order object from a read stream. |
|
67 |
|
68 @param aStream The stream to read from. */ |
|
69 { |
|
70 iSpare = aStream.ReadInt32L(); |
|
71 iSpare2 = aStream.ReadInt32L(); |
|
72 iSpare3 = aStream.ReadInt32L(); |
|
73 TInt numFields; |
|
74 numFields = aStream.ReadInt32L(); |
|
75 for (TInt ii=0;ii<numFields;++ii) |
|
76 { |
|
77 TFieldType thisField; |
|
78 aStream >> thisField.iUid; |
|
79 AppendL(thisField); |
|
80 } |
|
81 } |
|
82 |
|
83 EXPORT_C void RContactViewSortOrder::ExternalizeL(RWriteStream& aStream) const |
|
84 /** Externalises a sort order object to a write stream. |
|
85 |
|
86 @param aStream The stream to write to. */ |
|
87 { |
|
88 aStream.WriteInt32L(iSpare); |
|
89 aStream.WriteInt32L(iSpare2); |
|
90 aStream.WriteInt32L(iSpare3); |
|
91 const TInt numFields=iFields.Count(); |
|
92 aStream.WriteInt32L(numFields); |
|
93 for (TInt ii=0;ii<numFields;++ii) |
|
94 { |
|
95 aStream << iFields[ii].iUid; |
|
96 } |
|
97 } |
|
98 |
|
99 /* |
|
100 * The current implementation relies on the externalized size provided by |
|
101 * the STORE implementation. |
|
102 */ |
|
103 EXPORT_C TInt RContactViewSortOrder::ExternalizedSize() const |
|
104 /** Retrieves the number of bytes required to store the sort order when externalised. |
|
105 |
|
106 @return The size of the sort order object. */ |
|
107 { |
|
108 return (sizeof(TInt)*4)+(iFields.Count()*sizeof(TFieldType)); |
|
109 } |
|
110 |
|
111 EXPORT_C TBool RContactViewSortOrder::operator==(const RContactViewSortOrder& aSortOrder) const |
|
112 /** Compares two sort order objects for equivalence. |
|
113 |
|
114 @param aSortOrder The sort order object to compare with this one. |
|
115 @return ETrue if the two sort orders are the same, EFalse if not. */ |
|
116 { |
|
117 TBool sortOrdersMatch = ETrue; |
|
118 |
|
119 const TInt numFields=iFields.Count(); |
|
120 if (numFields!=aSortOrder.Count()) |
|
121 { |
|
122 sortOrdersMatch = EFalse; |
|
123 } |
|
124 else |
|
125 { |
|
126 for (TInt ii=0;ii<numFields;++ii) |
|
127 { |
|
128 if (iFields[ii]!=aSortOrder.iFields[ii]) |
|
129 { |
|
130 sortOrdersMatch = EFalse; |
|
131 break; |
|
132 } |
|
133 } |
|
134 } |
|
135 |
|
136 return sortOrdersMatch; |
|
137 } |
|
138 |
|
139 |
|
140 EXPORT_C void CContactViewBase::OpenL(MContactViewObserver& aObserver) |
|
141 /** Appends an observer to the view's observer array. |
|
142 |
|
143 If the view's state is EReady, the observer is notified asynchronously that |
|
144 the view is ready. |
|
145 |
|
146 An error causes the function to leave. |
|
147 |
|
148 @param aObserver The contact view observer to be added. */ |
|
149 { |
|
150 #ifdef CONTACTS_API_PROFILING |
|
151 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiOpenL); |
|
152 #endif |
|
153 iObserverArray.AppendL(&aObserver); |
|
154 if (GetErrorValueFromExtensionClass()!=KErrNone) |
|
155 { |
|
156 NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError,iExtension->iError)); |
|
157 } |
|
158 if (iState==EReady) |
|
159 { |
|
160 User::LeaveIfError(NotifyObserverAsync(aObserver,TContactViewEvent(TContactViewEvent::EReady))); |
|
161 } |
|
162 } |
|
163 |
|
164 EXPORT_C TInt CContactViewBase::Open(MContactViewObserver& aObserver) |
|
165 /** Appends an observer to the view's observer array. |
|
166 |
|
167 If the view's state is EReady, the observer is notified asynchronously that |
|
168 the view is ready. |
|
169 |
|
170 This function does not leave; an error code is returned instead. |
|
171 |
|
172 @param aObserver The contact view observer to add. |
|
173 @return A standard error code, or KErrNone if the function completed without |
|
174 an error. */ |
|
175 { |
|
176 #ifdef CONTACTS_API_PROFILING |
|
177 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiOpen); |
|
178 #endif |
|
179 TInt err=iObserverArray.Append(&aObserver); |
|
180 if (iExtension->iError!=KErrNone) |
|
181 { |
|
182 NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError,iExtension->iError)); |
|
183 } |
|
184 if (err) |
|
185 { |
|
186 return err; |
|
187 } |
|
188 if (iState==EReady) |
|
189 { |
|
190 err = NotifyObserverAsync(aObserver,TContactViewEvent(TContactViewEvent::EReady)); |
|
191 if (err!=KErrNone) |
|
192 { |
|
193 return err; |
|
194 } |
|
195 } |
|
196 return err; |
|
197 } |
|
198 |
|
199 /** |
|
200 Removes an observer from the view's observer array. |
|
201 |
|
202 Any outstanding notifications for aObserver are first cancelled. |
|
203 |
|
204 @capability None |
|
205 @param aObserver The contact view observer to be removed. |
|
206 @return ETrue if the view's observer array is empty as a result of the removal; |
|
207 EFalse if it is not empty or if aObserver could not be found in the observer |
|
208 array. |
|
209 */ |
|
210 EXPORT_C TBool CContactViewBase::Close(const MContactViewObserver& aObserver) |
|
211 { |
|
212 #ifdef CONTACTS_API_PROFILING |
|
213 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiClose); |
|
214 #endif |
|
215 const TInt observerIndex = iObserverArray.Find(&aObserver); |
|
216 if (observerIndex != KErrNotFound) |
|
217 { |
|
218 //the observer that just closed may be expecting a notification |
|
219 for (TInt outstandingIndex=iOutstandingNotifications.Count()-1; outstandingIndex>=0; --outstandingIndex) |
|
220 { |
|
221 if (iOutstandingNotifications[outstandingIndex].iObserverToNotify == &aObserver) |
|
222 { |
|
223 iOutstandingNotifications.Remove(outstandingIndex); |
|
224 } |
|
225 } |
|
226 if(iOutstandingNotifications.Count()==0) |
|
227 { |
|
228 iOutstandingNotifications.Reset(); |
|
229 if(iAsyncNotifier->IsActive()) |
|
230 { |
|
231 //AsyncNotifier is Active with nothing to notifiy so we need to cancel it. |
|
232 iAsyncNotifier->Cancel(); |
|
233 } |
|
234 } |
|
235 //remove observer from main array. |
|
236 iObserverArray.Remove(observerIndex); |
|
237 if (iObserverArray.Count()==0) |
|
238 { |
|
239 delete this; |
|
240 return ETrue; |
|
241 } |
|
242 } |
|
243 return EFalse; |
|
244 } |
|
245 |
|
246 EXPORT_C CContactViewBase::CContactViewBase(const CContactDatabase& aDb) |
|
247 : iDb(aDb),iState(EInitializing) |
|
248 /** Protected C++ constructor. |
|
249 |
|
250 Initialises the view's state to EInitializing. |
|
251 |
|
252 @param aDb The database that contains the contact items. */ |
|
253 { |
|
254 } |
|
255 |
|
256 EXPORT_C CContactViewBase::~CContactViewBase() |
|
257 /** Destructor. |
|
258 |
|
259 Cancels all outstanding notifications and deletes all resources owned by the object. */ |
|
260 { |
|
261 #ifdef CONTACTS_API_PROFILING |
|
262 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewDestructor); |
|
263 #endif |
|
264 delete iExtension; |
|
265 REComSession::FinalClose(); // This line is necessary to make sure the plug-in is unloaded properly |
|
266 iObserverArray.Close(); |
|
267 delete iAsyncNotifier; |
|
268 iOutstandingNotifications.Close(); |
|
269 } |
|
270 |
|
271 EXPORT_C void CContactViewBase::ConstructL() |
|
272 /** Protected second phase constructor. |
|
273 |
|
274 Called from a derived class's ConstructL(). Creates the view's asynchronous |
|
275 notifier and adds it to the active scheduler. */ |
|
276 { |
|
277 #ifdef CONTACTS_API_PROFILING |
|
278 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiConstructL); |
|
279 #endif |
|
280 iAsyncNotifier=CIdle::NewL(CActive::EPriorityStandard); |
|
281 iExtension = CContactViewBaseExtension::NewL(); |
|
282 if(iExtension) |
|
283 { |
|
284 iExtension->iFindPluginUid = KNullUid; |
|
285 iExtension->iError = KErrNone; |
|
286 } |
|
287 } |
|
288 |
|
289 EXPORT_C void CContactViewBase::NotifyObservers(const TContactViewEvent& aEvent) |
|
290 /** Called by derived view classes to notify their observers synchronously of an |
|
291 event, by calling their HandleContactViewEvent() function. |
|
292 |
|
293 @param aEvent Identifies the event that occurred. */ |
|
294 { |
|
295 #ifdef CONTACTS_API_PROFILING |
|
296 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiNotifyObservers, aEvent); |
|
297 #endif |
|
298 TInt Observer=iObserverArray.Count(); |
|
299 #if defined(__VERBOSE_DEBUG__) |
|
300 //Print the message to be broadcated to the views |
|
301 if (Observer) |
|
302 { |
|
303 DebugLogViewNotification(_L("[CNTMODEL] CContactViewBase::NotifyObservers"), aEvent); |
|
304 } |
|
305 #endif |
|
306 // We iterate backwards to allow for observers removing themselves from the array |
|
307 while (Observer--) |
|
308 { |
|
309 iObserverArray[Observer]->HandleContactViewEvent(*this,aEvent); |
|
310 } |
|
311 } |
|
312 |
|
313 EXPORT_C TInt CContactViewBase::NotifyObserverAsync(MContactViewObserver& aObserver,const TContactViewEvent& aEvent) |
|
314 /** Called to notify a single view observer asynchronously of an event. |
|
315 |
|
316 If other notifications are outstanding, this notification is appended to the |
|
317 queue. |
|
318 |
|
319 If the view's asynchronous notifier is not active, it is started as a background |
|
320 task. |
|
321 |
|
322 This function is called by OpenL() and Open() to notify the observer that |
|
323 the view is ready. |
|
324 |
|
325 @param aObserver The contact view observer to notify. This must have previously |
|
326 been added to the view's observer array. |
|
327 @param aEvent Identifies the event that occurred. |
|
328 @return KErrNone if the function completed without error, otherwise one of |
|
329 the standard error codes. */ |
|
330 { |
|
331 #ifdef CONTACTS_API_PROFILING |
|
332 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiNotifyObserverAsync, aEvent); |
|
333 #endif |
|
334 TInt err = KErrNone; |
|
335 __ASSERT_DEBUG(iObserverArray.Find(&aObserver)!=KErrNotFound,Panic(ECntPanicObserverNotFound)); |
|
336 TObserverAndEvent outstandingNotification; |
|
337 outstandingNotification.iAsyncEvent=aEvent; |
|
338 outstandingNotification.iObserverToNotify=&aObserver; |
|
339 err = iOutstandingNotifications.Append(outstandingNotification); |
|
340 if (err==KErrNone) |
|
341 { |
|
342 if(!(iAsyncNotifier->IsActive())) |
|
343 { |
|
344 //No current outstanding notifications, start the asyn notifier to deal with the event that |
|
345 //was just added |
|
346 __ASSERT_DEBUG(iAsyncNotifier->IsActive()==EFalse,Panic(ECntPanicAsyncViewNotificationPending)); |
|
347 iAsyncNotifier->Start(TCallBack(AsyncNotifyCallBack,this)); |
|
348 } |
|
349 } |
|
350 return err; |
|
351 } |
|
352 |
|
353 TInt CContactViewBase::AsyncNotifyCallBack(TAny* aSelf) |
|
354 { |
|
355 //Notifiy the bottom element in the outstanding notifiers array, |
|
356 //at the end of the function if the array is not empty there are further observers to notify. |
|
357 CContactViewBase* self=STATIC_CAST(CContactViewBase*,aSelf); |
|
358 #ifdef _DEBUG |
|
359 TInt outstandingNotifCount = self->iOutstandingNotifications.Count(); |
|
360 __ASSERT_DEBUG(outstandingNotifCount>0,Panic(ECntPanicObserverNotFound)); |
|
361 #endif |
|
362 TContactViewEvent event=self->iOutstandingNotifications[0].iAsyncEvent; |
|
363 MContactViewObserver* observerToNotify=self->iOutstandingNotifications[0].iObserverToNotify; |
|
364 __ASSERT_DEBUG(observerToNotify && self->iObserverArray.Find(observerToNotify)!=KErrNotFound,Panic(ECntPanicObserverNotFound)); |
|
365 self->iOutstandingNotifications.Remove(0); |
|
366 observerToNotify->HandleContactViewEvent(*self,event); |
|
367 return self->iOutstandingNotifications.Count(); |
|
368 } |
|
369 |
|
370 EXPORT_C TBool CContactViewBase::IdsMatch(const CViewContact& aFirst,const CViewContact& aSecond) |
|
371 /** Tests whether the IDs of two contact items are the same. |
|
372 |
|
373 @param aFirst The first contact item. |
|
374 @param aSecond The second contact item. |
|
375 @return True if the IDs match, otherwise false. */ |
|
376 { |
|
377 return (aFirst.Id()==aSecond.Id()); |
|
378 } |
|
379 |
|
380 EXPORT_C HBufC* CContactViewBase::FieldsWithSeparatorLC(const RPointerArray<CViewContact>& aContacts,TInt aIndex,const TDesC& aSeparator) const |
|
381 /** Allocates and returns a descriptor filled with the contents of all the fields |
|
382 in a contact item. |
|
383 |
|
384 The fields are separated by the specified separator. |
|
385 |
|
386 @param aContacts An array of contact items. |
|
387 @param aIndex An index into the specified array. |
|
388 @param aSeparator The text to use to separate the fields. |
|
389 @return A pointer to a heap descriptor containing the contents of each of the |
|
390 contact item's fields. The field separator is appended to each field except |
|
391 the last one. The pointer is left on the cleanup stack. */ |
|
392 { |
|
393 #ifdef CONTACTS_API_PROFILING |
|
394 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiFieldsWithSeparatorLC); |
|
395 #endif |
|
396 // Calculate the length of the buffer. |
|
397 TInt bufLength=0; |
|
398 const CViewContact& viewContact = *(aContacts[aIndex]); |
|
399 const TInt separatorLength=aSeparator.Length(); |
|
400 const TInt numFields=viewContact.FieldCount(); |
|
401 for (TInt ii=0;ii<numFields;++ii) |
|
402 { |
|
403 bufLength+=viewContact.Field(ii).Length()+separatorLength; |
|
404 } |
|
405 HBufC* buf=HBufC::NewLC(bufLength); |
|
406 TPtr bufPtr(buf->Des()); |
|
407 |
|
408 // Fill the buffer. |
|
409 for (TInt j=0;j<numFields;++j) |
|
410 { |
|
411 bufPtr.Append(viewContact.Field(j)); |
|
412 |
|
413 // Only put a separator in if this isn't the last field. |
|
414 if (j!=numFields-1) |
|
415 { |
|
416 bufPtr.Append(aSeparator); |
|
417 } |
|
418 } |
|
419 return buf; |
|
420 } |
|
421 |
|
422 EXPORT_C TBool CContactViewBase::MatchesCriteriaL(const CViewContact& aContact,const MDesCArray& aFindWords) |
|
423 /** Searches a single contact item for fields that contain one or more search strings. |
|
424 |
|
425 The search uses wildcard matching so that the search strings can occur anywhere |
|
426 in any of the item's fields. For a match to occur, all of the search strings |
|
427 must be found in the contact item. |
|
428 |
|
429 Any find configuration plug-in that has been set (by calling SetViewFindConfigPlugin()) |
|
430 will be used. |
|
431 |
|
432 @param aContact The contact item to search. |
|
433 @param aFindWords A descriptor array containing one or more search strings. |
|
434 @return True if all of the search strings were present in the contact item's |
|
435 fields. False if not. */ |
|
436 { |
|
437 return MatchesCriteriaL(aContact,aFindWords,EFullSearch,iExtension); |
|
438 } |
|
439 |
|
440 EXPORT_C TBool CContactViewBase::MatchesCriteriaL(const CViewContact& aContact,const MDesCArray& aFindWords, TSearchType aSearchType) |
|
441 /** Searches a single contact item for fields that contain one or more search strings. |
|
442 |
|
443 The search type indicates whether the search strings can occur anywhere in |
|
444 a field, or must occur at the start of a field only. For a match to occur, |
|
445 all of the search strings must be found in the contact item. |
|
446 |
|
447 This function does not use any find configuration plug-in that has been set |
|
448 (by calling SetViewFindConfigPlugin()), so new code should use one of the other |
|
449 overloads instead. This function has been maintained for binary compatibility |
|
450 with previous OS versions. |
|
451 |
|
452 @param aContact The contact item to search. |
|
453 @param aFindWords A descriptor array containing one or more search strings. |
|
454 @param aSearchType The search type. This controls whether a search term can |
|
455 occur anywhere in a contact item field, or just at the beginning of a field. |
|
456 @return True if all of the search strings were present in the contact item's |
|
457 fields. False if not. */ |
|
458 { |
|
459 return MatchesCriteriaL(aContact,aFindWords,aSearchType,NULL); |
|
460 } |
|
461 |
|
462 EXPORT_C TBool CContactViewBase::MatchesCriteriaL(const CViewContact& aContact,const MDesCArray& aFindWords, TSearchType aSearchType,CContactViewBase::CContactViewBaseExtension* aExtension) |
|
463 /** Searches a single contact item for fields that contain one or more search strings. |
|
464 |
|
465 The search type indicates whether the search strings can occur anywhere in |
|
466 a field, or must occur at the start of a field only. For a match to occur, |
|
467 all of the search strings must be found in the contact item. |
|
468 |
|
469 If a find configuration plug-in UID is specified in the fourth parameter, |
|
470 this overload uses it, loading it first if necessary. This overrides any plug-in |
|
471 that had previously been set by a call to SetViewFindConfigPlugin(). |
|
472 |
|
473 @param aContact The contact item to search. |
|
474 @param aFindWords A descriptor array containing one or more search strings. |
|
475 @param aSearchType The search type. This controls whether a search term can |
|
476 occur anywhere in a contact item field, or just at the beginning of a field. |
|
477 @param aExtension Optionally, this can be used to specify the UID of a find |
|
478 configuration plug-in, overriding any that has previously been set by a call |
|
479 to SetViewFindConfigPlugin(). |
|
480 @return True if all of the search strings were present in the contact item's |
|
481 fields. False if not. */ |
|
482 { |
|
483 #ifdef CONTACTS_API_PROFILING |
|
484 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiMatchesCriteriaL, aContact.Id()); |
|
485 #endif |
|
486 CDesCArrayFlat* findWordArray = CreateFindWordArrayLC(aFindWords, aSearchType); |
|
487 TBool result = ContactMatchesCriteriaL(aContact, *findWordArray,aExtension); |
|
488 CleanupStack::PopAndDestroy(findWordArray); |
|
489 return result; |
|
490 } |
|
491 |
|
492 /* |
|
493 * Create an array of words to use when matching contact data. |
|
494 * @param aFindWords Array of words |
|
495 * @param aSearchType Specifies a prefix or substring match |
|
496 * @return Array of words |
|
497 */ |
|
498 CDesCArrayFlat* CContactViewBase::CreateFindWordArrayLC(const MDesCArray& aFindWords, TSearchType aSearchType) |
|
499 { |
|
500 const TInt numFindWords=aFindWords.MdcaCount(); |
|
501 CDesCArrayFlat* findWordArray = new (ELeave) CDesCArrayFlat(numFindWords); |
|
502 CleanupStack::PushL(findWordArray); |
|
503 |
|
504 for (TInt i=0; i<numFindWords; ++i) |
|
505 { |
|
506 TPtrC original(aFindWords.MdcaPoint(i)); |
|
507 HBufC* findString=HBufC::NewLC(original.Length()+2); |
|
508 TPtr ptr(findString->Des()); |
|
509 switch(aSearchType) |
|
510 { |
|
511 case EFullSearch: |
|
512 ptr.Append('*'); |
|
513 break; |
|
514 case EPrefixSearch: |
|
515 break; |
|
516 default: // programming error. |
|
517 break; |
|
518 } |
|
519 ptr.Append(original); |
|
520 ptr.Append('*'); |
|
521 findWordArray->AppendL(*findString); |
|
522 CleanupStack::PopAndDestroy(findString); |
|
523 } |
|
524 return findWordArray; |
|
525 } |
|
526 |
|
527 /* |
|
528 * Check if aContact matches aFindWords |
|
529 * @return ETrue if matched, EFalse otherwise |
|
530 * new parameter has been added aExtension CContactViewBase extension class. |
|
531 */ |
|
532 TBool CContactViewBase::ContactMatchesCriteriaL(const CViewContact& aContact,const MDesCArray& aFindWords,CContactViewBase::CContactViewBaseExtension* aExtension) |
|
533 { |
|
534 TInt hits = 0; |
|
535 const TInt numFields=aContact.FieldCount(); |
|
536 const TInt numFindWords=aFindWords.MdcaCount(); |
|
537 if(aExtension->iFindPluginUid != KNullUid && aExtension->iFindPluginImpl == NULL) |
|
538 { |
|
539 //Load plug-in |
|
540 aExtension->iFindPluginImpl = CContactViewFindConfigInterface::NewL(aExtension->iFindPluginUid); |
|
541 } |
|
542 if (aExtension->iFindPluginImpl) |
|
543 { |
|
544 for (TInt jj=0;jj<numFindWords;++jj) |
|
545 { |
|
546 TPtrC word(aFindWords.MdcaPoint(jj)); |
|
547 if (aExtension->iFindPluginImpl->IsWordValidForMatching(word)) |
|
548 { |
|
549 for (TInt kk=0;kk<numFields;++kk) |
|
550 { |
|
551 if (aExtension->iFindPluginImpl->Match(aContact.Field(kk), word)) |
|
552 { |
|
553 ++hits; |
|
554 break; |
|
555 } |
|
556 } |
|
557 } |
|
558 else |
|
559 { |
|
560 for (TInt kk=0;kk<numFields;++kk) |
|
561 { |
|
562 if (aContact.Field(kk).MatchC(word)!=KErrNotFound) |
|
563 { |
|
564 ++hits; |
|
565 break; |
|
566 } |
|
567 } |
|
568 } |
|
569 } |
|
570 } |
|
571 else |
|
572 { |
|
573 for (TInt jj=0;jj<numFindWords;++jj) |
|
574 { |
|
575 TPtrC word(aFindWords.MdcaPoint(jj)); |
|
576 for (TInt kk=0;kk<numFields;++kk) |
|
577 { |
|
578 if (aContact.Field(kk).MatchC(word)!=KErrNotFound) |
|
579 { |
|
580 ++hits; |
|
581 break; |
|
582 } |
|
583 } |
|
584 } |
|
585 } |
|
586 return (hits==numFindWords); |
|
587 } |
|
588 |
|
589 /* Implementation of ContactsMatchingCriteriaL and ContactsMatchingPrefixL */ |
|
590 void CContactViewBase::MatchContactsL(const MDesCArray& aFindWords,RPointerArray<CViewContact>& aMatchedContacts, TSearchType aSearchType) |
|
591 { |
|
592 CDesCArrayFlat* findWordArray = CreateFindWordArrayLC(aFindWords, aSearchType); |
|
593 const TInt viewCount = CountL(); |
|
594 TBool match = EFalse; |
|
595 for (TInt ii=0;ii<viewCount;++ii) |
|
596 { |
|
597 const CViewContact& contact = ContactAtL(ii); |
|
598 match=ContactMatchesCriteriaL(contact,*findWordArray,iExtension); |
|
599 if (match) |
|
600 { |
|
601 CViewContact* thisContact = CViewContact::NewL(contact); |
|
602 CleanupStack::PushL(thisContact); |
|
603 aMatchedContacts.AppendL(thisContact); |
|
604 CleanupStack::Pop(thisContact); |
|
605 } |
|
606 } |
|
607 CleanupStack::PopAndDestroy(findWordArray); |
|
608 } |
|
609 |
|
610 /** Searches all contact items in the view for fields that contain all of the search |
|
611 strings specified. |
|
612 |
|
613 The search uses wildcard matching so that the search strings can occur anywhere |
|
614 in the item's fields. For a match to occur, all of the search strings must |
|
615 be found in a contact item. |
|
616 |
|
617 @capability ReadUserData |
|
618 @param aFindWords A descriptor array containing one or more search strings. |
|
619 @param aMatchedContacts On return, an array of matching contact items. */ |
|
620 EXPORT_C void CContactViewBase::ContactsMatchingCriteriaL(const MDesCArray& aFindWords, RPointerArray<CViewContact>& aMatchedContacts) |
|
621 { |
|
622 MatchContactsL(aFindWords,aMatchedContacts,EFullSearch); |
|
623 } |
|
624 |
|
625 /** Searches all contact items in the view for fields that contain all of the search |
|
626 strings specified. |
|
627 |
|
628 Unlike ContactsMatchingCriteriaL(), the search term can only occur at the |
|
629 beginning of a field. |
|
630 |
|
631 @capability ReadUserData |
|
632 @param aFindWords A descriptor array containing one or more search strings. |
|
633 @param aMatchedContacts On return, an array of matching contact items. */ |
|
634 EXPORT_C void CContactViewBase::ContactsMatchingPrefixL(const MDesCArray& aFindWords, RPointerArray<CViewContact>& aMatchedContacts) |
|
635 { |
|
636 MatchContactsL(aFindWords,aMatchedContacts, EPrefixSearch); |
|
637 } |
|
638 |
|
639 /** |
|
640 This is a reserved virtual exported function that is used for BC proofing against |
|
641 addition of new exported virtual functions. |
|
642 This function now aids addition of new exported virtual methods without |
|
643 having to break BC,by simply having those virtual methods as |
|
644 non-virtual and helper methods, called from this one and only reserved virtual |
|
645 exported method.A public enumeration type that is defined in the base class |
|
646 CContactViewBase identifies which of the helper 'virtual' methods are being called. |
|
647 All derived classes of CContactViewBase that are public should mandatorily implement |
|
648 this method. |
|
649 |
|
650 Returns any return values of the helper methods called from this function. |
|
651 |
|
652 @capability ReadUserData |
|
653 @param aFunction an enum value that identifies which helper method is called. |
|
654 @param aParams parameters to the helper method being called. |
|
655 @return Any return values of the helper methods called from this function or NULL. |
|
656 */ |
|
657 EXPORT_C TAny* CContactViewBase::CContactViewBase_Reserved_1(TFunction aFunction,TAny* aParams) |
|
658 { |
|
659 #ifdef CONTACTS_API_PROFILING |
|
660 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiContactViewBase_Reserved_1); |
|
661 #endif |
|
662 switch(aFunction) |
|
663 { |
|
664 case ECContactViewBaseVirtualFunction1: |
|
665 { |
|
666 TVirtualFunction1Params* vFuncParams = STATIC_CAST(TVirtualFunction1Params*,aParams); |
|
667 GetContactIdsL(*vFuncParams->iIndexes,*vFuncParams->iIdArray); |
|
668 } |
|
669 break; |
|
670 case ECContactViewBaseVirtualFunction2: |
|
671 { |
|
672 TVirtualFunction2Params* vFuncParams = STATIC_CAST(TVirtualFunction2Params*,aParams); |
|
673 GetContactsMatchingFilterL(vFuncParams->iFilter, vFuncParams->iMatchingContacts); |
|
674 } |
|
675 break; |
|
676 case ECContactViewBaseVirtualFunction3: |
|
677 { |
|
678 TVirtualFunction3Params* vFuncParams = STATIC_CAST(TVirtualFunction3Params*,aParams); |
|
679 TInt error = KErrNone; |
|
680 error = InsertContactInView(vFuncParams->iContacts,vFuncParams->iNewContact,EFalse,NULL); |
|
681 // stuff error code into a TAny * |
|
682 return reinterpret_cast<TAny*> (error); |
|
683 } |
|
684 default: |
|
685 break; |
|
686 } |
|
687 return NULL; |
|
688 } |
|
689 |
|
690 EXPORT_C void CContactViewBase::SetViewFindConfigPlugin(TUid aUid) |
|
691 /** Sets the UID of the view's find configuration plug-in to use in calls to ContactsMatchingCriteriaL(), |
|
692 ContactsMatchingPrefixL() and MatchesCriteriaL(). |
|
693 |
|
694 @param aUid The UID of the view's find configuration plug-in. |
|
695 @see CContactViewFindConfigInterface */ |
|
696 { |
|
697 #ifdef CONTACTS_API_PROFILING |
|
698 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiSetViewFindConfigPlugin); |
|
699 #endif |
|
700 iExtension->iFindPluginUid = aUid; |
|
701 } |
|
702 |
|
703 EXPORT_C TUid CContactViewBase::GetViewFindConfigPlugin() |
|
704 /** Gets the UID of the view's find configuration plug-in, as set by SetViewFindConfigPlugin(). |
|
705 |
|
706 @return The UID of the view's find configuration plug-in. KNullUid if none |
|
707 has been set. |
|
708 @see CContactViewFindConfigInterface */ |
|
709 { |
|
710 #ifdef CONTACTS_API_PROFILING |
|
711 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiGetViewFindConfigPlugin); |
|
712 #endif |
|
713 return iExtension->iFindPluginUid ; |
|
714 } |
|
715 |
|
716 /** Gets an array containing the IDs of the contact items at the specified view |
|
717 indexes. |
|
718 |
|
719 The IDs are appended to the array. |
|
720 |
|
721 @capability ReadUserData |
|
722 @param aIndexes An array of indexes into this view. |
|
723 @param aContactIds On return, an array to which the contact item IDs of each |
|
724 of the indexed items are appended. */ |
|
725 EXPORT_C void CContactViewBase::GetContactIdsL(const CArrayFix<TInt>& aIndexes, CContactIdArray& aContactIds) |
|
726 { |
|
727 #ifdef CONTACTS_API_PROFILING |
|
728 TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassViewBase, TContactsApiProfile::ECntViewApiGetContactIdsL); |
|
729 #endif |
|
730 const TInt myCount = CountL(); |
|
731 const TInt indexCount = aIndexes.Count(); |
|
732 for (TInt i=0; i < indexCount; ++i) |
|
733 { |
|
734 const TInt index = aIndexes[i]; |
|
735 if (index >= 0 && index < myCount) |
|
736 { |
|
737 aContactIds.AddL(AtL(index)); |
|
738 } |
|
739 } |
|
740 } |
|
741 /** |
|
742 * Gets an array containing the IDs of the contact items that match |
|
743 * the filter supplied by the client. |
|
744 * |
|
745 * @param aFilter Filter The filter to use |
|
746 * @param aMatchingContacts Array of matching contact IDs |
|
747 */ |
|
748 void CContactViewBase::GetContactsMatchingFilterL(TInt aFilter, RArray<TContactIdWithMapping>& aMatchingContacts) |
|
749 { |
|
750 TContactIdWithMapping idMap; |
|
751 const TInt viewCount(CountL()); |
|
752 for (TInt i=0;i<viewCount;++i) |
|
753 { |
|
754 const CViewContact& contact = ContactAtL(i); |
|
755 if(contact.ContactMatchesFilter(aFilter)) |
|
756 { |
|
757 idMap.iId=contact.Id(); |
|
758 idMap.iMapping=i; |
|
759 aMatchingContacts.AppendL(idMap); |
|
760 } |
|
761 } |
|
762 } |
|
763 |
|
764 EXPORT_C TBool CContactViewBase::IdsEqual(const TContactIdWithMapping& aFirst,const TContactIdWithMapping& aSecond) |
|
765 /** Tests whether the IDs of two contact items are the same. |
|
766 |
|
767 @param aFirst The contact ID/view index struct representing the first item. |
|
768 @param aSecond The contact ID/view index struct representing the second item. |
|
769 @return True if the IDs match, false if not. */ |
|
770 { |
|
771 return (aFirst.iId==aSecond.iId); |
|
772 } |
|
773 |
|
774 EXPORT_C TBool CContactViewBase::IndexesEqual(const TContactIdWithMapping& aFirst,const TContactIdWithMapping& aSecond) |
|
775 /** Tests whether the view indexes of two contact items are the same. |
|
776 |
|
777 @param aFirst The contact ID/view index struct representing the first item. |
|
778 @param aSecond The contact ID/view index struct representing the second item. |
|
779 @return True if the indexes match, false if not. */ |
|
780 { |
|
781 return (aFirst.iMapping==aSecond.iMapping); |
|
782 } |
|
783 |
|
784 /* |
|
785 See defect EXT-59BFK6 "Contact view sorting does not use default collation rules" |
|
786 for further information. |
|
787 This 'static' function is used by Sort Plugin. |
|
788 See method below for version used by default sort. |
|
789 Generally fixes should be applied to both! |
|
790 */ |
|
791 EXPORT_C TInt CContactViewBase::CompareFieldsL(const CViewContact& aFirst,const CViewContact& aSecond) |
|
792 /** Collates two contact items' field contents. |
|
793 |
|
794 This is done by comparing each contact item on a field by field basis starting |
|
795 with the loosest collation level initially, and then progressing to tighter |
|
796 collation levels only if the items are considered the same at the looser level. |
|
797 This is required so that items differing by case only are sorted correctly. |
|
798 If a field isn't present, then the comparison is done using the first field |
|
799 that is present. |
|
800 |
|
801 @param aFirst The first contact item. |
|
802 @param aSecond The second contact item. |
|
803 @return A positive value indicates that aFirst's field contents are greater |
|
804 than aSecond's (so that aFirst would occur after aSecond in a sort order). |
|
805 A negative value indicates that aFirst's field contents are less than aSecond's |
|
806 (so that aFirst would occur before aSecond in a sort order). Zero indicates |
|
807 that aFirst and aSecond have identical field contents. */ |
|
808 { |
|
809 const TInt KDefaultCollationLevel=3; |
|
810 TInt comparison = 0; // result of comparison, Zero = fields are identical |
|
811 TInt collationLevel = 0; |
|
812 |
|
813 TCollationMethod collateMethod = *Mem::CollationMethodByIndex(0); |
|
814 collateMethod.iFlags|=TCollationMethod::EIgnoreNone; |
|
815 |
|
816 do |
|
817 { |
|
818 comparison = CompareFieldsWithCollationLevel(aFirst, aSecond, collationLevel, &collateMethod); |
|
819 ++collationLevel; |
|
820 } |
|
821 while (comparison == 0 && collationLevel <= KDefaultCollationLevel); |
|
822 |
|
823 return comparison; |
|
824 } |
|
825 |
|
826 /* |
|
827 Similar to 'static', exported CompareFieldsL() method above. |
|
828 Except (for performance) it uses cached copy of TCollationMethod belonging to the view. |
|
829 Generally fixes should be applied to both! |
|
830 */ |
|
831 TInt CContactViewBase::TextCompareFieldsL(const CViewContact& aFirst,const CViewContact& aSecond) const |
|
832 /** Collates two contact items' field contents. |
|
833 |
|
834 This is done by comparing each contact item on a field by field basis starting |
|
835 with the loosest collation level initially, and then progressing to tighter |
|
836 collation levels only if the items are considered the same at the looser level. |
|
837 This is required so that items differing by case only are sorted correctly. |
|
838 If a field isn't present, then the comparison is done using the first field |
|
839 that is present. |
|
840 |
|
841 Faster than static CompareFieldsL() method as it uses prefetched collation method. |
|
842 |
|
843 @param aFirst The first contact item. |
|
844 @param aSecond The second contact item. |
|
845 @return A positive value indicates that aFirst's field contents are greater |
|
846 than aSecond's (so that aFirst would occur after aSecond in a sort order). |
|
847 A negative value indicates that aFirst's field contents are less than aSecond's |
|
848 (so that aFirst would occur before aSecond in a sort order). Zero indicates |
|
849 that aFirst and aSecond have identical field contents. */ |
|
850 { |
|
851 const TInt KDefaultCollationLevel=3; |
|
852 TInt comparison = 0; // result of comparison, Zero = fields are identical |
|
853 TInt collationLevel = 0; |
|
854 |
|
855 do |
|
856 { |
|
857 comparison = CompareFieldsWithCollationLevel(aFirst, aSecond, collationLevel, &iExtension->iCollationMethod); |
|
858 ++collationLevel; |
|
859 } |
|
860 while (comparison == 0 && collationLevel <= KDefaultCollationLevel); |
|
861 |
|
862 return comparison; |
|
863 } |
|
864 |
|
865 /** Gets the recorded error value. |
|
866 If an error occurs within the view, before each of the views |
|
867 observers are notified, then the view records the error code internally. |
|
868 This function provides access to a copy of that error code. |
|
869 |
|
870 |
|
871 @return The recorded error value. If this does not equal KErrNone, then something is wrong with the view. |
|
872 */ |
|
873 EXPORT_C TInt CContactViewBase::Error() const |
|
874 { |
|
875 return iExtension->iError; |
|
876 } |
|
877 |
|
878 /* |
|
879 * Extension class for maintaining BC in member variables. |
|
880 */ |
|
881 CContactViewBase::CContactViewBaseExtension* CContactViewBase::CContactViewBaseExtension::NewL() |
|
882 /** Constructs a new instance of the class. |
|
883 |
|
884 If a plug-in has been loaded, its OpenL() function is called, see CContactViewFindConfigInterface::OpenL(). |
|
885 |
|
886 @return Pointer to the newly created extension object. */ |
|
887 { |
|
888 CContactViewBaseExtension* self = |
|
889 new( ELeave ) CContactViewBaseExtension; |
|
890 CleanupStack::PushL( self ); |
|
891 self->ConstructL(); |
|
892 CleanupStack::Pop(self); |
|
893 return self; |
|
894 } |
|
895 |
|
896 CContactViewBase::CContactViewBaseExtension::CContactViewBaseExtension() |
|
897 { |
|
898 } |
|
899 |
|
900 CContactViewBase::CContactViewBaseExtension::~CContactViewBaseExtension() |
|
901 /* Destructor. |
|
902 |
|
903 If a Find plug-in has been loaded, its Close() function is called. See CContactViewFindConfigInterface::Close() */ |
|
904 { |
|
905 if ( iFindPluginImpl ) |
|
906 { |
|
907 delete iFindPluginImpl; |
|
908 } |
|
909 if (iSortPluginImpl) |
|
910 { // unload |
|
911 delete iSortPluginImpl; |
|
912 } |
|
913 } |
|
914 |
|
915 |
|
916 TInt CContactViewBase::CompareFieldsWithCollationLevel(const CViewContact& aFirst, const CViewContact& aSecond, |
|
917 TInt aCollationLevel, TCollationMethod* aCollateMethod) |
|
918 { |
|
919 const TInt KLastField = aFirst.FieldCount() - 1; |
|
920 |
|
921 TInt retval = 0; // result of comparison, Zero = fields are identical |
|
922 TInt firstField(-1); |
|
923 TInt secondField(-1); |
|
924 TPtrC first; |
|
925 TPtrC second; |
|
926 |
|
927 for (TInt counter=0; !retval && (counter <= KLastField); counter++) |
|
928 { |
|
929 // if the 1st populated field has a greater index than counter, |
|
930 // that means we'd get the same result from FindFirstPopulatedField. |
|
931 // So, don't bother. Of course we always have to run it at least once. |
|
932 |
|
933 if (firstField < counter) |
|
934 { |
|
935 first.Set(aFirst.FindFirstPopulatedField(counter, firstField)); |
|
936 } |
|
937 |
|
938 if (secondField < counter) |
|
939 { |
|
940 second.Set(aSecond.FindFirstPopulatedField(counter, secondField)); |
|
941 } |
|
942 |
|
943 // no fields in either item |
|
944 if ((firstField < 0) && (secondField < 0)) |
|
945 { |
|
946 break; |
|
947 } |
|
948 |
|
949 if (firstField < 0) |
|
950 { |
|
951 // first item sorts lower |
|
952 retval = -1; |
|
953 } |
|
954 else if (secondField < 0) |
|
955 { |
|
956 // second item sorts lower |
|
957 retval = 1; |
|
958 } |
|
959 else |
|
960 { |
|
961 // set counter to the first field populated by either contact |
|
962 while ((firstField > counter) && (secondField > counter)) |
|
963 counter++; |
|
964 |
|
965 retval = first.CompareC(second, aCollationLevel, aCollateMethod); |
|
966 } |
|
967 } |
|
968 |
|
969 return retval; |
|
970 } |
|
971 |
|
972 |
|
973 void CContactViewBase::CContactViewBaseExtension::ConstructL() |
|
974 { |
|
975 if ( iFindPluginImpl ) |
|
976 { |
|
977 iFindPluginImpl->OpenL(); |
|
978 } |
|
979 |
|
980 // Collation method by index 0 stays the same (only changes at a reboot) |
|
981 iCollationMethod = *Mem::CollationMethodByIndex(0); |
|
982 iCollationMethod.iFlags |= TCollationMethod::EIgnoreNone; |
|
983 } |
|
984 |
|
985 /* |
|
986 * Finds the first populated field within a contact. |
|
987 * |
|
988 * Starting at aOffset search for the first populated field. Search up to |
|
989 * the maximum number of fields available within the contact. |
|
990 * |
|
991 * If no populated field is found, then this function will return a zero |
|
992 * length TPtrC and set aFoundPosition to -1. |
|
993 * |
|
994 * @param aOffset The starting offset |
|
995 * @param aFoundPosition The offset of the field found |
|
996 * @return The contents of the field located at the found position |
|
997 */ |
|
998 TPtrC CViewContact::FindFirstPopulatedField(TInt aOffset, TInt& aFoundPosition) const |
|
999 { |
|
1000 if (iExtension) |
|
1001 { |
|
1002 const TInt max = iTextIndexes.Count() - 1; |
|
1003 TInt lengthOfText=0; |
|
1004 |
|
1005 for (TInt counter = aOffset; counter <= max; counter++) |
|
1006 { |
|
1007 const TInt fieldStartPos = iTextIndexes[counter]; |
|
1008 |
|
1009 if (counter < max) |
|
1010 { |
|
1011 lengthOfText = iTextIndexes[counter+1] - fieldStartPos; |
|
1012 } |
|
1013 else |
|
1014 { |
|
1015 lengthOfText = iExtension->FieldText().Length() - fieldStartPos; |
|
1016 } |
|
1017 |
|
1018 if (lengthOfText > 0 ) |
|
1019 { |
|
1020 aFoundPosition = counter; |
|
1021 return iExtension->FieldText().Mid(fieldStartPos, lengthOfText); |
|
1022 } |
|
1023 } |
|
1024 } |
|
1025 |
|
1026 // no more fields with text |
|
1027 aFoundPosition = -1; |
|
1028 return TPtrC(KNullDesC); |
|
1029 } |
|
1030 |
|
1031 /** |
|
1032 @internalComponent |
|
1033 */ |
|
1034 EXPORT_C CViewContact::CViewContact(TContactItemId aId) |
|
1035 : iId(aId), iExtension(NULL) |
|
1036 /** Constructs a CViewContact object. |
|
1037 |
|
1038 This should not be called by clients. CViewContact::NewLC() should be used instead. |
|
1039 |
|
1040 @param aId The contact ID to assign to the object. */ |
|
1041 { |
|
1042 } |
|
1043 |
|
1044 EXPORT_C void CViewContact::InternalizeL(RReadStream& aStream) |
|
1045 /** Internalises a CViewContact object from a read stream. |
|
1046 |
|
1047 @param aStream Stream from which the object is internalised. */ |
|
1048 { |
|
1049 // |
|
1050 if(!iExtension) |
|
1051 { |
|
1052 iExtension = CViewContactExtension::NewL(); |
|
1053 } |
|
1054 |
|
1055 iId = aStream.ReadInt32L(); |
|
1056 iContactType = STATIC_CAST(TViewContactType,aStream.ReadInt32L()); |
|
1057 SetContactTypeUid(TUid::Uid(aStream.ReadInt32L())); |
|
1058 iExtension->HintBitField() = aStream.ReadInt32L(); |
|
1059 const TInt indxCount = aStream.ReadInt32L(); |
|
1060 TInt fieldpos=0; |
|
1061 for (TInt ii=0;ii<indxCount;++ii) |
|
1062 { |
|
1063 fieldpos=aStream.ReadInt32L(); |
|
1064 iTextIndexes.AppendL(fieldpos); |
|
1065 } |
|
1066 |
|
1067 const TInt fieldLength = aStream.ReadInt32L(); |
|
1068 if(fieldLength>0) |
|
1069 { |
|
1070 HBufC* field = HBufC::NewLC(fieldLength); |
|
1071 TPtr ptr(field->Des()); |
|
1072 aStream.ReadL(ptr, fieldLength); |
|
1073 CleanupStack::Pop(field); |
|
1074 iExtension->SetFieldText(field); |
|
1075 } |
|
1076 else |
|
1077 { |
|
1078 iExtension->CreateEmptyFieldTextL(); |
|
1079 } |
|
1080 } |
|
1081 |
|
1082 /* |
|
1083 * Stores the data in a CViewContact. |
|
1084 * |
|
1085 * The chevron operator is not used when externalizing the field text buffer |
|
1086 * because using the Unicode compression scheme varies the size of the |
|
1087 * externalized text. Using the standard operators is less efficient but |
|
1088 * guaranteed to be consistent. |
|
1089 * |
|
1090 * The descriptor is only externalized if it has some length. Store doesn't |
|
1091 * like externalizing Null descriptors. |
|
1092 * |
|
1093 * @param aStream Stream to write data to |
|
1094 */ |
|
1095 EXPORT_C void CViewContact::ExternalizeL(RWriteStream& aStream) const |
|
1096 /** Externalises a CViewContact object to a write stream. |
|
1097 |
|
1098 @param aStream Stream to which the object is externalised. */ |
|
1099 { |
|
1100 aStream.WriteInt32L(iId); |
|
1101 aStream.WriteInt32L(iContactType); |
|
1102 aStream.WriteInt32L(ContactTypeUid().iUid); |
|
1103 |
|
1104 TPtrC pFieldText(KNullDesC); |
|
1105 TInt hintBitValue = 0; |
|
1106 if (iExtension) |
|
1107 { |
|
1108 hintBitValue = iExtension->HintBitField(); |
|
1109 pFieldText.Set(iExtension->FieldText()); |
|
1110 } |
|
1111 // |
|
1112 aStream.WriteInt32L(hintBitValue); |
|
1113 const TInt indxCount = iTextIndexes.Count(); |
|
1114 aStream.WriteInt32L(indxCount); |
|
1115 for (TInt ii=0;ii<indxCount;++ii) |
|
1116 { |
|
1117 aStream.WriteInt32L((iTextIndexes)[ii]); |
|
1118 } |
|
1119 // |
|
1120 const TInt fieldLength = pFieldText.Length(); |
|
1121 aStream.WriteInt32L(fieldLength); |
|
1122 if (fieldLength>0) |
|
1123 { |
|
1124 aStream.WriteL(pFieldText); |
|
1125 } |
|
1126 } |
|
1127 |
|
1128 EXPORT_C TInt CViewContact::ExternalizedSize() const |
|
1129 /** Retrieves the number of bytes required to store the contact view item when |
|
1130 externalised. |
|
1131 |
|
1132 @return The size of the contact view item. */ |
|
1133 { |
|
1134 TInt size = sizeof(TContactItemId); |
|
1135 const TInt indxCount = iTextIndexes.Count(); |
|
1136 size += sizeof(TViewContactType);//for contact Type; |
|
1137 size += sizeof(TUid); |
|
1138 size += sizeof(TInt); // for iExtension->HintBitField() |
|
1139 size += sizeof(TInt);//for index count; |
|
1140 size += sizeof(TInt)*indxCount;//for indexes |
|
1141 size += sizeof(TInt);//for fieldTextSize |
|
1142 // |
|
1143 TInt fieldTextSize = 0; |
|
1144 if (iExtension) |
|
1145 { |
|
1146 fieldTextSize = iExtension->FieldText().Size(); |
|
1147 } |
|
1148 size += fieldTextSize; |
|
1149 // |
|
1150 return size; |
|
1151 } |
|
1152 |
|
1153 /** |
|
1154 @internalTechnology |
|
1155 */ |
|
1156 EXPORT_C TUid CViewContact::ContactTypeUid() const |
|
1157 { |
|
1158 if(iExtension) |
|
1159 { |
|
1160 return iExtension->ContactTypeUid(); |
|
1161 } |
|
1162 |
|
1163 return TUid::Null(); |
|
1164 } |
|
1165 |
|
1166 /** |
|
1167 @internalTechnology |
|
1168 Note: This method can leave. |
|
1169 |
|
1170 @leave KErrNoMemory The CViewContactExtension cannot be allocated. |
|
1171 */ |
|
1172 EXPORT_C void CViewContact::SetContactTypeUid(TUid aUid) |
|
1173 { |
|
1174 if(!iExtension) |
|
1175 { |
|
1176 iExtension = CViewContactExtension::NewL(); // can leave |
|
1177 } |
|
1178 |
|
1179 iExtension->SetContactTypeUid(aUid); |
|
1180 } |
|
1181 |
|
1182 EXPORT_C CViewContact::~CViewContact() |
|
1183 /** Destructor. */ |
|
1184 { |
|
1185 iTextIndexes.Close(); |
|
1186 delete iExtension; |
|
1187 } |
|
1188 |
|
1189 /** |
|
1190 @internalTechnology |
|
1191 */ |
|
1192 CViewContact* CViewContact::NewLC(RReadStream& aStream) |
|
1193 { |
|
1194 CViewContact* viewContact = new (ELeave) CViewContact(KErrNotFound); |
|
1195 CleanupStack::PushL(viewContact); |
|
1196 viewContact->ConstructL(); |
|
1197 viewContact->InternalizeL(aStream); |
|
1198 return viewContact; |
|
1199 } |
|
1200 |
|
1201 /* |
|
1202 * Second phase constructor |
|
1203 */ |
|
1204 void CViewContact::ConstructL(TInt aLength) |
|
1205 { |
|
1206 iExtension = CViewContactExtension::NewL(aLength); |
|
1207 } |
|
1208 |
|
1209 /* |
|
1210 * Second phase constructor |
|
1211 * @param aContact Contact item to copy |
|
1212 */ |
|
1213 void CViewContact::ConstructL(const CViewContact& aContact) |
|
1214 { |
|
1215 CopyL(aContact); |
|
1216 } |
|
1217 |
|
1218 EXPORT_C CViewContact* CViewContact::NewLC(TContactItemId aId) |
|
1219 /** Allocates and constructs a CViewContact object, based on an existing one. |
|
1220 @param aId ID of the existing CViewContact object whose values are used to initialise |
|
1221 the new one. |
|
1222 @return Pointer to the newly created representation of a contact item used in contact views. |
|
1223 */ |
|
1224 { |
|
1225 CViewContact* contact = new(ELeave) CViewContact(aId); |
|
1226 CleanupStack::PushL(contact); |
|
1227 contact->ConstructL(); |
|
1228 return contact; |
|
1229 } |
|
1230 |
|
1231 |
|
1232 /** Allocates and constructs a CViewContact object, based on an existing one. |
|
1233 |
|
1234 @param aId ID of the existing CViewContact object whose values are used |
|
1235 to initialise the new one. |
|
1236 @param aLength initial MaxLenght of a contact buffer |
|
1237 @internalTechnology |
|
1238 */ |
|
1239 EXPORT_C CViewContact* CViewContact::NewL(TContactItemId aId, TInt aLength) |
|
1240 { |
|
1241 CViewContact* contact = new(ELeave) CViewContact(aId); |
|
1242 CleanupStack::PushL(contact); |
|
1243 contact->ConstructL(aLength); |
|
1244 CleanupStack::Pop(contact); |
|
1245 return contact; |
|
1246 } |
|
1247 |
|
1248 |
|
1249 |
|
1250 EXPORT_C CViewContact* CViewContact::NewL(const CViewContact& aContact) |
|
1251 /** Allocates and constructs a CViewContact object, based on an existing one. |
|
1252 @param aContact An existing CViewContact object whose values are used to initialise |
|
1253 the new one. |
|
1254 @return Pointer to the newly created representation of a contact item used in contact views. |
|
1255 */ |
|
1256 { |
|
1257 CViewContact* contact=new(ELeave)CViewContact(aContact.iId); |
|
1258 CleanupStack::PushL(contact); |
|
1259 contact->ConstructL(aContact); |
|
1260 CleanupStack::Pop(contact); |
|
1261 return contact; |
|
1262 } |
|
1263 |
|
1264 EXPORT_C TBool CViewContact::ContactMatchesFilter(TInt aFilter) const |
|
1265 /** Checks if this contact matches the supplied filter. |
|
1266 @return ETrue, if this contact matches the filter supplied; EFalse, otherwise. |
|
1267 */ |
|
1268 { |
|
1269 TInt hintBitField = 0; |
|
1270 if (iExtension) |
|
1271 { |
|
1272 hintBitField = iExtension->HintBitField(); |
|
1273 } |
|
1274 // |
|
1275 return HintFieldMatchesFilter(hintBitField, aFilter); |
|
1276 } |
|
1277 |
|
1278 EXPORT_C TInt CViewContact::FieldCount() const |
|
1279 /** Gets the number of fields in the contact view item. |
|
1280 |
|
1281 @return The number of fields in the item. */ |
|
1282 { |
|
1283 return iTextIndexes.Count(); |
|
1284 } |
|
1285 |
|
1286 EXPORT_C TPtrC CViewContact::Field(TInt aPosition) const |
|
1287 /** Gets a pointer descriptor to the contents of the single field located |
|
1288 at the specified field index. |
|
1289 |
|
1290 @param aPosition A field index. |
|
1291 @return The contents of the field located at the specified field index. |
|
1292 @panic CNTMODEL 27 In debug builds, this indicates that aPosition is invalid. |
|
1293 It must be less than the number of fields in the item. */ |
|
1294 { |
|
1295 __ASSERT_DEBUG(aPosition >= 0 && aPosition < FieldCount(),Panic(ECntPanicInvalidViewIndex)); |
|
1296 // |
|
1297 if (!iExtension) |
|
1298 { |
|
1299 // Have to resort to default value if there is no extension |
|
1300 // since we cannot obtain the field text without it. |
|
1301 return TPtrC(KNullDesC); |
|
1302 } |
|
1303 // |
|
1304 const TPtrC pFullFieldText(iExtension->FieldText()); |
|
1305 const TInt fieldStartPos = iTextIndexes[aPosition]; |
|
1306 TInt lengthOfText=0; |
|
1307 TPtrC fieldPtr; |
|
1308 if(aPosition<FieldCount()-1) |
|
1309 { |
|
1310 //work out the length of the buffer. |
|
1311 TInt nextFieldPos = iTextIndexes[aPosition+1]; |
|
1312 lengthOfText=nextFieldPos-fieldStartPos; |
|
1313 fieldPtr.Set(pFullFieldText.Mid(fieldStartPos,lengthOfText)); |
|
1314 } |
|
1315 else |
|
1316 { |
|
1317 //this is the last field. |
|
1318 fieldPtr.Set(pFullFieldText.Mid(fieldStartPos)); |
|
1319 } |
|
1320 return fieldPtr; |
|
1321 } |
|
1322 |
|
1323 /* |
|
1324 * Adds a new field to the CViewContact. |
|
1325 * Fields are stored in one HBufC. Each field can be accessed using the |
|
1326 * indexes stored in the iTextIndexes member. |
|
1327 * @param aField Field data |
|
1328 */ |
|
1329 EXPORT_C void CViewContact::AddFieldL(const TDesC& aField) |
|
1330 { |
|
1331 if(!iExtension) |
|
1332 { |
|
1333 iExtension = CViewContactExtension::NewL(); |
|
1334 } |
|
1335 |
|
1336 const TInt insertionPosition = iExtension->FieldText().Length(); |
|
1337 if (aField.Length()) |
|
1338 { |
|
1339 iExtension->AppendToFieldTextL(aField); |
|
1340 } |
|
1341 iTextIndexes.AppendL(insertionPosition); |
|
1342 |
|
1343 #ifdef _DEBUG |
|
1344 // Ensure the field added to single hbuf & index is identical to aField when retrieved. |
|
1345 TPtrC addedField= Field(FieldCount()-1); |
|
1346 TInt comp=addedField.Compare(aField); |
|
1347 __ASSERT_DEBUG(comp==0,Panic(ECntPanicInvalidFieldText)); |
|
1348 #endif |
|
1349 } |
|
1350 |
|
1351 |
|
1352 /** |
|
1353 Set the first field text for the CViewContact. |
|
1354 Fields are stored in one HBufC. Each field can be accessed using the |
|
1355 indexes stored in the iTextIndexes member. |
|
1356 |
|
1357 @param aField Field data |
|
1358 @internalTechnology |
|
1359 */ |
|
1360 EXPORT_C void CViewContact::SetFirstFieldForBlankContactL(const TDesC& aFirstField) |
|
1361 { |
|
1362 if(!iExtension) |
|
1363 { |
|
1364 iExtension = CViewContactExtension::NewL(); |
|
1365 } |
|
1366 |
|
1367 // shouldn't be any existing text |
|
1368 __ASSERT_DEBUG(iExtension->FieldText().Length()==0,Panic(ECntPanicFieldTextNotBlank)); |
|
1369 |
|
1370 iExtension->AppendToFieldTextL(aFirstField); |
|
1371 |
|
1372 const TInt length = aFirstField.Length(); |
|
1373 const TInt count = iTextIndexes.Count(); |
|
1374 if (count) |
|
1375 { |
|
1376 for (TInt j = 1; j < count; ++j) |
|
1377 { |
|
1378 iTextIndexes[j] = length; |
|
1379 } |
|
1380 } |
|
1381 else |
|
1382 { |
|
1383 iTextIndexes.AppendL(0); |
|
1384 } |
|
1385 |
|
1386 #ifdef _DEBUG |
|
1387 // Ensure the field added to single hbuf & index is identical to aField when retrieved. |
|
1388 TPtrC addedField= Field(0); |
|
1389 TInt comp=addedField.Compare(aFirstField); |
|
1390 __ASSERT_DEBUG(comp==0,Panic(ECntPanicInvalidFieldText)); |
|
1391 #endif |
|
1392 } |
|
1393 |
|
1394 |
|
1395 |
|
1396 /** |
|
1397 Used for creating a view. |
|
1398 Allows to re-use the same contact object what reduces the number of memory re-allocations. |
|
1399 Resets the indexes array and contact buffer. The buffer MaxLength stays the same. |
|
1400 @internalTechnology |
|
1401 */ |
|
1402 EXPORT_C void CViewContact::Reset() |
|
1403 { |
|
1404 SetId(KNullContactId); |
|
1405 SetContactType(EContactItem); |
|
1406 SetContactTypeUid(KNullUid); |
|
1407 iTextIndexes.Reset(); |
|
1408 if(iExtension) |
|
1409 { |
|
1410 iExtension->SetLengthZero(); |
|
1411 } |
|
1412 } |
|
1413 |
|
1414 |
|
1415 |
|
1416 /** |
|
1417 * Compares a given hint field with any given filter. |
|
1418 * static function. Used to support member function ContactMatchesFilter |
|
1419 * and exported function ContactMatchesHintFieldL, from CContactDatabase. |
|
1420 * |
|
1421 * @param aHintField the hint bit flag field |
|
1422 * @param aFilter the filter to compare against |
|
1423 */ |
|
1424 TBool CViewContact::HintFieldMatchesFilter(TInt aHintField, TInt aFilter) |
|
1425 { |
|
1426 TBool match=EFalse; |
|
1427 |
|
1428 if (aFilter==CContactDatabase::EUnfiltered) |
|
1429 { |
|
1430 return ETrue; |
|
1431 } |
|
1432 |
|
1433 if (aFilter & ~aHintField & (CContactDatabase::EWork | CContactDatabase::EHome)) |
|
1434 { |
|
1435 return EFalse; |
|
1436 } |
|
1437 |
|
1438 match = aFilter & aHintField |
|
1439 & ( |
|
1440 CContactDatabase::ELandLine |
|
1441 | CContactDatabase::ESmsable |
|
1442 | CContactDatabase::EMailable |
|
1443 | CContactDatabase::EFaxable |
|
1444 | CContactDatabase::EPhonable |
|
1445 | CContactDatabase::ERingTone |
|
1446 | CContactDatabase::EVoiceDial |
|
1447 | CContactDatabase::EIMAddress |
|
1448 | CContactDatabase::EWirelessVillage |
|
1449 | CContactDatabase::ECustomFilter1 |
|
1450 | CContactDatabase::ECustomFilter2 |
|
1451 | CContactDatabase::ECustomFilter3 |
|
1452 | CContactDatabase::ECustomFilter4 |
|
1453 ); |
|
1454 |
|
1455 return match; |
|
1456 } |
|
1457 |
|
1458 /** |
|
1459 Get this contact's hint field value |
|
1460 @return The contact hint value |
|
1461 @internalTechnology |
|
1462 */ |
|
1463 EXPORT_C TInt CViewContact::ContactHint() const |
|
1464 { |
|
1465 TInt hint = 0; |
|
1466 if (iExtension) |
|
1467 { |
|
1468 hint = iExtension->HintBitField(); |
|
1469 } |
|
1470 return hint; |
|
1471 } |
|
1472 |
|
1473 /** |
|
1474 Set this contact's hint field value |
|
1475 |
|
1476 @param aHint The new contact hint value |
|
1477 @internalTechnology |
|
1478 */ |
|
1479 EXPORT_C void CViewContact::SetContactHint(TInt aHint) |
|
1480 { |
|
1481 if(iExtension) |
|
1482 { |
|
1483 iExtension->HintBitField() = aHint; |
|
1484 } |
|
1485 } |
|
1486 |
|
1487 |
|
1488 /** |
|
1489 Test if contact is 'Sortable' |
|
1490 @internalTechnology |
|
1491 */ |
|
1492 EXPORT_C TBool CViewContact::IsSortable() const |
|
1493 { |
|
1494 // If total field text length > 0 then contact is sortable |
|
1495 if (iExtension && iExtension->FieldText().Length()) |
|
1496 { |
|
1497 return ETrue; |
|
1498 } |
|
1499 |
|
1500 return EFalse; |
|
1501 } |
|
1502 |
|
1503 /** |
|
1504 Change the view contact object to lightweight object to save memory. |
|
1505 It actually just delete the instance of CViewContactExtension. |
|
1506 |
|
1507 @internalTechnology |
|
1508 */ |
|
1509 EXPORT_C void CViewContact::ChangeToLightweightObject() |
|
1510 { |
|
1511 iTextIndexes.Reset(); |
|
1512 delete iExtension; |
|
1513 iExtension = NULL; |
|
1514 } |
|
1515 |
|
1516 |
|
1517 /** |
|
1518 Check if the view contact object is a lightweight object. |
|
1519 |
|
1520 @internalComponent |
|
1521 */ |
|
1522 TBool CViewContact::IsLightweightObject() const |
|
1523 { |
|
1524 return (iExtension == NULL); |
|
1525 } |
|
1526 |
|
1527 |
|
1528 /** |
|
1529 Copy the given view contact object to this instance. |
|
1530 |
|
1531 @param aContact the view contact to be copied. |
|
1532 @leave KErrNoMemory |
|
1533 @internalComponent |
|
1534 */ |
|
1535 void CViewContact::CopyL(const CViewContact& aContact) |
|
1536 { |
|
1537 iTextIndexes.Reset(); |
|
1538 if(!iExtension) |
|
1539 { |
|
1540 iExtension = CViewContactExtension::NewL(); |
|
1541 } |
|
1542 |
|
1543 iContactType = aContact.iContactType; |
|
1544 SetContactTypeUid( aContact.ContactTypeUid() ); |
|
1545 iExtension->HintBitField() = aContact.iExtension->HintBitField(); |
|
1546 HBufC* fieldText = aContact.iExtension->FieldText().AllocL(); |
|
1547 iExtension->SetFieldText(fieldText); |
|
1548 // |
|
1549 const TInt indxCount= aContact.iTextIndexes.Count(); |
|
1550 TInt textPos=0; |
|
1551 for(TInt ii=0;ii<indxCount;++ii) |
|
1552 { |
|
1553 textPos = aContact.iTextIndexes[ii]; |
|
1554 iTextIndexes.AppendL(textPos); |
|
1555 } |
|
1556 } |
|
1557 |
|
1558 |
|
1559 /** Used for view sorting and insersion. In order to give a stable result |
|
1560 if contact details match, it falls back to comparing contact IDs. |
|
1561 If a contact view sort plugin is loaded it uses its SortCompareViewContactsL() method. |
|
1562 |
|
1563 @internalAll */ |
|
1564 EXPORT_C TInt CContactViewBase::CompareContactsAndIdsL(const CViewContact& aFirst, const CViewContact& aSecond) const |
|
1565 { |
|
1566 TInt result = 0; |
|
1567 |
|
1568 // Profiler |
|
1569 #ifdef __PROFILE_SORT__ |
|
1570 RDebug::ProfileStart(3); |
|
1571 #endif |
|
1572 |
|
1573 CViewContactSortPlugin* sortPluginImpl = iExtension->iSortPluginImpl; |
|
1574 if (sortPluginImpl) |
|
1575 { |
|
1576 // use View Sort plugin |
|
1577 result = sortPluginImpl->SortCompareViewContactsL(aFirst,aSecond); |
|
1578 } |
|
1579 else |
|
1580 { |
|
1581 // no View sort plugin loaded |
|
1582 result = TextCompareFieldsL(aFirst, aSecond); |
|
1583 } |
|
1584 |
|
1585 if (result == 0) |
|
1586 { |
|
1587 result = aFirst.Id() - aSecond.Id(); |
|
1588 } |
|
1589 |
|
1590 // Profiler |
|
1591 #ifdef __PROFILE_SORT__ |
|
1592 RDebug::ProfileEnd(3); |
|
1593 #endif |
|
1594 |
|
1595 return result; |
|
1596 } |
|
1597 |
|
1598 |
|
1599 /** @internalAll */ |
|
1600 EXPORT_C TInt CContactViewBase::CompareContactIds(const CViewContact& aFirst, const CViewContact& aSecond) |
|
1601 { |
|
1602 return aFirst.Id() - aSecond.Id(); |
|
1603 } |
|
1604 |
|
1605 |
|
1606 /** Asks the contact if it is sortable. |
|
1607 'static' function used by Sort Plugin. |
|
1608 |
|
1609 @internalAll */ |
|
1610 EXPORT_C TBool CContactViewBase::ContactIsSortable(const CViewContact& aContact) |
|
1611 { |
|
1612 return aContact.IsSortable(); |
|
1613 } |
|
1614 |
|
1615 |
|
1616 /** @internalAll */ |
|
1617 EXPORT_C TUid CContactViewBase::GetViewSortPluginImplUid() const |
|
1618 { |
|
1619 return iExtension->iSortPluginUid; |
|
1620 } |
|
1621 |
|
1622 |
|
1623 /** @internalComponent */ |
|
1624 TUid CContactViewBase::FindSortPluginImplL (const TDesC8& aSortPluginName,TBool aWildCard) const |
|
1625 { |
|
1626 TUid result = KNullUid; |
|
1627 |
|
1628 TEComResolverParams resolverParams; |
|
1629 RImplInfoPtrArray implInfoArray; |
|
1630 |
|
1631 CleanupResetAndDestroyPushL(implInfoArray); |
|
1632 |
|
1633 resolverParams.SetDataType(aSortPluginName); |
|
1634 resolverParams.SetWildcardMatch(aWildCard); |
|
1635 |
|
1636 // look for ECOM implementations, only in ROM |
|
1637 REComSession::ListImplementationsL(KCntSortPluginInterfaceUid, resolverParams, |
|
1638 KRomOnlyResolverUid, implInfoArray); |
|
1639 |
|
1640 if (implInfoArray.Count() == 1) |
|
1641 { |
|
1642 result = implInfoArray[0]->ImplementationUid(); |
|
1643 } |
|
1644 |
|
1645 CleanupStack::PopAndDestroy(&implInfoArray); |
|
1646 return result; |
|
1647 } |
|
1648 |
|
1649 |
|
1650 /** @internalComponent */ |
|
1651 void CContactViewBase::LoadViewSortPluginL (TUid aSortPluginUid, TContactViewPreferences& aViewPreferences) |
|
1652 { |
|
1653 if (aSortPluginUid == KNullUid) |
|
1654 { |
|
1655 User::Leave(KErrNotFound); |
|
1656 } |
|
1657 |
|
1658 // Parameter block for View |
|
1659 TSortPluginViewParamsRev1 pluginViewParams(aViewPreferences, CompareFieldsL, ContactIsSortable); |
|
1660 // General parameter block to load plug-in |
|
1661 TSortPluginParams pluginParams(KCntSortPluginInterfaceUid, aSortPluginUid, &pluginViewParams); |
|
1662 |
|
1663 iExtension->iSortPluginImpl = CViewContactSortPlugin::NewL(&pluginParams); |
|
1664 iExtension->iSortPluginUid = aSortPluginUid; |
|
1665 } |
|
1666 |
|
1667 |
|
1668 /** @internalComponent */ |
|
1669 TUid CContactViewBase::FindDefaultViewSortPluginImplL () const |
|
1670 { |
|
1671 // _LIT8(KTestDefaultPluginName, "contacts.vnd.symbian.com/reverse sort"); |
|
1672 return FindSortPluginImplL (KViewSortPluginDefaultName /* KTestDefaultPluginName */ ,ETrue); |
|
1673 } |
|
1674 |
|
1675 /** This function determines whether a contact should be added to the normal |
|
1676 sorted array (iContacts) or put into the alternative iUnSortedContacts array. |
|
1677 Depending on the view preferences, these "unsorted" contacts are either |
|
1678 ignored (deleted), or added to the beginning or end of the iContacts |
|
1679 sorted list by At(), Find() etc... methods. |
|
1680 |
|
1681 @internalComponent */ |
|
1682 TBool CContactViewBase::IsContactSortable(const CViewContact& aContact, TContactViewPreferences& aViewPreferences) const |
|
1683 { |
|
1684 TBool sortableContact=EFalse; |
|
1685 |
|
1686 // only test contact if it matters |
|
1687 if(aViewPreferences & (EIgnoreUnSorted | EUnSortedAtBeginning | EUnSortedAtEnd)) //Distinguish Unsorted |
|
1688 { |
|
1689 CViewContactSortPlugin* sortPluginImpl = iExtension->iSortPluginImpl; |
|
1690 if (sortPluginImpl) |
|
1691 { |
|
1692 // use plugin |
|
1693 sortableContact = sortPluginImpl->ViewContactIsSortable(aContact); |
|
1694 } |
|
1695 else |
|
1696 { |
|
1697 // ask contact itself |
|
1698 sortableContact = aContact.IsSortable(); |
|
1699 } |
|
1700 } |
|
1701 else |
|
1702 { |
|
1703 // Sortable |
|
1704 sortableContact = ETrue; |
|
1705 } |
|
1706 |
|
1707 return sortableContact; |
|
1708 } |
|
1709 |
|
1710 /** @internalComponent */ |
|
1711 CViewContactSortPlugin* CContactViewBase::SortPluginImpl() const |
|
1712 { |
|
1713 return iExtension->iSortPluginImpl; |
|
1714 } |
|
1715 |
|
1716 |
|
1717 /** Does a binary search of the contacts array, and inserts a new contact. |
|
1718 Uses the current sort plugin, if any. |
|
1719 |
|
1720 @internalComponent */ |
|
1721 TInt CContactViewBase::InsertContactInView(RPointerArray<CViewContact>& aContacts, const CViewContact* aNewContact, TBool aSortByIdOnly, TInt* aIndex) const |
|
1722 { |
|
1723 CViewContactSortPlugin* sortPluginImpl = SortPluginImpl(); |
|
1724 |
|
1725 TInt error = KErrNone; |
|
1726 |
|
1727 TInt maxPos = aContacts.Count() - 1; |
|
1728 TInt minPos = 0; |
|
1729 TInt position = 0; |
|
1730 |
|
1731 if (maxPos >= 0) |
|
1732 { |
|
1733 // at least one compare required |
|
1734 if (sortPluginImpl) |
|
1735 { |
|
1736 error = sortPluginImpl->SortStart(CViewContactSortPlugin::ESortStartInsertOne, 1); |
|
1737 if (error) |
|
1738 { |
|
1739 return error; |
|
1740 } |
|
1741 } |
|
1742 |
|
1743 |
|
1744 position = (minPos + maxPos + 1) / 2; |
|
1745 |
|
1746 while (maxPos >= minPos) |
|
1747 { |
|
1748 TInt diff = 0; |
|
1749 |
|
1750 if (aSortByIdOnly) |
|
1751 { |
|
1752 diff = CompareContactIds(*aNewContact, *aContacts[position]); |
|
1753 } |
|
1754 else |
|
1755 { |
|
1756 TRAP(error,diff = CompareContactsAndIdsL(*aNewContact, *aContacts[position])); |
|
1757 if (error) |
|
1758 { |
|
1759 return error; |
|
1760 } |
|
1761 } |
|
1762 |
|
1763 if (diff == 0) |
|
1764 { |
|
1765 // duplicate Id |
|
1766 error = KErrAlreadyExists; |
|
1767 break; |
|
1768 } |
|
1769 |
|
1770 if (diff < 0) |
|
1771 { |
|
1772 maxPos = position - 1; |
|
1773 } |
|
1774 else // diff > 0 |
|
1775 { |
|
1776 minPos = position + 1; |
|
1777 } |
|
1778 |
|
1779 position = (minPos + maxPos + 1) / 2; |
|
1780 } |
|
1781 |
|
1782 // all compares done |
|
1783 if (sortPluginImpl) |
|
1784 { |
|
1785 sortPluginImpl->SortCompleted(); |
|
1786 } |
|
1787 } |
|
1788 |
|
1789 |
|
1790 if (error == KErrNone) |
|
1791 { |
|
1792 error = aContacts.Insert(aNewContact, position); |
|
1793 } |
|
1794 |
|
1795 if (aIndex) |
|
1796 { |
|
1797 // index of new item for caller |
|
1798 *aIndex = position; |
|
1799 } |
|
1800 return error; |
|
1801 } |
|
1802 |
|
1803 TInt CContactViewBase::GetErrorValueFromExtensionClass() |
|
1804 { |
|
1805 return iExtension->iError; |
|
1806 } |
|
1807 |