phonebookengines/contactsmodel/cntplsql/src/csqlitelocalview.cpp
changeset 0 e686773b3f54
child 3 04ab22b956c2
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     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 			
       
   611 			
       
   612 #if defined(__VERBOSE_DEBUG__)
       
   613 		else
       
   614 			{
       
   615 			DebugLogNotification(_L("[CNTMODEL] . . . . . Discarding Database Event "), aEvent);
       
   616 			}
       
   617 #endif
       
   618 		}
       
   619 	else
       
   620 		{
       
   621 		TContactViewEvent event;
       
   622 		event.iInt = KErrNone;
       
   623 		switch(aEvent.iType)
       
   624 			{
       
   625 			case EContactDbObserverEventGroupChanged:
       
   626 				{
       
   627 				//Groups are a special case the base view may not contain the group
       
   628 				//but a sub view may be such a group and need to know its changed
       
   629 				//Local views can contain groups so this case carries on to the next so no break;
       
   630 				event.iEventType=TContactViewEvent::EGroupChanged;
       
   631 				event.iContactId=aEvent.iContactId;
       
   632 				NotifyObservers(event);
       
   633 				}
       
   634 			case EContactDbObserverEventContactChanged:
       
   635 			case EContactDbObserverEventOwnCardChanged:
       
   636 				{// Remove from old position, and notify.
       
   637 				TRAPD(err,event.iInt=RemoveL(aEvent.iContactId));
       
   638 
       
   639                 if (err == KErrNone && event.iInt != KErrNotFound)
       
   640                     {
       
   641 				    event.iEventType=TContactViewEvent::EItemRemoved;
       
   642 				    event.iContactId=aEvent.iContactId;
       
   643 				    NotifyObservers(event);
       
   644 					}
       
   645 				
       
   646 				// Insert at new position, and notify.
       
   647 				event.iInt=InsertL(aEvent.iContactId);
       
   648                 if (event.iInt != KErrNotFound)
       
   649 					{
       
   650 				    event.iEventType=TContactViewEvent::EItemAdded;
       
   651 				    event.iContactId=aEvent.iContactId;
       
   652 				    NotifyObservers(event);
       
   653                     }
       
   654 				break;
       
   655 				}
       
   656 			case EContactDbObserverEventContactAdded:
       
   657 			case EContactDbObserverEventGroupAdded:
       
   658 #if defined(__VERBOSE_DEBUG__)
       
   659 			DebugLogNotification(_L("[CNTMODEL] DatabaseEvent -> Contact/Group Added"), aEvent);
       
   660 #endif
       
   661 				event.iInt=InsertL(aEvent.iContactId);
       
   662 				if (event.iInt != KErrNotFound)
       
   663 					{
       
   664 					event.iEventType=TContactViewEvent::EItemAdded;
       
   665 					event.iContactId=aEvent.iContactId;
       
   666 					NotifyObservers(event);
       
   667 					}
       
   668 				break;
       
   669 			case EContactDbObserverEventContactDeleted:
       
   670 				if(aEvent.iContactId == KNullContactId) // KNullContactId indicates a bulk delete.
       
   671 					{ 
       
   672 					SetState(EInitializing); // Use initializing state to avoid ESortOrderChanged event being sent to observers. 
       
   673 					SafeResort(); 
       
   674 					} 
       
   675 				else 
       
   676 					{ 
       
   677 					event.iInt=RemoveL(aEvent.iContactId); 
       
   678 					if (event.iInt != KErrNotFound) 
       
   679 						{ 
       
   680 						event.iEventType=TContactViewEvent::EItemRemoved; 
       
   681 						event.iContactId=aEvent.iContactId; 
       
   682 						NotifyObservers(event); 
       
   683 						} 
       
   684 					} 
       
   685 				break; 
       
   686 			case EContactDbObserverEventGroupDeleted:
       
   687 			case EContactDbObserverEventOwnCardDeleted:
       
   688 				event.iInt=RemoveL(aEvent.iContactId);
       
   689 				if (event.iInt != KErrNotFound)
       
   690 					{
       
   691 					event.iEventType=TContactViewEvent::EItemRemoved;
       
   692 					event.iContactId=aEvent.iContactId;
       
   693 					NotifyObservers(event);
       
   694 					}
       
   695 				break;
       
   696 			case EContactDbObserverEventUnknownChanges:
       
   697 			case EContactDbObserverEventCurrentDatabaseChanged:
       
   698 				SetState(EInitializing); // Use initializing state to avoid ESortOrderChanged event being sent to observers.
       
   699 				SafeResort();
       
   700 				break;
       
   701 			case EContactDbObserverEventSortOrderChanged: // event is not currently used
       
   702 				SetState(ENotReady);
       
   703 				SafeResort();
       
   704 				break;
       
   705 			case EContactDbObserverEventTablesClosed:
       
   706 				if (iState == EReady)
       
   707 					{
       
   708 					SetState(ENotReady);
       
   709 					}
       
   710 				break;
       
   711 			case EContactDbObserverEventTablesOpened:
       
   712 				// re-read database and sort
       
   713 				SafeResort();
       
   714 				break;
       
   715 
       
   716 			case EContactDbObserverEventNull:
       
   717 			case EContactDbObserverEventUnused:
       
   718 			case EContactDbObserverEventRecover:
       
   719 			case EContactDbObserverEventCompress:
       
   720 			case EContactDbObserverEventRollback:
       
   721 			case EContactDbObserverEventTemplateChanged:
       
   722 			case EContactDbObserverEventTemplateDeleted:
       
   723 			case EContactDbObserverEventTemplateAdded:
       
   724 			case EContactDbObserverEventCurrentItemDeleted:
       
   725 			case EContactDbObserverEventCurrentItemChanged:				
       
   726 			case EContactDbObserverEventPreferredTemplateChanged:
       
   727 			case EContactDbObserverEventSpeedDialsChanged:
       
   728 			case EContactDbObserverEventRestoreBadDatabase:
       
   729 				break;
       
   730 
       
   731 			// these events should not come here, but be dealt with at the top of HandleDatabaseEventL
       
   732 			case EContactDbObserverEventBackupBeginning:
       
   733 			case EContactDbObserverEventRestoreBeginning:
       
   734 			case EContactDbObserverEventBackupRestoreCompleted:
       
   735 				break;
       
   736 				
       
   737 			default:
       
   738 				ASSERT(EFalse);
       
   739 			}
       
   740 		}
       
   741 	}
       
   742 
       
   743 	
       
   744 /**
       
   745 Called from view contact item manager to notify the sorting has finished.
       
   746 
       
   747 @param aSortErr error occurs in sorting or KErrNone if sorting completes without error.
       
   748 */
       
   749 void CContactLocalView::SortComplete(TInt aSortErr)
       
   750 	{
       
   751     if(aSortErr != KErrNone)
       
   752         {
       
   753 		NotifySortError(aSortErr);
       
   754 		return;
       
   755         }
       
   756         
       
   757 	if (iState != EInitializing)
       
   758 		{
       
   759 		//The view has just been re-sorted, notifiy observers ESortOrderChanged
       
   760 		iState = EReady;
       
   761 		NotifyObservers(TContactViewEvent(TContactViewEvent::ESortOrderChanged));
       
   762 		HandleOutstandingEvents();
       
   763 		}
       
   764 	else
       
   765 		{
       
   766 		// Sorted for the first time, notifiy ready
       
   767 		SetState(EReady);
       
   768 		}
       
   769 	}
       
   770 
       
   771 	
       
   772 /**
       
   773 Set database state
       
   774 
       
   775 @param aState database state to set.
       
   776 */
       
   777 void CContactLocalView::SetState(TState aState)
       
   778 	{
       
   779 	switch (iState)
       
   780 		{
       
   781 		case EInitializing:
       
   782 		case ENotReady:
       
   783 			ASSERT(aState==EReady);
       
   784 			iState=EReady;
       
   785 			NotifyObservers(TContactViewEvent(TContactViewEvent::EReady));
       
   786 			HandleOutstandingEvents();
       
   787 			break;
       
   788 		case EReady:
       
   789 			ASSERT(aState==ENotReady || aState==EInitializing);
       
   790 			// ensure sort error is reset
       
   791 			iExtension->iError = KErrNone;
       
   792 			iState=aState;
       
   793 			NotifyObservers(TContactViewEvent(TContactViewEvent::EUnavailable));
       
   794 			break;
       
   795 		default:
       
   796 			ASSERT(EFalse);
       
   797 		}
       
   798 	}
       
   799 
       
   800 
       
   801 /**
       
   802 Handle a particular queued event 
       
   803 */
       
   804 void CContactLocalView::HandleOutstandingEventL()
       
   805 	{
       
   806 	TContactDbObserverEvent event = iOutstandingEvents[0];
       
   807 	iOutstandingEvents.Remove(0);
       
   808 	HandleDatabaseEventL(event);
       
   809 	}
       
   810 
       
   811 /**
       
   812 Handle queued events when view is ready - sorting completes
       
   813 */
       
   814 void CContactLocalView::HandleOutstandingEvents()
       
   815 	{
       
   816 	while (iOutstandingEvents.Count() > 0)
       
   817 		{
       
   818 		// loop through as many events as possible in the one Trap harness
       
   819 		TRAP_IGNORE(HandleOutstandingEventL());
       
   820 		// if HandleDatabaseEventL left we must remove the event
       
   821 		}
       
   822 	}
       
   823 
       
   824 /**
       
   825 Gets the view preferences, as set during construction.
       
   826 
       
   827 @return The view preferences. 
       
   828 */
       
   829 TContactViewPreferences CContactLocalView::ContactViewPreferences()
       
   830 	{
       
   831 	return iViewPreferences;
       
   832 	}
       
   833 
       
   834 
       
   835 /**
       
   836 Gets the sort order, as set during construction.
       
   837 
       
   838 This function cannot leave.
       
   839 
       
   840 @return The sort order. 
       
   841 */
       
   842 const RContactViewSortOrder& CContactLocalView::SortOrderL() const
       
   843 	{
       
   844 	return iSortOrder;
       
   845 	}
       
   846 
       
   847 
       
   848 /**
       
   849 Notify observers that view construction failed.
       
   850 The error is stored so that if another client tries to open the view
       
   851 they will receive the same error.
       
   852 
       
   853 @param aError Leave code from CIdleContactSorter::RunL
       
   854 */
       
   855 void CContactLocalView::NotifySortError(TInt aError)
       
   856 	{
       
   857 	iExtension->iError = aError;
       
   858 	NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError, aError));
       
   859 	}
       
   860 
       
   861 
       
   862 /**
       
   863 This is a reserved virtual exported function that is used for BC proofing 
       
   864 against present and future additions of new exported virtual functions.
       
   865 
       
   866 @return Any return values of the helper methods called from this function or NULL.
       
   867 */
       
   868 EXPORT_C TAny* CContactLocalView::CContactViewBase_Reserved_1(TFunction aFunction,TAny* aParams)
       
   869 	{
       
   870 	return CContactViewBase::CContactViewBase_Reserved_1(aFunction,aParams);
       
   871 	}
       
   872