phonebookengines_old/contactsmodel/cntview/ViewBase.cpp
branchRCL_3
changeset 62 5b6f26637ad3
equal deleted inserted replaced
58:d4f567ce2e7c 62:5b6f26637ad3
       
     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