phonebookengines/contactsmodel/cntplsql/src/csqlitelocalview.cpp
branchRCL_3
changeset 20 f4a778e096c2
equal deleted inserted replaced
19:5b6f26637ad3 20:f4a778e096c2
       
     1 // Copyright (c) 2007-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 /**
       
    17  @file
       
    18  @internalComponent
       
    19  @released
       
    20 */
       
    21 
       
    22 #include <cntviewbase.h>
       
    23 #include <cntitem.h>
       
    24 #include "cntviewprivate.h"
       
    25 #include <cntviewsortplugin.h>
       
    26 #include "persistencelayer.h"
       
    27 #include "cviewcontactmanager.h"
       
    28 #include "CNTSTD.H"
       
    29 #include <phbksync.h>
       
    30 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    31 #include <cntviewsortpluginbase.h>
       
    32 #endif
       
    33 //uncomment to test
       
    34 //#define __PROFILE_SORT__
       
    35 
       
    36 //uncomment for commonly required debug printing
       
    37 //#define __VERBOSE_DEBUG__
       
    38 
       
    39 //Define the patchable constants for the number of CViewContacts to read into memory 
       
    40 //before merging them into a larger sorted list (via a heap sort).This is actually used
       
    41 //in cviewcontactmanager.cpp but must be defined here so that the compiler can not 
       
    42 //perform any "constant folding" with the value   
       
    43 EXPORT_C extern const TInt KNumberOfContactsToReadPerMerge = 500;
       
    44 
       
    45 extern void DebugLogNotification(const TDesC& aMethod, const TContactDbObserverEvent &aEvent);
       
    46 
       
    47 
       
    48 //
       
    49 // CContactLocalView.
       
    50 //
       
    51 CContactLocalView::CContactLocalView(const CContactDatabase& aDb,TContactViewPreferences aContactTypes, MLplPersistenceLayerFactory* aFactory) 
       
    52 : CContactViewBase(aDb), 
       
    53   iFactory(aFactory),
       
    54   iContacts(), 
       
    55   iUnSortedContacts(),
       
    56   iViewPreferences(aContactTypes)
       
    57 	{
       
    58 	}
       
    59 
       
    60 	
       
    61 /**
       
    62 Protected C++ constructor.
       
    63 
       
    64 Called by NewL().
       
    65 
       
    66 @param aDb The underlying database that contains the contact items.
       
    67 @param aContactTypes Specifies which types of contact items should be included 
       
    68 in the view and the behaviour for items that do not have content in any of 
       
    69 the fields specified in the sort order. 
       
    70 */
       
    71 EXPORT_C CContactLocalView::CContactLocalView(const CContactDatabase& aDb,TContactViewPreferences aContactTypes) 
       
    72 : CContactViewBase(aDb), 
       
    73   iContacts(), 
       
    74   iUnSortedContacts(),
       
    75   iViewPreferences(aContactTypes)
       
    76 	{
       
    77 	}
       
    78 
       
    79 	
       
    80 /**
       
    81 Destructor.
       
    82 
       
    83 Deletes all resources owned by the object, and removes itself as the contact 
       
    84 database observer. 
       
    85 */
       
    86 EXPORT_C CContactLocalView::~CContactLocalView()
       
    87 	{
       
    88 #ifdef CONTACTS_API_PROFILING
       
    89 	TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassLocalView, TContactsApiProfile::ECntViewDestructor);
       
    90 #endif
       
    91 	delete iTextDef;
       
    92 	iContacts.ResetAndDestroy();
       
    93 	iUnSortedContacts.ResetAndDestroy();
       
    94 	iOutstandingEvents.Close();
       
    95 	iSortOrder.Close();
       
    96 
       
    97 	if (&iDb != NULL)
       
    98 		{
       
    99         const_cast<CContactDatabase&>(iDb).RemoveObserver(*this);
       
   100 		}
       
   101 		
       
   102 	delete iAsyncSorter; //Add this though we don't use it in local view any more
       
   103 	delete iViewCntMgr;
       
   104 	}
       
   105 
       
   106 	
       
   107 /**
       
   108 Allocates and constructs the local view object.
       
   109 
       
   110 The view is sorted according to the sort order and view preferences specified, 
       
   111 using a low priority idle time active object. The specified view observer 
       
   112 is notified when the view is sorted and ready for use.
       
   113 
       
   114 @param aObserver An observer that receives notifications when this view is 
       
   115 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady 
       
   116 event when the view is ready. Any attempt to use the view before this notification will Leave with KErrNotReady
       
   117 @param aDb The underlying database that contains the contact items. The view 
       
   118 observes the database, so that it handles change events sent from the database.
       
   119 @param aSortOrder Specifies the fields to use to sort the items in the view.
       
   120 @param aContactTypes Specifies which types of contact items should be included 
       
   121 in the view and the behaviour for items that do not have content in any of 
       
   122 the fields specified in the sort order.
       
   123 @return The newly constructed local view object. 
       
   124 */
       
   125 EXPORT_C CContactLocalView* CContactLocalView::NewL(MContactViewObserver& aObserver,const CContactDatabase& aDb,
       
   126 													const RContactViewSortOrder& aSortOrder,TContactViewPreferences aContactTypes)
       
   127 	{
       
   128 #ifdef CONTACTS_API_PROFILING
       
   129 	TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassLocalView, TContactsApiProfile::ECntViewApiNewL, aSortOrder, aContactTypes);
       
   130 #endif
       
   131 	CContactLocalView* self = new(ELeave) CContactLocalView(aDb, aContactTypes);
       
   132 	CleanupStack::PushL(self);
       
   133 	self->ConstructL(aObserver, aSortOrder);
       
   134 	CleanupStack::Pop(self); 
       
   135 	return self;
       
   136 	}
       
   137 
       
   138 	
       
   139 /**
       
   140 Protected second phase constructor.
       
   141 
       
   142 The view is sorted according to the sort order and view preferences specified, 
       
   143 using a low priority idle time active object. The specified view observer 
       
   144 is notified when the view is sorted and ready for use.
       
   145 
       
   146 Called by NewL().
       
   147 
       
   148 @param aObserver An observer that receives notifications when this view is 
       
   149 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady 
       
   150 event when the view is ready. Any attempt to use the view before this notification will Leave with KErrNotReady.
       
   151 @param aSortOrder Specifies the fields to use to sort the items in the view. 
       
   152 */
       
   153 EXPORT_C void CContactLocalView::ConstructL(MContactViewObserver& aObserver, const RContactViewSortOrder& aSortOrder)
       
   154 	{
       
   155 	// call new ConstructL
       
   156 	ConstructL(aObserver, aSortOrder, EFalse, KNullDesC8);
       
   157 	}
       
   158 
       
   159 	
       
   160 /**
       
   161 Allocates and constructs the local view object.
       
   162 
       
   163 The view is sorted according to the sort order and view preferences specified, 
       
   164 using a low priority idle time active object. The specified view observer 
       
   165 is notified when the view is sorted and ready for use.
       
   166 
       
   167 @param aObserver An observer that receives notifications when this view is 
       
   168 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady 
       
   169 event when the view is ready. Any attempt to use the view before this notification will Leave with KErrNotReady
       
   170 @param aDb The underlying database that contains the contact items. The view 
       
   171 observes the database, so that it handles change events sent from the database.
       
   172 @param aSortOrder Specifies the fields to use to sort the items in the view.
       
   173 @param aContactTypes Specifies which types of contact items should be included 
       
   174 in the view and the behaviour for items that do not have content in any of 
       
   175 the fields specified in the sort order.
       
   176 @param aSortPluginName Specifies a plug-in that will be used to compare view contacts
       
   177 when the the view is sorted. This name is used by ECOM to select the plugin, and is matched
       
   178 with the "default_data" of all ECOM plugins that support the required interface.
       
   179 @return The newly constructed local view object. 
       
   180 */
       
   181 EXPORT_C CContactLocalView* CContactLocalView::NewL(MContactViewObserver& aObserver,const CContactDatabase& aDb, const RContactViewSortOrder& aSortOrder, TContactViewPreferences aContactTypes, const TDesC8& aSortPluginName)
       
   182 	{
       
   183 #ifdef CONTACTS_API_PROFILING
       
   184 	TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassLocalView, TContactsApiProfile::ECntViewApiNewL, aSortOrder, aContactTypes, aSortPluginName);
       
   185 #endif
       
   186 	CContactLocalView* self = new(ELeave) CContactLocalView(aDb, aContactTypes);
       
   187 	CleanupStack::PushL(self);
       
   188 	self->ConstructL(aObserver, aSortOrder, ETrue, aSortPluginName);
       
   189 	CleanupStack::Pop(self); 
       
   190 	return self;
       
   191 	}
       
   192 
       
   193 	
       
   194 /**
       
   195 CContactLocalView contructor, used in the server
       
   196 @internalTechnology 
       
   197 */
       
   198 EXPORT_C CContactLocalView* CContactLocalView::NewL(MContactViewObserver& aObserver,const CContactDatabase& aDb,const RContactViewSortOrder& aSortOrder,TContactViewPreferences aContactTypes, MLplPersistenceLayerFactory* aFactory, const TDesC8& aSortPluginName)
       
   199 	{
       
   200 	CContactLocalView* self = new (ELeave) CContactLocalView(aDb, aContactTypes, aFactory);
       
   201 	CleanupStack::PushL(self);
       
   202 	self->ConstructL(aObserver, aSortOrder, ETrue, aSortPluginName);
       
   203 	CleanupStack::Pop(self); 
       
   204 	return self;
       
   205 	}
       
   206 
       
   207 	
       
   208 /**
       
   209 Protected second phase constructor.
       
   210 
       
   211 The view is sorted according to the sort order and view preferences specified, 
       
   212 using a low priority idle time active object. The specified view observer 
       
   213 is notified when the view is sorted and ready for use.
       
   214 
       
   215 Called by NewL().
       
   216 
       
   217 @param aObserver An observer that receives notifications when this view is 
       
   218 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady 
       
   219 event when the view is ready. Any attempt to use the view before this notification will Leave with KErrNotReady.
       
   220 @param aSortOrder Specifies the fields to use to sort the items in the view. 
       
   221 @param aUseNamedPlugin A flag indicates whether the aSortPluginName parameter is valid.
       
   222 @param aSortPluginName Specifies a plug-in that will be used to compare view contacts
       
   223 when the the view is sorted. This name is used by ECOM to select the plugin, and is matched
       
   224 with the "default_data" of all ECOM plugins that support the required interface.
       
   225 */
       
   226 void CContactLocalView::ConstructL(MContactViewObserver& aObserver,const RContactViewSortOrder& aSortOrder, TBool aUseNamedPlugin, const TDesC8& aSortPluginName)
       
   227 	{
       
   228 	CContactViewBase::ConstructL();
       
   229 	if(iFactory == NULL)
       
   230 		{
       
   231 		iFactory = const_cast<CContactDatabase&>(iDb).FactoryL();
       
   232 		}
       
   233     
       
   234 	OpenL(aObserver);
       
   235 	if (aUseNamedPlugin)
       
   236 		{
       
   237 		// find and load Sort plug-in
       
   238 		if (aSortPluginName.Length())
       
   239 			{
       
   240 			TUid sortPluginUid = FindSortPluginImplL (aSortPluginName);
       
   241 			LoadViewSortPluginL(sortPluginUid, iViewPreferences);
       
   242 			}
       
   243 		}
       
   244 	else
       
   245 		{
       
   246 		// find and load default Sort plug-in (if any)
       
   247 		TUid sortPluginUid = FindDefaultViewSortPluginImplL();
       
   248 		if (sortPluginUid != KNullUid)
       
   249 			{
       
   250 			LoadViewSortPluginL(sortPluginUid, iViewPreferences);
       
   251 			}
       
   252 		}
       
   253 	
       
   254 	//Initialise sort order and textdef.
       
   255 	SetSortOrderL(aSortOrder);
       
   256 	
       
   257 	//Create view contact manager to handle sorting
       
   258     iViewCntMgr = CViewContactManager::NewL(*this, *iFactory, *iTextDef, iViewPreferences, SortPluginImpl());
       
   259 	
       
   260 	if (&iDb != NULL)
       
   261 		{
       
   262         const_cast<CContactDatabase&>(iDb).AddObserverL(*this);
       
   263 		}
       
   264 	
       
   265 	//Doing the sort.
       
   266 	SortL();
       
   267 	}
       
   268 
       
   269 
       
   270 /**
       
   271 Gets the sort order, as set during construction.
       
   272 
       
   273 @return The sort order. 
       
   274 */
       
   275 EXPORT_C const RContactViewSortOrder& CContactLocalView::SortOrder() const
       
   276 	{
       
   277 #ifdef CONTACTS_API_PROFILING
       
   278 	TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassLocalView, TContactsApiProfile::ECntViewApiSortOrder);
       
   279 #endif
       
   280 	return iSortOrder;
       
   281 	}
       
   282 
       
   283 	
       
   284 /**
       
   285 Returns the ID of the contact item at a specified index into the view.
       
   286 
       
   287 @param aIndex An index into the view.
       
   288 @leave KErrNotFound The index is out of bounds.
       
   289 @return The ID of the contact item at the specified index.
       
   290 @leave KErrNotReady The view is not ready for use.  
       
   291 */
       
   292 TContactItemId CContactLocalView::AtL(TInt aIndex) const
       
   293 	{
       
   294 #ifdef CONTACTS_API_PROFILING
       
   295 	TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassLocalView, TContactsApiProfile::ECntViewApiAtL, aIndex);
       
   296 #endif
       
   297 	return iViewCntMgr->AtL(aIndex);
       
   298 	}
       
   299 
       
   300 	
       
   301 /**
       
   302 Returns the contact item at a specified index into the view.
       
   303 
       
   304 @param aIndex An index into the view.
       
   305 @leave KErrNotFound The index is out of bounds.
       
   306 @leave KErrNotReady The view is not ready for use.
       
   307 @return The reference to the copy of contact item at the specified index. 
       
   308 */
       
   309 const CViewContact& CContactLocalView::ContactAtL(TInt aIndex) const
       
   310 	{
       
   311 #ifdef CONTACTS_API_PROFILING
       
   312 	TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassLocalView, TContactsApiProfile::ECntViewApiContactAtL, aIndex);
       
   313 #endif
       
   314 	// state cannot be EInitializing or ENotReady
       
   315 	if( iState != EReady )
       
   316 		{
       
   317 		User::Leave(KErrNotReady);
       
   318 		}
       
   319 
       
   320 	return iViewCntMgr->ContactAtL(aIndex);
       
   321 	}
       
   322 
       
   323 	
       
   324 /**
       
   325 Gets the total number of contact items in the view.
       
   326 
       
   327 @return The number of contact items in the view. This includes both sorted 
       
   328 and unsorted items.
       
   329 @leave KErrNotReady The view is not ready for use. 
       
   330 */
       
   331 TInt CContactLocalView::CountL() const
       
   332 	{
       
   333 #ifdef CONTACTS_API_PROFILING
       
   334 	TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassLocalView, TContactsApiProfile::ECntViewApiCountL);
       
   335 #endif
       
   336 	// state cannot be EInitializing or ENotReady
       
   337 	if( iState != EReady )
       
   338 		{
       
   339 		User::Leave(KErrNotReady);
       
   340 		}
       
   341 	
       
   342 	return iViewCntMgr->Count();
       
   343 	}
       
   344 
       
   345 	
       
   346 /**
       
   347 Searches for a contact item in the view with the specified ID.
       
   348 
       
   349 @param aId The ID of the contact item to search for.
       
   350 @return If found, the index into the view of the matching item. Otherwise, 
       
   351 KErrNotFound.
       
   352 @leave KErrNotReady The view is not ready for use.  
       
   353 */
       
   354 TInt CContactLocalView::FindL(TContactItemId aId) const
       
   355 	{
       
   356 #ifdef CONTACTS_API_PROFILING
       
   357 	TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassLocalView, TContactsApiProfile::ECntViewApiFindL, aId);
       
   358 #endif
       
   359 	// state cannot be EInitializing or ENotReady
       
   360 	if( iState != EReady )
       
   361 		{
       
   362 		User::Leave(KErrNotReady);
       
   363 		}
       
   364 
       
   365 	return iViewCntMgr->FindL(aId);
       
   366 	}
       
   367 
       
   368 	
       
   369 /**
       
   370 Gets a descriptor containing the contents of all fields specified in the view's 
       
   371 sort order for an item in the view.
       
   372 
       
   373 The field separator is used to separate the contents of each field. It is 
       
   374 not appended to the last field.
       
   375 
       
   376 @param aIndex The index of the contact item into the view.
       
   377 @param aSeparator The string to use to separate the fields.
       
   378 @return Pointer to the contact item descriptor. 
       
   379 */
       
   380 HBufC* CContactLocalView::AllFieldsLC(TInt aIndex,const TDesC& aSeparator) const
       
   381 	{
       
   382 #ifdef CONTACTS_API_PROFILING
       
   383 	TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassLocalView, TContactsApiProfile::ECntViewApiAllFieldsLC, aIndex);
       
   384 #endif
       
   385 	if( iState != EReady )
       
   386 		{
       
   387 		User::Leave(KErrNotReady);
       
   388 		}
       
   389 
       
   390 	return iViewCntMgr->AllFieldsLC(aIndex, aSeparator);
       
   391 	}
       
   392 
       
   393 	
       
   394 /**
       
   395 Sorts the view using the specified sort order, using a low priority idle time 
       
   396 active object.
       
   397 
       
   398 This function is called during view construction and on receipt of certain 
       
   399 change events from the underlying database.
       
   400 
       
   401 @param aSortOrder Specifies the fields to use to sort the items in the view. 
       
   402 */
       
   403 EXPORT_C void CContactLocalView::SortL(const RContactViewSortOrder& aSortOrder)
       
   404 	{
       
   405 #ifdef CONTACTS_API_PROFILING
       
   406 	TContactsApiProfile::CntViewMethodLog(TContactsApiProfile::ECntVwClassLocalView, TContactsApiProfile::ECntViewApiSortL);
       
   407 #endif
       
   408 
       
   409 	if (&iDb != NULL)
       
   410 		{
       
   411 		if (!iDb.DatabaseReadyL())
       
   412 			{
       
   413 			User::Leave(KErrNotReady);
       
   414 			}
       
   415 		}
       
   416 	
       
   417 	//set new sort order which also updates iTextDef.
       
   418 	SetSortOrderL(aSortOrder);	
       
   419 	
       
   420 	// reset sort error
       
   421 	iExtension->iError = KErrNone;
       
   422 	iViewCntMgr->SortL(*iTextDef);
       
   423 	}
       
   424 
       
   425 
       
   426 /**
       
   427  Set sort order used to sorting the view contacts.
       
   428  */
       
   429 void CContactLocalView::SetSortOrderL(const RContactViewSortOrder& aSortOrder)
       
   430 	{
       
   431 	// copy new sort order
       
   432 	iSortOrder.CopyL(aSortOrder);
       
   433 	
       
   434 	// New sort order for Sort Plugin
       
   435 	CViewContactSortPlugin* sortPluginImpl = SortPluginImpl();
       
   436 	if (sortPluginImpl)
       
   437 		{
       
   438 		sortPluginImpl->SetSortOrderL(aSortOrder);
       
   439 		}
       
   440 
       
   441 	// Initialisation for each explicitly requested sort or initialise sort
       
   442 	// Construct a text def to read out the required fields from the db.
       
   443 	CContactTextDef* textDef=CContactTextDef::NewLC();
       
   444 	TInt sortOrderCount=iSortOrder.Count();
       
   445 
       
   446 	for (TInt sortIndex=0;sortIndex<sortOrderCount;sortIndex++)
       
   447 		{
       
   448 		textDef->AppendL(TContactTextDefItem(iSortOrder[sortIndex]));
       
   449 		}
       
   450 	CleanupStack::Pop(); // textDef.
       
   451 	
       
   452 	delete iTextDef;
       
   453 	iTextDef=textDef;
       
   454 	}
       
   455 
       
   456 
       
   457 /**
       
   458 Start sorting if database is ready
       
   459 */
       
   460 void CContactLocalView::SortL()
       
   461 	{
       
   462 	// View can Sort only if database is 'ready'.
       
   463 	if (&iDb != NULL)
       
   464 		{
       
   465 		if (!iDb.DatabaseReadyL())
       
   466 			{
       
   467 			return;
       
   468 			}
       
   469 		}
       
   470 
       
   471 	// reset sort error
       
   472 	iExtension->iError = KErrNone;
       
   473 	iViewCntMgr->SortL();
       
   474 	}
       
   475 
       
   476 
       
   477 /**
       
   478 Unleavable(safe) resorting
       
   479 */
       
   480 void CContactLocalView::SafeResort()
       
   481 	{
       
   482 	TRAPD(sortError, SortL());
       
   483 
       
   484 	// notify any error
       
   485 	if (sortError)
       
   486 		{
       
   487 		NotifySortError(sortError);
       
   488 		}
       
   489 	}
       
   490 
       
   491 	
       
   492 /**
       
   493 Inserts a contact item into the view, maintaining the view's sort order.
       
   494 
       
   495 For the item to be inserted, it must exist in the underlying database, and 
       
   496 it must be of the correct type according to the view preferences.
       
   497 
       
   498 This function is called when a contact item or group is added to or changed 
       
   499 in the underlying database.
       
   500 
       
   501 @param aId The ID of a contact item that exists in the underlying database.
       
   502 @return The index at which the item was inserted into the view, or KErrNotFound 
       
   503 if the contact item was not found in the underlying database, or it already 
       
   504 exists in the view. 
       
   505 */
       
   506 EXPORT_C TInt CContactLocalView::InsertL(TContactItemId aId)
       
   507 	{
       
   508 #if defined(__VERBOSE_DEBUG__)
       
   509 	RDebug::Print(_L("[CNTMODEL] CContactLocalView{ViewPrefs = 0x%08X}::InsertL into view Contact Id %i\r\n"), 
       
   510 		iViewPreferences, aId);
       
   511 #endif
       
   512 
       
   513 	TContactViewPreferences view = iViewPreferences;
       
   514 	return iViewCntMgr->InsertL(aId, view);
       
   515 	}
       
   516 
       
   517 	
       
   518 /**
       
   519 Removes a contact item from the view.
       
   520 
       
   521 This function is called when a contact item or group is deleted from or changed 
       
   522 in the underlying database.
       
   523 
       
   524 @param aId The ID of the contact item to remove from the view.
       
   525 @return The index of the removed item into the view's list of sorted or unsorted 
       
   526 contact items, or KErrNotFound if the item was not found in the view. 
       
   527 */
       
   528 EXPORT_C TInt CContactLocalView::RemoveL(TContactItemId aId)
       
   529 	{
       
   530 	return iViewCntMgr->RemoveL(aId);
       
   531 	}
       
   532 
       
   533 EXPORT_C void CContactLocalView::CContactLocalView_Reserved_1()
       
   534 	{
       
   535 	}
       
   536 
       
   537 EXPORT_C void CContactLocalView::CContactLocalView_Reserved_2()
       
   538 	{
       
   539 	}
       
   540 
       
   541 
       
   542 /**
       
   543 Database event handler.
       
   544 
       
   545 @param aEvent the database event.
       
   546 */
       
   547 void CContactLocalView::HandleDatabaseEventL(TContactDbObserverEvent aEvent)
       
   548 	{
       
   549 	// handle Backup / Restore notifications before checking View State
       
   550 	switch (aEvent.iType)
       
   551 		{
       
   552 		case EContactDbObserverEventBackupBeginning:
       
   553 		case EContactDbObserverEventRestoreBeginning:
       
   554 #if defined(__VERBOSE_DEBUG__)
       
   555 			RDebug::Print(_L("[CNTMODEL] CContactLocalView{ViewPrefs = 0x%08X}::HandleDatabaseEventL -> Backup/Restore Beginning, state = %i\r\n"), 
       
   556 				iViewPreferences, iState);
       
   557 #endif
       
   558 			if (iState == EReady)
       
   559 				{
       
   560 				SetState(ENotReady);
       
   561 				}
       
   562 			else
       
   563 				{
       
   564 				// stop sorting
       
   565 				iViewCntMgr->StopSortL();
       
   566 				}
       
   567 			return;
       
   568 
       
   569 		case EContactDbObserverEventBackupRestoreCompleted:
       
   570 #if defined(__VERBOSE_DEBUG__)
       
   571 			RDebug::Print(_L("[CNTMODEL] CContactLocalView{ViewPrefs = 0x%08X}::HandleDatabaseEventL -> Backup/Restore Completed, state = %i, old sort error %i\r\n"), 
       
   572 				iViewPreferences, iState, iExtension->iError);
       
   573 #endif
       
   574 			if (iState == ENotReady && iExtension->iError == KErrNone)
       
   575 				{
       
   576 				// view was ready before tables were closed
       
   577 				SetState(EReady);
       
   578 				}
       
   579 			else // view was Initializing (sorting) before tables were closed
       
   580 				{
       
   581 				// re-read database and sort
       
   582 				SafeResort();
       
   583 				}
       
   584 			return;
       
   585 
       
   586 		default:
       
   587 			// other events dealt with below
       
   588 			break;
       
   589 		}
       
   590 
       
   591 
       
   592 	if (iState!=EReady)
       
   593 		{
       
   594 		if (iViewCntMgr->IsICCSynchronised())
       
   595 			{
       
   596 			/*
       
   597 			 * View events are only queued when the ICC has been synchronised. This prevents
       
   598 			 * duplicate contacts in an ICC view because add events are not queued until the 
       
   599 			 * SIM is fully synchronised. 
       
   600 			 * 
       
   601 			 * See LUD-5EBHZF "ICC contacts view broadcasts add item events after view is 
       
   602 			 * ready" for more detail.
       
   603        		 */
       
   604 			
       
   605 #if defined(__VERBOSE_DEBUG__)
       
   606 			DebugLogNotification(_L("[CNTMODEL] . . . . . Queueing Database Event "), aEvent);
       
   607 #endif
       
   608 			iOutstandingEvents.AppendL(aEvent);
       
   609 			
       
   610             // The view state is set to ENotReady when a recovery takes place, and also when the tables
       
   611             // are closed, so set ready here.
       
   612             if (iState == ENotReady && (aEvent.iType
       
   613                     == EContactDbObserverEventRecover || aEvent.iType
       
   614                     == EContactDbObserverEventTablesOpened))
       
   615                 {
       
   616                 SetState(EReady);
       
   617                 }
       
   618             // view was Initializing (sorting) before recovery or compression started!  
       
   619             if (iState == EInitializing && (aEvent.iType
       
   620                     == EContactDbObserverEventRecover || aEvent.iType
       
   621                     == EContactDbObserverEventCompress))
       
   622                 {
       
   623                 // re-read database and sort
       
   624                 SafeResort();
       
   625                 }
       
   626                 
       
   627 			}		
       
   628 			
       
   629 			
       
   630 #if defined(__VERBOSE_DEBUG__)
       
   631 		else
       
   632 			{
       
   633 			DebugLogNotification(_L("[CNTMODEL] . . . . . Discarding Database Event "), aEvent);
       
   634 			}
       
   635 #endif
       
   636 		}
       
   637 	else
       
   638 		{
       
   639 		TContactViewEvent event;
       
   640 		event.iInt = KErrNone;
       
   641 		switch(aEvent.iType)
       
   642 			{
       
   643 			case EContactDbObserverEventGroupChanged:
       
   644 				{
       
   645 				//Groups are a special case the base view may not contain the group
       
   646 				//but a sub view may be such a group and need to know its changed
       
   647 				//Local views can contain groups so this case carries on to the next so no break;
       
   648 				event.iEventType=TContactViewEvent::EGroupChanged;
       
   649 				event.iContactId=aEvent.iContactId;
       
   650 				NotifyObservers(event);
       
   651 				}
       
   652 			case EContactDbObserverEventContactChanged:
       
   653 			case EContactDbObserverEventOwnCardChanged:
       
   654 				{// Remove from old position, and notify.
       
   655 				TRAPD(err,event.iInt=RemoveL(aEvent.iContactId));
       
   656 
       
   657                 if (err == KErrNone && event.iInt != KErrNotFound)
       
   658                     {
       
   659 				    event.iEventType=TContactViewEvent::EItemRemoved;
       
   660 				    event.iContactId=aEvent.iContactId;
       
   661 				    NotifyObservers(event);
       
   662 					}
       
   663 				
       
   664 				// Insert at new position, and notify.
       
   665 				event.iInt=InsertL(aEvent.iContactId);
       
   666                 if (event.iInt != KErrNotFound)
       
   667 					{
       
   668 				    event.iEventType=TContactViewEvent::EItemAdded;
       
   669 				    event.iContactId=aEvent.iContactId;
       
   670 				    NotifyObservers(event);
       
   671                     }
       
   672 				break;
       
   673 				}
       
   674 			case EContactDbObserverEventContactAdded:
       
   675 			case EContactDbObserverEventGroupAdded:
       
   676 #if defined(__VERBOSE_DEBUG__)
       
   677 			DebugLogNotification(_L("[CNTMODEL] DatabaseEvent -> Contact/Group Added"), aEvent);
       
   678 #endif
       
   679 				event.iInt=InsertL(aEvent.iContactId);
       
   680 				if (event.iInt != KErrNotFound)
       
   681 					{
       
   682 					event.iEventType=TContactViewEvent::EItemAdded;
       
   683 					event.iContactId=aEvent.iContactId;
       
   684 					NotifyObservers(event);
       
   685 					}
       
   686 				break;
       
   687 			case EContactDbObserverEventContactDeleted:
       
   688 				if(aEvent.iContactId == KNullContactId) // KNullContactId indicates a bulk delete.
       
   689 					{ 
       
   690 					SetState(EInitializing); // Use initializing state to avoid ESortOrderChanged event being sent to observers. 
       
   691 					SafeResort(); 
       
   692 					} 
       
   693 				else 
       
   694 					{ 
       
   695 					event.iInt=RemoveL(aEvent.iContactId); 
       
   696 					if (event.iInt != KErrNotFound) 
       
   697 						{ 
       
   698 						event.iEventType=TContactViewEvent::EItemRemoved; 
       
   699 						event.iContactId=aEvent.iContactId; 
       
   700 						NotifyObservers(event); 
       
   701 						} 
       
   702 					} 
       
   703 				break; 
       
   704 			case EContactDbObserverEventGroupDeleted:
       
   705 			case EContactDbObserverEventOwnCardDeleted:
       
   706 				event.iInt=RemoveL(aEvent.iContactId);
       
   707 				if (event.iInt != KErrNotFound)
       
   708 					{
       
   709 					event.iEventType=TContactViewEvent::EItemRemoved;
       
   710 					event.iContactId=aEvent.iContactId;
       
   711 					NotifyObservers(event);
       
   712 					}
       
   713 				break;
       
   714 			case EContactDbObserverEventUnknownChanges:
       
   715 			case EContactDbObserverEventCurrentDatabaseChanged:
       
   716 				SetState(EInitializing); // Use initializing state to avoid ESortOrderChanged event being sent to observers.
       
   717 				SafeResort();
       
   718 				break;
       
   719 			case EContactDbObserverEventSortOrderChanged: // event is not currently used
       
   720 				SetState(ENotReady);
       
   721 				SafeResort();
       
   722 				break;
       
   723 			case EContactDbObserverEventTablesClosed:
       
   724 				if (iState == EReady)
       
   725 					{
       
   726 					SetState(ENotReady);
       
   727 					}
       
   728 				break;
       
   729 			case EContactDbObserverEventTablesOpened:
       
   730 				// re-read database and sort
       
   731 				SafeResort();
       
   732 				break;
       
   733 
       
   734 			case EContactDbObserverEventNull:
       
   735 			case EContactDbObserverEventUnused:
       
   736 			case EContactDbObserverEventRecover:
       
   737 			case EContactDbObserverEventCompress:
       
   738 			case EContactDbObserverEventRollback:
       
   739 			case EContactDbObserverEventTemplateChanged:
       
   740 			case EContactDbObserverEventTemplateDeleted:
       
   741 			case EContactDbObserverEventTemplateAdded:
       
   742 			case EContactDbObserverEventCurrentItemDeleted:
       
   743 			case EContactDbObserverEventCurrentItemChanged:				
       
   744 			case EContactDbObserverEventPreferredTemplateChanged:
       
   745 			case EContactDbObserverEventSpeedDialsChanged:
       
   746 			case EContactDbObserverEventRestoreBadDatabase:
       
   747 				break;
       
   748 
       
   749 			// these events should not come here, but be dealt with at the top of HandleDatabaseEventL
       
   750 			case EContactDbObserverEventBackupBeginning:
       
   751 			case EContactDbObserverEventRestoreBeginning:
       
   752 			case EContactDbObserverEventBackupRestoreCompleted:
       
   753 				break;
       
   754 				
       
   755 			default:
       
   756 				ASSERT(EFalse);
       
   757 			}
       
   758 		}
       
   759 	}
       
   760 
       
   761 	
       
   762 /**
       
   763 Called from view contact item manager to notify the sorting has finished.
       
   764 
       
   765 @param aSortErr error occurs in sorting or KErrNone if sorting completes without error.
       
   766 */
       
   767 void CContactLocalView::SortComplete(TInt aSortErr)
       
   768 	{
       
   769     if(aSortErr != KErrNone)
       
   770         {
       
   771 		NotifySortError(aSortErr);
       
   772 		return;
       
   773         }
       
   774         
       
   775 	if (iState != EInitializing)
       
   776 		{
       
   777 		//The view has just been re-sorted, notifiy observers ESortOrderChanged
       
   778 		iState = EReady;
       
   779 		NotifyObservers(TContactViewEvent(TContactViewEvent::ESortOrderChanged));
       
   780 		HandleOutstandingEvents();
       
   781 		}
       
   782 	else
       
   783 		{
       
   784 		// Sorted for the first time, notifiy ready
       
   785 		SetState(EReady);
       
   786 		}
       
   787 	}
       
   788 
       
   789 	
       
   790 /**
       
   791 Set database state
       
   792 
       
   793 @param aState database state to set.
       
   794 */
       
   795 void CContactLocalView::SetState(TState aState)
       
   796 	{
       
   797 	switch (iState)
       
   798 		{
       
   799 		case EInitializing:
       
   800 		case ENotReady:
       
   801 			ASSERT(aState==EReady);
       
   802 			iState=EReady;
       
   803 			NotifyObservers(TContactViewEvent(TContactViewEvent::EReady));
       
   804 			HandleOutstandingEvents();
       
   805 			break;
       
   806 		case EReady:
       
   807 			ASSERT(aState==ENotReady || aState==EInitializing);
       
   808 			// ensure sort error is reset
       
   809 			iExtension->iError = KErrNone;
       
   810 			iState=aState;
       
   811 			NotifyObservers(TContactViewEvent(TContactViewEvent::EUnavailable));
       
   812 			break;
       
   813 		default:
       
   814 			ASSERT(EFalse);
       
   815 		}
       
   816 	}
       
   817 
       
   818 
       
   819 /**
       
   820 Handle a particular queued event 
       
   821 */
       
   822 void CContactLocalView::HandleOutstandingEventL()
       
   823 	{
       
   824 	TContactDbObserverEvent event = iOutstandingEvents[0];
       
   825 	iOutstandingEvents.Remove(0);
       
   826 	HandleDatabaseEventL(event);
       
   827 	}
       
   828 
       
   829 /**
       
   830 Handle queued events when view is ready - sorting completes
       
   831 */
       
   832 void CContactLocalView::HandleOutstandingEvents()
       
   833 	{
       
   834 	while (iOutstandingEvents.Count() > 0)
       
   835 		{
       
   836 		// loop through as many events as possible in the one Trap harness
       
   837 		TRAP_IGNORE(HandleOutstandingEventL());
       
   838 		// if HandleDatabaseEventL left we must remove the event
       
   839 		}
       
   840 	}
       
   841 
       
   842 /**
       
   843 Gets the view preferences, as set during construction.
       
   844 
       
   845 @return The view preferences. 
       
   846 */
       
   847 TContactViewPreferences CContactLocalView::ContactViewPreferences()
       
   848 	{
       
   849 	return iViewPreferences;
       
   850 	}
       
   851 
       
   852 
       
   853 /**
       
   854 Gets the sort order, as set during construction.
       
   855 
       
   856 This function cannot leave.
       
   857 
       
   858 @return The sort order. 
       
   859 */
       
   860 const RContactViewSortOrder& CContactLocalView::SortOrderL() const
       
   861 	{
       
   862 	return iSortOrder;
       
   863 	}
       
   864 
       
   865 
       
   866 /**
       
   867 Notify observers that view construction failed.
       
   868 The error is stored so that if another client tries to open the view
       
   869 they will receive the same error.
       
   870 
       
   871 @param aError Leave code from CIdleContactSorter::RunL
       
   872 */
       
   873 void CContactLocalView::NotifySortError(TInt aError)
       
   874 	{
       
   875 	iExtension->iError = aError;
       
   876 	NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError, aError));
       
   877 	}
       
   878 
       
   879 
       
   880 /**
       
   881 This is a reserved virtual exported function that is used for BC proofing 
       
   882 against present and future additions of new exported virtual functions.
       
   883 
       
   884 @return Any return values of the helper methods called from this function or NULL.
       
   885 */
       
   886 EXPORT_C TAny* CContactLocalView::CContactViewBase_Reserved_1(TFunction aFunction,TAny* aParams)
       
   887 	{
       
   888 	return CContactViewBase::CContactViewBase_Reserved_1(aFunction,aParams);
       
   889 	}
       
   890