phonebookengines/contactsmodel/cntview/findview.cpp
changeset 0 e686773b3f54
child 24 0ba2181d7c28
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <cntview.h>
       
    17 #include "CNTSTD.H"
       
    18 #include <cntviewsortplugin.h>
       
    19 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    20 #include <cntviewsortpluginbase.h>
       
    21 #endif
       
    22 
       
    23 //#define CNTVIEW_API_PROFILING
       
    24 // To see the diferences between class versions check the in source documentation of TContactViewEvent
       
    25 const TUint KClassVersion1 = 1;
       
    26 const TUint KClassVersion2 = 2;
       
    27 
       
    28 /* Default C++ Constructor */
       
    29 CContactFindView::CContactFindView(const CContactDatabase& aDb,CContactViewBase& aView, TSearchType aSearchType)
       
    30 :CContactViewBase(aDb),iView(aView),iSearchType(aSearchType), iClassVersion(KClassVersion1)
       
    31 
       
    32 	{}
       
    33 
       
    34 CContactFindView::~CContactFindView() 
       
    35 /** Destructor */
       
    36 	{
       
    37 	iView.Close(*this);
       
    38 	DeleteFindContacts();
       
    39 	DestroyFindWordsArray();
       
    40 	}
       
    41 
       
    42 /* Helper method to delete find results */
       
    43 void CContactFindView::DeleteFindContacts()
       
    44 	{
       
    45 	iFindContacts.ResetAndDestroy();
       
    46 	}
       
    47 
       
    48 EXPORT_C CContactFindView* CContactFindView::NewL(const CContactDatabase& aDb,CContactViewBase& aView,MContactViewObserver& aObserver,MDesCArray* aFindWords)
       
    49 /** Allocates and constructs a new CContactFindView version 1 object, using a default search  
       
    50 type of CContactViewBase::EFullSearch.
       
    51 
       
    52 When adding/deleting contacts in the view, MContactViewObserver observer will receive 
       
    53 TContactViewEvent events with iInt parameter set to KErrNone.
       
    54 
       
    55 @param aDb The database containing the contact items.
       
    56 @param aView The underlying contact view.
       
    57 @param aObserver An observer that receives notifications when this view is 
       
    58 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady 
       
    59 event when the view is ready. An attempt to use the view before this notification 
       
    60 causes a panic.
       
    61 @param aFindWords The array of search terms. The view does not take ownership 
       
    62 of this - it makes its own copy of it to prevent it from going out of scope.
       
    63 @return The newly constructed find view object. */
       
    64 	{
       
    65 	return NewL(aDb,aView,aObserver,aFindWords,EFullSearch);
       
    66 	}
       
    67 
       
    68 EXPORT_C CContactFindView* CContactFindView::NewL(const CContactDatabase& aDb,CContactViewBase& aView,MContactViewObserver& aObserver,MDesCArray* aFindWords, TSearchType aSearchType)
       
    69 /** Allocates and constructs a new CContactFindView version 1 object, specifying a search 
       
    70 type.
       
    71 
       
    72 When adding/deleting contacts in the view, MContactViewObserver observer will receive 
       
    73 TContactViewEvent events with iInt parameter set to KErrNone.
       
    74 
       
    75 @param aDb The database containing the contact items.
       
    76 @param aView The underlying contact view.
       
    77 @param aObserver An observer that receives notifications when this view is 
       
    78 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady 
       
    79 event when the view is ready. An attempt to use the view before this notification 
       
    80 causes a panic.
       
    81 @param aFindWords The array of search terms. The view does not take ownership 
       
    82 of this - it makes its own copy of it to prevent it from going out of scope.
       
    83 @param aSearchType The search type. This controls whether a search term can 
       
    84 occur anywhere in a contact item field, or just at the beginning of the field.
       
    85 @return The newly constructed find view object. */
       
    86 	{
       
    87 #ifdef CNTVIEW_API_PROFILING
       
    88 	RDebug::Print(_L("[CNTMODEL] CContactFindView::NewL()\n"));
       
    89 #endif
       
    90 	CContactFindView* self=new(ELeave) CContactFindView(aDb, aView, aSearchType);
       
    91 	CleanupStack::PushL(self);
       
    92 	self->ConstructL(aObserver,aFindWords);
       
    93 	CleanupStack::Pop(self);
       
    94 	return self;
       
    95 	}
       
    96 
       
    97 EXPORT_C CContactFindView* CContactFindView::NewL(CContactViewBase& aView,const CContactDatabase& aDb,MContactViewObserver& aObserver,MDesCArray* aFindWords)
       
    98 /** Allocates and constructs a new CContactFindView version 2 object, using a default search 
       
    99 type of CContactViewBase::EFullSearch.
       
   100 
       
   101 When adding/deleting contacts in the view, MContactViewObserver observer will receive 
       
   102 TContactViewEvent events with iInt parameter set to index into the observed view of the added/deleted item
       
   103 
       
   104 @param aDb The database containing the contact items.
       
   105 @param aView The underlying contact view.
       
   106 @param aObserver An observer that receives notifications when this view is 
       
   107 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady 
       
   108 event when the view is ready. An attempt to use the view before this notification 
       
   109 causes a panic.
       
   110 @param aFindWords The array of search terms. The view does not take ownership 
       
   111 of this - it makes its own copy of it to prevent it from going out of scope.
       
   112 @return The newly constructed find view object. */
       
   113 	{
       
   114 	return NewL(aView,aDb,aObserver,aFindWords,EFullSearch);
       
   115 	}
       
   116 
       
   117 EXPORT_C CContactFindView* CContactFindView::NewL(CContactViewBase& aView,const CContactDatabase& aDb,MContactViewObserver& aObserver,MDesCArray* aFindWords, TSearchType aSearchType)
       
   118 /** Allocates and constructs a new CContactFindView version 2 object, specifying a search 
       
   119  type.
       
   120  
       
   121 When adding/deleting contacts in the view, MContactViewObserver observer will receive 
       
   122 TContactViewEvent events with iInt parameter set to index into the observed view of the added/deleted item
       
   123 
       
   124 @param aDb The database containing the contact items.
       
   125 @param aView The underlying contact view.
       
   126 @param aObserver An observer that receives notifications when this view is 
       
   127 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady 
       
   128 event when the view is ready. An attempt to use the view before this notification 
       
   129 causes a panic.
       
   130 @param aFindWords The array of search terms. The view does not take ownership 
       
   131 of this - it makes its own copy of it to prevent it from going out of scope.
       
   132 @param aSearchType The search type. This controls whether a search term can 
       
   133 occur anywhere in a contact item field, or just at the beginning of the field.
       
   134 @return The newly constructed find view object. */
       
   135 	{
       
   136 #ifdef CNTVIEW_API_PROFILING
       
   137 	RDebug::Print(_L("[CNTMODEL] CContactFindView::NewL()\n"));
       
   138 #endif
       
   139 	CContactFindView* self=new(ELeave) CContactFindView(aDb, aView, aSearchType);
       
   140 	CleanupStack::PushL(self);
       
   141 	self->ConstructL(aObserver,aFindWords);
       
   142 	self->iClassVersion = KClassVersion2;
       
   143 	CleanupStack::Pop(self);
       
   144 	return self;
       
   145 	}
       
   146 
       
   147 /* 
       
   148  * Second phase constructor 
       
   149  * @param aObserver view observer
       
   150  * @param aFindWords Array of words to find
       
   151  */
       
   152 void CContactFindView::ConstructL(MContactViewObserver& aObserver,MDesCArray* aFindWords)
       
   153 	{
       
   154 	CContactViewBase::ConstructL();
       
   155 	OpenL(aObserver);
       
   156 	iView.OpenL(*this);
       
   157 	CopyNewFindWordsL(aFindWords);
       
   158 	}
       
   159 
       
   160 /* Helper method for deleting iFindWords member */
       
   161 void CContactFindView::DestroyFindWordsArray()
       
   162 	{
       
   163 	if(iFindWords)
       
   164 		{
       
   165 		iFindWords->Reset();
       
   166 		delete iFindWords;
       
   167 		iFindWords=NULL;
       
   168 		}
       
   169 	}
       
   170 
       
   171 /* Duplicate array provided by client to prevent it going out of scope */
       
   172 void CContactFindView::CopyNewFindWordsL(MDesCArray* aFindWords)
       
   173 	{
       
   174 	DestroyFindWordsArray();
       
   175 	const TInt count = aFindWords->MdcaCount();
       
   176 	CPtrCArray* findWordArray = new (ELeave) CPtrCArray(count);
       
   177 	CleanupStack::PushL(findWordArray);
       
   178 	findWordArray->CopyL(*aFindWords);
       
   179 	CleanupStack::Pop(findWordArray);
       
   180 	iFindWords=findWordArray;
       
   181 	}
       
   182 
       
   183 EXPORT_C void CContactFindView::UpdateFindViewL()
       
   184 /** Populates the view.
       
   185 
       
   186 This deletes any existing matching contacts list and searches the underlying 
       
   187 view for items matching the search criteria. */
       
   188 	{
       
   189 	DeleteFindContacts();
       
   190 	if (iSearchType==EFullSearch)
       
   191 		iView.ContactsMatchingCriteriaL(*iFindWords,iFindContacts);
       
   192 	else
       
   193 		iView.ContactsMatchingPrefixL(*iFindWords,iFindContacts);
       
   194 	}
       
   195 
       
   196 /**
       
   197  * This is a reserved virtual exported function that is used for BC proofing 
       
   198  * against present and future additions of new exported virtual functions.
       
   199  @return Any return values of the helper methods called from this function or NULL.
       
   200  */
       
   201 TAny* CContactFindView::CContactViewBase_Reserved_1(TFunction aFunction,TAny* aParams)
       
   202 	{
       
   203 	return CContactViewBase::CContactViewBase_Reserved_1(aFunction,aParams);
       
   204 	}
       
   205 
       
   206 /* Refines an existing find view selection based on new criteria */
       
   207 void CContactFindView::TightenFindViewCriteriaL()
       
   208 	{
       
   209 	RPointerArray<CViewContact> updatedContacts;
       
   210 	CleanupClosePushL(updatedContacts);
       
   211 	const TInt viewCount = iFindContacts.Count();
       
   212 	CViewContact* contact;
       
   213 	TBool match = EFalse;
       
   214 	for (TInt ii=0;ii<viewCount;++ii)
       
   215 		{
       
   216 		contact =(iFindContacts)[ii];
       
   217 		match=MatchesCriteriaL(*contact,*iFindWords, iSearchType,iExtension);
       
   218 		if (match)
       
   219 			{
       
   220 			TContactItemId id = contact->Id();
       
   221 			CViewContact* matchContact = CViewContact::NewLC(id);
       
   222 			User::LeaveIfError(updatedContacts.Append(matchContact));
       
   223 			CleanupStack::Pop(matchContact);
       
   224 			}
       
   225 		}
       
   226 	DeleteFindContacts();
       
   227 	iFindContacts=updatedContacts;
       
   228 	CleanupStack::Pop(&updatedContacts);
       
   229 	}
       
   230 
       
   231 EXPORT_C void CContactFindView::RefineFindViewL(MDesCArray* aFindWords)
       
   232 /** Refines the search criteria and updates the find view.
       
   233 
       
   234 This may involve either narrowing or replacing the search criteria.
       
   235 
       
   236 This function can be used to narrow the existing search criteria, by specifying 
       
   237 an array of search terms that consists of the existing search terms (as passed 
       
   238 to the NewL()) with additional terms appended to it. In this case, the function 
       
   239 searches the existing list of matching contact items only. This assumes that 
       
   240 UpdateFindViewL() has previously been called.
       
   241 
       
   242 It can alternatively be used to replace entirely the existing search criteria. 
       
   243 In this case, the whole underlying view is searched again.
       
   244 
       
   245 @param aFindWords The new search criteria. This can be a superset of the existing 
       
   246 search criteria, i.e. the existing criteria with additional terms appended 
       
   247 to it; otherwise it replaces the existing search criteria entirely. */
       
   248 	{
       
   249 	const TInt originalFindWords=iFindWords->MdcaCount();
       
   250 	if(aFindWords->MdcaCount()>=originalFindWords)
       
   251 		{
       
   252 		TInt compare = KErrNotFound;
       
   253 		TBool hit=EFalse;
       
   254 		//Check that the new words are equal to a greater than the original find words.
       
   255 		for (TInt ii=0;ii<originalFindWords;++ii)
       
   256 			{
       
   257 			TPtrC originalWord(iFindWords->MdcaPoint(ii));
       
   258 			//RDebug::Print(_L("orig=== %S"),&originalWord);
       
   259 			//RDebug::Print(_L("new=== %S"),&aFindWords->MdcaPoint(ii));
       
   260 			compare = aFindWords->MdcaPoint(ii).CompareF(originalWord);
       
   261 			if(compare>=0)
       
   262 				{
       
   263 				hit=ETrue;
       
   264 				}
       
   265 			else
       
   266 				{
       
   267 				//its something completely different we need to do a fresh search
       
   268 				hit=EFalse;
       
   269 				break;
       
   270 				}
       
   271 			}
       
   272 		if(hit)
       
   273 			{
       
   274 			//Results is a subset of what we already have so just refine it.
       
   275 			CopyNewFindWordsL(aFindWords);
       
   276 			TightenFindViewCriteriaL();
       
   277 			return;
       
   278 			}
       
   279 		}
       
   280 	CopyNewFindWordsL(aFindWords);
       
   281 	//Do a new find from scratch
       
   282 	UpdateFindViewL();
       
   283 	}
       
   284 
       
   285 /* Handle events from the parent view */
       
   286 void CContactFindView::HandleContactViewEvent(const CContactViewBase& aView,const TContactViewEvent& aEvent)
       
   287 	{
       
   288 	ASSERT(&aView==&iView);
       
   289 	TContactViewEvent event=aEvent;
       
   290 
       
   291 	TInt err = KErrNone;
       
   292 
       
   293 	switch (event.iEventType)
       
   294 		{
       
   295 		case TContactViewEvent::EUnavailable:
       
   296 		case TContactViewEvent::ESortError:
       
   297 		case TContactViewEvent::EServerError:
       
   298 			iState=ENotReady;
       
   299 			break;
       
   300 		case TContactViewEvent::ESortOrderChanged:
       
   301 		case TContactViewEvent::EReady:
       
   302 			{
       
   303 			if(&iView==&aView)
       
   304 				{
       
   305 				TRAP(err,UpdateFindViewL());
       
   306 				iState=EReady;
       
   307 				}
       
   308 			}
       
   309 			break;
       
   310 		case TContactViewEvent::EItemAdded:
       
   311 			if(&iView==&aView)
       
   312 				{
       
   313 				TRAP(err,HandleAddEventL(event));
       
   314 				}
       
   315 			break;
       
   316 		case TContactViewEvent::EItemRemoved:
       
   317 			if(&iView==&aView)
       
   318 				{
       
   319 				TRAP(err,HandleRemoveEventL(event));
       
   320 				}
       
   321 			break;
       
   322 		case TContactViewEvent::EGroupChanged:
       
   323 			break;
       
   324 		default:
       
   325 			ASSERT(EFalse);
       
   326 		}	
       
   327 	
       
   328 	if (err != KErrNone)
       
   329 		{
       
   330 		NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError,err));
       
   331 		}
       
   332 	else
       
   333 		{
       
   334 		NotifyObservers(event);
       
   335 		}
       
   336 	}
       
   337 
       
   338 /* Handles a EItemRemoved event from the underlying view */
       
   339 void CContactFindView::HandleRemoveEventL(TContactViewEvent& aEvent)
       
   340 	{
       
   341 	aEvent.iInt = KErrNone;
       
   342 	const TInt pos = FindL(aEvent.iContactId);
       
   343 	if (pos != KErrNotFound)
       
   344 		{
       
   345 		delete iFindContacts[pos];
       
   346 		iFindContacts.Remove(pos);
       
   347 		if(iClassVersion == KClassVersion2) //update the iInt with correct value
       
   348 			{
       
   349 			aEvent.iInt = pos;	
       
   350 			}
       
   351 		}
       
   352 	}
       
   353 
       
   354 /* Handles a EItemAdded event from the underlying view */
       
   355 void CContactFindView::HandleAddEventL(TContactViewEvent& aEvent)
       
   356 	{
       
   357 	// The id contained in aEvent can refer to a inexistent contact by now
       
   358 	// The contact may have been deleted or changed index position,
       
   359 	// so check that the contact with that id still exist first
       
   360 	TInt underlyingViewIndex = iView.FindL(aEvent.iContactId);
       
   361 	User::LeaveIfError(underlyingViewIndex);
       
   362 	aEvent.iInt = KErrNone;
       
   363 	// get contact data from view rather than re-read from disk (speeds up access time)
       
   364 	const CViewContact& contact = iView.ContactAtL(underlyingViewIndex);
       
   365 	const TBool match=MatchesCriteriaL(contact,*iFindWords, iSearchType,iExtension);
       
   366 	if (match)
       
   367 		{
       
   368 		CViewContact* thisContact = CViewContact::NewL(contact);
       
   369 		// Insert using Sort Plugin compare method
       
   370 		const TInt insertError = InsertContact(thisContact);
       
   371 		if(insertError!=KErrNone)
       
   372 			{
       
   373 			delete thisContact;
       
   374 			User::Leave(insertError);
       
   375 			}
       
   376 
       
   377 		if(iClassVersion == KClassVersion2)  //update iInt with the correct value
       
   378 			{
       
   379 			TInt pos = FindL(aEvent.iContactId);
       
   380 			if ( pos != KErrNotFound ) // contact is a member of our list
       
   381 				{
       
   382 				aEvent.iInt = pos;	//update the iInt according
       
   383 				}		
       
   384 			}
       
   385 		}
       
   386 	}
       
   387 
       
   388 TContactItemId CContactFindView::AtL(TInt aIndex) const
       
   389 /** Gets the contact item ID at the specified index into the find view.
       
   390 
       
   391 @param aIndex Index of the contact item ID into the find view.
       
   392 @leave KErrNotFound aIndex is outside the bounds of the array.
       
   393 @return The contact item ID. */
       
   394 	{
       
   395 	if(aIndex>=iFindContacts.Count())
       
   396 		{
       
   397 		//Out of Bounds.
       
   398 		User::Leave(KErrNotFound);
       
   399 		}
       
   400 	return (iFindContacts)[aIndex]->Id();
       
   401 	}
       
   402 
       
   403 const CViewContact& CContactFindView::ContactAtL(TInt aIndex) const
       
   404 /** Gets the contact item at the specified index into the view.
       
   405 
       
   406 @param aIndex Index into the view of the required item.
       
   407 @leave KErrNotFound aIndex is outside the bounds of the array.
       
   408 @return The contact item. */
       
   409 	{
       
   410 	if(aIndex>=iFindContacts.Count())
       
   411 		{
       
   412 		//Out of Bounds.
       
   413 		User::Leave(KErrNotFound);
       
   414 		}
       
   415 	return *(iFindContacts)[aIndex];
       
   416 	}
       
   417 
       
   418 TInt CContactFindView::CountL() const
       
   419 /** Gets the number of contact item IDs in the find view.
       
   420 
       
   421 @return The number of contact items in the find view. */
       
   422 	{
       
   423 	return iFindContacts.Count();
       
   424 	}
       
   425 
       
   426 TInt CContactFindView::FindL(TContactItemId aId) const
       
   427 /** Finds the index into the array of the specified contact item.
       
   428 
       
   429 @param aId The contact item ID to search for. 
       
   430 @leave KErrNotReady The view is not ready for use.
       
   431 @return The index of the first matching item in the find view or KErrNotFound 
       
   432 if no matching item can be found. 
       
   433 */
       
   434 	{
       
   435 	if(iState != EReady)
       
   436 		{
       
   437 		User::Leave(KErrNotReady);
       
   438 		}
       
   439 	TInt index=KErrNotFound;
       
   440 	CViewContact* contact = CViewContact::NewLC(aId);
       
   441 	index = iFindContacts.Find(contact,TIdentityRelation<CViewContact>(IdsMatch));
       
   442 	CleanupStack::PopAndDestroy(contact);
       
   443 	return index;
       
   444 	}
       
   445 
       
   446 HBufC* CContactFindView::AllFieldsLC(TInt aIndex,const TDesC& aSeparator) const
       
   447 /** Returns a descriptor containing the contents of all fields in an item in the 
       
   448 view.
       
   449 
       
   450 The fields are separated by aSeparator.
       
   451 
       
   452 @param aIndex The index into the view of the contact item.
       
   453 @param aSeparator The string to use to separate the fields.
       
   454 @return Pointer to the contact item descriptor. */
       
   455 	{
       
   456 	return FieldsWithSeparatorLC(iFindContacts,aIndex,aSeparator);
       
   457 	}
       
   458 
       
   459 TContactViewPreferences CContactFindView::ContactViewPreferences()
       
   460 /** Gets the underlying view's view preferences.
       
   461 
       
   462 @return The view preferences. */
       
   463 	{
       
   464 	return iView.ContactViewPreferences();
       
   465 	}
       
   466 
       
   467 const RContactViewSortOrder& CContactFindView::SortOrderL() const
       
   468 /** Gets the underlying view's sort order.
       
   469 
       
   470 @return The sort order. */
       
   471 	{
       
   472 	return iView.SortOrderL();
       
   473 	}
       
   474 
       
   475 /**
       
   476  * Do binary search of Contacts Array, and insert new contact.
       
   477  * Uses current Sort Plugin, if any.
       
   478  *
       
   479  * @internalComponent
       
   480  * @released
       
   481  */
       
   482 TInt CContactFindView::InsertContact(const CViewContact* aNewContact)
       
   483 	{
       
   484 	TInt error = KErrNone;
       
   485 
       
   486 	if (iFindContacts.Count() == 0)
       
   487 		{ // easy
       
   488 		error = iFindContacts.Append(aNewContact);
       
   489 		}
       
   490 	else
       
   491 		{
       
   492 		// To insert in correct order we use parent view & its Sort method (Plug-in).
       
   493 		// Virtual Function 3 calls  CContactViewBase::InsertContactInView() method
       
   494 		// in the parent view.
       
   495 		TVirtualFunction3Params vFuncParams(iFindContacts,aNewContact);
       
   496 
       
   497 		error = reinterpret_cast<TInt>(iView.CContactViewBase_Reserved_1(CContactViewBase::ECContactViewBaseVirtualFunction3, &vFuncParams));
       
   498 		}
       
   499 
       
   500 	return error;
       
   501 	}
       
   502