pimprotocols/pbap/server/pbapcontactdbviews.cpp
changeset 0 e686773b3f54
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "pbapcontactdbviews.h"
       
    17 #include <cntfldst.h>
       
    18 #include <cntitem.h>
       
    19 #include <cntfield.h>
       
    20 #include "pbapserver.h"
       
    21 #include "btaccesshostlog.h"
       
    22 
       
    23 _LIT(KNameFieldSeparator, ";");
       
    24 
       
    25 	
       
    26 
       
    27 /*static*/ CPbapContactDbViews* CPbapContactDbViews::NewL(CContactDatabase& aDatabase)
       
    28 	{
       
    29 	LOG_STATIC_FUNC
       
    30 	CPbapContactDbViews* self=new(ELeave) CPbapContactDbViews(aDatabase);
       
    31 	return self;
       
    32 	}
       
    33 
       
    34 
       
    35 CPbapContactDbViews::CPbapContactDbViews(CContactDatabase& aDatabase)
       
    36 	: iDatabase(aDatabase)
       
    37 	{
       
    38 	LOG_FUNC
       
    39 	}
       
    40 
       
    41 
       
    42 CPbapContactDbViews::~CPbapContactDbViews()
       
    43 	{
       
    44 	LOG_FUNC
       
    45 	CloseAllViews();
       
    46 	}	
       
    47 
       
    48 
       
    49 /**
       
    50 Close all currently open views and abort current asynchronous search and sort request. 
       
    51 This function should be called when the PBAP session ends (gracefully or otherwise)
       
    52 to save memory while there is no PBAP session open
       
    53 */
       
    54 void CPbapContactDbViews::CloseAllViews()
       
    55 	{
       
    56 	LOG_FUNC
       
    57 	
       
    58 	CancelAndCleanup();
       
    59 	if (iNameView)
       
    60 		{
       
    61 		iNameView->Close(*this);
       
    62 		iNameView=NULL;
       
    63 		}
       
    64 	if (iPhoneticView)
       
    65 		{
       
    66 		iPhoneticView->Close(*this);
       
    67 		iPhoneticView=NULL;
       
    68 		}
       
    69 	iNameViewReady = EFalse;
       
    70 	iPhoneticViewReady = EFalse;	
       
    71 	}
       
    72 	
       
    73 /**
       
    74 Get contact name string with fields separated by a semi-colon. The fields are read from the name
       
    75 view when it is ready, otherwise they are read from the database
       
    76 */
       
    77 HBufC* CPbapContactDbViews::GetContactNameFromIdL(TContactItemId aContactId) const
       
    78 	{
       
    79 	LOG_FUNC
       
    80 
       
    81 	HBufC* name=NULL;
       
    82 	
       
    83 	// check to see if the view of the underlying database is ready, i.e. HandleContactViewEvent
       
    84 	// has been called back after we created iNameView
       
    85 	if (iNameViewReady)
       
    86 		{
       
    87 		// find the contact id in the name view
       
    88 		TInt index=iNameView->FindL(aContactId);
       
    89 		User::LeaveIfError(index); //leave with KErrNotFound if contact id not found
       
    90 
       
    91 		// read concatenated name from name view
       
    92 		name=iNameView->AllFieldsLC(index, KNameFieldSeparator);
       
    93 		}
       
    94 	else
       
    95 		{
       
    96 		// create buffer large enough to contain name fields with separators
       
    97 		// NB We can't use the 'separator' functionality of 
       
    98 		// TContactTextDefItem because the separator is elided when there is 
       
    99 		// no text in the field following, which isn't what we want.
       
   100 		name=HBufC::NewLC(5*KCntMaxTextFieldLength+4);
       
   101 
       
   102 		CContactItem* item = iDatabase.ReadMinimalContactLC(aContactId);
       
   103 		const CContactItemFieldSet& fieldSet = item->CardFields();
       
   104 
       
   105 		AppendField(name, KUidContactFieldFamilyName, fieldSet);
       
   106 		AppendField(name, KUidContactFieldGivenName, fieldSet);
       
   107 		AppendField(name, KUidContactFieldAdditionalName, fieldSet);
       
   108 		AppendField(name, KUidContactFieldPrefixName, fieldSet);
       
   109 		AppendField(name, KUidContactFieldSuffixName, fieldSet, ETrue); // ETrue- last field: don't add ;
       
   110 
       
   111 		CleanupStack::PopAndDestroy(item);
       
   112 		}
       
   113 	CleanupStack::Pop(name); //ownership passed
       
   114 	return name;
       
   115 	}
       
   116 
       
   117 // Append the field aUid from field set aFieldSet to aBuf. 
       
   118 // Also append KNameFieldSeparator to that, unless aLast.
       
   119 void CPbapContactDbViews::AppendField(HBufC* aBuf, TUid aUid, const CContactItemFieldSet& aFieldSet, TBool aLast) const
       
   120 	{
       
   121 	LOG_FUNC
       
   122 	TPtr ptr(aBuf->Des());
       
   123 	const TInt index = aFieldSet.Find(aUid);
       
   124 	if ( index != KErrNotFound )
       
   125 		{
       
   126 		ptr.Append(aFieldSet[index].TextStorage()->Text());
       
   127 		}
       
   128 	if ( !aLast )
       
   129 		{
       
   130 		ptr.Append(KNameFieldSeparator);
       
   131 		}
       
   132 	}
       
   133 
       
   134 /**
       
   135 Finds contacts matching search parameters and returns the ids sorted in the requested order
       
   136 */		
       
   137 void CPbapContactDbViews::GetContactIdsMatchingCriteriaL(SymbianPBAP::TOrder aOrder, SymbianPBAP::TSearchAttribute aSearchAttribute,
       
   138 						const TDesC& aSearchValue, CContactIdArray& aResults, MPbapContactDbViewsCallback& aCallback)
       
   139 	{
       
   140 	LOG_FUNC
       
   141 	
       
   142 	// the only supported sort orders are alphabetical and phonetical
       
   143 	if (aOrder != SymbianPBAP::EAlphabetical && aOrder != SymbianPBAP::EPhonetical)
       
   144 		{
       
   145 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicInvalidViewSortOrder));
       
   146 		// leave if sort order not supported
       
   147 		User::Leave(KErrNotSupported);
       
   148 		}
       
   149 		
       
   150 	// store callback and results array
       
   151 	iCallback = &aCallback;
       
   152 	iResults = &aResults;
       
   153 
       
   154 	// abort previous request and cleanup
       
   155 	CancelAndCleanup();
       
   156 	
       
   157 	// store sort and search parameters
       
   158 	iOrder = aOrder;
       
   159 	iSearchAttribute = aSearchAttribute;
       
   160 	iSearchValue = aSearchValue.AllocL();
       
   161 	
       
   162 	if (!iNameView)
       
   163 		{
       
   164 		// first request so create name view now
       
   165 		CreateNameViewL();
       
   166 		}
       
   167 		
       
   168 	if (!iPhoneticView && IsPhoneticViewRequired())
       
   169 		{
       
   170 		// phonetic search or sort required so create phonetic name view
       
   171 		CreatePhoneticViewL();
       
   172 		}
       
   173 	
       
   174 	iOpState = EPendingSearch;
       
   175 	if (iNameViewReady && (iPhoneticViewReady || !IsPhoneticViewRequired()))
       
   176  		{
       
   177 		// views are ready (or not required depending on sort order) so start search and sort now
       
   178 		TCallBack callback(SearchAndSortCallback,this);
       
   179 		iAsyncCallback = new(ELeave) CAsyncCallBack(callback, CActive::EPriorityStandard);
       
   180 		iAsyncCallback->CallBack();
       
   181 		}
       
   182 	}
       
   183 
       
   184 
       
   185 void CPbapContactDbViews::CancelSearchAndSortRequest()
       
   186 	{
       
   187 	LOG_FUNC
       
   188 	CancelAndCleanup();
       
   189 	iCallback=NULL;
       
   190 	}
       
   191 	
       
   192 	
       
   193 void CPbapContactDbViews::CreateNameViewL()
       
   194 	{
       
   195 	LOG_FUNC
       
   196 	// check name view does not already exist
       
   197 	if(iNameView)
       
   198 		{
       
   199 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNameViewExists));
       
   200 		User::Leave(KErrAlreadyExists);
       
   201 		}
       
   202 
       
   203 	RContactViewSortOrder viewSortOrder;
       
   204    	CleanupClosePushL(viewSortOrder);
       
   205    	viewSortOrder.AppendL(KUidContactFieldFamilyName);
       
   206    	viewSortOrder.AppendL(KUidContactFieldGivenName);
       
   207    	viewSortOrder.AppendL(KUidContactFieldAdditionalName);
       
   208    	viewSortOrder.AppendL(KUidContactFieldPrefixName);
       
   209    	viewSortOrder.AppendL(KUidContactFieldSuffixName);
       
   210 
       
   211 	const TContactViewPreferences prefs = static_cast<TContactViewPreferences>(EContactsOnly | EUnSortedAtEnd);
       
   212     iNameView = CContactLocalView::NewL(*this, iDatabase, viewSortOrder, prefs);
       
   213     CleanupStack::PopAndDestroy();  // viewSortOrder
       
   214 	}
       
   215 
       
   216 
       
   217 void CPbapContactDbViews::CreatePhoneticViewL()
       
   218 	{
       
   219 	LOG_FUNC
       
   220 	// check phonetic view does not already exist
       
   221 	if(iPhoneticView)
       
   222 		{
       
   223 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicPhoneticViewExists));
       
   224 		User::Leave(KErrAlreadyExists);
       
   225 		}
       
   226 
       
   227 	RContactViewSortOrder viewSortOrder;
       
   228    	CleanupClosePushL(viewSortOrder);
       
   229    	viewSortOrder.AppendL(KUidContactFieldFamilyNamePronunciation);
       
   230    	viewSortOrder.AppendL(KUidContactFieldGivenNamePronunciation);
       
   231 
       
   232 	const TContactViewPreferences prefs = static_cast<TContactViewPreferences>(EContactsOnly | EUnSortedAtEnd);
       
   233     iPhoneticView = CContactLocalView::NewL(*this, iDatabase, viewSortOrder, prefs);
       
   234     CleanupStack::PopAndDestroy();  // viewSortOrder
       
   235 	}
       
   236 	
       
   237 	
       
   238 TBool CPbapContactDbViews::IsPhoneticViewRequired() const
       
   239 	{
       
   240 	LOG_FUNC
       
   241 	return (iOrder==SymbianPBAP::EPhonetical || iSearchAttribute==SymbianPBAP::ESound);
       
   242 	}
       
   243 
       
   244 
       
   245 /*static*/ TInt CPbapContactDbViews::SearchAndSortCallback(TAny* aAny)
       
   246 	{
       
   247 	LOG_STATIC_FUNC
       
   248 	CPbapContactDbViews* self = static_cast<CPbapContactDbViews*>(aAny);
       
   249 	self->DoSearchAndSortCallback();
       
   250 	return KErrNone;	
       
   251 	}
       
   252 
       
   253 void CPbapContactDbViews::DoSearchAndSortCallback()
       
   254 	{
       
   255 	LOG_FUNC
       
   256 	if (iOpState == EPendingSearch)
       
   257 		{
       
   258 		iOpState = ESearching;
       
   259 		TRAPD(error, DoSearchAndSortL());
       
   260 		if (error != KErrNone)
       
   261 			{
       
   262 			LOG1(_L("Error %d from DoSearchAndSortL"), error);
       
   263 			// NotifySearchAndSortComplete will also cancel and cleanup search
       
   264 			NotifySearchAndSortComplete(error);
       
   265 			}
       
   266 		}	
       
   267 	}
       
   268 
       
   269 
       
   270 void CPbapContactDbViews::DoSearchAndSortL()
       
   271 	{
       
   272 	LOG_FUNC
       
   273 	if (!iSearchValue->Length())
       
   274 		{
       
   275 		// no search value so just sort
       
   276 		DoSortL();
       
   277 		}
       
   278 	else
       
   279 		{
       
   280 		if (iSearchAttribute==SymbianPBAP::ENumber)
       
   281 			{
       
   282 			FindInPhoneFieldsL();
       
   283 			}
       
   284 		else if (iSearchAttribute==SymbianPBAP::EName)
       
   285 			{
       
   286 			FindInViewL(*iNameView);
       
   287 			}
       
   288 		else if (iSearchAttribute==SymbianPBAP::ESound)
       
   289 			{
       
   290 			FindInViewL(*iPhoneticView);
       
   291 			}
       
   292 		}
       
   293 	}
       
   294 	
       
   295 	
       
   296 void CPbapContactDbViews::FindInViewL(CContactViewBase& aView)
       
   297 	{
       
   298 	LOG_FUNC
       
   299 	// check search values in correct state
       
   300 	if(iSearchValueArray || iFindView)
       
   301 		{
       
   302 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicInvalidViewSearchState));
       
   303 		User::Leave(KErrAlreadyExists);
       
   304 		}
       
   305 
       
   306 	iSearchValueArray = new(ELeave) CPtrCArray(1);
       
   307 	iSearchValueArray->AppendL(*iSearchValue);
       
   308 
       
   309 	// start asynchronous search of view
       
   310 	iFindView = CContactFindView::NewL(iDatabase, aView, *this, iSearchValueArray, CContactViewBase::EPrefixSearch);
       
   311 	}
       
   312 
       
   313 
       
   314 void CPbapContactDbViews::FindInPhoneFieldsL()
       
   315 	{
       
   316 	LOG_FUNC
       
   317 	// check search values in correct state
       
   318 	if(iFindFieldDef || iIdleFinder)
       
   319 		{
       
   320 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicInvalidFieldSearchState));
       
   321 		User::Leave(KErrAlreadyExists);
       
   322 		}
       
   323 
       
   324 	iFindFieldDef = new(ELeave) CContactItemFieldDef;
       
   325 	iFindFieldDef->AppendL(KUidContactFieldPhoneNumber);
       
   326 
       
   327 	// start an asynchronous search of phone fields in database
       
   328 	iIdleFinder = iDatabase.FindAsyncL(*iSearchValue, iFindFieldDef, this);
       
   329 	}
       
   330 
       
   331 
       
   332 void CPbapContactDbViews::IdleFindCallback()
       
   333 	{
       
   334 	LOG_FUNC
       
   335 	TInt idleFindError = iIdleFinder->Error();
       
   336 	if(idleFindError == KErrNone)
       
   337 		{
       
   338 		// this callback will be called for every 16 items searched to allow users to update their search
       
   339 		// status but we are only concerned when the entire search has completed
       
   340 		if(iIdleFinder->IsComplete())
       
   341 			{
       
   342 			// find completed successfully
       
   343 			iOpState = ESorting;
       
   344 			
       
   345 			TRAPD(error, HandleIdleFindCompleteL());
       
   346 			if (error != KErrNone)
       
   347 				{
       
   348 				LOG1(_L("Error %d from HandleIdleFindCompleteL"), error);
       
   349 				// NotifySearchAndSortComplete will also cancel and cleanup search
       
   350 				NotifySearchAndSortComplete(error);
       
   351 				}	
       
   352 			}
       
   353 		}
       
   354 	else
       
   355 		{
       
   356 		LOG1(_L("Idle finder error %d"), idleFindError);
       
   357 		// error occurred during find notify the observer (and abort find)	
       
   358 		NotifySearchAndSortComplete(idleFindError);
       
   359 		}
       
   360 	}
       
   361 
       
   362 
       
   363 void CPbapContactDbViews::HandleIdleFindCompleteL()
       
   364 	{
       
   365 	LOG_FUNC
       
   366 	CContactIdArray* contactIds=iIdleFinder->TakeContactIds();
       
   367 	LOG1(_L("Idle finder returned %d contacts"), contactIds->Count());
       
   368 	CleanupStack::PushL(contactIds);
       
   369 	DoSortSearchResultsL(*contactIds);
       
   370 	CleanupStack::PopAndDestroy(contactIds);	
       
   371 	}
       
   372 
       
   373 
       
   374 void CPbapContactDbViews::HandleFindInViewCompleteL()
       
   375 	{
       
   376 	LOG_FUNC
       
   377 	CContactIdArray* contactIds = GetContactIdsInViewL(*iFindView);
       
   378 	LOG1(_L("Find view contains %d contacts"), contactIds->Count());
       
   379 	CleanupStack::PushL(contactIds);
       
   380 	DoSortSearchResultsL(*contactIds);
       
   381 	CleanupStack::PopAndDestroy(contactIds);
       
   382 	}
       
   383 
       
   384 
       
   385 void CPbapContactDbViews::DoSortL()
       
   386 	{
       
   387 	LOG_FUNC
       
   388 	// get all the ids from the view
       
   389 	CContactIdArray* contactIds=NULL;
       
   390 	switch (iOrder)
       
   391 		{
       
   392 		case SymbianPBAP::EAlphabetical:
       
   393 			contactIds = GetContactIdsInViewL(*iNameView);
       
   394 			break;
       
   395 		case SymbianPBAP::EPhonetical:
       
   396 			contactIds = GetContactIdsInViewL(*iPhoneticView);
       
   397 			break;
       
   398 		default:
       
   399 			Panic(EPbapServerPanicInvalidViewSortOrder);
       
   400 		}
       
   401 
       
   402 	if (contactIds)
       
   403 		{
       
   404 		CleanupStack::PushL(contactIds);
       
   405 		CopyToResultsArrayL(*contactIds);
       
   406 		CleanupStack::PopAndDestroy(contactIds);
       
   407 		}
       
   408 
       
   409 	// the search and sort request is complete notify the observer
       
   410 	NotifySearchAndSortComplete(KErrNone);
       
   411 	}
       
   412 
       
   413 
       
   414 CContactIdArray* CPbapContactDbViews::GetContactIdsInViewL(CContactViewBase &aView)
       
   415 	{
       
   416 	LOG_FUNC
       
   417 	CContactIdArray* contactIds = CContactIdArray::NewLC();
       
   418 	CArrayFixFlat<TInt>* indexArray = new(ELeave) CArrayFixFlat<TInt>(32);	
       
   419 	CleanupStack::PushL(indexArray);
       
   420 	TInt count=aView.CountL();
       
   421 	for (TInt index=0; index < count; ++index)
       
   422 		{
       
   423 		indexArray->AppendL(index);
       
   424 		}
       
   425 
       
   426 	aView.GetContactIdsL(*indexArray, *contactIds);
       
   427 	CleanupStack::PopAndDestroy(indexArray);
       
   428 	CleanupStack::Pop(contactIds);
       
   429 	return contactIds; //ownership passed
       
   430 	}
       
   431 
       
   432 
       
   433 void CPbapContactDbViews::DoSortSearchResultsL(CContactIdArray& aContactIds)
       
   434 	{
       
   435 	LOG_FUNC
       
   436 
       
   437 	if (iOrder == SymbianPBAP::EAlphabetical)
       
   438 		{
       
   439 		if (iSearchAttribute != SymbianPBAP::EName)
       
   440 			{
       
   441 			// the find view was sorted on the phonetic name so we need to resort the
       
   442 			// ids in the find view to match the name view ordering
       
   443 			ResortIdsInViewOrderL(aContactIds, *iNameView);
       
   444 			}
       
   445 		}
       
   446 	else if (iOrder == SymbianPBAP::EPhonetical)
       
   447 		{	
       
   448 		if (iSearchAttribute != SymbianPBAP::ESound)
       
   449 			{
       
   450 			// the find view was sorted on the name so we need to resort the
       
   451 			// ids in the find view to match the phonetic name view ordering
       
   452 			ResortIdsInViewOrderL(aContactIds, *iPhoneticView);
       
   453 			}
       
   454 		}
       
   455 
       
   456 	CopyToResultsArrayL(aContactIds);
       
   457 
       
   458 	// the search and sort is complete notify the observer
       
   459 	NotifySearchAndSortComplete(KErrNone);
       
   460 	}
       
   461 
       
   462 /**
       
   463 aView will be sorted in a specific order and this function re-orders the contact ids in 
       
   464 aContectIds to be in the same order
       
   465 */
       
   466 void CPbapContactDbViews::ResortIdsInViewOrderL(CContactIdArray& aContactIds, CContactViewBase& aView)
       
   467 	{
       
   468 	LOG_FUNC
       
   469 	// create sorted array of indexes of ids in the view  
       
   470 	RArray<TInt> indexes;
       
   471 	CleanupClosePushL(indexes);
       
   472 	TInt count = aContactIds.Count();
       
   473 	for (TInt i = 0; i < count; ++i)
       
   474 		{
       
   475 		TInt pos = aView.FindL(aContactIds[i]);
       
   476 		if (pos != KErrNotFound)
       
   477 			{
       
   478 			indexes.InsertInOrderL(pos);
       
   479 			}
       
   480 		}
       
   481 		
       
   482 	// now replace id array contents with ids sorted in same order as view	
       
   483 	aContactIds.Reset();
       
   484 	count = indexes.Count();
       
   485 	for (TInt j = 0; j < count; ++j)
       
   486 		{
       
   487 		aContactIds.AddL(aView.AtL(indexes[j]));
       
   488 		}
       
   489 	CleanupStack::PopAndDestroy(); //indexes	
       
   490 	}
       
   491 
       
   492 
       
   493 void CPbapContactDbViews::CopyToResultsArrayL(const CContactIdArray& aContactIds)
       
   494 	{
       
   495 	LOG_FUNC
       
   496 	const TInt count = aContactIds.Count();
       
   497 	for (TInt i=0; i < count; ++i)
       
   498 		{
       
   499 		iResults->AddL(aContactIds[i]);
       
   500 		}
       
   501 	}
       
   502 
       
   503 /**
       
   504 this function is part of MContactViewObserver and is called back as a result
       
   505 of an event occurring on a specific view, in our case iNameView or iPhoneticView
       
   506 */
       
   507 void CPbapContactDbViews::HandleContactViewEvent(const CContactViewBase &aView,
       
   508 												 const TContactViewEvent &aEvent)
       
   509 	{
       
   510 	LOG_FUNC
       
   511 	TInt error=KErrNone;
       
   512 	switch(aEvent.iEventType)
       
   513 		{
       
   514 		case TContactViewEvent::ESortOrderChanged:
       
   515 		case TContactViewEvent::EReady:
       
   516 			{
       
   517 			if (&aView == iNameView)
       
   518 				{
       
   519 				iNameViewReady = ETrue;
       
   520 				}
       
   521 			else if (&aView == iPhoneticView)
       
   522 				{
       
   523 				iPhoneticViewReady = ETrue;
       
   524 				}
       
   525 			else if (&aView == iFindView && iOpState == ESearching)
       
   526 				{
       
   527 				iOpState = ESorting;
       
   528 				TRAP(error, HandleFindInViewCompleteL());
       
   529 				if (error != KErrNone)
       
   530 					{
       
   531 					LOG1(_L("Error %d from HandleFindInViewCompleteL"), error);
       
   532 					// NotifySearchAndSortComplete will also cancel and cleanup search
       
   533 					NotifySearchAndSortComplete(error);
       
   534 					}
       
   535 				return;	
       
   536 				}
       
   537 					
       
   538 			if (iNameViewReady && (iPhoneticViewReady || !IsPhoneticViewRequired())
       
   539 				&& iOpState == EPendingSearch)
       
   540 				{
       
   541 				// necessary views are ready now so start the find and sort
       
   542 				iOpState = ESearching;
       
   543 				TRAP(error, DoSearchAndSortL());
       
   544 				if (error != KErrNone)
       
   545 					{
       
   546 					LOG1(_L("Error %d from DoSearchAndSort"), error);
       
   547 					// NotifySearchAndSortComplete will also cancel and cleanup search
       
   548 					NotifySearchAndSortComplete(error);
       
   549 					}				
       
   550 				}
       
   551 			}
       
   552 			break;
       
   553 		case TContactViewEvent::EUnavailable:	
       
   554 		case TContactViewEvent::EServerError:
       
   555 		case TContactViewEvent::ESortError:	
       
   556 			{
       
   557 			if (iOpState != EIdle)
       
   558 				{
       
   559 				LOG1(_L("Error %d reported by contact views"), aEvent.iInt);
       
   560 				// error during find and sort request
       
   561 				NotifySearchAndSortComplete(aEvent.iInt);
       
   562 				}
       
   563 			}
       
   564 			break;
       
   565 		default:
       
   566 			break;
       
   567 		}
       
   568 	}
       
   569 	
       
   570 	
       
   571 void CPbapContactDbViews::NotifySearchAndSortComplete(TInt aError)
       
   572 	{
       
   573 	LOG_FUNC
       
   574 	if (iCallback)
       
   575 		{
       
   576 		iCallback->HandleSearchAndSortComplete(aError);
       
   577 		iCallback = NULL;
       
   578 		}
       
   579 	CancelAndCleanup();
       
   580 	}
       
   581 
       
   582 
       
   583 void CPbapContactDbViews::CancelAndCleanup()
       
   584 	{
       
   585 	LOG_FUNC
       
   586 	iOpState=EIdle;
       
   587 
       
   588 	if (iFindView)
       
   589 		{
       
   590 		iFindView->Close(*this);
       
   591 		iFindView=NULL;	
       
   592 		}
       
   593 	delete iSearchValue;
       
   594 	iSearchValue=NULL;
       
   595 	delete iSearchValueArray;
       
   596 	iSearchValueArray=NULL;
       
   597 	delete iFindFieldDef;
       
   598 	iFindFieldDef=NULL;
       
   599 
       
   600 	if (iIdleFinder)
       
   601 		{
       
   602 		iIdleFinder->Cancel();
       
   603 		delete iIdleFinder;
       
   604 		iIdleFinder=NULL;
       
   605 		}	
       
   606 	if (iAsyncCallback)
       
   607 		{
       
   608 		iAsyncCallback->Cancel();
       
   609 		delete iAsyncCallback;
       
   610 		iAsyncCallback=NULL;
       
   611 		}
       
   612 	}