phonebookengines/contactsmodel/cntmodel/src/ccontactdatabase.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
equal deleted inserted replaced
62:5b6f26637ad3 63:f4a778e096c2
       
     1 // Copyright (c) 2005-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 <cntitem.h>
       
    17 #include <f32file.h>
       
    18 #include <cntfldst.h>   //for ccontactfieldstorage used in setfieldasspeeddiall
       
    19 #include <phbksync.h>
       
    20 #include <cntdb.h>
       
    21 
       
    22 #include "CNTSTD.H"
       
    23 #include "rcntmodel.h"
       
    24 #include "ccontactprivate.h"
       
    25 
       
    26 #include "clplproxyfactory.h"
       
    27 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    28 #include "cntdb_internal.h"
       
    29 #include "cntsyncecom.h"
       
    30 
       
    31 const TInt KMajorVersion=1;
       
    32 
       
    33 const TInt KMinorVersion=0;
       
    34 
       
    35 const TInt KBuildNumber=40;
       
    36 #endif
       
    37 
       
    38 CContactDatabase::CContactDatabase():
       
    39 		iDbConnectionState(EDbConnectionNotReady),
       
    40 		iTablesOpen(EFalse),
       
    41 		iDbViewContactType(KUidContactItem),
       
    42 		iContactSynchroniser(NULL)
       
    43 	{
       
    44 	// Needed to ensure unicode sorting / inserting into sorted lists works the
       
    45 	// same as er5 i.e. that it encludes all spaces and punctuation.
       
    46 	iCollateMethod = *Mem::CollationMethodByIndex(0);
       
    47 	iCollateMethod.iFlags|=TCollationMethod::EIgnoreNone;
       
    48 	}
       
    49 
       
    50 
       
    51 /**
       
    52 Frees all resources owned by the contact database, prior to its destruction.
       
    53 */
       
    54 EXPORT_C CContactDatabase::~CContactDatabase()
       
    55 	{
       
    56 	delete iConv;
       
    57 	delete iProxyFactory;
       
    58 	delete iView;
       
    59 	delete iAllFieldsView;
       
    60 	delete iCardTemplateIds;
       
    61 	delete iGroupIds;
       
    62 	delete iTemplateCache;
       
    63 	delete iTextDef;
       
    64 	if (iCntSvr)
       
    65 		{
       
    66 		iCntSvr->RemoveObserver(*iDataBaseObserver);
       
    67 		iCntSvr->Close();
       
    68 		}
       
    69 	if (iContactSynchroniser)
       
    70 		{
       
    71 		iContactSynchroniser->Release();
       
    72 		iContactSynchroniser = NULL;
       
    73 		}
       
    74 	delete iDataBaseObserver;
       
    75 	delete iCntSvr;
       
    76 	delete iIdleSorter;
       
    77 	delete iSortedItems;
       
    78 	delete iSortOrder;
       
    79 	REComSession::FinalClose();
       
    80 	}
       
    81 
       
    82 
       
    83 /**
       
    84 Create a new CContactDatabase object 
       
    85 */
       
    86 CContactDatabase* CContactDatabase::NewLC()
       
    87 	{
       
    88 	CContactDatabase* db =new(ELeave) CContactDatabase();
       
    89 	CleanupStack::PushL(db);
       
    90 	db->ConstructL();
       
    91 	return db;
       
    92 	}
       
    93 
       
    94 
       
    95 void CContactDatabase::ConstructL()
       
    96 	{
       
    97 	iCntSvr = new (ELeave) RCntModel;
       
    98 	iCntSvr->ConnectL();
       
    99 	iProxyFactory = CProxyFactory::NewL(*this);
       
   100 	CreateViewDefL();
       
   101 	iTemplateCache = CCntTemplateCache::NewL(*iCntSvr);
       
   102 	iDataBaseObserver = CDataBaseChangeObserver::NewL(*this);
       
   103 	iCntSvr->AddObserverL(*iDataBaseObserver);
       
   104 	iIdleSorter = CCntIdleSorter::NewL(*this);
       
   105 	}
       
   106 
       
   107 
       
   108 void CContactDatabase::CreateViewDefL()
       
   109 	{
       
   110 	// The exact same object is created in the Session on the server. If
       
   111 	// it is changed here it must also be changed in the server code.
       
   112 	CContactItemViewDef* itemDef = CContactItemViewDef::NewLC(CContactItemViewDef::EIncludeFields,CContactItemViewDef::EMaskHiddenFields);
       
   113 	itemDef->AddL(KUidContactFieldMatchAll);
       
   114 	iView = CContactViewDef::NewL(itemDef);
       
   115 	CleanupStack::Pop(itemDef);
       
   116 
       
   117 	// iAllFieldView is not created on the server code - an exported getter method
       
   118 	// allows the user to modify this member and so it cannot be mirrored on the
       
   119 	// server
       
   120 	iAllFieldsView = CContactItemViewDef::NewL(CContactItemViewDef::EMaskFields,CContactItemViewDef::EIncludeHiddenFields);
       
   121 	}
       
   122 
       
   123 
       
   124 /**
       
   125 For BC.
       
   126 
       
   127 @internalComponent
       
   128 */
       
   129 EXPORT_C CContactDatabase* CContactDatabase::LockServerConnectL(const TDesC& /*aFileName*/)
       
   130 	{
       
   131 	return NULL;
       
   132 	}
       
   133 
       
   134 
       
   135 /**
       
   136 For BC.
       
   137 
       
   138 @internalComponent
       
   139 */
       
   140 EXPORT_C CContactDatabase* CContactDatabase::LockServerConnectL(const TDesC& /*aFileName*/, TInt /*aOperation*/)
       
   141 	{
       
   142 	return NULL;
       
   143 	}
       
   144 
       
   145 
       
   146 /**
       
   147 For BC.
       
   148 
       
   149 @internalComponent
       
   150 */
       
   151 EXPORT_C TInt CContactDatabase::LockServerCallBackL(TUint /*aServerOperation*/)
       
   152 	{
       
   153 	return NULL;
       
   154 	}
       
   155 
       
   156 
       
   157 /**
       
   158 For BC.
       
   159 
       
   160 @internalComponent
       
   161 */
       
   162 EXPORT_C void CContactDatabase::LockServerCleanup()
       
   163 	{
       
   164 	}
       
   165 
       
   166 
       
   167 /**
       
   168 Gets the file name of the default contact database.
       
   169 
       
   170 By default it is on drive C: but this can be changed using SetDatabaseDriveL().
       
   171 
       
   172 @capability None
       
   173 
       
   174 @param aDes On return, contains the drive and filename of the default 
       
   175 contact database. From v9.0 onwards, this has the form driveletter:filename, 
       
   176 in other words, it does not include a path.
       
   177 
       
   178 @see CContactDatabase::SetDatabaseDriveL()
       
   179 @see CContactDatabase::DatabaseDrive()
       
   180 @see CContactDatabase::DefaultContactDatabaseExistsL()
       
   181 */
       
   182 EXPORT_C void CContactDatabase::GetDefaultNameL(TDes& aDes)
       
   183 	{
       
   184 	CContactDatabase* db = NewLC();
       
   185 	User::LeaveIfError(db->iCntSvr->DefaultDatabase(aDes));
       
   186 	CleanupStack::PopAndDestroy(db);	
       
   187 	}
       
   188 
       
   189 
       
   190 /**
       
   191 Deletes the default contact database.
       
   192 
       
   193 @capability WriteUserData
       
   194 
       
   195 @leave	KErrInUse Another client has the database open.
       
   196 @leave	KErrNotFound The database file was not found or it did not have the correct UIDs.
       
   197 
       
   198 @see CContactDatabase::DeleteDatabaseL()
       
   199 @see CContactDatabase::GetDefaultNameL()
       
   200 @see CContactDatabase::DefaultContactDatabaseExistsL()
       
   201 */
       
   202 EXPORT_C void CContactDatabase::DeleteDefaultFileL()
       
   203 	{
       
   204 	CContactDatabase* db = NewLC();
       
   205 	User::LeaveIfError(db->iCntSvr->DeleteDatabase(KNullDesC));
       
   206 	CleanupStack::PopAndDestroy(db);
       
   207 	}
       
   208 
       
   209 
       
   210 /**
       
   211 Gets the current database drive. The database drive is the drive on which 
       
   212 the default contact database is located. Note: this function can leave.
       
   213 
       
   214 @capability None
       
   215 
       
   216 @param aDriveUnit On return, contains the database drive.
       
   217 
       
   218 @return ETrue if the database drive has been set using SetDatabaseDriveL(). 
       
   219 Otherwise EFalse and in this case, the function returns drive c: in aDriveUnit 
       
   220 as the current drive.
       
   221 
       
   222 @leave KErrNoMemory Out of memory.
       
   223 
       
   224 @see CContactDatabase::SetDatabaseDrive()
       
   225 @see CContactDatabase::GetDefaultNameL()
       
   226 */
       
   227 EXPORT_C TBool CContactDatabase::DatabaseDrive(TDriveUnit& aDriveUnit)
       
   228 	{
       
   229 	CContactDatabase* db = NewLC(); // this can leave
       
   230 	TBool ret = db->iCntSvr->DatabaseDrive(aDriveUnit);
       
   231 	CleanupStack::PopAndDestroy(db);
       
   232 	return ret;
       
   233 	}
       
   234 
       
   235 
       
   236 /**
       
   237 Sets the contact database drive and optionally moves the default contact database 
       
   238 from its current location to the new drive. This function guarantees an all 
       
   239 or nothing operation. If the database is not successfully moved, the drive 
       
   240 setting is not updated to reflect the change.
       
   241 
       
   242 In v8.1 when copying the file is moved to \\system\\data on the specified 
       
   243 drive, and if the destination file already exists it is replaced.
       
   244 
       
   245 From v9.0 onwards the file copying goes to the correct data caged directory
       
   246 on the destination drive. If the destination file already exists the copy 
       
   247 fails.
       
   248 
       
   249 @capability WriteUserData
       
   250 
       
   251 @param	aDriveUnit
       
   252 		The drive to which to move the database.
       
   253 @param	aCopy
       
   254 		ETrue moves the existing file to the specified drive. Deletion of
       
   255 		the source file will fail if it is in use.
       
   256 		EFalse does not move the file.
       
   257 
       
   258 @leave KErrNotReady There is no media present in the drive.
       
   259 @leave KErrInUse The destination file for the copy is already open.
       
   260 @leave KErrNotFound The source file for the copy was not found.
       
   261 @leave KErrAlreadyExists The destination file for the copy already exists, (v9.0).
       
   262 
       
   263 @see CContactdatabase::DatabaseDrive()
       
   264 @see CContactDatabase::GetDefaultNameL()
       
   265 @see CContactDatabase::DefaultContactDatabaseExistsL()
       
   266 */
       
   267 EXPORT_C void CContactDatabase::SetDatabaseDriveL(TDriveUnit aDriveUnit, TBool aCopy)
       
   268 	{
       
   269 	CContactDatabase* db = NewLC();
       
   270 	db->iCntSvr->SetDatabaseDriveL(aDriveUnit, aCopy);
       
   271 	CleanupStack::PopAndDestroy(db); 
       
   272 	}
       
   273 
       
   274 
       
   275 /**
       
   276 Opens the default contact database.
       
   277 
       
   278 Note: clients should not assume any knowledge of the default database name or location 
       
   279 because they may be changed in future releases.
       
   280 
       
   281 @capability ReadUserData
       
   282 
       
   283 @param  aAccess The default (ESingleThread) allows access to the session with the 
       
   284 database server from a single client thread only (as in v5 and v5.1). EMultiThread 
       
   285 allows multiple client threads to share the same session with the server. As 
       
   286 multi-threaded programs are uncommon in Symbian OS, this argument can be ignored 
       
   287 by most C++ developers
       
   288 
       
   289 @return Pointer to the open contact database. 
       
   290 
       
   291 @leave	KErrNotFound The database file was not found or it did not have the correct UIDs.
       
   292 @leave	KErrLocked Another client is writing to the database. 
       
   293 @leave	KErrDiskFull The disk does not have enough free space to perform the operation.
       
   294 */
       
   295 EXPORT_C CContactDatabase* CContactDatabase::OpenL(TThreadAccess aAccess)
       
   296 	{
       
   297 	CContactDatabase* db = NewLC();
       
   298 	User::LeaveIfError(db->iCntSvr->OpenDatabase(KNullDesC));
       
   299 	if( aAccess == EMultiThread )
       
   300 		{
       
   301 		db->iCntSvr->ShareAuto();
       
   302 		} 
       
   303 	db->FetchGroupAndTemplateListsL();
       
   304 	CleanupStack::Pop(db);
       
   305 	return db;
       
   306 	}
       
   307 
       
   308 
       
   309 /**
       
   310 Opens a named contact database.
       
   311 
       
   312 From v9.0 onwards, contact databases can only be located in the correct data caged 
       
   313 subdirectory. The filenames must have no path, for example c:contacts.cdb.
       
   314 The maximum length for the drive, filename and extension is 190 characters, and empty
       
   315 string is not accepted.
       
   316 
       
   317 @capability ReadUserData
       
   318 
       
   319 @param	aFileName The filename of the database to open.
       
   320 @param  aAccess The default (ESingleThread) allows access to the session with the 
       
   321 database server from a single client thread only (as in v5 and v5.1). EMultiThread 
       
   322 allows multiple client threads to share the same session with the server. As 
       
   323 multi-threaded programs are uncommon in Symbian OS, this argument can be ignored 
       
   324 by most C++ developers
       
   325 
       
   326 @leave	KErrNotFound The database file was not found or it did not have the correct UIDs.
       
   327 @leave	KErrLocked Another client is writing to the database.
       
   328 @leave	KErrBadName The filename is invalid; for example it contains 
       
   329 wildcard characters or the drive is missing.
       
   330 @leave	KErrDiskFull The disk does not have enough free space to perform the operation.
       
   331 @leave  KErrArgument if the given descriptor contains more than the maximum length 
       
   332         of 190 characters.
       
   333 
       
   334 @return A pointer to the open contact database.
       
   335 */
       
   336 EXPORT_C CContactDatabase* CContactDatabase::OpenL(const TDesC& aFileName, TThreadAccess aAccess)
       
   337 	{
       
   338 	__ASSERT_ALWAYS(aFileName.Length() != 0, User::Leave(KErrBadName) );
       
   339 	CContactDatabase* db = NewLC();
       
   340 	User::LeaveIfError(db->iCntSvr->OpenDatabase(aFileName));
       
   341 	if( aAccess == EMultiThread )
       
   342 		{
       
   343 		db->iCntSvr->ShareAuto();
       
   344 		} 
       
   345 	db->FetchGroupAndTemplateListsL();
       
   346 	CleanupStack::Pop(db);
       
   347 	return db;
       
   348 	}
       
   349 
       
   350 
       
   351 /** 
       
   352 Creates and opens an empty contact database, replacing the existing default 
       
   353 database. 
       
   354 
       
   355 @capability WriteUserData
       
   356 
       
   357 @param  aAccess The default (ESingleThread) allows access to the session with the 
       
   358 database server from a single client thread only (as in v5 and v5.1). EMultiThread 
       
   359 allows multiple client threads to share the same session with the server. As 
       
   360 multi-threaded programs are uncommon in Symbian OS, this argument can be ignored 
       
   361 by most C++ developers
       
   362 
       
   363 @return Pointer to the new contact database.
       
   364 
       
   365 @leave	KErrInUse Another client has an open connection to the database.
       
   366 @leave	KErrDiskFull The disk does not have enough free space to perform the operation.
       
   367 @leave	KErrNoMemory There is no memory to perform the operation.
       
   368 */
       
   369 EXPORT_C CContactDatabase* CContactDatabase::ReplaceL(TThreadAccess aAccess)
       
   370 	{
       
   371 	CContactDatabase* db = NewLC();
       
   372 	User::LeaveIfError(db->iCntSvr->ReplaceDatabase(KNullDesC));
       
   373 	if( aAccess == EMultiThread )
       
   374 		{
       
   375 		db->iCntSvr->ShareAuto();
       
   376 		} 
       
   377 	db->FetchGroupAndTemplateListsL();
       
   378 	CleanupStack::Pop(db);
       
   379 	return db;
       
   380 	}
       
   381 	
       
   382 	
       
   383 /**
       
   384 Creates and opens an empty contact database, replacing any existing file with 
       
   385 the same name.
       
   386 
       
   387 From v9.0 onwards, contact databases can only be located in the correct data caged 
       
   388 subdirectory. The filenames must have no path, for example c:contacts.cdb.
       
   389 The maximum length for the drive, filename and extension is 190 characters.
       
   390 
       
   391 @capability WriteUserData
       
   392 
       
   393 @param	aFileName The filename of the database to replace.
       
   394 @param  aAccess The default (ESingleThread) allows access to the session with the 
       
   395 database server from a single client thread only (as in v5 and v5.1). EMultiThread 
       
   396 allows multiple client threads to share the same session with the server. As 
       
   397 multi-threaded programs are uncommon in Symbian OS, this argument can be ignored 
       
   398 by most C++ developers
       
   399 
       
   400 @leave	KErrBadName The filename is invalid; for example it contains wildcard characters 
       
   401 or the drive letter is missing.
       
   402 @leave	KErrInUse Another client has an open connection to the database.
       
   403 @leave	KErrDiskFull The disk does not have enough free space to perform the operation.
       
   404 @leave	KErrNoMemory There is no memory to perform the operation.
       
   405 @leave  KErrArgument if the given descriptor contains more than the maximum length 
       
   406         of 190 characters.
       
   407 
       
   408 @return A pointer to the new contact database.
       
   409 */				
       
   410 EXPORT_C CContactDatabase* CContactDatabase::ReplaceL(const TDesC& aFileName, TThreadAccess aAccess)
       
   411 	{
       
   412 	__ASSERT_ALWAYS(aFileName.Length() != 0, User::Leave(KErrBadName) );
       
   413 	CContactDatabase* db = NewLC();
       
   414 	User::LeaveIfError(db->iCntSvr->ReplaceDatabase(aFileName)); 
       
   415 	if( aAccess == EMultiThread )
       
   416 		{
       
   417 		db->iCntSvr->ShareAuto();
       
   418 		} 
       
   419 	db->FetchGroupAndTemplateListsL();
       
   420 	CleanupStack::Pop(db);
       
   421 	return db;
       
   422 	}
       
   423 
       
   424 
       
   425 /** 
       
   426 Creates and opens an empty contact database using the default database name. 
       
   427 
       
   428 @capability WriteUserData
       
   429 
       
   430 @param  aAccess The default (ESingleThread) allows access to the session with the 
       
   431 database server from a single client thread only (as in v5 and v5.1). EMultiThread 
       
   432 allows multiple client threads to share the same session with the server. As 
       
   433 multi-threaded programs are uncommon in Symbian OS, this argument can be ignored 
       
   434 by most C++ developers
       
   435 
       
   436 @return A pointer to the new contact database. 
       
   437 
       
   438 @leave	KErrAlreadyExists The database already exists.
       
   439 @leave	KErrDiskFull The disk does not have enough free space to perform the operation.
       
   440 */
       
   441 EXPORT_C CContactDatabase* CContactDatabase::CreateL(TThreadAccess aAccess)
       
   442 	{
       
   443 	CContactDatabase* db = NewLC();
       
   444 	User::LeaveIfError(db->iCntSvr->CreateDatabase(KNullDesC)); 
       
   445 	if( aAccess == EMultiThread )
       
   446 		{
       
   447 		db->iCntSvr->ShareAuto();
       
   448 		} 
       
   449 	db->FetchGroupAndTemplateListsL();
       
   450 	CleanupStack::Pop  (db);
       
   451 	return db;	
       
   452 	}
       
   453 
       
   454 
       
   455 /**
       
   456 Creates and opens a named contact database. 
       
   457 
       
   458 From v9.0 onwards, contact databases can only be located in the correct data caged 
       
   459 subdirectory. The filenames must have no path, for example c:contacts.cdb.
       
   460 The maximum length for the drive, filename and extension is 190 characters.
       
   461 
       
   462 @capability WriteUserData
       
   463 
       
   464 @param	aFileName The filename of the database to create. 
       
   465 @param  aAccess The default (ESingleThread) allows access to the session with the 
       
   466 database server from a single client thread only (as in v5 and v5.1). EMultiThread 
       
   467 allows multiple client threads to share the same session with the server. As 
       
   468 multi-threaded programs are uncommon in Symbian OS, this argument can be ignored 
       
   469 by most C++ developers
       
   470 
       
   471 @leave	KErrAlreadyExists The database already exists. 
       
   472 @leave	KErrBadName The filename is invalid; for example it contains wildcard characters 
       
   473 or the drive letter is missing.
       
   474 @leave	KErrDiskFull The disk does not have enough free space to perform the operation.
       
   475 @leave  KErrArgument if the given descriptor contains more than the maximum length 
       
   476         of 190 characters.
       
   477 
       
   478 @return A pointer to the new contact database.
       
   479 */
       
   480 EXPORT_C CContactDatabase* CContactDatabase::CreateL(const TDesC& aFileName,TThreadAccess aAccess)
       
   481 	{
       
   482 	__ASSERT_ALWAYS(aFileName.Length() != 0, User::Leave(KErrBadName) );
       
   483 	CContactDatabase* db = NewLC();
       
   484 	User::LeaveIfError(db->iCntSvr->CreateDatabase(aFileName)); 
       
   485 	if( aAccess == EMultiThread )
       
   486 		{
       
   487 		db->iCntSvr->ShareAuto();
       
   488 		} 
       
   489 	db->FetchGroupAndTemplateListsL();
       
   490 	CleanupStack::Pop  (db);
       
   491 	return db;	
       
   492 	}
       
   493 
       
   494 
       
   495 /**
       
   496 This method is no longer required and should not be called.
       
   497 
       
   498 Closes all database tables. After a rollback and recover all tables need to 
       
   499 be closed and re-opened before the database can be accessed again.
       
   500 
       
   501 @capability WriteUserData
       
   502 @deprecated
       
   503 */
       
   504 EXPORT_C void CContactDatabase::CloseTables()
       
   505 	{  	
       
   506 	TRAP_IGNORE( iCntSvr->CloseTablesL() );   
       
   507 	}
       
   508 
       
   509 
       
   510 /** 
       
   511 This method is no longer required and should not be called.
       
   512 
       
   513 Opens all database tables. After a rollback and recover all tables need to 
       
   514 be closed and re-opened before the database can be accessed again.
       
   515 
       
   516 @capability ReadUserData
       
   517 @deprecated
       
   518 */
       
   519 EXPORT_C void CContactDatabase::OpenTablesL()
       
   520 	{
       
   521 	iCntSvr->OpenTablesL();	
       
   522 	}
       
   523 
       
   524 
       
   525 /**
       
   526 A static method to recreate the system template. 
       
   527 
       
   528 From v9.0 onwards, contact databases can only be located in the correct data caged 
       
   529 subdirectory. The filenames must have no path, for example c:contacts.cdb. 
       
   530 The maximum length for the drive, filename and extension is 190 characters.
       
   531 
       
   532 @publishedPartner
       
   533 @released
       
   534 @capability ReadUserData 
       
   535 @capability WriteUserData
       
   536 
       
   537 @param aFileName The contact database filename.
       
   538 
       
   539 @leave KErrBadName The filename is invalid; for example it contains wildcard characters 
       
   540 or the drive letter is missing.
       
   541 @leave  KErrArgument if the given descriptor contains more than the maximum length 
       
   542         of 190 characters.
       
   543 */
       
   544 EXPORT_C void CContactDatabase::RecreateSystemTemplateL(const TDesC& aFileName)
       
   545 	{
       
   546 	// Workaround for dynamic language switching because the system template may need to be recreated in a different language.
       
   547 	CContactDatabase* db = NewLC();
       
   548 	User::LeaveIfError(db->iCntSvr->OpenDatabase(aFileName)); 
       
   549 	User::LeaveIfError(db->iCntSvr->ReCreateTemplate());
       
   550 	CleanupStack::PopAndDestroy(db); 
       
   551 	}
       
   552 
       
   553 	
       
   554 /**
       
   555 Sets the default view definition. The contact database takes ownership of the 
       
   556 view definition specified. The default view definition is used in calls to 
       
   557 ReadContactL(), ReadContactLC() and ReadContactAndAgentL() when no view definition 
       
   558 is explicitly specified.
       
   559 
       
   560 @capability WriteUserData
       
   561 
       
   562 @param aView The view definition. This method does nothing if this is null.
       
   563 */
       
   564 EXPORT_C void CContactDatabase::SetViewDefinitionL(CContactViewDef* aView)
       
   565 	{
       
   566     if (aView)
       
   567         {
       
   568     	iCntSvr->SetViewDefinitionL(*aView);
       
   569     	// We also need to hold the ViewDef here - it is used in merging
       
   570     	delete iView;
       
   571     	iView = aView;
       
   572         }
       
   573 	}
       
   574 
       
   575 	
       
   576 /**
       
   577 Sets the text definition. The contact database takes ownership of the 
       
   578 text definition specified.
       
   579 
       
   580 @param aTextDef The new text definition. 
       
   581 */
       
   582 EXPORT_C void CContactDatabase::SetTextDefinitionL(CContactTextDef* aTextDef)
       
   583 	{
       
   584 	delete iTextDef;
       
   585 	iTextDef = aTextDef;
       
   586 	}
       
   587 
       
   588 	
       
   589 /**
       
   590 Gets a pointer to the text definition.
       
   591 
       
   592 @return A pointer to the text definition. 
       
   593 */
       
   594 EXPORT_C const CContactTextDef* CContactDatabase::TextDefinition() const
       
   595 	{
       
   596 	return iTextDef;
       
   597 	}
       
   598 
       
   599 
       
   600 void CContactDatabase::CleanupDatabaseRollback(TAny *aDatabase)
       
   601 	{
       
   602 	ASSERT(aDatabase);
       
   603 	CContactDatabase* db = static_cast<CContactDatabase*>(aDatabase);
       
   604 	db->DatabaseRollback();
       
   605 	}
       
   606 
       
   607 
       
   608 /**
       
   609 Starts a new transaction. Places and leaves a cleanup item to rollback
       
   610 the database on the cleanupstack. 
       
   611 
       
   612 @publishedPartner
       
   613 @released
       
   614 
       
   615 @param aIsInTransaction Used to determine whether or not to start the transaction depending on if a transaction is currently in progress.
       
   616 @leave KErrDiskFull There is insufficient disk space.
       
   617 */
       
   618 EXPORT_C void CContactDatabase::DatabaseBeginLC(TBool aIsInTransaction)
       
   619 	{
       
   620 	if (!aIsInTransaction)
       
   621 		{
       
   622 		User::LeaveIfError(iCntSvr->BeginDbTransaction());	
       
   623 		CleanupStack::PushL(TCleanupItem(CleanupDatabaseRollback, this));
       
   624 		}
       
   625 	}
       
   626 
       
   627 
       
   628 /**
       
   629 Commits an existing transaction, pops the rollback cleanup item off the CleanupStack.
       
   630 Closes the database if the connection state is EDbConnectionNeedToCloseForRestore.
       
   631 
       
   632 @publishedPartner
       
   633 @released
       
   634 
       
   635 @param aIsInTransaction Used to determine whether or not to commit the transaction depending on whether a transaction is currently in progress.
       
   636 */
       
   637 EXPORT_C void CContactDatabase::DatabaseCommitLP(TBool aIsInTransaction)
       
   638 	{
       
   639 	if (!aIsInTransaction)
       
   640 		{
       
   641 		User::LeaveIfError(iCntSvr->CommitDbTransaction());
       
   642 		CleanupStack::Pop(); // CleanupDatabaseRollback
       
   643 		}
       
   644 	}
       
   645 
       
   646 
       
   647 /**
       
   648 This function is not currently supported.
       
   649 @deprecated
       
   650 */
       
   651 EXPORT_C void CContactDatabase::StoreSortOrderL()
       
   652 	{
       
   653 	// Does nothing in the new architecture.
       
   654 	}
       
   655 
       
   656 
       
   657 /**
       
   658 This function is not currently supported.
       
   659 @deprecated
       
   660 */
       
   661 EXPORT_C void CContactDatabase::RestoreSortOrderL()
       
   662 	{
       
   663 	//Does nothing in the new architecture
       
   664 	}
       
   665 
       
   666 
       
   667 /** 
       
   668  Gets the array of sort preferences.
       
   669  
       
   670  Note: This method can leave.
       
   671  
       
   672  @deprecated
       
   673  @capability None
       
   674  @return A pointer to an array of sort preferences of the contact database.
       
   675 */
       
   676 EXPORT_C const CArrayFix<CContactDatabase::TSortPref>* CContactDatabase::SortOrder() const
       
   677     {
       
   678     CArrayFix<CContactDatabase::TSortPref>* prefs = NULL;
       
   679     TRAPD( err, prefs = iCntSvr->GetSortPreferenceL() );
       
   680     if ( err != KErrNone )
       
   681         {
       
   682 	prefs = NULL; // return NULL if have some error
       
   683 	}
       
   684     return prefs;
       
   685     }
       
   686 
       
   687 
       
   688 /** 
       
   689 Adds a new contact item to the database and returns its ID.
       
   690 
       
   691 @capability WriteUserData
       
   692 
       
   693 @param aContact The contact item to add to the database.
       
   694 
       
   695 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
   696 
       
   697 @return The ID of the new contact item. 
       
   698 */
       
   699 EXPORT_C TContactItemId CContactDatabase::AddNewContactL(CContactItem& aContact)
       
   700 	{
       
   701 	return doAddNewContactL(aContact, EFalse, EFalse);
       
   702 	}
       
   703 
       
   704 
       
   705 /** 
       
   706 Adds a new contact item to the database and returns its ID.
       
   707 
       
   708 @capability WriteUserData
       
   709 
       
   710 @param aContact The contact item to add to the database.
       
   711 @param aIsTemplate This argument should be ignored by developers.
       
   712 @param aIsInTransaction This argument should be ignored by developers.
       
   713 
       
   714 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
   715 
       
   716 @return The ID of the new contact item. 
       
   717 */
       
   718 EXPORT_C TContactItemId CContactDatabase::doAddNewContactL(CContactItem& aContact,TBool /*aIsTemplate*/,TBool /*aIsInTransaction*/)
       
   719 	{
       
   720 	if (aContact.Type() == KUidContactICCEntry)
       
   721 	    {
       
   722 		LoadSyncPluginL();
       
   723 	    }
       
   724 	
       
   725 	aContact.iId = iCntSvr->CreateContactL(aContact);
       
   726 
       
   727 	if (CheckType(aContact.Type()))
       
   728 		{
       
   729 		InsertInSortArray(aContact);
       
   730 		}
       
   731 
       
   732 	return aContact.iId;
       
   733 	}
       
   734 
       
   735 
       
   736 CContactItem* CContactDatabase::doCreateContactGroupLC(const TDesC& aGroupLabel)
       
   737 	{
       
   738 	CContactItem* newGroup = CContactGroup::NewLC();
       
   739 	newGroup->AddLabelFieldL();
       
   740 	if (aGroupLabel != KNullDesC)
       
   741 		STATIC_CAST(CContactGroup*, newGroup)->SetGroupLabelL(aGroupLabel);
       
   742 
       
   743 	newGroup->iId = AddNewContactL(*newGroup);
       
   744 	RespondToEventL(EContactDbObserverEventGroupAdded, newGroup->iId);
       
   745 	return newGroup;
       
   746 	}
       
   747 
       
   748 	
       
   749 /**
       
   750 Creates a new contact group with a default label of 'Group Label' and 
       
   751 adds it to the database. 
       
   752 
       
   753 The caller takes ownership of the returned object.
       
   754 
       
   755 @capability WriteUserData
       
   756 
       
   757 @param aInTransaction This argument should be ignored by developers.
       
   758 
       
   759 @return Pointer to the newly created contact group. 
       
   760 */
       
   761 EXPORT_C CContactItem* CContactDatabase::CreateContactGroupL(TBool aInTransaction)
       
   762 	{
       
   763 	CContactItem* newGroup = CContactDatabase::CreateContactGroupLC(aInTransaction);
       
   764 	CleanupStack::Pop(newGroup);
       
   765 	return newGroup;
       
   766 	}
       
   767 
       
   768 
       
   769 /**
       
   770 Creates a new contact group with a default label of 'Group Label' and 
       
   771 adds it to the database. 
       
   772 
       
   773 The caller takes ownership of the returned object.
       
   774 
       
   775 @capability WriteUserData
       
   776 
       
   777 @param aInTransaction This argument should be ignored by developers.
       
   778 
       
   779 @return Pointer to the newly created contact group. 
       
   780 */
       
   781 EXPORT_C CContactItem* CContactDatabase::CreateContactGroupLC(TBool /*aInTransaction*/)
       
   782 	{
       
   783 	return doCreateContactGroupLC();
       
   784 	}
       
   785 
       
   786 	
       
   787 /** 
       
   788 Creates a new contact group with a specified label and adds it to the database. 
       
   789 
       
   790 The pointer to the group is left on the cleanup stack. The caller takes 
       
   791 ownership of the returned object.
       
   792 
       
   793 @capability WriteUserData
       
   794 
       
   795 @param aGroupLabel The string to set as the group label.
       
   796 @param aInTransaction This argument should be ignored by developers.
       
   797 
       
   798 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
   799 
       
   800 @return Pointer to the newly created contact group. 
       
   801 */
       
   802 EXPORT_C CContactItem* CContactDatabase::CreateContactGroupLC(const TDesC& aGroupLabel, TBool /*aInTransaction*/)
       
   803 	{
       
   804 	return doCreateContactGroupLC(aGroupLabel);
       
   805 	}
       
   806 
       
   807 
       
   808 /** 
       
   809 Creates a new contact group with a specified label and adds it to the database. 
       
   810 
       
   811 The caller takes ownership of the returned object.
       
   812 
       
   813 @capability WriteUserData
       
   814 
       
   815 @param aGroupLabel The string to set as the group label.
       
   816 @param aInTransaction This argument should be ignored by developers.
       
   817 
       
   818 @return Pointer to the newly created contact group. 
       
   819 */
       
   820 EXPORT_C CContactItem* CContactDatabase::CreateContactGroupL(const TDesC& aGroupLabel,TBool aInTransaction)
       
   821 	{
       
   822 	CContactItem* newGroup = CContactDatabase::CreateContactGroupLC(aGroupLabel, aInTransaction);
       
   823 	CleanupStack::Pop(newGroup);
       
   824 	return newGroup;
       
   825 	}
       
   826 
       
   827 	
       
   828 /** 
       
   829 Creates a contact card template based on the system template and adds it to the database.
       
   830 
       
   831 A template label must be specifed. This can be changed later using CContactCardTemplate::SetTemplateLabelL(). 
       
   832 
       
   833 The pointer to the template is left on the cleanup stack. The caller takes ownership of the returned object.
       
   834 
       
   835 @capability WriteUserData
       
   836 
       
   837 @param aTempLabel The string to set as the template label. 
       
   838 @param aInTransaction This argument should be ignored by developers.
       
   839 
       
   840 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
   841 
       
   842 @return Pointer to the contact card template. 
       
   843 */
       
   844 EXPORT_C CContactItem* CContactDatabase::CreateContactCardTemplateLC(const TDesC& aTempLabel, TBool aInTransaction)
       
   845 	{
       
   846 	return CreateContactCardTemplateLC(&iTemplateCache->SystemTemplateL(), aTempLabel, aInTransaction);
       
   847 	}
       
   848 
       
   849 
       
   850 /** 
       
   851 Creates a contact card template based on the system template and adds it to the database.
       
   852 
       
   853 A template label must be specifed. This can be changed later using CContactCardTemplate::SetTemplateLabelL(). 
       
   854 
       
   855 The caller takes ownership of the returned object.
       
   856 
       
   857 @capability WriteUserData
       
   858 
       
   859 @param aTempLabel The string to set as the template label. 
       
   860 @param aInTransaction This argument should be ignored by developers.
       
   861 
       
   862 @return Pointer to the contact card template. 
       
   863 */
       
   864 EXPORT_C CContactItem* CContactDatabase::CreateContactCardTemplateL(const TDesC& aTempLabel, TBool aInTransaction)
       
   865 	{
       
   866 	CContactItem *cntItem = CreateContactCardTemplateLC(&iTemplateCache->SystemTemplateL(), aTempLabel, aInTransaction);
       
   867 	CleanupStack::Pop(cntItem);
       
   868 	return cntItem;
       
   869 	}
       
   870 
       
   871 	
       
   872 /** 
       
   873 Creates a contact card template and adds it to the database.
       
   874  
       
   875 The new template's field set is based on the specified contact item. This could be a 
       
   876 contact card, an own card, another template or even a group. Note that no field data 
       
   877 is copied into the new template. All of the new template's fields are marked as template 
       
   878 fields.
       
   879 
       
   880 A template label must be specifed. This can be changed later using CContactCardTemplate::SetTemplateLabelL(). 
       
   881 
       
   882 The caller takes ownership of the returned object.
       
   883 
       
   884 @capability WriteUserData
       
   885 
       
   886 @param aTemplate Pointer to an instance of a CContactItem-derived class. This 
       
   887 is used to initialise the new template's field set.
       
   888 @param aTemplateLabel The string to set as the template label.
       
   889 @param aInTransaction This argument should be ignored by developers.
       
   890 
       
   891 @return Pointer to the contact card template. 
       
   892 */
       
   893 EXPORT_C CContactItem* CContactDatabase::CreateContactCardTemplateL(const CContactItem* aTemplate,const TDesC& aTempLabel,TBool aInTransaction)
       
   894 	{
       
   895 	CContactItem *cntItem = CreateContactCardTemplateLC(aTemplate, aTempLabel, aInTransaction);
       
   896 	CleanupStack::Pop(cntItem);
       
   897 	return cntItem;
       
   898 	}
       
   899 
       
   900 
       
   901 /** 
       
   902 Creates a contact card template and adds it to the database.
       
   903  
       
   904 The new template's field set is based on the specified contact item. This could be a 
       
   905 contact card, an own card, another template or even a group. Note that no field data 
       
   906 is copied into the new template. All of the new template's fields are marked as template 
       
   907 fields.
       
   908 
       
   909 A template label must be specifed. This can be changed later using CContactCardTemplate::SetTemplateLabelL(). 
       
   910 
       
   911 The pointer to the object is left on the cleanup stack. The caller takes ownership of it.
       
   912 
       
   913 @capability WriteUserData
       
   914 
       
   915 @param aTemplate Pointer to an instance of a CContactItem-derived class. This 
       
   916 is used to initialise the new template's field set.
       
   917 @param aTemplateLabel The string to set as the template label.
       
   918 @param aInTransaction This argument should be ignored by developers.
       
   919 
       
   920 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
   921 
       
   922 @return Pointer to the contact card template. 
       
   923 */
       
   924 EXPORT_C CContactItem* CContactDatabase::CreateContactCardTemplateLC(const CContactItem* aTemplate, const TDesC& aLabel, TBool /*aInTransaction*/)
       
   925 	{
       
   926 	CContactItem* newTemplate = CContactCardTemplate::NewLC(aTemplate); 
       
   927 	// Clear all data from the new template
       
   928 	newTemplate->ClearFieldContent();
       
   929 
       
   930 	// Add label field
       
   931 	newTemplate->AddLabelFieldL();
       
   932 	static_cast<CContactCardTemplate*>(newTemplate)->SetTemplateLabelL(aLabel);
       
   933 
       
   934 	// Create the contact in the database	
       
   935 	newTemplate->iId = AddNewContactL(*newTemplate);
       
   936 	AddToTemplateListL(newTemplate->Id());
       
   937 	return newTemplate;
       
   938 	}
       
   939 
       
   940 
       
   941 void CContactDatabase::AddToTemplateListL(const TContactItemId aNewTemplateId)
       
   942 	{
       
   943 	if (!iCardTemplateIds)
       
   944 		{
       
   945 		iCardTemplateIds = CContactIdArray::NewL();
       
   946 		}
       
   947 	RespondToEventL(EContactDbObserverEventTemplateAdded, aNewTemplateId);
       
   948 	}
       
   949 
       
   950 
       
   951 void CContactDatabase::RemoveFromTemplateList(const TContactItemId aTemplateId)
       
   952 	{	
       
   953 	if (iCardTemplateIds)
       
   954  		{
       
   955 		TInt templatePos =	iCardTemplateIds->Find(aTemplateId);
       
   956 		if (templatePos != KErrNotFound)
       
   957 			{
       
   958 			iCardTemplateIds->Remove(templatePos);
       
   959 			}
       
   960  		}	
       
   961 	}
       
   962 
       
   963 
       
   964 /**
       
   965 Gets a copy of the database's template ID list. This is a list of the IDs 
       
   966 of all contact card templates which have been added to the database. The caller 
       
   967 takes ownership of the returned object.
       
   968 
       
   969 @return Pointer to a copy of the database's template ID list. This does 
       
   970 not include the system template. NULL if there are no templates in the database. 
       
   971 */
       
   972 EXPORT_C CContactIdArray* CContactDatabase::GetCardTemplateIdListL() const
       
   973 	{
       
   974 	if (iCardTemplateIds)
       
   975 		{
       
   976 		CContactIdArray* copyArray = CContactIdArray::NewL(iCardTemplateIds);
       
   977 		return copyArray;
       
   978 		}
       
   979 	else
       
   980 		return NULL;
       
   981 	}
       
   982 
       
   983 
       
   984 void CContactDatabase::ReadTemplateIdsL()
       
   985 	{
       
   986 	const_cast<CContactDatabase*>(this)->FetchGroupAndTemplateListsL();
       
   987 	}
       
   988 	
       
   989 
       
   990 /** Determines if the System template fields are valid.  Valid means that no
       
   991 fields contain data.
       
   992 @internalTechnology
       
   993 @released
       
   994 @capability None
       
   995 @param aContact Contact item representing the System template.
       
   996 @return ETrue if the System template fields are valid, EFalse otherwise.
       
   997 */
       
   998 TBool CContactDatabase::SystemTemplateFieldsValid( const CContactItem& aContact )
       
   999 	{
       
  1000 	// Precondition: aContact's ID must match the System template's ID.
       
  1001 	__ASSERT_ALWAYS( aContact.Id() == TemplateId(), Panic(ECntPanicSystemTemplate) );
       
  1002 
       
  1003 	TBool fieldsValid = ETrue;
       
  1004 	CContactItemFieldSet& fieldSet = aContact.CardFields();
       
  1005 
       
  1006 	for( TInt ii = 0; ii < fieldSet.Count(); ii++ )
       
  1007 		{
       
  1008 		CContactItemField& field = fieldSet[ii];
       
  1009 		CContactFieldStorage* fieldStorage = field.Storage();
       
  1010 		//
       
  1011 		// If the field contains data (is "full") then the System template
       
  1012 		// fields are not valid.
       
  1013 		//
       
  1014 		if( fieldStorage->IsFull() )
       
  1015 			{
       
  1016 			fieldsValid = EFalse;
       
  1017 			break;
       
  1018 			}
       
  1019 		}
       
  1020 	
       
  1021 	return fieldsValid;
       
  1022 	}
       
  1023 
       
  1024 
       
  1025 /**
       
  1026 Returns a copy of the database's group ID list. This is a list which contains 
       
  1027 the contact item IDs for each group in the database. The caller takes ownership 
       
  1028 of the returned object.
       
  1029 
       
  1030 @return Pointer to an array containing the contact item IDs for each group 
       
  1031 in the database. NULL if there are no groups in the database. 
       
  1032 */
       
  1033 EXPORT_C CContactIdArray* CContactDatabase::GetGroupIdListL() const
       
  1034 	{
       
  1035 	const_cast<CContactDatabase*>(this)->FetchGroupAndTemplateListsL();
       
  1036 	CContactIdArray* copyArray = CContactIdArray::NewL(iGroupIds);
       
  1037 	return copyArray;
       
  1038 	}
       
  1039 
       
  1040 
       
  1041 /** 
       
  1042 Sets a contact item in the database to be a member of a contact group.
       
  1043 
       
  1044 The item and group are identified by their IDs. 
       
  1045 
       
  1046 @capability WriteUserData
       
  1047 
       
  1048 @param aItemId The ID of the item to add to the group.
       
  1049 @param aGroupId  The ID of the group to which the item should be added. 
       
  1050 
       
  1051 @leave KErrNotFound Either the group or the item does not exist.
       
  1052 @leave KErrNotSupported The group is not of type KUidContactGroup. 
       
  1053 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  1054 */
       
  1055 EXPORT_C void CContactDatabase::AddContactToGroupL(TContactItemId aItemId, TContactItemId aGroupId)
       
  1056 	{
       
  1057 	//Remember if the group was already opened, if so open it at the end of the method
       
  1058 	TBool isAlreadyOpened = iCntSvr->CloseContact(aGroupId);
       
  1059 
       
  1060 	CContactItem* cntGroup = OpenNoMergeLCX(aGroupId); //double push
       
  1061 	
       
  1062 	if (cntGroup->Type() != KUidContactGroup)
       
  1063 		User::Leave(KErrNotSupported);
       
  1064 	AddCntToOpenedGroupL(aItemId, *cntGroup);
       
  1065 
       
  1066 	CleanupStack::PopAndDestroy(cntGroup);	// cntGroup
       
  1067 	CleanupStack::Pop(); // Pop the lock
       
  1068 	cntGroup = NULL;
       
  1069 	if (isAlreadyOpened)
       
  1070 		{
       
  1071 		CContactItem* dummy = OpenContactL(aGroupId);
       
  1072 		delete dummy;				
       
  1073 		}
       
  1074 	}
       
  1075 
       
  1076 
       
  1077 /** 
       
  1078 Sets a contact item in the database to be a member of a contact group.
       
  1079 
       
  1080 The item and group are identified by their IDs. 
       
  1081 
       
  1082 @capability WriteUserData
       
  1083 
       
  1084 @param aItemId The ID of the item to add to the group.
       
  1085 @param aGroupId  The ID of the group to which the item should be added. 
       
  1086 @param aInTransaction This argument should be ignored by developers.
       
  1087 
       
  1088 @leave KErrNotFound Either the group or the item does not exist.
       
  1089 @leave KErrNotSupported The group is not of type KUidContactGroup. 
       
  1090 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  1091 */
       
  1092 EXPORT_C void CContactDatabase::AddContactToGroupL(TContactItemId aItemId, TContactItemId aGroupId, TBool /*aInTransaction*/)
       
  1093 	{
       
  1094 	AddContactToGroupL(aItemId, aGroupId);	
       
  1095 	}
       
  1096 
       
  1097 	
       
  1098 /** 
       
  1099 Sets a contact item in the database to be a member of a contact group. 
       
  1100 
       
  1101 @capability WriteUserData
       
  1102 
       
  1103 @param aItem The item to add to the group.
       
  1104 @param aGroup  The group to which the item should be added. 
       
  1105 
       
  1106 @leave KErrNotFound Either the group or the item does not exist in the database.
       
  1107 @leave KErrNotSupported The group is not of type KUidContactGroup.
       
  1108 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  1109 */
       
  1110 EXPORT_C void CContactDatabase::AddContactToGroupL(CContactItem& aItem, CContactItem& aGroup)
       
  1111 	{
       
  1112 	if (aGroup.Type() != KUidContactGroup)
       
  1113 		{
       
  1114 		User::Leave(KErrNotSupported);
       
  1115 		}
       
  1116 
       
  1117 	AddContactToGroupL(aItem.Id(), aGroup.Id());
       
  1118 
       
  1119 	//Update client's group object
       
  1120 	static_cast<CContactGroup&>(aGroup).AddContactL(aItem.Id());
       
  1121 
       
  1122 	//Update client's contacts item object
       
  1123 	CContactItemPlusGroup& item = static_cast<CContactItemPlusGroup&>(aItem);
       
  1124 	if (!item.iGroups)
       
  1125 		{
       
  1126 		item.iGroups = CContactIdArray::NewL();
       
  1127 		}
       
  1128 	item.iGroups->AddL(aGroup.Id());
       
  1129 	}
       
  1130 
       
  1131 
       
  1132 /** 
       
  1133 Removes the association between a contact item and a group.
       
  1134 
       
  1135 @capability WriteUserData
       
  1136 
       
  1137 @param aItem The item to remove.
       
  1138 @param aGroup The group from which the item should be removed.
       
  1139 
       
  1140 @leave KErrDiskFull The disk does not have enough free space to perform the operation. 
       
  1141 */
       
  1142 EXPORT_C void CContactDatabase::RemoveContactFromGroupL(CContactItem& aItem, CContactItem& aGroup)
       
  1143 	{
       
  1144 	if (aGroup.Type() != KUidContactGroup)
       
  1145 		{
       
  1146 		User::Leave(KErrNotSupported);
       
  1147 		}
       
  1148 	
       
  1149 	RemoveContactFromGroupL(aItem.Id(), aGroup.Id()); //Perform the change in the database
       
  1150 
       
  1151 	//Update client's group object
       
  1152 	static_cast<CContactGroup&>(aGroup).RemoveContactL(aItem.Id());
       
  1153 
       
  1154 	//Update client's contacts item object
       
  1155 	CContactItemPlusGroup& item = static_cast<CContactItemPlusGroup&>(aItem);
       
  1156 	if (item.iGroups)
       
  1157 		{
       
  1158 		const TInt groupIndex = item.iGroups->Find(aGroup.Id());
       
  1159 		if (groupIndex>=0)
       
  1160 			{
       
  1161 			item.iGroups->Remove(groupIndex);
       
  1162 			}
       
  1163 		}
       
  1164 	}
       
  1165 
       
  1166 
       
  1167 void CContactDatabase::AddCntToOpenedGroupL(TContactItemId aItemId, CContactItem& aGroup)
       
  1168 	{
       
  1169 	CContactGroup& group = static_cast<CContactGroup&>(aGroup);
       
  1170 	if (!group.ContainsItem(aItemId))
       
  1171 		{
       
  1172 		group.AddContactL(aItemId);
       
  1173 		iCntSvr->CommitContactL(aGroup);
       
  1174 		}
       
  1175 	else
       
  1176 		{
       
  1177 		iCntSvr->CloseContact(aGroup.Id());
       
  1178 		}
       
  1179 	}
       
  1180 
       
  1181 
       
  1182 /** 
       
  1183 Removes the association between a contact item and a group.
       
  1184 
       
  1185 The item and group are identified by their IDs. 
       
  1186 
       
  1187 @capability WriteUserData
       
  1188 
       
  1189 @param aItemId The ID of the item to remove.
       
  1190 @param aGroupId The ID of the group from which the item should be removed. 
       
  1191 
       
  1192 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  1193 */
       
  1194 EXPORT_C void CContactDatabase::RemoveContactFromGroupL(TContactItemId aItemId, TContactItemId aGroupId)
       
  1195 	{
       
  1196 	//Remember if the group was already opened, if so open it at the end of the method
       
  1197 	TBool isAlreadyOpened = iCntSvr->CloseContact(aGroupId);
       
  1198 	CContactItem* cntGroup = OpenNoMergeLCX(aGroupId); //double push
       
  1199 	
       
  1200 	if (cntGroup->Type() != KUidContactGroup)
       
  1201 		{
       
  1202 		User::Leave(KErrNotSupported);
       
  1203 		}
       
  1204 	
       
  1205 	CContactGroup* group = static_cast<CContactGroup*>(cntGroup);
       
  1206 	if (group->ContainsItem(aItemId))
       
  1207 		{
       
  1208 		group->RemoveContactL(aItemId);
       
  1209 		iCntSvr->CommitContactL(*cntGroup);
       
  1210 		}
       
  1211 	else
       
  1212 		{
       
  1213 		iCntSvr->CloseContact(cntGroup->Id());
       
  1214 		}
       
  1215 		
       
  1216 	CleanupStack::PopAndDestroy(2); // cntGroup, CntItemClose
       
  1217 	cntGroup = NULL;
       
  1218 	
       
  1219 	if (isAlreadyOpened)
       
  1220 		{
       
  1221 		CContactItem* dummy = OpenContactL(aGroupId);
       
  1222 		delete dummy;				
       
  1223 		}
       
  1224 
       
  1225 	}
       
  1226 
       
  1227 
       
  1228 /**
       
  1229 Sets a field containing a telephone number as a speed dial field. The field 
       
  1230 is identified by aFieldIndex within the contact item aItem. It is assigned a 
       
  1231 speed dial position between 1 and 9 inclusive.
       
  1232 
       
  1233 The field's speed dial and user added attributes are set and the appropriate 
       
  1234 UID (KUidSpeedDialXxx) is added to the field's content type. The changes are 
       
  1235 committed to the database.
       
  1236 
       
  1237 Notes:
       
  1238 
       
  1239 If an item's telephone number field has already been assigned to position 
       
  1240 aSpeedDialPosition, that item is updated so that the speed dial attribute 
       
  1241 is removed from its field and the speed dial field type UID is removed from 
       
  1242 the field's content type, before the new speed dial field is set.
       
  1243 
       
  1244 The speed dial attribute can be tested for using the CContactItemField::IsSpeedDial() 
       
  1245 function.
       
  1246 
       
  1247 The contact item passed to this function (aItem) must have been obtained using 
       
  1248 one of the variants of CContactDatabase::OpenContactL(). This is because it 
       
  1249 is modified and committed to the database by this function - no further 
       
  1250 commits are necessary.
       
  1251 
       
  1252 @capability ReadUserData
       
  1253 @capability WriteUserData
       
  1254 
       
  1255 @param aItem The contact item containing the field to set as a speed dial 
       
  1256 field.
       
  1257 @param aFieldIndex Index of a field in aItem's field set to set as a speed dial field.
       
  1258 @param aSpeedDialPosition The speed dial position. This is an integer in the 
       
  1259 range 1 to 9 inclusive. If outside this range, the function leaves with KErrArgument. 
       
  1260 
       
  1261 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  1262 */
       
  1263 EXPORT_C void CContactDatabase::SetFieldAsSpeedDialL(CContactItem& aItem, TInt aFieldIndex, TInt aSpeedDialPosition)
       
  1264 	{
       
  1265 	//
       
  1266 	// aItem has been merged with the appropriate template.  On the server when
       
  1267 	// the contact is read it is not merged with the template.  Therefore we
       
  1268 	// need to determine an equivalent field index for the server.  The index
       
  1269 	// on the client's side takes account of the template fields so to compute
       
  1270 	// the equivalent index iterate through the contact fields up to and
       
  1271 	// including aFieldIndex and count the number of non-empty (i.e. non-
       
  1272 	// template) fields.  The total number is the equivalent index.
       
  1273 	//
       
  1274 	CContactItemFieldSet &fieldSet = aItem.CardFields();
       
  1275 	TInt svrFieldIndex = -1;
       
  1276 	if(fieldSet.Count() == 0) 
       
  1277 		{
       
  1278 		User::Leave(KErrArgument);
       
  1279 		}
       
  1280 	for( TInt fieldIndex = 0; fieldIndex <= aFieldIndex; fieldIndex++ )
       
  1281 		{
       
  1282 		CContactItemField& field = fieldSet[fieldIndex];
       
  1283 		if( field.Storage()->IsFull() )
       
  1284 			{
       
  1285 			svrFieldIndex++;
       
  1286 			}
       
  1287 		}
       
  1288 		
       
  1289 	
       
  1290 	CContactItemField& field = fieldSet[aFieldIndex];	
       
  1291 	if (field.StorageType() == KStorageTypeText)
       
  1292 		{
       
  1293 		iCntSvr->SetFieldAsSpeedDialL(aItem.Id(), svrFieldIndex, aSpeedDialPosition);
       
  1294 		}
       
  1295 	else	
       
  1296 		{
       
  1297 		User::Leave(KErrArgument);
       
  1298 		}
       
  1299 
       
  1300 
       
  1301 	//
       
  1302 	// The contact has been read from the database and modified on the server.
       
  1303 	// These changes have not been made to the CContactItem passed in to this
       
  1304 	// function.  We need to make these changes here for consistency with the
       
  1305 	// old model.  A future BC break will disallow this behaviour by changing
       
  1306 	// the parameter from CContactItem& to const CContactItem& thus forcing the
       
  1307 	// client to pass a constant object.
       
  1308 	//
       
  1309 
       
  1310 	// Get the field containing the number to be associated with the
       
  1311 	// speed dial.  Note that we use the original index passed in not the
       
  1312 	// equivalent server index.
       
  1313 	CContactItemField& speedDialField = aItem.CardFields()[aFieldIndex];
       
  1314 	// Add speed dial attributes to the contact item field.
       
  1315 	TUid fieldTypeUid = CContactDatabase::SpeedDialFieldUidFromSpeedDialPosition(aSpeedDialPosition);
       
  1316 	if (!speedDialField.ContentType().ContainsFieldType(fieldTypeUid))
       
  1317 		{
       
  1318 		speedDialField.AddFieldTypeL(fieldTypeUid);
       
  1319 		}
       
  1320 	speedDialField.SetUserAddedField(ETrue);
       
  1321 	speedDialField.SetSpeedDial(ETrue);
       
  1322 	}
       
  1323 
       
  1324 
       
  1325 /**
       
  1326 Returns the field UID for the given speed dial position.  This method is
       
  1327 copied from CCntServerSpeedDialManager::SpeedDialFieldUidFromSpeedDialPosition()
       
  1328 rather than export this method for use here and on the server.  Once the BC
       
  1329 break referred to in SetFieldAsSpeedDialL() has been made this method should be
       
  1330 removed.
       
  1331 
       
  1332 @internalTechnology
       
  1333 @released
       
  1334 
       
  1335 @param aSpeedDialPosition The speed dial position for which we want the field
       
  1336 UID.
       
  1337 
       
  1338 @return The field UID corresponding to aSpeedDialPosition.
       
  1339 */
       
  1340 TUid CContactDatabase::SpeedDialFieldUidFromSpeedDialPosition(TInt aSpeedDialPosition)
       
  1341 	{
       
  1342 	__ASSERT_ALWAYS(aSpeedDialPosition >= KCntMinSpeedDialIndex && aSpeedDialPosition <= KCntMaxSpeedDialIndex, Panic(ECntPanicInvalidSpeedDialIndex));
       
  1343 
       
  1344 	TUid fieldTypeUid = KNullUid;
       
  1345 	switch (aSpeedDialPosition)
       
  1346 		{
       
  1347 	case 1:
       
  1348 		fieldTypeUid = KUidSpeedDialOne;
       
  1349 		break;
       
  1350 	case 2:
       
  1351 		fieldTypeUid = KUidSpeedDialTwo;
       
  1352 		break;
       
  1353 	case 3:
       
  1354 		fieldTypeUid = KUidSpeedDialThree;
       
  1355 		break;
       
  1356 	case 4:
       
  1357 		fieldTypeUid = KUidSpeedDialFour;
       
  1358 		break;
       
  1359 	case 5:
       
  1360 		fieldTypeUid = KUidSpeedDialFive;
       
  1361 		break;
       
  1362 	case 6:
       
  1363 		fieldTypeUid = KUidSpeedDialSix;
       
  1364 		break;
       
  1365 	case 7:
       
  1366 		fieldTypeUid = KUidSpeedDialSeven;
       
  1367 		break;
       
  1368 	case 8:
       
  1369 		fieldTypeUid = KUidSpeedDialEight;
       
  1370 		break;
       
  1371 	case 9:
       
  1372 		fieldTypeUid = KUidSpeedDialNine;
       
  1373 		break;
       
  1374 		}
       
  1375 
       
  1376 	return fieldTypeUid; 
       
  1377 	}
       
  1378 
       
  1379 
       
  1380 /** 
       
  1381 Returns the ID of the contact item whose telephone number field is mapped to 
       
  1382 the speed dial position specified. This function is provided so that information 
       
  1383 may be displayed about a contact item whose telephone number is being dialled 
       
  1384 using speed dialling.
       
  1385 
       
  1386 The function also retrieves the telephone number stored in the field.
       
  1387 
       
  1388 @capability ReadUserData
       
  1389 
       
  1390 @param aSpeedDialPosition The speed dial position. This is an integer in the 
       
  1391 range 1 to 9 inclusive. If outside this range, the function leaves with KErrArgument.
       
  1392 @param aPhoneNumber On return, contains the telephone number which is mapped 
       
  1393 to the speed dial position specified. Returns KNullDesC if the speed dial 
       
  1394 position requested has not been set.
       
  1395 
       
  1396 @return The ID of the contact item for which the speed dial has been set. 
       
  1397 */
       
  1398 EXPORT_C TContactItemId CContactDatabase::GetSpeedDialFieldL(TInt aSpeedDialPosition, TDes& aPhoneNumber)
       
  1399 	{
       
  1400 	return iCntSvr->GetSpeedDialFieldL(aSpeedDialPosition, aPhoneNumber);
       
  1401 	}
       
  1402 
       
  1403 
       
  1404 /** 
       
  1405 Removes the mapping between a contact item field and a speed dial position.
       
  1406 
       
  1407 Removes the KUidSpeedDialXxx UID from the field's content type, removes the 
       
  1408 field's speed dial attribute and commits the changes to the item.
       
  1409 
       
  1410 @capability ReadUserData
       
  1411 @capability WriteUserData
       
  1412 
       
  1413 @param aContactId The ID of the contact item containing the speed dial field.
       
  1414 @param aSpeedDialPosition The speed dial position. This is an integer in the 
       
  1415 range 1 to 9 inclusive. If outside this range, the function leaves with KErrArgument. 
       
  1416 
       
  1417 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  1418 */
       
  1419 EXPORT_C void CContactDatabase::RemoveSpeedDialFieldL(TContactItemId aContactId, TInt aSpeedDialPosition)
       
  1420 	{
       
  1421 	iCntSvr->RemoveSpeedDialFieldL(aContactId, aSpeedDialPosition);	
       
  1422 	}
       
  1423 
       
  1424 	
       
  1425 /**
       
  1426 Reads a contact item without locking it.
       
  1427 
       
  1428 This function uses the default view definition (as set by SetViewDefinitionL()). The 
       
  1429 caller takes ownership of the returned object.
       
  1430 
       
  1431 @capability ReadUserData
       
  1432 
       
  1433 @param aContactId The ID of the contact item to read.
       
  1434 
       
  1435 @return Pointer to the contact item.
       
  1436 
       
  1437 @leave KErrNotFound The specified contact item does not exist in the database. */
       
  1438 EXPORT_C CContactItem* CContactDatabase::ReadContactL(TContactItemId aContactId)
       
  1439 	{
       
  1440 	CContactItem* cntItem = ReadContactLC(aContactId);
       
  1441 	CleanupStack::Pop(cntItem);
       
  1442 	return cntItem;
       
  1443 	}
       
  1444 
       
  1445 
       
  1446 /**
       
  1447 Reads a contact item without locking it.
       
  1448 
       
  1449 This function uses the view definition specified. The caller takes ownership 
       
  1450 of the returned object.
       
  1451 
       
  1452 @capability ReadUserData
       
  1453 
       
  1454 @param aContactId The ID of the contact item to read.
       
  1455 @param aViewDef The view definition to use. 
       
  1456 
       
  1457 @return Pointer to the contact item.
       
  1458 
       
  1459 @leave KErrNotFound The specified contact item does not exist in the database. */
       
  1460 EXPORT_C CContactItem* CContactDatabase::ReadContactL(TContactItemId aContactId, const CContactItemViewDef& aViewDef)
       
  1461 	{
       
  1462 	CContactItem* cntItem = ReadContactLC(aContactId, aViewDef);
       
  1463 	CleanupStack::Pop(cntItem);
       
  1464 	return cntItem;
       
  1465 	}
       
  1466 
       
  1467 
       
  1468 /**
       
  1469 Reads a contact item without locking it.
       
  1470 
       
  1471 This function uses the default view definition (as set by SetViewDefinitionL()). The 
       
  1472 caller takes ownership of the returned object.
       
  1473 
       
  1474 @capability ReadUserData
       
  1475 
       
  1476 @param aContactId The ID of the contact item to read.
       
  1477 
       
  1478 @return Pointer to the contact item. This is left on the cleanup stack.
       
  1479 
       
  1480 @leave KErrNotFound The specified contact item does not exist in the database. 
       
  1481 */
       
  1482 EXPORT_C CContactItem* CContactDatabase::ReadContactLC(TContactItemId aContactId)
       
  1483 	{
       
  1484 	CContactItem* cntItem = iCntSvr->ReadContactL(&iView->ItemDef(), aContactId);
       
  1485 	CleanupStack::PushL(cntItem);
       
  1486 
       
  1487 	iTemplateCache->MergeWithTemplateL(*cntItem, &iView->ItemDef());
       
  1488 	
       
  1489 	return cntItem;
       
  1490 	}
       
  1491 
       
  1492 
       
  1493 /**
       
  1494 Reads a contact item without locking it.
       
  1495 
       
  1496 This function uses the view definition specified. The caller takes ownership 
       
  1497 of the returned object.
       
  1498 
       
  1499 @capability ReadUserData
       
  1500 
       
  1501 @param aContactId The ID of the contact item to read.
       
  1502 @param aViewDef The view definition to use. 
       
  1503 
       
  1504 @return Pointer to the contact item. This is left on the cleanup stack.
       
  1505 
       
  1506 @leave KErrNotFound The specified contact item does not exist in the database. 
       
  1507 */
       
  1508 EXPORT_C CContactItem* CContactDatabase::ReadContactLC(TContactItemId aContactId,const CContactItemViewDef& aViewDef)
       
  1509 	{
       
  1510 	CContactItem* cntItem = iCntSvr->ReadContactL(&aViewDef, aContactId);
       
  1511 	CleanupStack::PushL(cntItem);
       
  1512 	iTemplateCache->MergeWithTemplateL(*cntItem, &aViewDef);
       
  1513 	return cntItem;
       
  1514 	}
       
  1515 
       
  1516 
       
  1517 /**
       
  1518 Reads a contact item and an agent if the item has an agent field. The item 
       
  1519 and agent (if present) are returned in an array. The function uses the database's 
       
  1520 default view definition (as set by SetViewDefinitionL()). The caller takes 
       
  1521 ownership of the returned object.
       
  1522 
       
  1523 @capability ReadUserData
       
  1524 
       
  1525 @param aContactId The ID of the contact item to read.
       
  1526 @leave KErrNotFound The specified contact item cannot be found in the database.
       
  1527 
       
  1528 @return Pointer to an array containing the contact item and agent, if present.
       
  1529 */
       
  1530 EXPORT_C CArrayPtr<CContactItem>* CContactDatabase::ReadContactAndAgentL(TContactItemId aContactId)
       
  1531 	{
       
  1532 	CArrayPtr<CContactItem>* cntItemsArray = new (ELeave)CArrayPtrFlat<CContactItem>(4);
       
  1533 	CleanupStack::PushL(cntItemsArray);
       
  1534 	CContactItem* contactItem = ReadContactLC(aContactId);
       
  1535 	cntItemsArray->AppendL(contactItem);
       
  1536 	CleanupStack::Pop(contactItem);	// from ReadContactLC
       
  1537 	
       
  1538 	// Determine whether the contactItem needs an agent
       
  1539 	TInt agentIndex = (*cntItemsArray)[0]->Agent();
       
  1540 	if (agentIndex != KErrNotFound)
       
  1541   		{
       
  1542   		CContactItem* contactItemAgent = ReadContactLC(agentIndex);
       
  1543   		cntItemsArray->AppendL(contactItemAgent); // Will use the Viewdef on the server - no need to marshal ViewDef
       
  1544 		CleanupStack::Pop(contactItemAgent);// from ReadContactLC
       
  1545   		}
       
  1546 	CleanupStack::Pop(cntItemsArray);	// cntItemsArray
       
  1547 	return cntItemsArray;
       
  1548 	}
       
  1549 
       
  1550 
       
  1551 /**
       
  1552 Reads a contact item (contact card, own card, template, or contact group), 
       
  1553 but does not read the group or template information. 
       
  1554 
       
  1555 This function is identical to the variant of ReadContactL() which uses the database's 
       
  1556 default view definition, except that this function does not read:
       
  1557 
       
  1558 - the list of group members and the group label (if the item is a CContactGroup)
       
  1559 - the template label (if the item is a CContactCardTemplate)
       
  1560 - the list of groups to which the item belongs, if any (not applicable to templates)
       
  1561 - any fields inherited from a non-system template, if any (not applicable if 
       
  1562 the item is a CContactCardTemplate)
       
  1563 
       
  1564 Notes:
       
  1565 
       
  1566 This function is faster than the standard reading function (ReadContactL()), 
       
  1567 which needs to match the template fields and groups etc.
       
  1568 
       
  1569 The caller takes ownership of the returned object.
       
  1570 
       
  1571 @capability ReadUserData
       
  1572 
       
  1573 @param aContactId The ID of the contact to read.
       
  1574 
       
  1575 @leave KErrNotFound The specified contact item cannot be found in the database.
       
  1576 
       
  1577 @return Pointer to the contact whose ID is aContactId.
       
  1578 */
       
  1579 EXPORT_C CContactItem* CContactDatabase::ReadMinimalContactL(TContactItemId aContactId)
       
  1580 	{
       
  1581 	return iCntSvr->ReadContactL(NULL, aContactId);
       
  1582 	}
       
  1583 
       
  1584 
       
  1585 /**
       
  1586 Reads a contact item (contact card, own card, template, or contact group), 
       
  1587 but does not read the group or template information. 
       
  1588 
       
  1589 This function is identical to the variant of ReadContactLC() which uses the server's 
       
  1590 default view definition, except that this function does not read:
       
  1591 	
       
  1592 - the list of group members and the group label (if the item is a CContactGroup)
       
  1593 - the template label (if the item is a CContactCardTemplate)
       
  1594 - the list of groups to which the item belongs, if any (not applicable to templates)
       
  1595 - any fields inherited from a non-system template, if any (not applicable if 
       
  1596 the item is a CContactCardTemplate)
       
  1597 
       
  1598 Notes:
       
  1599 
       
  1600 This function is faster than the standard reading function (ReadContactLC()), 
       
  1601 which needs to match the template fields and groups etc.
       
  1602 
       
  1603 The caller takes ownership of the returned object.
       
  1604 
       
  1605 @capability ReadUserData
       
  1606 
       
  1607 @param aContactId The ID of the contact to read.
       
  1608 
       
  1609 @leave KErrNotFound The specified contact item cannot be found in the database.
       
  1610 
       
  1611 @return Pointer to the contact whose ID is aContactId. The contact is left 
       
  1612 on the cleanup stack. 
       
  1613 */
       
  1614 EXPORT_C CContactItem* CContactDatabase::ReadMinimalContactLC(TContactItemId aContactId)
       
  1615 	{
       
  1616 	CContactItem* cntItem = iCntSvr->ReadContactL(NULL, aContactId);
       
  1617 	CleanupStack::PushL(cntItem);
       
  1618 	return cntItem;
       
  1619 	}
       
  1620 
       
  1621 	
       
  1622 /**
       
  1623 Gets the content type of the template field which a specified field maps onto. 
       
  1624 If the field does not map onto a field in a template, then its own content 
       
  1625 type is returned.
       
  1626 
       
  1627 Note: this function can leave.
       
  1628 
       
  1629 @param aField The field of interest. 
       
  1630 
       
  1631 @return The content type of the field. 
       
  1632 */
       
  1633 EXPORT_C const CContentType& CContactDatabase::TemplateContentType(const CContactItemField& aField) const
       
  1634 	{
       
  1635 	return(aField.TemplateContentType(iTemplateCache->SystemTemplateL().CardFields())); // this can leave
       
  1636 	}
       
  1637 
       
  1638 
       
  1639 //
       
  1640 // Logic cut and paste with minor edit from old CContactTables.
       
  1641 // Create a descriptor with field values separated by the 'separator' from a
       
  1642 // CContactItemFieldSet.
       
  1643 // No database read.
       
  1644 //
       
  1645 void CContactDatabase::DoReadContactTextDefL(const CContactItemFieldSet* aFieldSet,TDes& aResult,CContactTextDef* aTextDef)
       
  1646 	{
       
  1647 	TBool firstText=ETrue;
       
  1648 	if (aTextDef)
       
  1649 		{
       
  1650 		TBuf<KMaxContactTextSeperator> nextSeperator;
       
  1651 		for(TInt loop=0;loop<aTextDef->Count();loop++)
       
  1652 			{
       
  1653 			CContactDatabase::TTextFieldMinimal textFieldMin;
       
  1654 			TContactTextDefItem textDefItem=(*aTextDef)[loop];
       
  1655 			const TInt startOfFieldSet=0;
       
  1656 			aFieldSet->FieldText(textDefItem.iFieldType,textFieldMin,startOfFieldSet);
       
  1657 			if (textFieldMin.Length()>0)
       
  1658 				{
       
  1659 				if (!firstText && aResult.MaxLength()>aResult.Length())
       
  1660 					aResult.Append(nextSeperator.Left(Min(aResult.MaxLength()-aResult.Length(),nextSeperator.Length())));
       
  1661 				aResult.Append(textFieldMin.Left(Min(aResult.MaxLength()-aResult.Length(),textFieldMin.Length())));
       
  1662 				firstText=EFalse;
       
  1663 				}
       
  1664 			nextSeperator=textDefItem.iSeperator;
       
  1665 			}
       
  1666 		}
       
  1667 	if (firstText)
       
  1668 		{
       
  1669 		if(aTextDef && aTextDef->ExactMatchOnly()!=EFalse)
       
  1670 			return;//text def specifies an exact match only
       
  1671 		CContactDatabase::TTextFieldMinimal textFieldMin;
       
  1672 		if (aTextDef)
       
  1673 			{
       
  1674 			TFieldType fieldType=aTextDef->iFallbackFieldType;
       
  1675 			if (fieldType!=KUidContactFieldNone)
       
  1676 				{
       
  1677 				const TInt startOfFieldSet=0;
       
  1678 				aFieldSet->FieldText(fieldType,textFieldMin,startOfFieldSet);
       
  1679 				}
       
  1680 			}
       
  1681 		if (textFieldMin.Length()==0)
       
  1682 			{
       
  1683 			TInt findPos=KContactFieldSetSearchAll;
       
  1684 			do
       
  1685 				{
       
  1686 				findPos=aFieldSet->FindNext(KUidContactFieldMatchAll,findPos+1);
       
  1687 				if (findPos<0)
       
  1688 					break;
       
  1689 				(*aFieldSet)[findPos].GetFieldText(textFieldMin);
       
  1690 				} while(textFieldMin.Length()==0);
       
  1691 		}
       
  1692 		aResult.Append(textFieldMin.Left(Min(aResult.MaxLength(),textFieldMin.Length())));
       
  1693 		}
       
  1694 	}
       
  1695 
       
  1696 
       
  1697 /**
       
  1698 Reads text into a descriptor from a pre-loaded contact item.
       
  1699 
       
  1700 This function uses the database's current text definition (as set using 
       
  1701 CContactDatabase::SetTextDefinitionL()).
       
  1702 
       
  1703 @capability ReadUserData
       
  1704 
       
  1705 @param aItem The contact item to read.
       
  1706 @param aResult On return, contains the text read from the contact item aItem, 
       
  1707 using the database's current text definition. 
       
  1708 */
       
  1709 EXPORT_C void CContactDatabase::ReadContactTextDefL(const CContactItem& aItem, TDes& aResult)
       
  1710 	{
       
  1711 	DoReadContactTextDefL(&aItem.CardFields(),aResult,iTextDef);
       
  1712 	}
       
  1713 
       
  1714 
       
  1715 /**
       
  1716 Reads text into a descriptor from a pre-loaded contact item, using the specified
       
  1717 text definition.
       
  1718 
       
  1719 @capability ReadUserData
       
  1720 
       
  1721 @param aItem The contact item to read.
       
  1722 @param aResult On return, contains the text read from the contact item aItem, 
       
  1723 using the text definition specified in aTextDef.
       
  1724 @param aTextDef The text definition to use. 
       
  1725 */
       
  1726 EXPORT_C void CContactDatabase::ReadContactTextDefL(const CContactItem& aItem, TDes& aResult,CContactTextDef* aTextDef)
       
  1727 	{
       
  1728 	DoReadContactTextDefL(&aItem.CardFields(),aResult,aTextDef);
       
  1729 	}
       
  1730 
       
  1731 
       
  1732 /**
       
  1733 Reads text from a contact item stored in the database into a descriptor.
       
  1734 
       
  1735 This function uses the database's currently set text definition (as set using 
       
  1736 CContactDatabase::SetTextDefinitionL()).
       
  1737 
       
  1738 @capability ReadUserData
       
  1739 
       
  1740 @param aContactId The ID of the contact to read.
       
  1741 @param aResult On return, contains the text read from the contact item identified by aContactId, using 
       
  1742 the database's current text definition.
       
  1743 
       
  1744 @leave KErrNotFound The specified contact item cannot be found in the database. 
       
  1745 */
       
  1746 EXPORT_C void CContactDatabase::ReadContactTextDefL(TContactItemId aContactId, TDes& aResult)
       
  1747 	{
       
  1748 	ReadContactTextDefL(aContactId,aResult,iTextDef);
       
  1749 	}
       
  1750 
       
  1751 
       
  1752 /**
       
  1753 Reads text from a contact item stored in the database into a descriptor 
       
  1754 using the specified text definition.
       
  1755 
       
  1756 @capability ReadUserData
       
  1757 
       
  1758 @param aContactId The ID of the contact to read.
       
  1759 @param aResult On return, contains the text read from the contact item identified by aContactId, using 
       
  1760 the text definition specified in aTextDef.
       
  1761 @param aTextDef The text definition to use.
       
  1762 
       
  1763 @leave KErrNotFound The specified contact item cannot be found in the database. 
       
  1764 */
       
  1765 EXPORT_C void CContactDatabase::ReadContactTextDefL(TContactItemId aContactId, TDes& aResult,CContactTextDef* aTextDef)
       
  1766 	{
       
  1767 	CContactTextDef* textDef = NULL;
       
  1768 	if(aTextDef == NULL)
       
  1769 		{
       
  1770 		textDef = CContactTextDef::NewLC();
       
  1771 		}
       
  1772 	else
       
  1773 		{
       
  1774 		textDef = aTextDef;
       
  1775 		}
       
  1776 	MLplViewIteratorManager& manager = FactoryL()->GetViewIteratorManagerL();
       
  1777 	manager.ReadContactTextDefL(aContactId,aResult,*textDef);
       
  1778 	if(aTextDef == NULL)
       
  1779 		{
       
  1780 		CleanupStack::PopAndDestroy(textDef);
       
  1781 		}
       
  1782 	}
       
  1783 
       
  1784 
       
  1785 CContactIdArray* CContactDatabase::SortLC(const CArrayFix<CContactDatabase::TSortPref>* aSortOrder, const CContactIdArray* aIdArray)
       
  1786 	{
       
  1787 	CContactIdArray* sortedItems=CContactIdArray::NewLC();
       
  1788 	if (aSortOrder->Count()==0)
       
  1789 		{
       
  1790 		TContactItemId currentId(1);
       
  1791 		TContactItemId actualId;
       
  1792 		TUid contactType;
       
  1793 		TBool deleted;
       
  1794 		MLplCollection& collection = FactoryL()->GetCollectorL();
       
  1795 		while(collection.SeekContactL(currentId,actualId,contactType,deleted))
       
  1796 			{
       
  1797 			if(CheckType(contactType) && !deleted)
       
  1798 				{
       
  1799 				sortedItems->AddL(actualId);
       
  1800 				}
       
  1801 			currentId = actualId+1;
       
  1802 			}
       
  1803 		}
       
  1804 	else
       
  1805 		{
       
  1806 		CContactTextDef* textDef;
       
  1807 		TUid fieldType=(*aSortOrder)[0].iFieldType;
       
  1808 		if (fieldType==KUidContactFieldDefinedText)
       
  1809 			{
       
  1810 			textDef=iTextDef;
       
  1811 			}
       
  1812 		else
       
  1813 			{
       
  1814 			//We are sorting on aSortOrder.
       
  1815 			textDef=CContactTextDef::NewLC();
       
  1816 			TInt sortOrderCount=aSortOrder->Count();
       
  1817 			for (TInt sortIndex=0;sortIndex<sortOrderCount;sortIndex++)
       
  1818 				{
       
  1819 				textDef->AppendL(TContactTextDefItem((*aSortOrder)[sortIndex].iFieldType));
       
  1820 				}
       
  1821 			}
       
  1822 		CSortArray* sortedList=new(ELeave) CSortArray;
       
  1823 		CleanupStack::PushL(sortedList);
       
  1824 		TContactItemId currentId(1);
       
  1825 		TInt arrayIndex(0);
       
  1826 		for(;;)
       
  1827 			{
       
  1828 			TUid contactType;
       
  1829 			TContactItemId actualId;
       
  1830 			TBool deleted;
       
  1831 			if(aIdArray)
       
  1832 				{
       
  1833 				if (arrayIndex==aIdArray->Count())
       
  1834 					break;
       
  1835 				MLplCollection& collection = FactoryL()->GetCollectorL();
       
  1836 				if(!collection.SeekContactL((*aIdArray)[arrayIndex],actualId,contactType,deleted) || actualId != (*aIdArray)[arrayIndex])
       
  1837 					{
       
  1838 					User::Leave(KErrNotFound);	
       
  1839 					}
       
  1840 				++arrayIndex;
       
  1841 				}
       
  1842 			else
       
  1843 				{
       
  1844 				MLplCollection& collection = FactoryL()->GetCollectorL();
       
  1845 				if(!collection.SeekContactL(currentId,actualId,contactType,deleted))
       
  1846 					{
       
  1847 					break;	
       
  1848 					}
       
  1849 				currentId = actualId+1;
       
  1850 				}
       
  1851 			if(CheckType(contactType) && !deleted)
       
  1852 				{
       
  1853 				CContactDatabase::TTextFieldMinimal textFieldMin;
       
  1854 				ReadContactTextDefL(actualId,textFieldMin,textDef);
       
  1855 				sortedList->AppendL(textFieldMin,actualId);
       
  1856 				}
       
  1857 			}
       
  1858 		sortedList->SortL((*aSortOrder)[0].iOrder);
       
  1859 		SortDuplicatesL(*aSortOrder,*sortedList,1);
       
  1860 		const TInt count=sortedList->Count();
       
  1861 		for (TInt ii=0;ii<count;ii++)
       
  1862 			sortedItems->AddL(sortedList->Id(ii));
       
  1863 		CleanupStack::PopAndDestroy(); // sortedList ,
       
  1864 		if (fieldType!=KUidContactFieldDefinedText)
       
  1865 			{
       
  1866 			CleanupStack::PopAndDestroy();//textdef
       
  1867 			}
       
  1868 		}
       
  1869 	CContactIdArray* newSortedItems=CContactIdArray::NewL(sortedItems);
       
  1870 	CleanupStack::PopAndDestroy(sortedItems);
       
  1871 	CleanupStack::PushL(newSortedItems);
       
  1872 	User::Heap().Compress();
       
  1873 	return(newSortedItems);		
       
  1874 	}
       
  1875 
       
  1876 
       
  1877 void CContactDatabase::ReSortL(CArrayFix<TSortPref>* aSortOrder)
       
  1878 	{
       
  1879 	CContactIdArray* sortedItems=SortLC(aSortOrder,NULL);
       
  1880 	delete iSortedItems;
       
  1881 	iSortedItems=sortedItems;
       
  1882 	CleanupStack::Pop(sortedItems);
       
  1883 	}
       
  1884 
       
  1885 
       
  1886 void CContactDatabase::SortDuplicatesL(const CArrayFix<TSortPref>& aSortOrder,
       
  1887 											CSortArray& aList,TInt aSortIndex)
       
  1888 	{ // is this too heavy on stack usage to be called recursively ???
       
  1889 	__ASSERT_DEBUG(&aSortOrder!=NULL,Panic(ECntPanicNullPointer));
       
  1890 	__ASSERT_DEBUG(&aList!=NULL,Panic(ECntPanicNullPointer));
       
  1891 	if (aSortIndex<aSortOrder.Count())
       
  1892 		{
       
  1893 		const TInt count=aList.Count();
       
  1894 		if (count<=1)
       
  1895 			return;
       
  1896 		TInt ii=0;
       
  1897 		HBufC *text1=aList.Text(ii);
       
  1898 		TInt startPos=KErrNotFound;
       
  1899 		TBool checkedList=EFalse;
       
  1900 		while (!checkedList)
       
  1901 			{
       
  1902 			checkedList=(++ii==count-1);
       
  1903 			HBufC *text2=aList.Text(ii);
       
  1904 			const TInt compare=text1->CompareC(*text2,3,&iCollateMethod);
       
  1905 			if (compare==0)
       
  1906 				{
       
  1907 				if (startPos==KErrNotFound)
       
  1908 					startPos=ii-1;
       
  1909 				}
       
  1910 			else if (startPos!=KErrNotFound)
       
  1911 				{
       
  1912 				SortDuplicatesL(aSortOrder,aList,aSortIndex,startPos,ii);
       
  1913 				startPos=KErrNotFound;
       
  1914 				}
       
  1915 			text1=text2;
       
  1916 			}
       
  1917 		if (startPos!=KErrNotFound)
       
  1918 			SortDuplicatesL(aSortOrder,aList,aSortIndex,startPos,ii+1);
       
  1919 		}
       
  1920 	}
       
  1921 
       
  1922 
       
  1923 void CContactDatabase::SortDuplicatesL(const CArrayFix<TSortPref>& /*aSortOrder*/,CSortArray& /*aList*/,
       
  1924 											TInt /*aIndex*/,TInt /*aStartPos*/,TInt /*aEndPos*/)
       
  1925 	{ 
       
  1926 	}
       
  1927 
       
  1928 
       
  1929 TBool CContactDatabase::CheckType(TUid aUid) const
       
  1930 	{
       
  1931 	// checks the view on the db whether the uid supplied complies to the rules below
       
  1932 	if (aUid == KUidContactTemplate)  // do not include golden template;
       
  1933 		return EFalse;
       
  1934 	if (iDbViewContactType == KUidContactItem)  // any type of contact;
       
  1935 		return ETrue;
       
  1936 	if (iDbViewContactType == KUidContactCardOrGroup &&
       
  1937 		(aUid == KUidContactCard || aUid == KUidContactGroup)) // cards and/or groups
       
  1938 		return ETrue;
       
  1939 	if (iDbViewContactType == KUidContactCard && aUid == KUidContactOwnCard)
       
  1940 		// if the card being checked is an own card - allow it to be included
       
  1941 		return ETrue;
       
  1942 	else if (aUid == iDbViewContactType)		// only a specific match
       
  1943 		return ETrue;
       
  1944 	return EFalse;
       
  1945 	}
       
  1946 
       
  1947 
       
  1948 /**
       
  1949 Sets the template id on the contact item to that of the SystemTemplate
       
  1950 after each update or commit operation.
       
  1951 */
       
  1952 void CContactDatabase::CheckTemplateField(CContactItem& aCnt)
       
  1953 	{
       
  1954 	if (aCnt.iTemplateRefId == KNoValueSet)	
       
  1955 		{
       
  1956 		aCnt.iTemplateRefId = KGoldenTemplateId;	
       
  1957 		}
       
  1958 	if (aCnt.iAccessCount == (TUint32)KNoValueSet)	
       
  1959 		{
       
  1960 		aCnt.iAccessCount = 0;	
       
  1961 		}
       
  1962 	}
       
  1963 
       
  1964 
       
  1965 /** 
       
  1966 Opens a contact item for editing using a specified view definition. 
       
  1967 
       
  1968 The returned contact item is locked and left open until either CommitContactL() or CloseContactL() 
       
  1969 is called.
       
  1970 
       
  1971 Note: care should be taken when specifying a view definition because when committing 
       
  1972 the contact item, any fields not loaded by the view definition are deleted 
       
  1973 from the item.
       
  1974 
       
  1975 The caller takes ownership of the returned object.
       
  1976 
       
  1977 @deprecated
       
  1978 @capability WriteUserData
       
  1979 
       
  1980 @param aContactId The ID of the contact item to open.
       
  1981 
       
  1982 @leave KErrInUse The contact item is already open.
       
  1983 @leave KErrNotFound The contact item is not present in the database. 
       
  1984 
       
  1985 @return The open, locked contact. 
       
  1986 */
       
  1987 EXPORT_C CContactItem* CContactDatabase::OpenContactLX(TContactItemId aContactId)
       
  1988 	{
       
  1989 	// Since the AllFieldsView method returns a modifiable ptr to the iAllFieldsView
       
  1990 	// we must always send it across the IPC as it may have changed.
       
  1991 	return OpenContactLX(aContactId, *iAllFieldsView);
       
  1992 	}
       
  1993 
       
  1994 
       
  1995 /**
       
  1996 Opens a contact item for editing.
       
  1997 
       
  1998 The returned contact item is locked and left open until either CommitContactL() 
       
  1999 or CloseContactL() is called.
       
  2000 
       
  2001 This function uses a view definition that loads every field. If you need to 
       
  2002 specify your own view definition use the other overload of this function.
       
  2003 
       
  2004 The caller takes ownership of the returned object.
       
  2005 
       
  2006 @capability WriteUserData
       
  2007 
       
  2008 @param aContactId The ID of the contact item to open. 
       
  2009 
       
  2010 @return The open, locked contact.
       
  2011 
       
  2012 @leave KErrInUse The contact item is already open.
       
  2013 @leave KErrNotFound The contact item is not present in the database. 
       
  2014 */
       
  2015 EXPORT_C CContactItem* CContactDatabase::OpenContactL(TContactItemId aContactId)
       
  2016 	{
       
  2017 	CContactItem* cntItem = OpenContactLX(aContactId);
       
  2018 	CleanupStack::Pop(); // Pop the lock
       
  2019 	return cntItem;
       
  2020 	}
       
  2021 
       
  2022 
       
  2023 /** 
       
  2024 Opens a contact item for editing, leaving the lock record on the cleanup stack.
       
  2025 
       
  2026 The returned item is locked and left open until either CommitContactL() or 
       
  2027 CloseContactL() is called.
       
  2028 
       
  2029 This function uses the specified view definition. Note: Care should be taken 
       
  2030 when specifying a view definition because when committing the contact item 
       
  2031 any fields not loaded by the view definition are deleted from the item.
       
  2032 
       
  2033 The caller takes ownership of the returned object.
       
  2034 
       
  2035 @deprecated
       
  2036 @capability WriteUserData
       
  2037 
       
  2038 @param aContactId The ID of the contact item to open.
       
  2039 @param aViewDef The view definition.
       
  2040 
       
  2041 @return The open, locked contact item.
       
  2042 
       
  2043 @leave KErrInUse The contact item is already open
       
  2044 @leave KErrNotFound The contact item is not present in the database. 
       
  2045 */
       
  2046 EXPORT_C CContactItem* CContactDatabase::OpenContactL(TContactItemId aContactId, const CContactItemViewDef& aViewDef)
       
  2047 	{
       
  2048 	CContactItem* cntItem = OpenContactLX(aContactId, aViewDef);
       
  2049 	CleanupStack::Pop();
       
  2050 	return cntItem;
       
  2051 	}
       
  2052 
       
  2053 
       
  2054 /** 
       
  2055 Opens a contact item for editing, leaving the lock record on the cleanup stack.
       
  2056 
       
  2057 The returned item is locked and left open until either CommitContactL() or 
       
  2058 CloseContactL() is called.
       
  2059 
       
  2060 This function uses the specified view definition. Note: Care should be taken 
       
  2061 when specifying a view definition because when committing the contact item 
       
  2062 any fields not loaded by the view definition are deleted from the item.
       
  2063 
       
  2064 The caller takes ownership of the returned object.
       
  2065 
       
  2066 @deprecated
       
  2067 @capability WriteUserData
       
  2068 
       
  2069 @param aContactId The ID of the contact item to open.
       
  2070 @param aViewDef The view definition.
       
  2071 
       
  2072 @return The open, locked contact item.
       
  2073 
       
  2074 @leave KErrInUse The contact item is already open
       
  2075 @leave KErrNotFound The contact item is not present in the database. 
       
  2076 */
       
  2077 EXPORT_C CContactItem* CContactDatabase::OpenContactLX(TContactItemId aContactId, const CContactItemViewDef& aViewDef)
       
  2078 	{
       
  2079 	CContactItem* cntItem = iCntSvr->OpenContactLX(&aViewDef, aContactId);
       
  2080 
       
  2081 	CleanupStack::PushL(cntItem);
       
  2082 	iTemplateCache->MergeWithTemplateL(*cntItem, &aViewDef);
       
  2083 	CleanupStack::Pop(cntItem);	
       
  2084 	return cntItem;
       
  2085 	}
       
  2086 
       
  2087 
       
  2088 CContactItem* CContactDatabase::OpenNoMergeLCX(TContactItemId aContactId)
       
  2089 	{
       
  2090 	CContactItem* cntItem = iCntSvr->OpenContactLX(NULL, aContactId);
       
  2091 	CleanupStack::PushL(cntItem);
       
  2092 
       
  2093 	return cntItem;
       
  2094 	}
       
  2095 
       
  2096 
       
  2097 /** 
       
  2098 Gets the ID of the system template. This can then be read, opened and committed 
       
  2099 like any other contact item.
       
  2100 
       
  2101 @return ID of the system template. 
       
  2102 */
       
  2103 EXPORT_C TContactItemId CContactDatabase::TemplateId() const
       
  2104 	{
       
  2105 	return iTemplateCache->TemplateId();
       
  2106 	}
       
  2107 
       
  2108 
       
  2109 /** 
       
  2110 Creates a default own card based on the system template and adds it to the 
       
  2111 database. This is set as the database's current own card, replacing any existing 
       
  2112 current own card. The caller takes ownership of the returned object.
       
  2113 
       
  2114 @capability WriteUserData
       
  2115 
       
  2116 @return Pointer to the new default own card. The pointer is left on the cleanup 
       
  2117 stack.
       
  2118 */
       
  2119 EXPORT_C CContactItem* CContactDatabase::CreateOwnCardLC()
       
  2120 	{
       
  2121 	CContactCard* ownCard = CContactCard::NewLC(&iTemplateCache->SystemTemplateL());
       
  2122 	TInt cntId = AddNewContactL(*ownCard);
       
  2123 	ownCard->iId = cntId;
       
  2124 	// set and persist newowncard id
       
  2125 	iCntSvr->SetOwnCardL(*ownCard);
       
  2126 	CleanupStack::PopAndDestroy(ownCard);
       
  2127     return ReadContactLC(cntId);	
       
  2128 	}
       
  2129 
       
  2130 
       
  2131 /** 
       
  2132 Creates a default own card based on the system template and adds it to the 
       
  2133 database. This is set as the database's current own card, replacing any existing 
       
  2134 current own card. The caller takes ownership of the returned object.
       
  2135 
       
  2136 @capability WriteUserData
       
  2137 
       
  2138 @return Pointer to the new default own card. 
       
  2139 */
       
  2140 EXPORT_C CContactItem* CContactDatabase::CreateOwnCardL()
       
  2141 	{
       
  2142 	CContactItem* ownCard = CreateOwnCardLC();
       
  2143 	CleanupStack::Pop(ownCard);
       
  2144 	return ownCard;
       
  2145 	}
       
  2146 
       
  2147 	
       
  2148 /**
       
  2149 Returns the ID of the database's current own card. 
       
  2150 
       
  2151 Having obtained this ID, the client may then open the own card in the same 
       
  2152 way as an ordinary contact card (using ReadContactL() or OpenContactL()).
       
  2153 
       
  2154 @capability None
       
  2155 
       
  2156 @return The ID of the database's current own card. KNullContactId if the own 
       
  2157 card has been deleted or has not yet been set.
       
  2158 */
       
  2159 EXPORT_C TContactItemId CContactDatabase::OwnCardId() const
       
  2160 	{
       
  2161 	return iCntSvr->OwnCard();
       
  2162 	}
       
  2163 
       
  2164 
       
  2165 /**
       
  2166 Returns the ID of the database's preferred template, as set by SetPrefTemplateL(). 
       
  2167 KNullContactId if not set. The preferred template is for clients who may have 
       
  2168 multiple templates but want to identify one as preferred.
       
  2169 
       
  2170 @capability None
       
  2171 
       
  2172 @return The ID of the database's current preferred template.
       
  2173 */
       
  2174 EXPORT_C TContactItemId CContactDatabase::PrefTemplateId() const
       
  2175 	{
       
  2176 	return(iCntSvr->PrefTemplateId());
       
  2177 	}
       
  2178 
       
  2179 
       
  2180 /** 
       
  2181 Sets an existing contact item to be the database's current own card.
       
  2182 
       
  2183 @capability WriteUserData
       
  2184 
       
  2185 @param aContact The contact item to set as the database's current own card. 
       
  2186 It must already exist in the database. It cannot be a group or a template.
       
  2187 
       
  2188 @leave KErrNotFound aContact does not exist in the database. 
       
  2189 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  2190 */
       
  2191 EXPORT_C void CContactDatabase::SetOwnCardL(const CContactItem& aContact)
       
  2192 	{
       
  2193 	iCntSvr->SetOwnCardL(aContact);	
       
  2194 	}
       
  2195 
       
  2196 	
       
  2197 /**
       
  2198 Sets the time out of operations on the database server.
       
  2199 
       
  2200 This API allows the behaviour of the Contacts Model to be tuned for scenarios
       
  2201 where clients either expect to encounter or know they will encounter operations
       
  2202 failing primarily due to the database being locked.
       
  2203 
       
  2204 Not all clients will find they need to use this API.  By default the operation
       
  2205 timeout is 1 second.
       
  2206 
       
  2207 The timeout only needs to be set once per session.  Multiple clients using the
       
  2208 same database can specify independent values for the operation timeout.
       
  2209 
       
  2210 @capability None
       
  2211 
       
  2212 @publishedPartner
       
  2213 
       
  2214 @released
       
  2215 
       
  2216 @param aMicroSeconds The operation timeout in microseconds.  This timeout will
       
  2217 only be applied to requests sent by clients of this database after this point in
       
  2218 time.
       
  2219 
       
  2220 @leave KErrArgument If aMicroSeconds is less than 0 or is greater than 300000000
       
  2221 (equivalent to 5 minutes). 
       
  2222 */	
       
  2223 EXPORT_C void CContactDatabase::SetOperationTimeOutL(const TInt aMicroSeconds) const
       
  2224 	{
       
  2225 	if (aMicroSeconds < 0 || aMicroSeconds > KFiveMins)
       
  2226 		{
       
  2227 		User::Leave(KErrArgument);
       
  2228 		}
       
  2229 	iCntSvr->SetOperationTimeOutL(aMicroSeconds);
       
  2230 	}
       
  2231 
       
  2232 
       
  2233 /** 
       
  2234 Sets the database's preferred template.
       
  2235 
       
  2236 The preferred template's ID persists when the database is opened and closed. 
       
  2237 If the preferred template is subsequently deleted, the preferred template 
       
  2238 ID is set to KNullContactId.
       
  2239 
       
  2240 @capability WriteUserData
       
  2241 
       
  2242 @param aContact The contact card template to set as the database's preferred 
       
  2243 template.
       
  2244 
       
  2245 @leave KErrNotSupported The item is not a template (of type KUidContactCardTemplate).
       
  2246 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  2247 */
       
  2248 EXPORT_C void CContactDatabase::SetPrefTemplateL(const CContactItem& aContact)
       
  2249 	{
       
  2250 	TUid aContactType = aContact.Type();
       
  2251 	__ASSERT_ALWAYS(aContactType==KUidContactCardTemplate,User::Leave(KErrNotSupported));
       
  2252 	if (aContact.Id()==PrefTemplateId())
       
  2253 		{
       
  2254 		// leave quietly if already set as the preferred template
       
  2255 		return;
       
  2256 		}
       
  2257 	iCntSvr->SetPrefTemplateL(aContact.Id());
       
  2258 	}
       
  2259 
       
  2260 
       
  2261 /** 
       
  2262 Sets the ID of the current item and persists it in the database. The current 
       
  2263 item is provided for use by clients who want to identify one contact item 
       
  2264 in the database as the currently selected item.
       
  2265 
       
  2266 @capability WriteUserData
       
  2267 
       
  2268 @param aContactId The ID of the current item. 
       
  2269 */
       
  2270 EXPORT_C void CContactDatabase::SetCurrentItem(const TContactItemId aContactId)
       
  2271 	{
       
  2272 	iCntSvr->SetCurrentItem(aContactId);	
       
  2273 	}
       
  2274 
       
  2275 
       
  2276 /** 
       
  2277 Gets the ID of the current item, as set by SetCurrentItem(). The current item 
       
  2278 ID is initialised to KNullContactId when the database is opened.
       
  2279 
       
  2280 @capability None
       
  2281 
       
  2282 @return The ID of the current item. 
       
  2283 */	
       
  2284 EXPORT_C TContactItemId CContactDatabase::GetCurrentItem() const
       
  2285 	{	
       
  2286 	return iCntSvr->CurrentItem();
       
  2287 	}
       
  2288 
       
  2289 
       
  2290 /**
       
  2291 Updates a contact identified by aContactId with the data in aNewContact.
       
  2292 All empty fields are deleted.
       
  2293 
       
  2294 @deprecated
       
  2295 @publishedPartner
       
  2296 
       
  2297 @capability WriteUserData
       
  2298 @capability ReadUserData 
       
  2299 
       
  2300 @param aContactId This argument should be ignored by developers.
       
  2301 @param aNewContact The contact item to replace it with.
       
  2302 
       
  2303 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  2304 
       
  2305 @return The contact item after the update.
       
  2306 */
       
  2307 EXPORT_C CContactItem* CContactDatabase::UpdateContactLC(TContactItemId aContactId,CContactItem* aNewContact)
       
  2308 	{
       
  2309 	CContactItemViewDef* viewDef = CContactItemViewDef::NewLC(CContactItemViewDef::EIncludeFields,CContactItemViewDef::EIncludeHiddenFields);
       
  2310 	viewDef->AddL(KUidContactFieldMatchAll);
       
  2311 
       
  2312 	CContactItem* cntItem = OpenContactLX(aContactId, *viewDef);
       
  2313 	CleanupStack::PushL(cntItem);
       
  2314 
       
  2315 	CContactItemFieldSet& newfieldSet = aNewContact->CardFields();
       
  2316 
       
  2317 	TInt count=newfieldSet.Count();
       
  2318 	for (TInt ii=0; ii<count; ++ii)
       
  2319 		{
       
  2320 		//In the case there are duplicate fields in the field Set
       
  2321 		//matchCount need to be increased, so the previous field won't be 
       
  2322 		//overwritten by the later one. 
       
  2323 		TInt matchCount =1;
       
  2324 		for (TInt jj=ii-1; jj>=0; jj--)
       
  2325 			{
       
  2326 			if(newfieldSet[ii].ContentType()==newfieldSet[jj].ContentType())
       
  2327 			matchCount++;
       
  2328 			}
       
  2329 			
       
  2330 		cntItem->CardFields().UpdateFieldL(newfieldSet[ii],matchCount);
       
  2331 		}
       
  2332 		
       
  2333 	doCommitContactL(*cntItem,ETrue,ETrue);
       
  2334 	if (!count)
       
  2335 	    {
       
  2336 	    doDeleteContactL(aContactId,ETrue,ETrue);
       
  2337 	    CleanupStack::PopAndDestroy(cntItem); // Pop and destroy cntItem
       
  2338 
       
  2339 	    cntItem = NULL;
       
  2340 	    CleanupStack::PushL(cntItem); // push a NULL ptr to cleanup stack
       
  2341 	    }
       
  2342 
       
  2343 	if(cntItem != NULL)
       
  2344 	    {
       
  2345 	    CheckTemplateField(*cntItem);
       
  2346 	    }
       
  2347 	CleanupStack::Pop(); // cntItem
       
  2348 	CleanupStack::Pop(); // Pop the lock
       
  2349 	CleanupStack::PopAndDestroy(viewDef);	
       
  2350 	CleanupStack::PushL(cntItem);	
       
  2351 	return(cntItem);
       
  2352 	}
       
  2353 
       
  2354 
       
  2355 /**
       
  2356 Closes the contact item, allowing other applications to access it. Specifying 
       
  2357 a contact item that is not open, or cannot be found, is harmless. This function 
       
  2358 does not commit any changes made to the item. Despite the trailing L in the 
       
  2359 function's name, this function cannot leave.
       
  2360 
       
  2361 @capability None
       
  2362 
       
  2363 @param aContactId The ID of the contact to close.
       
  2364 */
       
  2365 EXPORT_C void CContactDatabase::CloseContactL(TContactItemId aContactId)
       
  2366 	{
       
  2367 	iCntSvr->CloseContact(aContactId);
       
  2368 	}
       
  2369 
       
  2370 
       
  2371 /**
       
  2372 Overwrites a contact item with the values contained in aContact. The contact 
       
  2373 item is also closed by this call.
       
  2374 
       
  2375 @capability ReadUserData
       
  2376 @capability WriteUserData 
       
  2377 
       
  2378 @param aContact Contains the new values for the contact item.
       
  2379 
       
  2380 @leave KErrAccessDenied The contact item is not locked by the caller.
       
  2381 @leave KErrNotFound The contact item's ID is not present in the database. 
       
  2382 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  2383 @leave KErrNotSupported The contact item cannot be committed because it contains
       
  2384 invalid data.
       
  2385 */
       
  2386 EXPORT_C void CContactDatabase::CommitContactL(const CContactItem& aContact)
       
  2387 	{
       
  2388 	// If the contact item being committed is the System template then check if
       
  2389 	// the fields are valid.
       
  2390 	if (aContact.Id()==TemplateId())
       
  2391 		{
       
  2392 		if (!SystemTemplateFieldsValid(aContact))
       
  2393 			{
       
  2394 			User::Leave(KErrNotSupported);
       
  2395 			}
       
  2396 		}
       
  2397 
       
  2398 	iCntSvr->CommitContactL(aContact);
       
  2399 	RespondToEventL(EContactDbObserverEventTemplateChanged, aContact.Id());
       
  2400 	}
       
  2401 
       
  2402 	
       
  2403 /** Updates the existing contact information.
       
  2404 @publishedPartner
       
  2405 @released
       
  2406 
       
  2407 @capability ReadUserData
       
  2408 @capability WriteUserData 
       
  2409 
       
  2410 @param aContact Contains the new values for the contact item.
       
  2411 @param aIsInTransaction This argument should be ignored by developers.
       
  2412 @param aSendChangedEvent This argument should be ignored by developers.
       
  2413 
       
  2414 @leave KErrAccessDenied The contact item is not locked by the caller.
       
  2415 @leave KErrNotFound The contact item's ID is not present in the database. 
       
  2416 @leave KErrNotSupported The contact item cannot be committed because it contains
       
  2417 invalid data.
       
  2418 */	
       
  2419 EXPORT_C void CContactDatabase::doCommitContactL(const CContactItem& aContact,TBool /*aIsInTransaction*/, TBool aSendChangedEvent)
       
  2420 	{
       
  2421 	// If the contact item being committed is the System template then check if
       
  2422 	// the fields are valid.
       
  2423 	if (aContact.Id()==TemplateId())
       
  2424 		{
       
  2425 		if (!SystemTemplateFieldsValid(aContact))
       
  2426 			{
       
  2427 			User::Leave(KErrNotSupported);
       
  2428 			}
       
  2429 		}
       
  2430 
       
  2431 	iCntSvr->CommitContactL(aContact, aSendChangedEvent);
       
  2432 	MoveInSortArray(aContact);
       
  2433 	}
       
  2434 
       
  2435 
       
  2436 /**
       
  2437 Deletes an array of contacts. 
       
  2438 
       
  2439 The function commits the changes for every 32 (for 9.5 onwards it commits after every 50)
       
  2440 contacts deleted, and compresses the database as required. A changed message 
       
  2441 is not sent for every contact deleted, instead a single unknown change event 
       
  2442 message (EContactDbObserverEventUnknownChanges) is sent after all the contacts 
       
  2443 have been deleted and the changes committed.
       
  2444 
       
  2445 @capability WriteUserData 
       
  2446 @capability ReadUserData 
       
  2447 
       
  2448 @param aContactIds An array of contacts to delete.
       
  2449 
       
  2450 @leave KErrNotFound A contact item ID contained in the array is not present 
       
  2451 in the database.
       
  2452 @leave KErrInUse One or more of the contact items is open. 
       
  2453 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  2454 */
       
  2455 EXPORT_C void CContactDatabase::DeleteContactsL(const CContactIdArray& aContactIds)
       
  2456 	{
       
  2457     const TInt KDeleteTransactionGranularity = 50;
       
  2458 	TInt count = aContactIds.Count();
       
  2459 	if (count == 0)
       
  2460 		{
       
  2461 		return;
       
  2462 		}
       
  2463 
       
  2464 	// Clone the ContactIdArray so it can be sorted into ascending order
       
  2465 	CContactIdArray* sortedIdArray = CContactIdArray::NewLC(&aContactIds);
       
  2466 	sortedIdArray->Sort();
       
  2467 
       
  2468     if (count > 1)
       
  2469 	    {	    
       
  2470 	    for(TInt ii = 0; ii < count-1; ++ii)
       
  2471 		    {
       
  2472 		    if ((ii % KDeleteTransactionGranularity) == 0)
       
  2473 			    {
       
  2474 			    if (ii > 0)
       
  2475 				    {
       
  2476 				    DatabaseCommitLP(EFalse);
       
  2477 				    }
       
  2478 			    DatabaseBeginLC(EFalse);			
       
  2479 			    }
       
  2480 		    // Delete the contact but do not trigger any event		
       
  2481 		    DeleteContactSendEventActionL((*sortedIdArray)[ii], EDeferEvent);
       
  2482 		    }
       
  2483 	    }
       
  2484 	else	 
       
  2485 		{ // edge case
       
  2486 		DatabaseBeginLC(EFalse);	
       
  2487 		}		
       
  2488 		
       
  2489 	// Delete the last item and trigger EContactDbObserverEventUnknownChanges 
       
  2490 	DeleteContactSendEventActionL((*sortedIdArray)[count-1], ESendUnknownChangesEvent);	
       
  2491 			
       
  2492 	DatabaseCommitLP(EFalse);		
       
  2493 
       
  2494 	CleanupStack::PopAndDestroy(sortedIdArray);	
       
  2495 	}
       
  2496 
       
  2497 
       
  2498 /**
       
  2499 Deletes a contact item.
       
  2500 
       
  2501 Note: if the contact's access count is greater than zero, the contact is not fully 
       
  2502 deleted from the database. A 'skeleton' of the contact is left, containing only 
       
  2503 basic information, and no field data. The skeleton contact can still be accessed 
       
  2504 if a record of its contact ID has been retained (or call DeletedContactsLC()). 
       
  2505 The skeleton is removed when the access count is zero.
       
  2506 
       
  2507 @capability ReadUserData
       
  2508 @capability WriteUserData
       
  2509 
       
  2510 @param aContactId The contact item ID of the contact to delete.
       
  2511 
       
  2512 @leave KErrNotFound aContactId is not present in the database.
       
  2513 @leave KErrInUse The contact item is open.
       
  2514 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  2515 */
       
  2516 EXPORT_C void CContactDatabase::DeleteContactL(TContactItemId aContactId)
       
  2517 	{
       
  2518 	iCntSvr->DeleteContactL(aContactId, ESendEvent);	
       
  2519 	//Now we check if the contact belonged to the sort array, if so 
       
  2520 	//remove it from iSortedItems
       
  2521     RemoveFromSortArray(aContactId);
       
  2522 	//Now we check if the contact belonged to the template list, if so 
       
  2523 	//remove it from iCardTemplateIds
       
  2524 	RemoveFromTemplateList(aContactId);
       
  2525 	//Now we check if the contact belonged to the Group Id list, if so 
       
  2526 	//remove it from iGroupIds	
       
  2527 	RemoveFromGroupIds(aContactId);
       
  2528 	}
       
  2529 
       
  2530 
       
  2531 /**
       
  2532 Deletes a contact item. 
       
  2533 
       
  2534 Note: if the contact's access count is greater than zero, the contact is not fully 
       
  2535 deleted from the database. A 'skeleton' of the contact is left, containing only 
       
  2536 basic information, and no field data. The skeleton contact can still be accessed 
       
  2537 if a record of its contact ID has been retained (or call DeletedContactsLC()). 
       
  2538 The skeleton is removed when the access count is zero.
       
  2539 
       
  2540 @publishedPartner
       
  2541 @released
       
  2542 
       
  2543 @capability ReadUserData
       
  2544 @capability WriteUserData
       
  2545 
       
  2546 @param aContactId The contact item ID of the contact to delete.
       
  2547 @param aIsInTransaction This argument should be ignored by developers.
       
  2548 @param aSendChangedEvent This argument should be ignored by developers.
       
  2549 @param aDecAccessCount This argument should be ignored by developers.
       
  2550 
       
  2551 @leave KErrNotSupported An attempt has been made to delete the system template.
       
  2552 @leave KErrNotFound aContactId is not present in the database.
       
  2553 @leave KErrInUse The contact item is open.
       
  2554 */
       
  2555 EXPORT_C void CContactDatabase::doDeleteContactL(TContactItemId aContactId, TBool /*aIsInTransaction*/, TBool aSendChangedEvent, TBool aDecAccessCount)
       
  2556 	{
       
  2557 	TCntSendEventAction action = aSendChangedEvent ? ESendEvent : EDeferEvent;
       
  2558 	iCntSvr->DeleteContactL(aContactId, action, aDecAccessCount);	
       
  2559 	//Now we check if the contact belonged to the sort array, if so 
       
  2560 	//remove it from iSortedItems
       
  2561     RemoveFromSortArray(aContactId);
       
  2562 	//Now we check if the contact belonged to the template list, if so 
       
  2563 	//remove it from iCardTemplateIds
       
  2564 	RemoveFromTemplateList(aContactId);
       
  2565 	//Now we check if the contact belonged to the Group Id list, if so 
       
  2566 	//remove it from iGroupIds	
       
  2567 	RemoveFromGroupIds(aContactId);
       
  2568 	}
       
  2569 
       
  2570 	
       
  2571 /**
       
  2572 Returns the full view definition, that loads every field,
       
  2573 the returned pointer is owned by the CContactDatabase object.
       
  2574 
       
  2575 @publishedPartner
       
  2576 @released
       
  2577 
       
  2578 @capability None
       
  2579 
       
  2580 @return The definition for a full view with all the contact item fields.
       
  2581 */	
       
  2582 EXPORT_C CContactItemViewDef* CContactDatabase::AllFieldsView()
       
  2583 	{
       
  2584 	return iAllFieldsView;
       
  2585 	}
       
  2586 
       
  2587 
       
  2588 /**
       
  2589 Imports one or more vCards from a read stream. The vCards are converted into 
       
  2590 contact items, and added to the database. If at least one contact item was 
       
  2591 successfully imported, aImportSuccessful is set to ETrue. If EImportSingleContact 
       
  2592 is specified in aOption, the read stream marker is left at the next position, 
       
  2593 ready to read the next contact item. The caller takes ownership of the returned 
       
  2594 object.
       
  2595 
       
  2596 @capability WriteUserData
       
  2597 
       
  2598 @param aFormat Indicates the format for imported and exported contacts. Its 
       
  2599 value must be KUidVCardConvDefaultImpl.
       
  2600 @param aReadStream The stream to read from.
       
  2601 @param aImportSuccessful On return, ETrue if at least one contact was successfully 
       
  2602 imported. EFalse if not.
       
  2603 @param aOption Indicates the options for import and export. See the TOptions 
       
  2604 enum.
       
  2605 
       
  2606 @leave KErrNotSupported aFormat.iUid is not KUidVCardConvDefaultImpl.
       
  2607 
       
  2608 @return The array of contact items imported.
       
  2609 */
       
  2610 EXPORT_C CArrayPtr<CContactItem>* CContactDatabase::ImportContactsL(const TUid& aFormat,RReadStream& aReadStream,TBool& aImportSuccessful,TInt aOption)
       
  2611 	{
       
  2612 	const TBool importSingleContact= aOption & EImportSingleContact;
       
  2613 	return ConverterL(aFormat).ImportL(*this,aReadStream,aImportSuccessful,aOption,importSingleContact);
       
  2614 	}
       
  2615 
       
  2616 
       
  2617 /**
       
  2618 Converts an array of contact items to vCards and exports them to a write stream.
       
  2619 
       
  2620 The default character set CVersitParser::EUTF8CharSet is used to convert into. If 
       
  2621 you need a different character set, use the other overload of this function.
       
  2622 
       
  2623 @capability ReadUserData
       
  2624 
       
  2625 @param aFormat Indicates the format for imported and exported contacts. Must 
       
  2626 have a value of KUidVCardConvDefaultImpl.
       
  2627 @param aSelectedContactIds Array of contact IDs to export.
       
  2628 @param aWriteStream The stream to write to.
       
  2629 @param aOption Indicates the options for import and export. See the TOptions 
       
  2630 enum.
       
  2631 @param aExportPrivateFields ETrue exports fields marked as private. EFalse 
       
  2632 does not export fields marked as private. See CContactItemField::SetPrivate().
       
  2633 
       
  2634 @leave KErrNotSupported aFormat.iUid is not KUidVCardConvDefaultImpl.
       
  2635 @leave KErrNotFound One or more of the contact items does not exist in the 
       
  2636 database.
       
  2637 */
       
  2638 EXPORT_C void CContactDatabase::ExportSelectedContactsL(const TUid& aFormat,const CContactIdArray& aSelectedContactIds, RWriteStream& aWriteStream, TInt aOption, TBool aExportPrivateFields)
       
  2639 	{
       
  2640 	ExportSelectedContactsL(aFormat,aSelectedContactIds,aWriteStream,aOption,Versit::EUTF8CharSet,aExportPrivateFields);
       
  2641 	}
       
  2642 
       
  2643 
       
  2644 /**
       
  2645 Converts an array of contact items to vCards and exports them to a write 
       
  2646 stream using the specified character set.
       
  2647 
       
  2648 @capability ReadUserData
       
  2649 
       
  2650 @param aFormat Indicates the format for imported and exported contacts. Must 
       
  2651 have a value of KUidVCardConvDefaultImpl.
       
  2652 @param aSelectedContactIds Array of contact IDs to export.
       
  2653 @param aWriteStream The stream to write to.
       
  2654 @param aOption Indicates the options for import and export. See the TOptions 
       
  2655 enum.
       
  2656 @param aCharSet The character set to convert into.
       
  2657 @param aExportPrivateFields ETrue exports fields marked as private. EFalse 
       
  2658 does not export fields marked as private. See CContactItemField::SetPrivate().
       
  2659 
       
  2660 @leave KErrNotSupported aFormat.iUid is not KUidVCardConvDefaultImpl.
       
  2661 @leave KErrNotFound One or more of the contact items does not exist in the 
       
  2662 database.
       
  2663 */
       
  2664 EXPORT_C void CContactDatabase::ExportSelectedContactsL(const TUid& aFormat,const CContactIdArray& aSelectedContactIds, RWriteStream& aWriteStream,TInt aOption,const Versit::TVersitCharSet aCharSet, TBool aExportPrivateFields)
       
  2665 	{
       
  2666 	ConverterL(aFormat).ExportL(*this,aSelectedContactIds,aWriteStream,aOption,aCharSet,aExportPrivateFields);
       
  2667 	}
       
  2668 
       
  2669 
       
  2670 /**
       
  2671 Converts an array of contact items to PBAP compliant vCards following vCard2.1 and vCard3.0 specifications and exports them to a write 
       
  2672 stream using UTF-8 as the character set. It also provides support for exporting contacts as standard vCard2.1.
       
  2673 
       
  2674 @capability ReadUserData
       
  2675 @internalTechnology
       
  2676 @released 
       
  2677 
       
  2678 @param aFormat Indicates the format for imported and exported contacts. It should have a value of KUidPBAPVCardConvImpl if user
       
  2679 wants to export contacts as PBAP specific vCards and KUidVCardConvDefaultImpl for standard vCard2.1.
       
  2680 @param aSelectedContactIds Array of contact IDs to export.
       
  2681 @param aWriteStream The stream to write to.
       
  2682 @param aOption Indicates the options for import and export. See the TOptions 
       
  2683 enum.
       
  2684 @param aContactFieldFilter 64-bit filter,specifies the contact fields to export, argument value not considered for standard vCard2.1 export.
       
  2685 @param aCallback Calls client which has to implement class MConverterCallBack, used to add intra-contact properties,
       
  2686 argument value not considered for standard vCard2.1 export.
       
  2687 @param aVersion TVCardVersion specifies vCard version to which contacts should be exported.
       
  2688 @param aExportTel If TEL property should be exported, it should be set to ETrue, argument value not considered for standard vCard2.1 export.
       
  2689 @param aCharSet The character set to convert into.Must be UTF-8 for PBAP export, provided as default value.
       
  2690 @param aExportPrivateFields ETrue exports fields marked as private. EFalse does not export fields marked as private. See CContactItemField::SetPrivate().
       
  2691 
       
  2692 @leave KErrNotSupported aFormat.iUid is not KUidPBAPVCardConvImpl for PBAP export.
       
  2693 @leave KErrNotSupported aFormat.iUid is not KUidVCardConvDefaultImpl for standard vCard2.1 export.
       
  2694 @leave KErrNotSupported aCharSet is other than UTF-8 for PBAP export. 
       
  2695 @leave KErrNotFound One or more of the contact items does not exist in the database.
       
  2696 */
       
  2697 EXPORT_C void CContactDatabase::ExportSelectedContactsL(const TUid& aFormat, const CContactIdArray& aSelectedContactIds, RWriteStream& aWriteStream, TInt aOption, const TInt64 aContactFieldFilter, MConverterCallBack* aCallback, const TVCardVersion aVersion, const TBool aExportTel, Versit::TVersitCharSet aCharSet, TBool aExportPrivateFields)
       
  2698 	{
       
  2699 	if(aVersion == EVCard21)
       
  2700 		{
       
  2701 		//client wants to export contacts as standard vCard2.1.
       
  2702 		ConverterL(aFormat).ExportL(*this, aSelectedContactIds, aWriteStream, aOption, aCharSet, aExportPrivateFields);		
       
  2703 		}
       
  2704 	else
       
  2705 		{
       
  2706 		if(aCharSet != Versit::EUTF8CharSet)
       
  2707 			{
       
  2708 			User::Leave(KErrNotSupported);	
       
  2709 			}
       
  2710 		ConverterL(aFormat, aContactFieldFilter, aCallback, aVersion, aExportTel).ExportL(*this, aSelectedContactIds, aWriteStream, aOption, aCharSet, aExportPrivateFields);		
       
  2711 		}
       
  2712 	}
       
  2713 
       
  2714 CContactConverter& CContactDatabase::ConverterL(const TUid& aFormat, const TInt64 aContactFieldFilter, MConverterCallBack* aCallback, const TVCardVersion aVersion, const TBool aExportTel)
       
  2715 	{
       
  2716 	if(aFormat.iUid != KUidPBAPVCardConvImpl)
       
  2717 		{
       
  2718 		User::Leave(KErrNotSupported);
       
  2719 		}
       
  2720 	//since version, filter and boolean TEL are initialised only when PBAP plug-in is created,
       
  2721 	//if there is any change in these arguments provided by Client, The plugin should be loaded once again.
       
  2722 	if(iConv && (iConv->GetCurrentVersion() != aVersion || iConv->GetPBAPFilter() != aContactFieldFilter || iConv->GetExportTel() != aExportTel) )
       
  2723 		{
       
  2724 		delete iConv;
       
  2725 		iConv = NULL;
       
  2726 		}
       
  2727 	if(!iConv)
       
  2728 		{
       
  2729 		iConv = CPrivConverter::NewL(aFormat, aContactFieldFilter, aCallback, aVersion, aExportTel);	
       
  2730 		}
       
  2731 	return *iConv->Converter();
       
  2732 	}
       
  2733 
       
  2734 
       
  2735 CContactConverter& CContactDatabase::ConverterL(const TUid& aFormat)
       
  2736 	{
       
  2737 	if(iConv && iConv->GetCurrentVersion() != EVCard21)
       
  2738 		{
       
  2739 		delete iConv;
       
  2740 		iConv = NULL;				
       
  2741 		}
       
  2742 
       
  2743 	switch (aFormat.iUid)
       
  2744 		{
       
  2745 		case KVersitEntityUidVCard:
       
  2746 		case KUidVCardConvDefaultImpl:
       
  2747 		if (!iConv)
       
  2748 			{
       
  2749 			if(aFormat.iUid == KVersitEntityUidVCard)
       
  2750 				{
       
  2751 				iConv=CPrivConverter::NewL(	TUid::Uid(KUidVCardConvDefaultImpl));
       
  2752 				}
       
  2753 			else
       
  2754 				{
       
  2755 				iConv=CPrivConverter::NewL(aFormat);
       
  2756 				}
       
  2757 			}
       
  2758 		break;
       
  2759 		default:
       
  2760 		User::Leave(KErrNotSupported);
       
  2761 		};
       
  2762 
       
  2763 	return *iConv->Converter();
       
  2764 	}
       
  2765 
       
  2766 
       
  2767 /**
       
  2768 Searches the contact tables for the contact described by aGuid.
       
  2769 
       
  2770 @publishedPartner
       
  2771 @released
       
  2772 @capability ReadUserData
       
  2773 
       
  2774 @param aGuid Describes the contact item to be found.
       
  2775 
       
  2776 @leave KErrNotReady The database is not yet ready to read from, could be because an asynchronous open is in progress 
       
  2777 or because a recover is required after a rollback.
       
  2778 @leave KErrBadHandle An asynchronous open either failed or was cancelled.
       
  2779 @leave KErrLocked The database has been closed for a restore.
       
  2780 
       
  2781 @return The unique id of the contact item within the database.
       
  2782 */
       
  2783 EXPORT_C TContactItemId CContactDatabase::ContactIdByGuidL(const TDesC& aGuid)
       
  2784 	{
       
  2785 	TTime time(0);
       
  2786 	MLplCollection& collection = FactoryL()->GetCollectorL();
       
  2787 	CContactIdArray* idArray = collection.CollectionL(MLplCollection::EFindGuid,time,aGuid);
       
  2788 	// Assume a contact with aGuid will not be found.
       
  2789 	TContactItemId id = KNullContactId;
       
  2790 	// Check there is an entry in idArray before attempting to access it.
       
  2791 	if(idArray->Count() > 0)
       
  2792 		{
       
  2793 		// Since aGuid is unique only one contact can match it therefore always
       
  2794 		// expect one and only one entry in the array.
       
  2795 		id = (*idArray)[0];
       
  2796 		}
       
  2797 	delete idArray;
       
  2798 	return id;
       
  2799 	}
       
  2800 
       
  2801 
       
  2802 /** 
       
  2803 Returns a pointer to the array of contact items which have been sorted by either 
       
  2804 SortByTypeL() or SortL(). This pointer is valid until a change is made to 
       
  2805 the database or until the database's active object is allowed to run. If 
       
  2806 the array is required after one of the above two events has occurred, a copy 
       
  2807 of the array must first be made.
       
  2808 
       
  2809 @deprecated
       
  2810 @capability None
       
  2811 
       
  2812 @return A pointer to the array of sorted items. The caller does not take ownership 
       
  2813 of this object.
       
  2814 */
       
  2815 EXPORT_C const CContactIdArray* CContactDatabase::SortedItemsL()
       
  2816 	{
       
  2817 	if(!iSortedItems)
       
  2818 		{
       
  2819 		CArrayFix<TSortPref>* sortPref = iCntSvr->GetSortPreferenceL();
       
  2820 		CleanupStack::PushL(sortPref);
       
  2821 		iSortedItems = SortLC(sortPref,NULL);
       
  2822 		CleanupStack::Pop(iSortedItems);
       
  2823 		CleanupStack::PopAndDestroy(sortPref);
       
  2824 		}
       
  2825 	return iSortedItems;
       
  2826 	}
       
  2827 
       
  2828 
       
  2829 /**
       
  2830 Gets the database's UID. This value is used to identify a particular contact 
       
  2831 database. The database UID is generated when the database is first created.
       
  2832 
       
  2833 Note: This method can leave.
       
  2834 
       
  2835 @capability None
       
  2836 
       
  2837 @return Descriptor containing the database UID.
       
  2838 */
       
  2839 EXPORT_C TPtrC CContactDatabase::FileUid()
       
  2840 	{
       
  2841 	return iCntSvr->FileUidL(); // this can leave
       
  2842 	}
       
  2843 
       
  2844 
       
  2845 /**
       
  2846 Sorts an array of contact IDs. The sort uses the same logic as SortL(). The 
       
  2847 caller takes ownership of the returned object.
       
  2848 
       
  2849 @deprecated
       
  2850 @capability None
       
  2851 
       
  2852 @param aIdArray Pointer to array of contact IDs to sort.
       
  2853 @param aSortOrder Sort order array.
       
  2854 
       
  2855 @return Pointer to sorted array of contact IDs.
       
  2856 */
       
  2857 EXPORT_C CContactIdArray* CContactDatabase::SortArrayL(const CContactIdArray* aIdArray, const CArrayFix<TSortPref>* aSortOrder)
       
  2858 	{
       
  2859 	CContactIdArray* sortedItems = SortArrayLC(aIdArray, aSortOrder);
       
  2860 	CleanupStack::Pop(sortedItems);
       
  2861 	return (sortedItems);
       
  2862 	}
       
  2863 
       
  2864 
       
  2865 /**
       
  2866 Sorts an array of contact IDs. The sort uses the same logic as SortL(). The 
       
  2867 returned array is left on the cleanup stack. The caller takes ownership of 
       
  2868 the returned object.
       
  2869 
       
  2870 @deprecated
       
  2871 @capability None
       
  2872 
       
  2873 @param aIdArray Pointer to array of contact IDs to sort.
       
  2874 @param aSortOrder Sort order array.
       
  2875 
       
  2876 @return Pointer to sorted array of contact IDs.
       
  2877 */
       
  2878 EXPORT_C CContactIdArray* CContactDatabase::SortArrayLC(const CContactIdArray* aIdArray, const CArrayFix<TSortPref>* aSortOrder)
       
  2879 	{
       
  2880 	return SortLC(aSortOrder,aIdArray);
       
  2881 	}
       
  2882 
       
  2883 
       
  2884 /**
       
  2885 Sorts the database using the view type value set by SetDbViewContactType(). 
       
  2886 The database takes ownership of the sort order array passed in.
       
  2887 
       
  2888 The sort uses the same logic as SortL(). The two functions have the same 
       
  2889 effect.
       
  2890 
       
  2891 After calling this function, use CContactDatabase::SortedItemsL() to retrieve 
       
  2892 the sorted array of contact IDs.
       
  2893 
       
  2894 @deprecated
       
  2895 @capability None
       
  2896 
       
  2897 @param aSortOrder Sort order array. 
       
  2898 */
       
  2899 EXPORT_C void CContactDatabase::SortByTypeL(CArrayFix<TSortPref>* aSortOrder)
       
  2900 	{
       
  2901 	CContactIdArray* sortedItems=SortLC(aSortOrder,NULL);
       
  2902 	CleanupStack::Pop(sortedItems);
       
  2903 	delete iSortedItems;
       
  2904 	iSortedItems=sortedItems;
       
  2905 	iCntSvr->SetSortPreferenceL(*aSortOrder);
       
  2906 	delete aSortOrder;
       
  2907 	}
       
  2908 
       
  2909 
       
  2910 /**
       
  2911 Sorts the database. The sort only includes items of the type set by SetDbViewContactType(). 
       
  2912 The database takes ownership of the sort order array passed in. Contacts are 
       
  2913 sorted using the first TSortPref in the array. Any identical matches are then 
       
  2914 sorted using the next TSortPref and so on. When there are no more TSortPrefs 
       
  2915 to use, any remaining unsorted contacts are left in the original database order.
       
  2916 
       
  2917 Note: after calling this function, use CContactDatabase::SortedItemsL() to retrieve 
       
  2918 the sorted array of contact IDs.
       
  2919 
       
  2920 @deprecated
       
  2921 @capability None
       
  2922 
       
  2923 @param aSortOrder Sort order array. If the array's count is zero, no sorting 
       
  2924 takes place. 
       
  2925 */
       
  2926 EXPORT_C void CContactDatabase::SortL(CArrayFix<TSortPref>* aSortOrder)
       
  2927 	{
       
  2928 	TBool reverse=ETrue;
       
  2929 	CArrayFix<TSortPref>* sortPref = iCntSvr->GetSortPreferenceL();
       
  2930 	CleanupStack::PushL(sortPref);
       
  2931 	if (aSortOrder->Count()!=sortPref->Count())
       
  2932 		reverse=EFalse;
       
  2933 	else for(TInt loop=0;loop<aSortOrder->Count();loop++)
       
  2934 		{
       
  2935 		TSortPref oldSort=(*sortPref)[loop];
       
  2936 		TSortPref newSort=(*aSortOrder)[loop];
       
  2937 		if (oldSort.iFieldType!=newSort.iFieldType || oldSort.iOrder==newSort.iOrder)
       
  2938 			{
       
  2939 			reverse=EFalse;
       
  2940 			break;
       
  2941 			}
       
  2942 		}
       
  2943 	if (reverse)
       
  2944 		{
       
  2945 		if (iSortedItems)
       
  2946 			iSortedItems->ReverseOrder();
       
  2947 		}
       
  2948 	else
       
  2949 		{
       
  2950 		ReSortL(aSortOrder);
       
  2951 		}
       
  2952 
       
  2953 	iCntSvr->SetSortPreferenceL(*aSortOrder);
       
  2954 	CleanupStack::PopAndDestroy(sortPref);
       
  2955 
       
  2956 	// Having taken ownership, we deleted aSortOrder here after storing the sort
       
  2957 	// preferences in iCntSrv. Earlier versions of cntmodel stored it in
       
  2958 	// iSortOrder. Some 3rd party apps wrongly use aSortOrder after calling us.
       
  2959 	// As it was held until deletion in the destructor, they used to get away
       
  2960 	// with it. Since the new way broke these apps, we've reverted to the old
       
  2961 	// delayed deletion to maintain compatibility, reinstating iSortOrder.	
       
  2962 	delete iSortOrder;
       
  2963 	iSortOrder = aSortOrder;
       
  2964 	}
       
  2965 
       
  2966 	
       
  2967 /**
       
  2968 Gets the number of CContactItems in the database. The count includes non-system 
       
  2969 template items. It does not include items marked as deleted.
       
  2970 
       
  2971 @deprecated
       
  2972 @capability None
       
  2973 
       
  2974 @return The number of contact items in the database.
       
  2975 */
       
  2976 EXPORT_C TInt CContactDatabase::CountL()
       
  2977 	{
       
  2978 	MLplCollection& collection = FactoryL()->GetCollectorL();
       
  2979 	return collection.ContactCountL();
       
  2980 	}
       
  2981 
       
  2982 	
       
  2983 /**
       
  2984 Sets the type of contact items to be included in sorted views of the database. 
       
  2985 
       
  2986 See also SortL() and SortByTypeL().
       
  2987 
       
  2988 This value is initialised to KUidContactItem when the database is opened. 
       
  2989 This means that all CContactItem-derived types (cards, non-system templates, 
       
  2990 groups, own cards) are included in database views.
       
  2991 
       
  2992 @deprecated
       
  2993 @capability None
       
  2994 
       
  2995 @param aUid Specifies a contact type. One of the following: KUidContactCard 
       
  2996 (contact cards), KUidContactGroup (contact item groups), KUidContactOwnCard 
       
  2997 (own cards), KUidContactCardTemplate (templates which are not system templates, 
       
  2998 in other words, which have been added to the database), KUidContactItem (all of the above)
       
  2999 */
       
  3000 EXPORT_C void CContactDatabase::SetDbViewContactType(const TUid aUid)
       
  3001 	{
       
  3002 	iDbViewContactType = aUid;
       
  3003 	iCntSvr->SetDbViewContactType(aUid);
       
  3004 	}
       
  3005 
       
  3006 
       
  3007 /**
       
  3008 Gets the type of contact items which are included in sorted views of the database, 
       
  3009 as set by SetDbViewContactType(). 
       
  3010 
       
  3011 @deprecated
       
  3012 
       
  3013 @return Specifies a contact type. One of the following: KUidContactCard 
       
  3014 (contact cards), KUidContactGroup (contact item groups), KUidContactOwnCard 
       
  3015 (own cards), KUidContactCardTemplate (templates which are not system, in other words, 
       
  3016 which have been added to the database), KUidContactItem (all of the above)
       
  3017 */
       
  3018 EXPORT_C TUid CContactDatabase::GetDbViewContactType() const
       
  3019 	{
       
  3020 	return iDbViewContactType;
       
  3021 	}
       
  3022 
       
  3023 
       
  3024 /** 
       
  3025 This function does nothing and has been deprecated.
       
  3026 
       
  3027 @capability WriteUserData
       
  3028 @deprecated
       
  3029 */
       
  3030 EXPORT_C void CContactDatabase::CompactL()
       
  3031 	{
       
  3032 	}
       
  3033 
       
  3034 
       
  3035 /**
       
  3036 This function is deprecated. It returns an object whose functions do nothing.
       
  3037 
       
  3038 @capability WriteUserData
       
  3039 @return Pointer to an active compressor.
       
  3040 @deprecated
       
  3041 */
       
  3042 EXPORT_C CContactActiveCompress* CContactDatabase::CreateCompressorLC()
       
  3043 	{
       
  3044 	CContactActiveCompress* compressor = new (ELeave) CContactActiveCompress;
       
  3045 	CleanupStack::PushL(compressor);
       
  3046 	return compressor;
       
  3047 	}
       
  3048 
       
  3049 
       
  3050 /**
       
  3051 This function is deprecated. It returns an object whose functions do nothing.
       
  3052 
       
  3053 @capability WriteUserData
       
  3054 @return Pointer to an active recoverer.
       
  3055 @deprecated
       
  3056 */
       
  3057 EXPORT_C CContactActiveRecover* CContactDatabase::CreateRecoverLC()
       
  3058 	{
       
  3059 	CContactActiveRecover* recover = new(ELeave) CContactActiveRecover;
       
  3060 	CleanupStack::PushL(recover);		
       
  3061 	return recover;
       
  3062 	}
       
  3063 
       
  3064 
       
  3065 /**
       
  3066 Recovers the database from a rollback. It first closes all tables and then reopens 
       
  3067 them after the recover. 
       
  3068 
       
  3069 @capability WriteUserData
       
  3070 */
       
  3071 EXPORT_C void CContactDatabase::RecoverL()
       
  3072 	{
       
  3073 	}
       
  3074 
       
  3075 
       
  3076 /**
       
  3077 This function is deprecated. It always returns EFalse.
       
  3078 
       
  3079 @capability None
       
  3080 @return EFalse
       
  3081 @deprecated
       
  3082 */
       
  3083 EXPORT_C TBool CContactDatabase::CompressRequired()
       
  3084 	{
       
  3085     return EFalse;
       
  3086 	}
       
  3087 
       
  3088 
       
  3089 /** 
       
  3090 This function is deprecated. It always returns EFalse.
       
  3091 
       
  3092 @capability None
       
  3093 @return EFalse
       
  3094 @deprecated
       
  3095 */
       
  3096 EXPORT_C TBool CContactDatabase::IsDamaged() const
       
  3097 	{
       
  3098 	return EFalse;
       
  3099 	}
       
  3100 
       
  3101 
       
  3102 /** 
       
  3103 Debug Only
       
  3104 
       
  3105 @internalTechnology
       
  3106 @released 
       
  3107 @capability WriteUserData
       
  3108 */
       
  3109 EXPORT_C void CContactDatabase::DamageDatabaseL(TInt /*aSecretCode*/)
       
  3110 	{
       
  3111 	}
       
  3112 
       
  3113 
       
  3114 /** 
       
  3115 Gets the size of the database file in bytes.
       
  3116 
       
  3117 @capability None
       
  3118 
       
  3119 @return The size of the contact database. 
       
  3120 */
       
  3121 EXPORT_C TInt CContactDatabase::FileSize() const
       
  3122 	{
       
  3123 	return iCntSvr->FileSize();
       
  3124 	}
       
  3125 
       
  3126 
       
  3127 /** 
       
  3128 This function is deprecated and always returns 0.
       
  3129 
       
  3130 @capability None
       
  3131 @return The wasted space in the contacts database.
       
  3132 @deprecated
       
  3133 */
       
  3134 EXPORT_C TInt CContactDatabase::WastedSpaceInBytes() const
       
  3135 	{	
       
  3136     return 0;  
       
  3137 	}
       
  3138 
       
  3139 
       
  3140 /**
       
  3141 Filters the database. On return, aFilter contains an array of filtered contact 
       
  3142 item IDs.
       
  3143 
       
  3144 @capability ReadUserData
       
  3145 
       
  3146 @param aFilter The filter to use. On return, contains a filtered array of 
       
  3147 contact item IDs.
       
  3148 */
       
  3149 EXPORT_C void CContactDatabase::FilterDatabaseL(CCntFilter& aFilter)
       
  3150 	{
       
  3151 	iCntSvr->FilterDatabaseL(aFilter);
       
  3152 	}
       
  3153 
       
  3154 
       
  3155 /**
       
  3156 Gets an array of contacts modified since the specified date/time.  The array
       
  3157 includes those contacts that have changed since the beginning of the specified
       
  3158 micro-second.  The caller takes ownership of the returned object. 
       
  3159 
       
  3160 @capability ReadUserData
       
  3161 
       
  3162 @param aTime The date/time of interest.
       
  3163 
       
  3164 @return Pointer to the array of contacts modified since the specified time.
       
  3165 */
       
  3166 EXPORT_C CContactIdArray* CContactDatabase::ContactsChangedSinceL(const TTime& aTime)
       
  3167 	{
       
  3168 	MLplCollection& collection = FactoryL()->GetCollectorL();
       
  3169 	return collection.CollectionL(MLplCollection::EChangedSince,aTime);
       
  3170 	}
       
  3171 
       
  3172 
       
  3173 /**
       
  3174 Sets the date/time the database was last synchronised. 
       
  3175 
       
  3176 This overload sets the last synchronised date/time where the sync ID is not
       
  3177 known, and returns the sync ID that was created (a sync ID identifies a machine
       
  3178 with which the database has been synchronised).
       
  3179 
       
  3180 @deprecated
       
  3181 
       
  3182 @param aSyncDate The database's new last synchronised date/time.
       
  3183 
       
  3184 @return The sync ID created by the function.
       
  3185 */
       
  3186 EXPORT_C TContactSyncId CContactDatabase::SetLastSyncDateL(const TTime& aSyncDate)
       
  3187 	{
       
  3188 	//
       
  3189 	// Quick workaround for these APIs rather than implement IPC call to server
       
  3190 	// and a Sync table class.  If we can establish that these APIs are never
       
  3191 	// used (they have been deprecated for a long time) then this workaround can
       
  3192 	// be made permanent.
       
  3193 	//
       
  3194 	iSyncDate = aSyncDate;
       
  3195 	return 0;
       
  3196 	}
       
  3197 
       
  3198 
       
  3199 /**
       
  3200 Sets the date/time the database was last synchronised. 
       
  3201 
       
  3202 This overload is for a known sync ID and updates the database's last 
       
  3203 synchronised date/time for that ID.
       
  3204 
       
  3205 @deprecated
       
  3206 
       
  3207 @param aSyncId This argument should be ignored by developers.
       
  3208 @param aSyncDate The database's new last synchronised date/time.
       
  3209 
       
  3210 @leave KErrNotFound The specified sync ID is not found.
       
  3211 */
       
  3212 EXPORT_C void CContactDatabase::SetLastSyncDateL(TContactSyncId /*aSyncId*/, const TTime& aSyncDate)
       
  3213 	{
       
  3214 	//
       
  3215 	// Quick workaround for these APIs rather than implement IPC call to server
       
  3216 	// and a Sync table class.  If we can establish that these APIs are never
       
  3217 	// used (they have been deprecated for a long time) then this workaround can
       
  3218 	// be made permanent.
       
  3219 	//
       
  3220 	iSyncDate = aSyncDate;
       
  3221 	}
       
  3222 
       
  3223 
       
  3224 /**
       
  3225 Gets the date/time the database was last synchronised with a particular 
       
  3226 sync ID, as set by SetLastSyncDateL().
       
  3227 
       
  3228 @deprecated
       
  3229 
       
  3230 @param aSyncId This argument should be ignored by developers.
       
  3231 @param aSyncDate On return contains the date/time the database was last
       
  3232 synchronised with the sync ID specified.
       
  3233 
       
  3234 @leave KErrNotFound The ID cannot be found in the database.
       
  3235 */
       
  3236 EXPORT_C void CContactDatabase::GetLastSyncDateL(TContactSyncId /*aSyncId*/, TTime& aSyncDate)
       
  3237 	{
       
  3238 	//
       
  3239 	// Quick workaround for these APIs rather than implement IPC call to server
       
  3240 	// and a Sync table class.  If we can establish that these APIs are never
       
  3241 	// used (they have been deprecated for a long time) then this workaround can
       
  3242 	// be made permanent.
       
  3243 	//
       
  3244 	aSyncDate = iSyncDate;
       
  3245 	}
       
  3246 
       
  3247 
       
  3248 /**
       
  3249 Gets the ID of the connection to the Contacts server. 
       
  3250 
       
  3251 This can be compared with the connection IDs of incoming messages to identify 
       
  3252 which connection generated the message.
       
  3253 
       
  3254 @capability None
       
  3255 
       
  3256 @return The ID of the connection to the Contacts server.
       
  3257 */
       
  3258 EXPORT_C TUint CContactDatabase::ConnectionId() const
       
  3259 	{
       
  3260 	return iCntSvr->ConnectionId();
       
  3261 	}
       
  3262 
       
  3263 
       
  3264 /** 
       
  3265 Debug only.
       
  3266 
       
  3267 @internalTechnology
       
  3268 @released 
       
  3269 
       
  3270 @capability None
       
  3271 
       
  3272 @return return the heap size usage of the server in debug mode, 0 in release mode.
       
  3273 */
       
  3274 EXPORT_C TInt CContactDatabase::CntServerResourceCount()
       
  3275 	{
       
  3276 	return(iCntSvr->ResourceCount());
       
  3277 	}
       
  3278 	
       
  3279 
       
  3280 /** 
       
  3281 Debug only.
       
  3282 
       
  3283 @internalTechnology
       
  3284 @released 
       
  3285 
       
  3286 @capability None
       
  3287 */	
       
  3288 EXPORT_C void CContactDatabase::SetCntServerHeapFailure(TInt aTAllocFailType, TInt aRate)
       
  3289 	{
       
  3290 	iCntSvr->SetHeapFailure((RHeap::TAllocFail)aTAllocFailType,aRate);
       
  3291 	}
       
  3292 
       
  3293 
       
  3294 /** 
       
  3295 Debug only.
       
  3296 
       
  3297 @internalTechnology
       
  3298 @released 
       
  3299 
       
  3300 @capability None
       
  3301 
       
  3302 @param aMachineUniqueId The Machine ID to set.
       
  3303 */
       
  3304 EXPORT_C void CContactDatabase::OverrideMachineUniqueId(TInt64 aMachineUniqueId)
       
  3305 	{
       
  3306 	iCntSvr->OverrideMachineUniqueId(aMachineUniqueId);	
       
  3307 	}
       
  3308 
       
  3309 
       
  3310 /** 
       
  3311 Gets the contact model's version number.
       
  3312 
       
  3313 @return The version number of the contacts model. 
       
  3314 */
       
  3315 EXPORT_C TVersion CContactDatabase::Version() const
       
  3316 	{
       
  3317 	return(TVersion(KMajorVersion,KMinorVersion,KBuildNumber));
       
  3318 	}
       
  3319 
       
  3320 
       
  3321 /**
       
  3322 Returns a number unique to the contacts database. This value may be passed 
       
  3323 to CContactItem::UidStringL().
       
  3324 
       
  3325 @capability None
       
  3326 
       
  3327 @return The database's unique ID.
       
  3328 */
       
  3329 EXPORT_C TInt64 CContactDatabase::MachineId() const
       
  3330 	{
       
  3331 	return iCntSvr->MachineId();
       
  3332 	}
       
  3333 
       
  3334 
       
  3335 /**
       
  3336 Gets an array of IDs for contact items that still exist in the database, but 
       
  3337 are marked as deleted. These are contact items which have been deleted, but 
       
  3338 which have a non-zero access count. The caller takes ownership of the returned 
       
  3339 object.
       
  3340 
       
  3341 Debug only.
       
  3342 
       
  3343 @internalTechnology
       
  3344 @released
       
  3345 @capability ReadUserData
       
  3346 
       
  3347 @return Pointer to the array of contacts marked as deleted. 
       
  3348 */
       
  3349 EXPORT_C CContactIdArray* CContactDatabase::DeletedContactsLC()
       
  3350 	{
       
  3351 #if defined(_DEBUG)
       
  3352 	MLplCollection& collection = FactoryL()->GetCollectorL();
       
  3353 	CContactIdArray* deletedContactsIdArray =
       
  3354 		collection.CollectionL(MLplCollection::EDeleted);
       
  3355 	CleanupStack::PushL(deletedContactsIdArray);
       
  3356 	return deletedContactsIdArray;
       
  3357 #else
       
  3358 	// Do nothing (except avoid compiler errors)
       
  3359 	return NULL;
       
  3360 #endif
       
  3361 	}
       
  3362 
       
  3363 
       
  3364 /** 
       
  3365 Requests that the server reset all its speed dials to a NULL state.
       
  3366 Needed so that T_NOMACH works (since deleting the db no longer resets the speed dials)
       
  3367 
       
  3368 Debug only.
       
  3369 
       
  3370 @internalTechnology
       
  3371 @released 
       
  3372 @capability WriteUserData
       
  3373 */
       
  3374 EXPORT_C void CContactDatabase::ResetServerSpeedDialsL()
       
  3375 	{	
       
  3376 #if defined(_DEBUG)
       
  3377 	for(TInt i = KCntMinSpeedDialIndex; i <= KCntMaxSpeedDialIndex; i++)
       
  3378 		{
       
  3379 		// Pass -1 as field index to indicate that speed dial position is to
       
  3380 		// be reset.
       
  3381 		iCntSvr->SetFieldAsSpeedDialL(KNullContactId, -1, i);
       
  3382 		}
       
  3383 #endif
       
  3384 	}
       
  3385 	
       
  3386 	
       
  3387 /** 
       
  3388 Where there are multiple contact databases on a device, this function can be 
       
  3389 used to enquire which database is the current one. The current database functions 
       
  3390 are provided as part of current item functionality. In order to pass a current 
       
  3391 item from one contacts model client to another, the receiving client needs 
       
  3392 to be using the same database.
       
  3393 
       
  3394 The current database is a path and filename, set using SetCurrentDatabase() 
       
  3395 which is persisted by the contacts server.
       
  3396 
       
  3397 @deprecated
       
  3398 @capability None
       
  3399 
       
  3400 @param aDatabase The path and filename of the current database. KNullDesC 
       
  3401 if no current database has been set.
       
  3402 
       
  3403 @return KErrNone if the function completed successfully, otherwise one of the 
       
  3404 standard error codes. 
       
  3405 */
       
  3406 EXPORT_C TInt CContactDatabase::GetCurrentDatabase(TDes& aDatabase) const
       
  3407 	{
       
  3408 	return iCntSvr->GetCurrentDatabase(aDatabase);
       
  3409 	}
       
  3410 
       
  3411 
       
  3412 /** 
       
  3413 Where there are multiple contact databases on a device, this function can be 
       
  3414 used to set a database as the current one.
       
  3415 
       
  3416 Note: this function simply updates a file name which is stored by the contacts server 
       
  3417 and its use is optional. It is provided as part of current item functionality. 
       
  3418 In order to pass a current item from one contacts model client to another, 
       
  3419 the receiving client needs to be using the same database.
       
  3420 
       
  3421 @deprecated
       
  3422 @capability WriteUserData
       
  3423 
       
  3424 @param aDatabase The path and filename of the current database.
       
  3425 
       
  3426 @return KErrNone if the function completed successfully, otherwise one of the 
       
  3427 standard error codes. 
       
  3428 */
       
  3429 EXPORT_C TInt CContactDatabase::SetCurrentDatabase(const TDesC& aDatabase) const
       
  3430 	{
       
  3431 	return iCntSvr->SetCurrentDatabase(aDatabase);
       
  3432 	}
       
  3433 
       
  3434 
       
  3435 /**
       
  3436 Starts a new transaction, without placing a cleanup item to rollback
       
  3437 the database onto the cleanupstack. This is to enable clients to call
       
  3438 contacts methods from an active object.
       
  3439 
       
  3440 @publishedPartner
       
  3441 @released
       
  3442 @capability WriteUserData
       
  3443 
       
  3444 @param aIsInTransaction ETrue if transaction already started
       
  3445 
       
  3446 @leave KErrDiskFull if used storage space above threshold
       
  3447 */
       
  3448 EXPORT_C void CContactDatabase::DatabaseBeginL(TBool aIsInTransaction)
       
  3449 	{
       
  3450 	if (!aIsInTransaction)
       
  3451 		{
       
  3452 		User::LeaveIfError(iCntSvr->BeginDbTransaction());	
       
  3453 		}
       
  3454 	}
       
  3455 	
       
  3456 
       
  3457 /**
       
  3458 Commits an existing transaction, without popping a cleanup item.
       
  3459 
       
  3460 @publishedPartner
       
  3461 @released
       
  3462 @capability WriteUserData
       
  3463 
       
  3464 @param aIsInTransaction ETrue if transaction already started
       
  3465 */
       
  3466 EXPORT_C void CContactDatabase::DatabaseCommitL(TBool aIsInTransaction)
       
  3467 	{
       
  3468 	if (!aIsInTransaction)
       
  3469 		{
       
  3470 		User::LeaveIfError(iCntSvr->CommitDbTransaction());
       
  3471 		}
       
  3472 	}
       
  3473 	
       
  3474 
       
  3475 /**
       
  3476 Force a rollback of the database.
       
  3477 
       
  3478 @publishedPartner
       
  3479 @released
       
  3480 @capability WriteUserData
       
  3481 */
       
  3482 EXPORT_C void CContactDatabase::DatabaseRollback()
       
  3483 	{
       
  3484 	iCntSvr->RollbackDbTransaction();	
       
  3485 	}
       
  3486 	
       
  3487 	
       
  3488 /**
       
  3489 This method allows clients of contacts model to set the sorted item list 
       
  3490 and sort order from a default sort order server as proposed for Crystal 6.0
       
  3491 
       
  3492 Note: This method can leave.
       
  3493 
       
  3494 @param aSortedItems Specifies an array sorted items
       
  3495 @param aSortOrder Specifies the sort order
       
  3496 @deprecated
       
  3497 @capability None
       
  3498 */
       
  3499 EXPORT_C void CContactDatabase::SetSortedItemsList(CContactIdArray* aSortedItems, CArrayFix<TSortPref>* aSortOrder)
       
  3500 	{
       
  3501 	__ASSERT_DEBUG(aSortedItems!=NULL,Panic(ECntPanicNullPointer));
       
  3502 	__ASSERT_DEBUG(aSortOrder!=NULL,Panic(ECntPanicNullPointer));
       
  3503 
       
  3504 	delete iSortedItems;
       
  3505 	iSortedItems=aSortedItems;
       
  3506 	iCntSvr->SetSortPreferenceL(*aSortOrder); // this can leave
       
  3507 	delete aSortOrder;
       
  3508 	}
       
  3509 
       
  3510 
       
  3511 /**
       
  3512 aSortOrder is owned by the idle sorter.
       
  3513 @param aSortOrder Specifies the sort order
       
  3514 @param aStatus The request status for the asynchronous phase request.
       
  3515 @deprecated
       
  3516 */
       
  3517 EXPORT_C void CContactDatabase::SortAsyncL(CArrayFix<TSortPref>* aSortOrder, TRequestStatus& aStatus)
       
  3518 	{
       
  3519 	iIdleSorter->ResetL();
       
  3520 	iIdleSorter->StartSortingL(aSortOrder, aStatus);
       
  3521 	}
       
  3522 
       
  3523 
       
  3524 /**
       
  3525 aSortOrder is owned by the idle sorter.
       
  3526 @param aSortOrder Specifies the sort order
       
  3527 @param aStatus The request status for the asynchronous phase request.
       
  3528 @deprecated
       
  3529 */
       
  3530 EXPORT_C void CContactDatabase::SortAsyncL(CArrayFix<TSortPref>* aSortOrder, TRequestStatus& aStatus, MContactSortObserver& aObserver)
       
  3531 	{
       
  3532 	iIdleSorter->ResetL();
       
  3533 	iIdleSorter->StartSortingL(aSortOrder, aStatus, aObserver);
       
  3534 	}
       
  3535 
       
  3536 
       
  3537 /**
       
  3538 Cancel the CCntIdleSorter object and clean up resources.
       
  3539 
       
  3540 @deprecated
       
  3541 */
       
  3542 EXPORT_C void CContactDatabase::CancelAsyncSort()
       
  3543 	{
       
  3544 	iIdleSorter->Cancel();
       
  3545 	}
       
  3546 
       
  3547 
       
  3548 /**
       
  3549 Tests whether a contact item's hint bit field matches a filter.
       
  3550 
       
  3551 For a match to occur, the item must be of the correct type for inclusion in 
       
  3552 the database (as returned by GetDbViewContactType()) and its hint bit field 
       
  3553 (which indicates whether the item contains a work or home telephone number, 
       
  3554 fax number or email address) must match the filter, according to the rules 
       
  3555 described in TContactViewFilter.
       
  3556 
       
  3557 @internalTechnology
       
  3558 @capability None
       
  3559 
       
  3560 @param aBitWiseFilter The filter to compare the item against. This is a combination 
       
  3561 of TContactViewFilter values.
       
  3562 @param aContactId The ID of the item in the database.
       
  3563 
       
  3564 @return ETrue if the item is of the correct type for inclusion in the database, 
       
  3565 and its hint bit field matches the specified filter, EFalse if either of these 
       
  3566 conditions are not met.
       
  3567 */
       
  3568 EXPORT_C TBool CContactDatabase::ContactMatchesHintFieldL(TInt aBitWiseFilter,TContactItemId aContactId)
       
  3569 	{//Returns ETrue if the contact Hint field matches any of the aBitWiseFilter fields
       
  3570 	return iCntSvr->ContactMatchesHintFieldL(aBitWiseFilter,aContactId);
       
  3571 	}
       
  3572 
       
  3573 
       
  3574 /**
       
  3575 Returns the ID of the template that should be used with CContactICCEntry items.
       
  3576 
       
  3577 @capability None
       
  3578 
       
  3579 @return A template ID.
       
  3580 */
       
  3581 EXPORT_C TContactItemId CContactDatabase::ICCTemplateIdL()
       
  3582 	{
       
  3583 	LoadSyncPluginL();
       
  3584 	return iCntSvr->ICCTemplateIdL(KUidIccGlobalAdnPhonebook);
       
  3585 	}
       
  3586 
       
  3587 
       
  3588 /**
       
  3589 Returns the ID of the template that should be used with CContactICCEntry items 
       
  3590 belonging to the phonebook with TUid aPhonebookUid.
       
  3591 
       
  3592 @capability None
       
  3593 
       
  3594 @param aPhonebookUid The phonebook ID.
       
  3595 
       
  3596 @return A template ID.
       
  3597 */
       
  3598 EXPORT_C TContactItemId CContactDatabase::ICCTemplateIdL(TUid aPhonebookUid)
       
  3599  	{
       
  3600  	LoadSyncPluginL();
       
  3601  	return iCntSvr->ICCTemplateIdL(aPhonebookUid);
       
  3602  	}
       
  3603 
       
  3604 
       
  3605 /**
       
  3606 Returns the ID of the contacts model group which represents the ADN phonebook.
       
  3607 
       
  3608 @capability None
       
  3609 
       
  3610 @return Group ID.
       
  3611 */ 
       
  3612 EXPORT_C TContactItemId CContactDatabase::PhonebookGroupIdL()
       
  3613 	{
       
  3614 	LoadSyncPluginL();
       
  3615 	return iCntSvr->PhonebookGroupIdL();
       
  3616 	}
       
  3617 
       
  3618 
       
  3619 /**
       
  3620 Returns a list of 'unfiled' contacts. These are contacts which do not belong to any group.
       
  3621 
       
  3622 @publishedPartner
       
  3623 @released
       
  3624 @capability ReadUserData
       
  3625 
       
  3626 @return The list of 'unfiled' contacts.
       
  3627 */
       
  3628 EXPORT_C CContactIdArray* CContactDatabase::UnfiledContactsL()
       
  3629 	{
       
  3630 	MLplCollection& collection = FactoryL()->GetCollectorL();
       
  3631 	return collection.CollectionL(MLplCollection::EUnfiled);
       
  3632 	}
       
  3633 
       
  3634 
       
  3635 /**
       
  3636 Opens the default contact database asynchronously.
       
  3637 
       
  3638 The Contacts server is asked to prepare the database to be opened. This may include
       
  3639 cleaning up incomplete writes from when the device was last switched off, or updating the 
       
  3640 database format.
       
  3641 
       
  3642 If an error is encountered starting the asynchronous open the return value is NULL and the
       
  3643 error is returned in the TRequestStatus parameter.
       
  3644 
       
  3645 Errors from the asynchronous open include:
       
  3646 KErrNotFound The database file was not found or it did not have the correct UIDs.
       
  3647 KErrLocked The file is in use by another client.
       
  3648 Other system wide error codes.
       
  3649 
       
  3650 If the return value is not NULL the ownership of the CContactOpenOperation object is passed 
       
  3651 to the client. This may be deleted before the asynchronous open completes.
       
  3652 
       
  3653 When the client supplied TRequestStatus is completed with KErrNone the TakeDatabase() method
       
  3654 of CContactOpenOperation is called to pass ownership of the open database to the client.
       
  3655 
       
  3656 @publishedAll
       
  3657 @released
       
  3658 @capability ReadUserData
       
  3659 
       
  3660 @param	aStatus
       
  3661 		On return, the request status for the asynchronous phase request.
       
  3662 		The Open() action can fail with one of the system wide error codes. In this case, the
       
  3663 		CContactDatabase object cannot access the database and must be deleted.
       
  3664 @param	aAccess
       
  3665 		This argument should be ignored by developers.
       
  3666 
       
  3667 @return NULL if there is an error starting the asynhchronous open, otherwise a pointer to an
       
  3668 		active object that manages the open operation.
       
  3669 
       
  3670 @see CContactOpenOperation
       
  3671 */
       
  3672 EXPORT_C CContactOpenOperation* CContactDatabase::Open(TRequestStatus& aStatus, TThreadAccess /*aAccess*/)
       
  3673 	{
       
  3674 	aStatus = KRequestPending;
       
  3675 	CContactOpenOperation* openOperation = NULL;
       
  3676 	
       
  3677 	TRAPD(newError, openOperation = CContactOpenOperation::NewL(aStatus));
       
  3678 	// failed? return the error in the TRequestStatus
       
  3679 	if (newError != KErrNone)
       
  3680 		{
       
  3681 		TRequestStatus* ptrStatus = &aStatus;
       
  3682 		User::RequestComplete(ptrStatus, newError);
       
  3683 		}
       
  3684 	return openOperation;
       
  3685 	}
       
  3686 
       
  3687 
       
  3688 /**
       
  3689 Opens a named contact database asynchronously.
       
  3690 
       
  3691 The Contacts server is asked to prepare the database to be opened. This may include
       
  3692 cleaning up incomplete writes from when the device was last switched off, or updating the 
       
  3693 database format.
       
  3694 
       
  3695 In v8.1, contact databases can be located in any directory on any writeable drive, and the 
       
  3696 format of the filename must include an absolute directory path such as 
       
  3697 c:\\system\\data\\contacts.cdb.
       
  3698 
       
  3699 From v9.0 onwards, contact databases can only be located in the correct data caged 
       
  3700 subdirectory. The filenames must have no path, for example c:contacts.cdb.
       
  3701 The maximum length for the drive, filename and extension is 190 characters.
       
  3702 
       
  3703 If an empty path is entered, it will be treated as a request to open the default contact 
       
  3704 database.
       
  3705 
       
  3706 If an error is encountered starting the asynchronous open the return value is NULL and the
       
  3707 error is returned in the TRequestStatus parameter.
       
  3708 
       
  3709 Errors from the asynchronous open include:
       
  3710 KErrNotFound The database file was not found or it did not have the correct UIDs.
       
  3711 KErrLocked The file is in use by another client.
       
  3712 KErrBadName The filename is invalid; for example it includes wildcard characters
       
  3713 or the drive is missing.
       
  3714 Other system wide error codes.
       
  3715 
       
  3716 If the return value is not NULL the ownership of the CContactOpenOperation object is passed 
       
  3717 to the client. This may be deleted before the asynchronous open completes.
       
  3718 
       
  3719 When the client supplied TRequestStatus is completed with KErrNone the TakeDatabase() method
       
  3720 of CContactOpenOperation is called to pass ownership of the open database to the client.
       
  3721 
       
  3722 @publishedAll
       
  3723 @released
       
  3724 @capability ReadUserData
       
  3725 
       
  3726 @param	aFileName
       
  3727 		The filename of the database to open.
       
  3728 @param	aStatus
       
  3729 		On return, the request status for the asynchronous phase request.
       
  3730 		The Open() action can fail with one of the system wide error codes. In this case the
       
  3731 		CContactDatabase object cannot access the database and must be deleted.
       
  3732 @param	aAccess
       
  3733 		This argument should be ignored by developers.
       
  3734 
       
  3735 @return NULL if there is an error starting the asynhchronous open, otherwise a pointer to an
       
  3736 		active object that manages the open operation.
       
  3737 
       
  3738 @see CContactOpenOperation
       
  3739 */
       
  3740 EXPORT_C CContactOpenOperation* CContactDatabase::Open(const TDesC& aFileName, TRequestStatus& aStatus, TThreadAccess /*aAccess*/)
       
  3741 	{
       
  3742 	TRequestStatus* ptrStatus = &aStatus;
       
  3743 	CContactOpenOperation* openOperation = NULL;
       
  3744 
       
  3745 	TRAPD(newError, openOperation = CContactOpenOperation::NewL(aFileName, aStatus));
       
  3746 	// failed? return the error in the TRequestStatus
       
  3747 	if (newError != KErrNone)
       
  3748 		{
       
  3749 		User::RequestComplete(ptrStatus, newError);
       
  3750 		}
       
  3751 
       
  3752 	return openOperation;
       
  3753 	}
       
  3754 
       
  3755 
       
  3756 /**
       
  3757 A static method to list the contact databases on all drives.
       
  3758 
       
  3759 In v8.1, this function finds contact databases located anywhere on the drives, 
       
  3760 and the format of the returned filenames is c:\\system\\data\\contacts.cdb.
       
  3761 
       
  3762 From v9.0 onwards, this function finds contact databases only in the correct 
       
  3763 data caged subdirectory. The returned filenames have no path, for example 
       
  3764 c:contacts.cdb. The maximum length for the drive, filename and extension is 190 
       
  3765 characters.
       
  3766 
       
  3767 In either case, the filenames returned are in the correct format for Open(), 
       
  3768 OpenL(), CreateL(), ReplaceL() and DeleteDatabaseL().
       
  3769 
       
  3770 @publishedAll
       
  3771 @released
       
  3772 @capability ReadUserData
       
  3773 
       
  3774 @return An array containing zero or more contact database names.
       
  3775 
       
  3776 @leave KErrNoMemory Out of memory.
       
  3777 */
       
  3778 EXPORT_C CDesCArray* CContactDatabase::ListDatabasesL()
       
  3779 	{
       
  3780 	CContactDatabase* db = NewLC();
       
  3781 	CDesCArray* list = db->iCntSvr->ListDatabasesL();
       
  3782 	CleanupStack::PopAndDestroy(db);
       
  3783 	return list;
       
  3784 	}
       
  3785 
       
  3786 
       
  3787 /**
       
  3788 A static method to list the contact databases on a specified drive.
       
  3789 
       
  3790 In v8.1, this function finds contact databases located anywhere on the drive, 
       
  3791 and the format of the returned filenames is c:\\system\\data\\contacts.cdb.
       
  3792 
       
  3793 From v9.0 onwards, this function finds contact databases only in the correct 
       
  3794 data caged subdirectory. The returned filenames have no path, for example 
       
  3795 c:contacts.cdb. The maximum length for the drive, filename and extension is 190 
       
  3796 characters.
       
  3797 
       
  3798 In either case, the filenames returned are in the correct format for Open(), 
       
  3799 OpenL(), CreateL(), ReplaceL() and DeleteDatabaseL().
       
  3800 
       
  3801 @publishedAll
       
  3802 @released
       
  3803 @capability ReadUserData
       
  3804 
       
  3805 @param	aDriveUnit
       
  3806 		The drive unit to search for contact databases.
       
  3807 
       
  3808 @return An array containing zero or more contact database names.
       
  3809 
       
  3810 @leave	KErrNoMemory Out of memory.
       
  3811 */
       
  3812 EXPORT_C CDesCArray* CContactDatabase::ListDatabasesL(TDriveUnit aDriveUnit)
       
  3813 	{
       
  3814 	CContactDatabase* db = NewLC();
       
  3815 	CDesCArray* list = db->iCntSvr->ListDatabasesL(&aDriveUnit);
       
  3816 	CleanupStack::PopAndDestroy(db);
       
  3817 	return list;
       
  3818 	}
       
  3819 
       
  3820 
       
  3821 /**
       
  3822 A static method to delete a named contact database.
       
  3823 
       
  3824 If the file is found, it is tested for the correct UIDs.
       
  3825 
       
  3826 In v8.1, contact databases can be located in any directory on any writeable drive, 
       
  3827 and the format of the filename must include an absolute directory path such as 
       
  3828 c:\\system\\data\\contacts.cdb.
       
  3829 
       
  3830 From v9.0 onwards, contact databases can only be located in the correct data caged 
       
  3831 subdirectory. The filenames must have no path, for example c:contacts.cdb.
       
  3832 The maximum length for the drive, filename and extension is 190 characters.
       
  3833 
       
  3834 @publishedAll
       
  3835 @released
       
  3836 @capability WriteUserData
       
  3837 
       
  3838 @param	aFileName
       
  3839 		The contact database file to delete.
       
  3840 
       
  3841 @leave	KErrBadName The filename is invalid; for example it contains 
       
  3842 wildcard characters or the drive is missing.
       
  3843 @leave	KErrInUse Another client has the database open.
       
  3844 @leave	KErrNotFound The database file was not found or it did not have the correct UIDs.
       
  3845 @leave  KErrArgument if the given descriptor contains more than the maximum length 
       
  3846         of 190 characters.
       
  3847 
       
  3848 @see CContactDatabase::DeleteDefaultFileL()
       
  3849 */
       
  3850 EXPORT_C void CContactDatabase::DeleteDatabaseL(const TDesC& aFileName)
       
  3851 	{
       
  3852 	CContactDatabase* db = NewLC();
       
  3853 	User::LeaveIfError(db->iCntSvr->DeleteDatabase(aFileName));
       
  3854 	CleanupStack::PopAndDestroy(db);
       
  3855 	}
       
  3856 
       
  3857 
       
  3858 /**
       
  3859 A static method to determine if the default contact database exists. 
       
  3860 
       
  3861 It searches the drive set by SetDatabaseDriveL(), or if no drive has been 
       
  3862 set, it searches drive c:.
       
  3863 
       
  3864 If the file is found, it is tested for the correct UIDs.
       
  3865 
       
  3866 @publishedAll
       
  3867 @released
       
  3868 @capability None
       
  3869 
       
  3870 @return ETrue if the file is found, EFalse otherwise.
       
  3871 @leave	KErrNotReady There is no media present in the drive.
       
  3872 @leave	KErrNotFound The database file was not found or it did not have the correct UIDs.
       
  3873 @leave	KErrCorrupt The file is not a valid database 
       
  3874 
       
  3875 @see CContactDatabase::ContactDatabaseExistsL()
       
  3876 */
       
  3877 EXPORT_C TBool CContactDatabase::DefaultContactDatabaseExistsL()
       
  3878 	{	
       
  3879 	CContactDatabase* db = NewLC();
       
  3880 	TBool theFlag = db->iCntSvr->DatabaseExistsL();
       
  3881 	CleanupStack::PopAndDestroy(db);	
       
  3882 	return theFlag;
       
  3883 	}
       
  3884 
       
  3885 
       
  3886 /**
       
  3887 A method to determine if a named contact database exists.
       
  3888 
       
  3889 If the file is found, it is tested for the correct UIDs.
       
  3890 
       
  3891 In v8.1, contact databases can be located in any directory on any writeable drive, 
       
  3892 and the format of the filename must include an absolute directory path such as 
       
  3893 c:\\system\\data\\contacts.cdb.
       
  3894 
       
  3895 From v9.0 onwards, contact databases can only be located in the correct data caged
       
  3896 subdirectory. The filenames must have no path, for example c:contacts.cdb.
       
  3897 The maximum length for the drive, filename and extension is 190 characters.
       
  3898 
       
  3899 @publishedAll
       
  3900 @released
       
  3901 @capability None
       
  3902 
       
  3903 @param	aFileName
       
  3904 		The contact database to search for.
       
  3905 
       
  3906 @return ETrue if the file is found, EFalse otherwise.
       
  3907 
       
  3908 @leave	KErrNotReady There is no media present in the drive.
       
  3909 @leave	KErrBadName The filename is invalid; for example it contains 
       
  3910 wildcard characters or the drive is missing.
       
  3911 @leave	KErrNotFound The database file was not found or it did not have the correct UIDs.
       
  3912 @leave	KErrCorrupt The file is not a valid database 
       
  3913 @leave  KErrArgument if the given descriptor contains more than the maximum length 
       
  3914         of 190 characters.
       
  3915 
       
  3916 @see CContactDatabase::DefaultContactDatabaseExistsL()
       
  3917 @see CContactDatabase::ListDatabasesL()
       
  3918 */
       
  3919 EXPORT_C TBool CContactDatabase::ContactDatabaseExistsL(const TDesC& aFileName)
       
  3920 	{
       
  3921 	// Leave if the filename format is bad
       
  3922 	TParse parseName;
       
  3923 	User::LeaveIfError(parseName.SetNoWild(aFileName,NULL,NULL));	
       
  3924 	CContactDatabase* db = NewLC();
       
  3925 	TBool dbExists = db->iCntSvr->DatabaseExistsL(aFileName);
       
  3926 	CleanupStack::PopAndDestroy(db);
       
  3927 	
       
  3928 	return dbExists;
       
  3929 	}
       
  3930 
       
  3931 
       
  3932 /**
       
  3933 Searches the database for a text string.  The function searches the fields
       
  3934 contained in the field definition.  The caller takes ownership of the returned
       
  3935 object. There is a limit of 255 characters on the search string length, due to
       
  3936 the implementation of the DBMS API, which also has a search string length
       
  3937 restriction of 255 chars. If the search string passed in is over 255 characters
       
  3938 this method will leave with KErrArgument.
       
  3939    
       
  3940 @param aText The text to search for.
       
  3941 @param aFieldDef Specifies the fields to search.
       
  3942 
       
  3943 @return Array of contact IDs identifying the contact items which contain the 
       
  3944 specified text.
       
  3945 */
       
  3946 EXPORT_C CContactIdArray* CContactDatabase::FindLC(const TDesC& aText,const CContactItemFieldDef* aFieldDef)
       
  3947 	{
       
  3948 	CContactIdArray* idArray = iCntSvr->FindL(aText,aFieldDef);
       
  3949 	CleanupStack::PushL(idArray);
       
  3950 	return idArray;
       
  3951 	}
       
  3952 
       
  3953 
       
  3954 /**
       
  3955 Searches the database asynchronously for a text string. The function searches 
       
  3956 the fields contained in the field definition asynchronously using the MIdleFindObserver 
       
  3957 and CIdleFinder classes. The caller takes ownership of the returned object.
       
  3958 
       
  3959 @param aText The text to search for.
       
  3960 @param aFieldDef Specifies the fields to search.
       
  3961 @param aObserver Implements the callback function IdleFindCallback(). NULL 
       
  3962 if no observer is needed.
       
  3963 
       
  3964 @return A CIdle-derived object which provides information about the progress 
       
  3965 of the operation, and which can be used to retrieve an array of contact IDs.
       
  3966 */
       
  3967 // !!! assert that the field definition doesn't contain any fields not included in the view?
       
  3968 // !!! should change to set the column found also
       
  3969 EXPORT_C CIdleFinder* CContactDatabase::FindAsyncL(const TDesC& aText,const CContactItemFieldDef *aFieldDef, MIdleFindObserver *aObserver)
       
  3970 	{
       
  3971 	return(CIdleFinder::NewL(*this,aText,aFieldDef,aObserver));
       
  3972 	}
       
  3973 
       
  3974 
       
  3975 /**
       
  3976 Enables the user to search the database for a string containing 
       
  3977 text that is stored in one or more fields.
       
  3978 
       
  3979 The string is specified as an array of words.
       
  3980 
       
  3981 For example, a user might want to search for the string "John Smith". 
       
  3982 To the user the string is a single item, but the text which makes up 
       
  3983 the string is stored in two separate fields in the database.
       
  3984 
       
  3985 The caller of this function needs to provide an array of words to find 
       
  3986 (aFindWords), and a function to break down the text in the contact item 
       
  3987 into a list of words (aWordParserCallback).
       
  3988 
       
  3989 The array of words to find would typically not contain punctuation. For 
       
  3990 example if the user searches for 'Smith, John' this would be passed to 
       
  3991 this function as an array of two words: 'Smith' and 'John', with the 
       
  3992 separator being discarded.
       
  3993 
       
  3994 For a match to succeed, all words in the aFindWords array must match 
       
  3995 words in the array generated from the contact item by the aWordParserCallback 
       
  3996 function. To match, the word generated from the contact item must begin with 
       
  3997 the search word, i.e. a search for "Sm" would find any word beginning in "Sm". 
       
  3998 If a word is specified twice in the aFindWords array, then it must exist in 
       
  3999 two separate places in the contact item.
       
  4000 
       
  4001 The function only searches the fields contained in the currently set text 
       
  4002 definition.
       
  4003 
       
  4004 The caller takes ownership of the returned object.
       
  4005 
       
  4006 @param aFindWords An array of words to find.
       
  4007 @param aWordParserCallback A function supplied by the caller to break the text 
       
  4008 in the contact down into a list of words.
       
  4009 
       
  4010 @return Array of contact IDs.
       
  4011 */
       
  4012 EXPORT_C CContactIdArray* CContactDatabase::FindInTextDefLC(const MDesCArray& aFindWords, const TCallBack &aWordParserCallback)
       
  4013 	{
       
  4014 	return(FindInTextDefLC(aFindWords,iTextDef,aWordParserCallback));
       
  4015 	}
       
  4016 
       
  4017 
       
  4018 /**
       
  4019 Enables the user to search the database for a string containing 
       
  4020 text that is stored in one or more fields.
       
  4021 
       
  4022 The string is specified as an array of words.
       
  4023 
       
  4024 For example, a user might want to search for the string "John Smith". 
       
  4025 To the user the string is a single item, but the text which makes up 
       
  4026 the string is stored in two separate fields in the database.
       
  4027 
       
  4028 The caller of this function needs to provide an array of words to find 
       
  4029 (aFindWords), and a function to break down the text in the contact item 
       
  4030 into a list of words (aWordParserCallback).
       
  4031 
       
  4032 The array of words to find would typically not contain punctuation. For 
       
  4033 example if the user searches for 'Smith, John' this would be passed to 
       
  4034 this function as an array of two words: 'Smith' and 'John', with the 
       
  4035 separator being discarded.
       
  4036 
       
  4037 For a match to succeed, all words in the aFindWords array must match 
       
  4038 words in the array generated from the contact item by the aWordParserCallback 
       
  4039 function. To match, the word generated from the contact item must begin with 
       
  4040 the search word, i.e. a search for "Sm" would find any word beginning in "Sm". 
       
  4041 If a word is specified twice in the aFindWords array, then it must exist in 
       
  4042 two separate places in the contact item.
       
  4043 
       
  4044 The function only searches the fields contained in the text definition aTextDef.
       
  4045 
       
  4046 The caller takes ownership of the returned object.
       
  4047 
       
  4048 @param aFindWords An array of words to find.
       
  4049 @param aTextDef The text definition.
       
  4050 @param aWordParserCallback A function supplied by the caller to break the text 
       
  4051 in the contact down into a list of words.
       
  4052 
       
  4053 @return Array of contact IDs.
       
  4054 */
       
  4055 EXPORT_C CContactIdArray* CContactDatabase::FindInTextDefLC(const MDesCArray& aFindWords,CContactTextDef* aTextDef, const TCallBack &aWordParserCallback)
       
  4056 	{
       
  4057 	CIdleFinder* idleFinder=FindInTextDefAsyncL(aFindWords,aTextDef,NULL,aWordParserCallback);
       
  4058 	CleanupStack::PushL(idleFinder);
       
  4059 	while(idleFinder->doFindL()) {};
       
  4060 	User::LeaveIfError(idleFinder->Error());
       
  4061 	CContactIdArray *ids=idleFinder->TakeContactIds();
       
  4062 	CleanupStack::PopAndDestroy();	// idleFinder
       
  4063 	CleanupStack::PushL(ids);
       
  4064 	return(ids);
       
  4065 	}
       
  4066 
       
  4067 
       
  4068 /**
       
  4069 Asynchronously searches the database for an array of words. 
       
  4070 
       
  4071 This function works in the same way as its corresponding variant in FindInTextDefLC(), 
       
  4072 except that it operates asynchronously using the MIdleFindObserver and CIdleFinder 
       
  4073 classes. The caller takes ownership of the returned object.
       
  4074 
       
  4075 @param aFindWords An array of words to find.
       
  4076 @param aObserver Implements the callback function IdleFindCallback(). May be NULL if 
       
  4077 no observer is needed.
       
  4078 @param aWordParserCallback A function to break the text in the contact down into a 
       
  4079 list of words.
       
  4080 
       
  4081 @return A CIdle-derived object which provides information about the progress of the 
       
  4082 operation, and which can be used to retrieve an array of contact IDs.
       
  4083 */
       
  4084 EXPORT_C CIdleFinder* CContactDatabase::FindInTextDefAsyncL(const MDesCArray& aFindWords, MIdleFindObserver *aObserver, const TCallBack &aWordParserCallback)
       
  4085 	{
       
  4086 	return(FindInTextDefAsyncL(aFindWords,iTextDef,aObserver,aWordParserCallback));
       
  4087 	}
       
  4088 
       
  4089 
       
  4090 /**
       
  4091 Asynchronously searches the database for an array of words. 
       
  4092 
       
  4093 This function works in the same way as its corresponding variant in FindInTextDefLC(), 
       
  4094 except that it operates asynchronously using the MIdleFindObserver and CIdleFinder 
       
  4095 classes. The caller takes ownership of the returned object.
       
  4096 
       
  4097 @param aFindWords An array of words to find.
       
  4098 @param aTextDef The text definition.
       
  4099 @param aObserver Implements the callback function IdleFindCallback(). May be NULL if 
       
  4100 no observer is needed.
       
  4101 @param aWordParserCallback A function to break the text in the contact down into a 
       
  4102 list of words.
       
  4103 
       
  4104 @return A CIdle-derived object which provides information about the progress of the 
       
  4105 operation, and which can be used to retrieve an array of contact IDs.
       
  4106 */
       
  4107 EXPORT_C CIdleFinder* CContactDatabase::FindInTextDefAsyncL(const MDesCArray& aFindWords,const CContactTextDef* aTextDef, MIdleFindObserver *aObserver, const TCallBack &aWordParserCallback)
       
  4108 	{
       
  4109 	return(CIdleFinder::NewL(*this,&aFindWords,aTextDef,aObserver,aWordParserCallback));
       
  4110 	}
       
  4111 
       
  4112 
       
  4113 /**
       
  4114 This function is not currently supported.
       
  4115 @param aFormat This parameter should be ignored.
       
  4116 @deprecated
       
  4117 */
       
  4118 EXPORT_C void CContactDatabase::SetDateFormatTextL(const TDesC& /*aFormat*/)
       
  4119 	{//Does nothing, Parameter should be ignored
       
  4120 	}
       
  4121 
       
  4122 
       
  4123 /**
       
  4124 Returns an array of contact item IDs for all the contact items which may contain
       
  4125 the specified telephone number in a telephone, fax or SMS type field.
       
  4126 
       
  4127 The comparison method used is not exact. The number is compared starting from
       
  4128 the right side of the number and the method returns an array of candidate 
       
  4129 matches. Punctuation (eg. spaces) and other alphabetic characters are 
       
  4130 ignored when comparing.
       
  4131 
       
  4132 Additionally, if the contacts model phone parser (CNTPHONE.DLL) is available, 
       
  4133 then any DTMF digits are also excluded from the comparision.
       
  4134 
       
  4135 Notes:
       
  4136 Due to the way numbers are stored in the database, it is recommended that at
       
  4137 least 7 match digits are specified even when matching a number containing fewer
       
  4138 digits. Failure to follow this guideline may (depending on the database contents)
       
  4139 mean that the function will not return the expected Contacts Id set.
       
  4140   
       
  4141 @released
       
  4142 @capability ReadUserData
       
  4143 
       
  4144 @param aNumber Phone number string. If the length of phone number string is greater than 
       
  4145 KCntMaxTextFieldLength then only the first KCntMaxTextFieldLength characters are used 
       
  4146 in the match.
       
  4147 @param aMatchLengthFromRight Number of digits from the right of the phone number to use
       
  4148 Up to 15 digits can be specified, and it is recommended that at least 7 match digits are
       
  4149 specified.
       
  4150 
       
  4151 @return CContactIdArray of candidate matches
       
  4152 */
       
  4153 EXPORT_C CContactIdArray* CContactDatabase::MatchPhoneNumberL(const TDesC& aNumber, const TInt aMatchLengthFromRight)
       
  4154   	{
       
  4155   	return iCntSvr->MatchPhoneNumberL(aNumber, aMatchLengthFromRight);
       
  4156 	}
       
  4157 
       
  4158 
       
  4159 TInt CContactDatabase::ContactPosL(TContactItemId aContactId) //for cntiter
       
  4160 	{
       
  4161 	return SortedItemsL()->Find(aContactId);
       
  4162 	}
       
  4163 
       
  4164 
       
  4165 TInt CContactDatabase::DoGotoL(TContactItemId /*aContactId*/)
       
  4166 	{
       
  4167     return KErrNone; 
       
  4168 	}
       
  4169 
       
  4170 
       
  4171 void CContactDatabase::AddObserverL(MContactDbObserver& aChangeNotifier)
       
  4172 	{
       
  4173 	iCntSvr->AddObserverL(aChangeNotifier);
       
  4174 	}
       
  4175 
       
  4176 
       
  4177 void CContactDatabase::RemoveObserver(const MContactDbObserver& aChangeNotifier)
       
  4178 	{
       
  4179 	iCntSvr->RemoveObserver(aChangeNotifier);
       
  4180 	}
       
  4181 	
       
  4182 
       
  4183 void CContactDatabase::CancelNotifyRequestL()
       
  4184 	{
       
  4185 	}
       
  4186 
       
  4187 
       
  4188 TBool CContactDatabase::IsICCSynchronisedL()
       
  4189 	{
       
  4190 	return EFalse;
       
  4191 	}
       
  4192 
       
  4193 
       
  4194 MLplPersistenceLayerFactory* CContactDatabase::FactoryL()
       
  4195 	{
       
  4196 	if(iProxyFactory == NULL)
       
  4197 		{
       
  4198 		iProxyFactory = CProxyFactory::NewL(*this);
       
  4199 		}
       
  4200 	return iProxyFactory;
       
  4201 	}
       
  4202 	
       
  4203 
       
  4204 void CContactDatabase::FetchGroupAndTemplateListsL()
       
  4205 	{
       
  4206 	delete iCardTemplateIds;
       
  4207 	// Set the iCardTemplateIds to null in order to avoid a corruption
       
  4208 	// should the FetchTemplateListIdsL leave. 
       
  4209 	iCardTemplateIds = NULL;
       
  4210 	iCardTemplateIds = iCntSvr->FetchTemplateListIdsL(); 
       
  4211 	
       
  4212 	delete iGroupIds;
       
  4213 	iGroupIds = NULL; // See previous comment
       
  4214 	iGroupIds = iCntSvr->FetchGroupListIdsL();	
       
  4215 	}
       
  4216 	
       
  4217 void CContactDatabase::LoadSyncPluginL()
       
  4218     {
       
  4219 	if (iContactSynchroniser == NULL)
       
  4220 	    {
       
  4221 	    //Instantiate a CContactSynchroniser object which loads the plugin.
       
  4222 	    //This is required to avoid a deadlock in the contacts server code.
       
  4223 		iContactSynchroniser = CContactSynchroniser::NewL();
       
  4224 	    }
       
  4225     }
       
  4226 
       
  4227 /**
       
  4228 @capability ReadUserData
       
  4229 */
       
  4230 CContactOpenOperation* CContactOpenOperation::NewL(TRequestStatus& aPtrStatus)
       
  4231 	{
       
  4232 	CContactOpenOperation* self = new (ELeave) CContactOpenOperation(aPtrStatus);
       
  4233 
       
  4234 	CleanupStack::PushL(self);
       
  4235 	self->ConstructL();
       
  4236 	CleanupStack::Pop(self);
       
  4237 	return self;
       
  4238 	}
       
  4239 
       
  4240 /**
       
  4241 @capability ReadUserData
       
  4242 */
       
  4243 CContactOpenOperation* CContactOpenOperation::NewL(const TDesC& aFileName, TRequestStatus& aPtrStatus)
       
  4244 	{
       
  4245 	CContactOpenOperation* self = new (ELeave) CContactOpenOperation(aPtrStatus);
       
  4246 	
       
  4247 	CleanupStack::PushL(self);
       
  4248 	self->ConstructL(aFileName);
       
  4249 	CleanupStack::Pop(self);
       
  4250 	return self;
       
  4251 	}
       
  4252 
       
  4253 
       
  4254 CContactOpenOperation::CContactOpenOperation(TRequestStatus& aClientStatus) : 
       
  4255 CActive(EPriorityIdle), iClientStatus(&aClientStatus)
       
  4256 	{}	
       
  4257 	
       
  4258 /**
       
  4259 @capability ReadUserData
       
  4260 @leave  KErrArgument if the given descriptor contains more than the maximum length 
       
  4261         of 190 characters.
       
  4262 */
       
  4263 void CContactOpenOperation::ConstructL(const TDesC& aFileName)
       
  4264 	{
       
  4265 	iContactDatabase = CContactDatabase::NewLC();
       
  4266 	CleanupStack::Pop(iContactDatabase);
       
  4267 	iContactDatabase->iCntSvr->OpenDatabaseAsyncL(*iClientStatus, aFileName);
       
  4268 	}
       
  4269 
       
  4270 
       
  4271 /**
       
  4272 For BC only, CActive is not used here.
       
  4273 */
       
  4274 void CContactOpenOperation::RunL()
       
  4275 	{
       
  4276 	}
       
  4277 
       
  4278 
       
  4279 /**
       
  4280 For BC only, CActive is not used here.
       
  4281 */
       
  4282 TInt CContactOpenOperation::RunError(TInt)
       
  4283 	{
       
  4284 	return KErrNone;
       
  4285 	}
       
  4286 
       
  4287 
       
  4288 /**
       
  4289 For BC only, CActive is not used here.
       
  4290 */
       
  4291 void CContactOpenOperation::DoCancel()
       
  4292 	{
       
  4293 	}
       
  4294 
       
  4295 
       
  4296 /**
       
  4297 Takes ownership of the contact database.
       
  4298 
       
  4299 Ownership of the contact database is passed to the client.
       
  4300 Subsequent calls return NULL.
       
  4301 
       
  4302 @return A pointer to the CContactDatabase on the first call after 
       
  4303 		the asynchronous open has succeeded. Otherwise NULL.
       
  4304 
       
  4305 @see CContactDatabase::Open()
       
  4306 */
       
  4307 EXPORT_C CContactDatabase* CContactOpenOperation::TakeDatabase()
       
  4308 	{
       
  4309 	// async open must have succeeded in server AND RunL must have completed
       
  4310 	CContactDatabase* contactDatabase = iContactDatabase;
       
  4311 	// prevent deletion of the database.
       
  4312 	iContactDatabase = NULL;
       
  4313 	return contactDatabase;
       
  4314 	}
       
  4315 
       
  4316 
       
  4317 /**
       
  4318 Deletes the active object.
       
  4319 
       
  4320 If the asynchronous open is still in progress it is cancelled.
       
  4321 
       
  4322 If the TakeDatabase() API has not been called and the database 
       
  4323 has been opened it is closed.
       
  4324 
       
  4325 @capability None
       
  4326 */
       
  4327 EXPORT_C CContactOpenOperation::~CContactOpenOperation()
       
  4328 	{
       
  4329 	if (iContactDatabase)
       
  4330 		{
       
  4331 		iContactDatabase->iCntSvr->CancelAsyncOpen();
       
  4332 		delete iContactDatabase;
       
  4333 		iContactDatabase = NULL;
       
  4334 		}
       
  4335 	}
       
  4336 
       
  4337 
       
  4338 CDataBaseChangeObserver* CDataBaseChangeObserver::NewL(MContactDbPrivObserver& aPrivateObserver)
       
  4339 	{
       
  4340 	CDataBaseChangeObserver* temp = new (ELeave) CDataBaseChangeObserver(aPrivateObserver);
       
  4341 	return temp;
       
  4342 	}
       
  4343 
       
  4344 
       
  4345 CDataBaseChangeObserver::CDataBaseChangeObserver(MContactDbPrivObserver& aPrivateObserver) : iPrivateObserver(aPrivateObserver)
       
  4346 	{}	
       
  4347 
       
  4348 
       
  4349 void CDataBaseChangeObserver::HandleDatabaseEventL(TContactDbObserverEvent aEvent)
       
  4350 	{
       
  4351 	iPrivateObserver.HandleDatabaseEventL(aEvent);
       
  4352 	}
       
  4353 
       
  4354 
       
  4355 CDataBaseChangeObserver::~CDataBaseChangeObserver()
       
  4356 	{}	
       
  4357 
       
  4358 
       
  4359 void CContactDatabase::HandleDiskSpaceEvent(TInt)
       
  4360 /** Default behaviour for handling a low disk event - This function is unimplemented. */
       
  4361 	{}//Do nothing.
       
  4362 	
       
  4363 
       
  4364 void CContactDatabase::RespondToEventL(const TContactDbObserverEventType aEventType, const TContactItemId aContactId)
       
  4365 	{
       
  4366 	switch(aEventType)
       
  4367 		{
       
  4368 		case EContactDbObserverEventContactChanged:
       
  4369 		case EContactDbObserverEventGroupChanged:
       
  4370 			HandleDbObserverEventGroupOrContactChangedL(aContactId);
       
  4371 			break;
       
  4372 		
       
  4373 		case EContactDbObserverEventContactAdded:
       
  4374 		case EContactDbObserverEventGroupAdded:
       
  4375 			HandleDbObserverEventGroupOrContactAddedL(aEventType, aContactId);
       
  4376 			break;
       
  4377 
       
  4378 		case EContactDbObserverEventSpeedDialsChanged:
       
  4379 			break;
       
  4380 			
       
  4381 		case EContactDbObserverEventOwnCardDeleted:
       
  4382 		case EContactDbObserverEventContactDeleted:
       
  4383             RemoveFromSortArray(aContactId);
       
  4384 			break;
       
  4385 		
       
  4386 		case EContactDbObserverEventGroupDeleted:
       
  4387 			HandleDbObserverEventGroupDeletedL(aContactId);
       
  4388 			break;
       
  4389 		
       
  4390 		case EContactDbObserverEventTemplateAdded:
       
  4391 			{
       
  4392 			if (!iCardTemplateIds)
       
  4393 				{
       
  4394 				//if database was opened async, iCardTemplate is null.
       
  4395 				//keep same behaviour like CContactDatabase::AddToTemplateListL
       
  4396 				iCardTemplateIds = CContactIdArray::NewL();
       
  4397 				}
       
  4398 			iCardTemplateIds->AddL(aContactId);
       
  4399 			}
       
  4400 			break;
       
  4401 
       
  4402 		case EContactDbObserverEventTemplateChanged:
       
  4403 			{
       
  4404 			iTemplateCache->RemoveTemplate(aContactId);
       
  4405 			}
       
  4406 			break;
       
  4407 
       
  4408 		case EContactDbObserverEventTemplateDeleted:
       
  4409 			{
       
  4410 			iTemplateCache->RemoveTemplate(aContactId);
       
  4411 			RemoveFromTemplateList(aContactId);
       
  4412 			}
       
  4413 			break;
       
  4414 		
       
  4415 		case EContactDbObserverEventOwnCardChanged:
       
  4416 			break;
       
  4417 
       
  4418 		case EContactDbObserverEventBackupBeginning:
       
  4419 		case EContactDbObserverEventRestoreBeginning:
       
  4420 		case EContactDbObserverEventBackupRestoreCompleted:
       
  4421 		case EContactDbObserverEventRestoreBadDatabase:
       
  4422 			// NB this handler decides on the event to send to observers
       
  4423 		//	HandleBackupOrRestoreEvent(aEvent);
       
  4424 			return;
       
  4425 
       
  4426 		case EContactDbObserverEventTablesOpened:
       
  4427 			iTablesOpen = ETrue;
       
  4428 			break;
       
  4429 			
       
  4430 		case EContactDbObserverEventTablesClosed:
       
  4431 			iTablesOpen = EFalse;
       
  4432 			break;
       
  4433 
       
  4434 		case EContactDbObserverEventUnknownChanges:
       
  4435 			{
       
  4436 			FetchGroupAndTemplateListsL();
       
  4437 			// Reset the template cache
       
  4438 			delete iTemplateCache;
       
  4439             iTemplateCache = NULL;
       
  4440 			iTemplateCache = CCntTemplateCache::NewL(*iCntSvr); 
       
  4441 			
       
  4442 			TInt err=KErrGeneral;
       
  4443 			if (iTablesOpen)
       
  4444 				{
       
  4445 				CArrayFix<TSortPref>* sortOrder = const_cast<CArrayFix<TSortPref>*>(iCntSvr->GetSortPreferenceL());
       
  4446 				CleanupStack::PushL(sortOrder);
       
  4447 				TRAP(err,ReSortL(sortOrder));
       
  4448 				CleanupStack::PopAndDestroy(sortOrder);
       
  4449 				}
       
  4450 			CheckSortError(err);
       
  4451 			}
       
  4452 			break;
       
  4453 		default:;
       
  4454 		}	
       
  4455 	}
       
  4456 
       
  4457 
       
  4458 /**  
       
  4459 Handle the Database event
       
  4460 @internalTechnology
       
  4461 @param aEvent Database change event
       
  4462 */
       
  4463 EXPORT_C void CContactDatabase::HandleDatabaseEventL(const TContactDbObserverEvent& aEvent)
       
  4464 	{
       
  4465 	//Just respond to events created by other sessions
       
  4466 	if (ConnectionId()!=aEvent.iConnectionId)
       
  4467 		{
       
  4468 		RespondToEventL(aEvent.iType, aEvent.iContactId);
       
  4469 		}
       
  4470 	}
       
  4471 	
       
  4472 
       
  4473 void CContactDatabase::RemoveFromSortArray(TContactItemId aContactId)
       
  4474 	{
       
  4475 	if (iSortedItems)
       
  4476 		{
       
  4477 		const TInt pos=iSortedItems->Find(aContactId);
       
  4478 		if (pos!=KErrNotFound)
       
  4479 			iSortedItems->Remove(pos);
       
  4480 		}
       
  4481 	}
       
  4482 	
       
  4483 
       
  4484 void CContactDatabase::RemoveFromGroupIds(const TContactItemId aContactId)
       
  4485 	{
       
  4486      if (iGroupIds) 
       
  4487          {
       
  4488           TInt pos = iGroupIds->Find(aContactId); 
       
  4489           if ( pos != KErrNotFound ) 
       
  4490               { 
       
  4491               iGroupIds->Remove( pos ); 
       
  4492               }
       
  4493          } 
       
  4494 	}
       
  4495 
       
  4496 
       
  4497 void CContactDatabase::HandleDbObserverEventGroupDeletedL(const TContactItemId aContactId)
       
  4498     {
       
  4499 	 RemoveFromGroupIds(aContactId);
       
  4500      RespondToEventL(EContactDbObserverEventContactDeleted, aContactId);
       
  4501     }
       
  4502 
       
  4503 
       
  4504 TBool CContactDatabase::AddContactToSortListL(TContactItemId aReqId, TContactItemId& aActualId,CBase* aItems, TUid& aFieldType, TBool aHasSortOrder)
       
  4505 	{
       
  4506 	TUid contactType;
       
  4507 	TBool deleted;
       
  4508 	
       
  4509 	if(!FactoryL()->GetCollectorL().SeekContactL(aReqId,aActualId,contactType,deleted))
       
  4510 		{
       
  4511 		return EFalse;
       
  4512 		}
       
  4513 	
       
  4514 	if(deleted || contactType != KUidContactCard)
       
  4515 		{
       
  4516 		return ETrue;
       
  4517 		}
       
  4518 	if (!aHasSortOrder)
       
  4519 		{
       
  4520 		((CContactIdArray*)aItems)->AddL(aActualId);
       
  4521 		}
       
  4522 	else
       
  4523 		{
       
  4524 		CContactDatabase::TTextFieldMinimal textFieldMin;
       
  4525 		if	(aFieldType == KUidContactFieldDefinedText)
       
  4526 			{
       
  4527 			ReadContactTextDefL(aActualId,textFieldMin,iTextDef);
       
  4528 			}
       
  4529 		else
       
  4530 			{
       
  4531 			FactoryL()->GetViewIteratorManagerL().TextFieldL(aActualId,aFieldType,textFieldMin);
       
  4532 			}
       
  4533 		((CSortArray*) aItems)->AppendL(textFieldMin,aActualId);
       
  4534 		}
       
  4535 	return ETrue;
       
  4536 	}
       
  4537 
       
  4538 
       
  4539 TInt CContactDatabase::NextExistingL(TInt aIndex)
       
  4540 	{
       
  4541 	TInt ret=KErrNotFound;
       
  4542 	const CContactIdArray* sortedItems=SortedItemsL();
       
  4543 	const TInt count=sortedItems->Count();
       
  4544 	TContactItemId contactId=KNullContactId;
       
  4545 	while ((ret==KErrNotFound) && (aIndex<count-1))
       
  4546 		{
       
  4547 		contactId=(*sortedItems)[++aIndex];
       
  4548 		ret=DoGotoL(contactId);
       
  4549 		}
       
  4550 	if (ret==KErrNotFound)
       
  4551 		return ret;
       
  4552 	return aIndex;
       
  4553 	}
       
  4554 
       
  4555 
       
  4556 TInt CContactDatabase::PreviousExistingL(TInt aIndex)
       
  4557 	{
       
  4558 	TInt ret=KErrNotFound;
       
  4559 	TContactItemId contactId=KNullContactId;
       
  4560 	const CContactIdArray* sortedItems=SortedItemsL();
       
  4561 	while (ret==KErrNotFound && aIndex>=1)
       
  4562 		{
       
  4563 		contactId=(*sortedItems)[--aIndex];
       
  4564 		ret=DoGotoL(contactId);
       
  4565 		}
       
  4566 	if (ret==KErrNotFound)
       
  4567 		return ret;
       
  4568 	return aIndex+1;
       
  4569 	}
       
  4570 
       
  4571 
       
  4572 TInt CContactDatabase::NewSortIndexL(const CContactItem& aContact, TInt aMin, TInt aMax)
       
  4573 	{
       
  4574 	__ASSERT_DEBUG(&aContact!=NULL,Panic(ECntPanicNullPointer));
       
  4575 	FOREVER
       
  4576 		{
       
  4577 		if (aMin==aMax)
       
  4578 			return(aMin);
       
  4579 		TInt index=(aMax-aMin)/2+aMin;
       
  4580 		User::LeaveIfError(DoGotoL((*iSortedItems)[index]));
       
  4581 		TInt compare=CompareSortFieldsL(aContact);
       
  4582 		if (compare<=0)
       
  4583 			{
       
  4584 			if (aMin==index)
       
  4585 				aMin++;
       
  4586 			else
       
  4587 				aMin=index;
       
  4588 			}
       
  4589 		else if (compare>0)
       
  4590 			aMax=index;
       
  4591 		}
       
  4592 	}
       
  4593 
       
  4594 
       
  4595 TBool CContactDatabase::CheckSortError(TInt aError)
       
  4596 	{
       
  4597 	if (aError!=KErrNone)
       
  4598 		{
       
  4599 		delete iSortedItems;
       
  4600 		iSortedItems=NULL;
       
  4601 		return(ETrue);
       
  4602 		}
       
  4603 	return(EFalse);
       
  4604 	}
       
  4605 
       
  4606 
       
  4607 void CContactDatabase::MoveInSortArray(const CContactItem& aContact)
       
  4608 	{
       
  4609 	TRAPD(err,MoveInSortArrayL(aContact));
       
  4610 	CheckSortError(err);
       
  4611 	}
       
  4612 
       
  4613 
       
  4614 void CContactDatabase::InsertInSortArray(const CContactItem& aContact)
       
  4615 	{
       
  4616 	TRAPD(err,InsertInSortArrayL(aContact));
       
  4617 	CheckSortError(err);
       
  4618 	}
       
  4619 
       
  4620 
       
  4621 void CContactDatabase::InsertInSortArrayL(const CContactItem& aContact)
       
  4622 	{
       
  4623 	__ASSERT_DEBUG(&aContact!=NULL,Panic(ECntPanicNullPointer));
       
  4624 	if (CheckType(aContact.Type()) && iSortedItems)
       
  4625 		{
       
  4626 		const TContactItemId id=aContact.Id();
       
  4627 		if (iSortedItems->Find(id)==KErrNotFound)
       
  4628 			{
       
  4629 			const TInt index=NewSortIndexL(aContact,0,iSortedItems->Count());
       
  4630 			if (index<iSortedItems->Count())
       
  4631 				iSortedItems->InsertL(index,id);
       
  4632 			else
       
  4633 				iSortedItems->AddL(id);
       
  4634 			}
       
  4635 		}
       
  4636 	}
       
  4637 
       
  4638 
       
  4639 void CContactDatabase::MoveInSortArrayL(const CContactItem& aContact)
       
  4640 	{
       
  4641 	__ASSERT_DEBUG(&aContact!=NULL,Panic(ECntPanicNullPointer));
       
  4642 	if (iSortedItems && CheckType(aContact.Type()))
       
  4643 		{
       
  4644 		const TInt pos=iSortedItems->Find(aContact.Id());
       
  4645 		TInt compare=0;
       
  4646 		if (pos!=0 && PreviousExistingL(pos)!=KErrNotFound)
       
  4647 			compare=CompareSortFieldsL(aContact);
       
  4648 		TInt index;
       
  4649 		TInt start=0;
       
  4650 		TInt end=pos;
       
  4651 		if (compare<=0)
       
  4652 			{
       
  4653 			if (NextExistingL(pos)!=KErrNotFound)
       
  4654 				compare=CompareSortFieldsL(aContact);
       
  4655 			if (compare>=0)
       
  4656 				return;
       
  4657 			start=pos;
       
  4658 			end=iSortedItems->Count();
       
  4659 			}
       
  4660 		index=NewSortIndexL(aContact,start,end);
       
  4661 		iSortedItems->MoveL(pos,index>pos?index-1:index);
       
  4662 		}
       
  4663 	}
       
  4664 
       
  4665 
       
  4666 TInt CContactDatabase::CompareSortFieldsL(const CContactItem& aContact)
       
  4667 	{
       
  4668 	TInt compare=0;
       
  4669 	TInt index=0;
       
  4670 	CArrayFix<TSortPref>* sortOrder = iCntSvr->GetSortPreferenceL();
       
  4671 	CleanupStack::PushL(sortOrder);
       
  4672 	const TInt sortDefs=sortOrder->Count();
       
  4673 	while (compare==0 && index<sortDefs)
       
  4674 		{
       
  4675 		TUid fieldType=(*sortOrder)[index++].iFieldType;
       
  4676 		TTextFieldMinimal textFieldMin;
       
  4677 		TTextFieldMinimal textFieldMin2;
       
  4678 		if (fieldType==KUidContactFieldDefinedText)
       
  4679 			{
       
  4680 			// Reads from database.
       
  4681 			ReadContactTextDefL(aContact.Id(),textFieldMin);
       
  4682 			// Does not read from database.
       
  4683 			ReadContactTextDefL(aContact,textFieldMin2);
       
  4684 			}
       
  4685 		else
       
  4686 			{
       
  4687 			MLplViewIteratorManager& manager = FactoryL()->GetViewIteratorManagerL();
       
  4688 			manager.TextFieldL(aContact.Id(),fieldType,textFieldMin);
       
  4689 			aContact.CardFields().NonZeroFieldText(fieldType,textFieldMin2);
       
  4690 			}
       
  4691 		compare=textFieldMin.CompareC(textFieldMin2,3,&iCollateMethod);		
       
  4692 		}
       
  4693 	if (index>0)
       
  4694 		--index;
       
  4695 	
       
  4696 	TInt retVal = ((sortDefs==0) || ((*sortOrder)[index].iOrder==CContactDatabase::TSortPref::EAsc)? compare : -compare);
       
  4697 	CleanupStack::PopAndDestroy(); //sortOrder
       
  4698 	return retVal;
       
  4699 	}
       
  4700 
       
  4701 
       
  4702 /**
       
  4703 Looks at the sort order and identifes what tables are required.
       
  4704 */
       
  4705 void CContactDatabase::ConstructTableUsageFlagsFromSortOrderL(TInt& aFlags)
       
  4706 	{
       
  4707 	CContactTextDef* textDef=CContactTextDef::NewLC();
       
  4708 	CArrayFix<TSortPref>* sortOrder = iCntSvr->GetSortPreferenceL();
       
  4709 	CleanupStack::PushL(sortOrder);
       
  4710 	TInt sortOrderCount=sortOrder->Count();
       
  4711 	TInt columns=0;
       
  4712 	aFlags=0;
       
  4713 	for (TInt sortIndex=0;sortIndex<sortOrderCount;sortIndex++)
       
  4714 		textDef->AppendL(TContactTextDefItem((*sortOrder)[sortIndex].iFieldType));
       
  4715 	MLplCollection& collection = FactoryL()->GetCollectorL();
       
  4716 	collection.ConstructBitwiseFlagsFromTextDef(aFlags,columns,textDef);
       
  4717 	CleanupStack::PopAndDestroy(sortOrder);
       
  4718 	CleanupStack::PopAndDestroy(textDef);
       
  4719 	}
       
  4720 
       
  4721 
       
  4722 /**
       
  4723 Update sorted items list using contact card/group change event.
       
  4724 
       
  4725 @internalTechnology
       
  4726 @since 7.0
       
  4727 
       
  4728 @param aEvent Database change event
       
  4729 */ 
       
  4730 void CContactDatabase::HandleDbObserverEventGroupOrContactChangedL(const TContactItemId aContactId)
       
  4731 	{
       
  4732 	if (iSortedItems)
       
  4733 		{
       
  4734 	 	CArrayFix<TSortPref>* sortOrder = iCntSvr->GetSortPreferenceL();
       
  4735 		CleanupStack::PushL(sortOrder);
       
  4736 		if(sortOrder!=NULL && sortOrder->Count() > 0)
       
  4737 			{
       
  4738 			if (iTablesOpen)
       
  4739 				{
       
  4740 				CContactItem* contact = NULL;
       
  4741 				TRAPD(error, contact = ReadContactL(aContactId));
       
  4742 				if (CheckSortError(error)==EFalse && contact != NULL)
       
  4743 					{
       
  4744 					MoveInSortArray(*contact);
       
  4745 					delete contact;
       
  4746 					}
       
  4747 				}
       
  4748 			else
       
  4749 				{
       
  4750 				CheckSortError(KErrGeneral);
       
  4751 				}
       
  4752 			}
       
  4753 		CleanupStack::PopAndDestroy(sortOrder);
       
  4754 		}
       
  4755 	}
       
  4756 
       
  4757 
       
  4758 /**
       
  4759 Add new contact card/group to sorted items list using add event.
       
  4760 
       
  4761 @internalTechnology
       
  4762 @since 7.0
       
  4763 
       
  4764 @param aEvent Database change event
       
  4765 */ 
       
  4766 void CContactDatabase::HandleDbObserverEventGroupOrContactAddedL(const TContactDbObserverEventType aEventType, const TContactItemId aContactId)
       
  4767 	{
       
  4768 	if (aEventType == EContactDbObserverEventGroupAdded)
       
  4769 		{
       
  4770 		if(iGroupIds == NULL)
       
  4771 			{
       
  4772 			//if database was opened async, iGroups is null, so we have to fetch the group ids first
       
  4773 			iGroupIds = iCntSvr->FetchGroupListIdsL();	
       
  4774 			if(iGroupIds->Find(aContactId) == KErrNotFound)
       
  4775 				{
       
  4776 				iGroupIds->AddL(aContactId);	
       
  4777 				}
       
  4778 			}
       
  4779 		else 
       
  4780 			{
       
  4781 			iGroupIds->AddL(aContactId);		
       
  4782 			}	
       
  4783 		}
       
  4784 
       
  4785 	if (iSortedItems)
       
  4786 		{
       
  4787 		if (iTablesOpen)
       
  4788 			{
       
  4789 			CContactItem* contact = NULL;
       
  4790 			TInt error = KErrGeneral;
       
  4791 			CArrayFix<TSortPref>* sortOrder = iCntSvr->GetSortPreferenceL();
       
  4792 			CleanupStack::PushL(sortOrder);
       
  4793 			if(sortOrder!= NULL && sortOrder->Count() > 0)
       
  4794 				//There is a sort order, so the contact must be read
       
  4795 				//to find out where to insert it into the sorted list
       
  4796 				{
       
  4797 				TRAP(error, contact = ReadContactL(aContactId));
       
  4798 				CheckSortError(error);
       
  4799 				if (error == KErrNone && contact != NULL)
       
  4800 					{
       
  4801 					InsertInSortArray(*contact);
       
  4802 					delete contact;
       
  4803 					}
       
  4804 				}
       
  4805 			else
       
  4806 				{
       
  4807 				// No sort order is defined only the contact's type is needed.
       
  4808 				TContactItemId actualId;
       
  4809 				TUid contactType = KNullUid;
       
  4810 				TBool deleted = EFalse;
       
  4811 	
       
  4812         		MLplCollection& collection = FactoryL()->GetCollectorL();
       
  4813 				TRAP(error, collection.SeekContactL(aContactId,actualId,contactType,deleted));
       
  4814 				
       
  4815 				if (CheckSortError(error)==EFalse)
       
  4816 					{
       
  4817 					if (CheckType(contactType))
       
  4818 						{
       
  4819 						iSortedItems->AddL(aContactId);
       
  4820 						}
       
  4821 					}
       
  4822 				}
       
  4823 			CleanupStack::PopAndDestroy(sortOrder);
       
  4824 			}
       
  4825 		else // iTablesOpen == EFalse
       
  4826 			{
       
  4827 			CheckSortError(KErrGeneral);
       
  4828 			}
       
  4829 		}
       
  4830 	}
       
  4831 
       
  4832 
       
  4833 /**
       
  4834 @internalTechnology
       
  4835 */
       
  4836 void CContactDatabase::StartAsyncActivityL()
       
  4837 	{
       
  4838 	// starting: Recover, Async Find, Compress
       
  4839 	++iAsyncActivityCount;
       
  4840 
       
  4841 	// At least one async activity in progress, tell server.
       
  4842 	if (iAsyncActivityCount == 1)
       
  4843 		{
       
  4844 		iCntSvr->SetAsyncActivityL(ETrue);
       
  4845 		}
       
  4846 	}
       
  4847  
       
  4848  
       
  4849 /**
       
  4850 @internalTechnology
       
  4851 */
       
  4852 void CContactDatabase::EndAsyncActivityL()
       
  4853 	{
       
  4854 	// ending: Recover, Async Find, Compress
       
  4855 	--iAsyncActivityCount;
       
  4856 	
       
  4857 	// All async activities finished, tell server this so that it can process
       
  4858 	// any pending database close.
       
  4859 	if (iAsyncActivityCount == 0)
       
  4860 		{
       
  4861 		iCntSvr->SetAsyncActivityL(EFalse);
       
  4862 		}
       
  4863 	}
       
  4864 
       
  4865 
       
  4866 /**
       
  4867 Determine if the database is ready.  Ready in this context means that the
       
  4868 database is open and readable/writable (i.e. the state machine is in
       
  4869 CStateWritable).
       
  4870 
       
  4871 @internalTechnology
       
  4872 @capability None
       
  4873 
       
  4874 @return ETrue if the database is ready, EFalse if the database is not ready.
       
  4875 */
       
  4876 TBool CContactDatabase::DatabaseReadyL() const
       
  4877 	{
       
  4878 	return iCntSvr->DatabaseReadyL();
       
  4879 	}
       
  4880 
       
  4881 
       
  4882 CCntIdleSorter::CCntIdleSorter(CContactDatabase &aContactDatabase)
       
  4883 :	iDb(aContactDatabase), iState(EReadContacts)
       
  4884 	{
       
  4885 	}
       
  4886 
       
  4887 
       
  4888 CCntIdleSorter::~CCntIdleSorter()
       
  4889 	{
       
  4890 	if (iSortStarted)
       
  4891 		{
       
  4892 		// async Sort blocks Backup or Restore closing the database handles
       
  4893 		TRAP_IGNORE(iDb.EndAsyncActivityL());
       
  4894 		iSortStarted = EFalse;
       
  4895 		}
       
  4896 
       
  4897 	if	(iIdle)
       
  4898 		iIdle->Cancel();
       
  4899 	delete iIdle;
       
  4900 	delete iSortOrder;
       
  4901 	delete iSortedList;
       
  4902 	delete iFinalItems;
       
  4903 	}
       
  4904 
       
  4905 
       
  4906 void CCntIdleSorter::ConstructL()
       
  4907 	{
       
  4908 	iIdle		= CIdle::NewL(CActive::EPriorityIdle);
       
  4909 	iSortedList	= new(ELeave) CSortArray();
       
  4910 	iFinalItems	= CContactIdArray::NewL();
       
  4911 
       
  4912 	// Must call this to ensure the system template is loaded
       
  4913 //	Not required in client for cntmodel
       
  4914 //	iDb.SystemTemplateL();
       
  4915 	}
       
  4916 
       
  4917 
       
  4918 CCntIdleSorter* CCntIdleSorter::NewL(CContactDatabase &aContactDatabase)
       
  4919 	{
       
  4920 	CCntIdleSorter* self= new(ELeave) CCntIdleSorter(aContactDatabase);
       
  4921 	CleanupStack::PushL(self);
       
  4922 	self->ConstructL();
       
  4923 	CleanupStack::Pop(self);
       
  4924 	return self;
       
  4925 	}
       
  4926 
       
  4927 
       
  4928 /**
       
  4929 Prepare and begin the sort.
       
  4930 */
       
  4931 void CCntIdleSorter::StartSortingL(CArrayFix<CContactDatabase::TSortPref>* aSortOrder, TRequestStatus& aStatus)
       
  4932 	{
       
  4933 	// Take ownership of sort order
       
  4934 	iSortOrder = aSortOrder;
       
  4935 
       
  4936 	// Save the TRequestStatus so we can signal the client
       
  4937 	iStatus = &aStatus;
       
  4938 
       
  4939 	// Set up how many records we will have to read
       
  4940 	TotalCount() = iDb.CountL();
       
  4941 
       
  4942 	// async Sort uses database tables, so Backup or Restore handling must wait for the async activity to finish
       
  4943 	iDb.StartAsyncActivityL();
       
  4944 	iSortStarted = ETrue;
       
  4945 
       
  4946 	// Indicate that the sort is in progress. This will result in the client's
       
  4947 	// RunL (if it's using an AO framework) to be called when the sort is completed
       
  4948 	// or cancelled.
       
  4949 	*iStatus = KRequestPending;
       
  4950 	
       
  4951 	// Start the idle sorter.
       
  4952 	iIdle->Start(TCallBack(CCntIdleSorter::SortCallBack, this));
       
  4953 	}
       
  4954 
       
  4955 
       
  4956 /**
       
  4957 Sort with observer.
       
  4958 */
       
  4959 void CCntIdleSorter::StartSortingL(CArrayFix<CContactDatabase::TSortPref>* aSortOrder, TRequestStatus& aStatus, MContactSortObserver& aObserver)
       
  4960 	{
       
  4961 	iObserver = &aObserver;
       
  4962 	HasObserver() = ETrue;
       
  4963 	StartSortingL(aSortOrder, aStatus);
       
  4964 	}
       
  4965 
       
  4966 
       
  4967 /**
       
  4968 Initialise values to defaults.
       
  4969 */
       
  4970 void CCntIdleSorter::ResetL()
       
  4971 	{
       
  4972 //	iDb.iItemTable->iTable.BeginningL();
       
  4973 	iState = EReadContacts;
       
  4974 	iIdle->Cancel();
       
  4975 
       
  4976 	delete iSortOrder;
       
  4977 	iSortOrder = NULL;
       
  4978 
       
  4979 	delete iSortedList;
       
  4980 	iSortedList = NULL;
       
  4981 	iSortedList	= new(ELeave) CSortArray();
       
  4982 
       
  4983 	if (iSortStarted)
       
  4984 		{
       
  4985 		// async Sort blocks Backup or Restore closing the database handles
       
  4986 		iDb.EndAsyncActivityL();
       
  4987 		iSortStarted = EFalse;
       
  4988 		}
       
  4989 
       
  4990 	delete iFinalItems;
       
  4991 	iFinalItems = NULL;
       
  4992 	iFinalItems	= CContactIdArray::NewL();
       
  4993 	
       
  4994 	iObserver = NULL;
       
  4995 	iStatus = NULL;
       
  4996 	HasObserver() = EFalse;
       
  4997 	TotalCount() = 0;
       
  4998 	ReadSoFar() = 0;
       
  4999 	iCurrentId = 0;
       
  5000 	}
       
  5001 
       
  5002 
       
  5003 /**
       
  5004 Callback function for idle object.
       
  5005 */
       
  5006 TInt CCntIdleSorter::SortCallBack(TAny* aThis)
       
  5007 	{
       
  5008 	return static_cast<CCntIdleSorter*>(aThis)->PeformSortStep();
       
  5009 	}
       
  5010 
       
  5011 
       
  5012 /**
       
  5013 Read a single contact.
       
  5014 */
       
  5015 TBool CCntIdleSorter::ReadContactsL(TInt aNumber)
       
  5016 	{
       
  5017 	// Do we have to sort using specified order criteria?
       
  5018 	TBool moreToDo		= ETrue;
       
  5019 	TBool haveSortOrder	= (iSortOrder->Count() > 0);
       
  5020 	TUid fieldType		= (haveSortOrder) ? iSortOrder->At(0).iFieldType : KNullUid;
       
  5021 	CBase* array =  (haveSortOrder) ? (CBase*) iSortedList : (CBase*)iFinalItems;
       
  5022 
       
  5023 	// Only retrieve aNumber contacts from the contact store before yeilding
       
  5024 	for (TInt i = 0; i < aNumber; i++)
       
  5025 		{
       
  5026 		++ReadSoFar();
       
  5027 		TContactItemId actualId(0);
       
  5028 		moreToDo = iDb.AddContactToSortListL(iCurrentId,actualId,array, fieldType, haveSortOrder) && moreToDo;
       
  5029 		iCurrentId = actualId+1;
       
  5030 		if(!moreToDo)
       
  5031 			break;
       
  5032 		}
       
  5033 
       
  5034 	// Report progress to observer (if there is one)
       
  5035 	ReportProgressL();
       
  5036 
       
  5037 	return moreToDo;
       
  5038 	}
       
  5039 
       
  5040 
       
  5041 /**
       
  5042 This function is called once the reading from the database is complete.
       
  5043 It replaces the contact database's sorted list (takes ownership of iFinalItems).
       
  5044 */
       
  5045 void CCntIdleSorter::SortListAndSaveL()
       
  5046 	{
       
  5047 	iSortedList->SortL(iSortOrder->At(0).iOrder);
       
  5048 	iDb.SortDuplicatesL(*iSortOrder, *iSortedList, 1);
       
  5049 	const TInt count = iSortedList->Count();
       
  5050 	for (TInt i=0; i<count; i++)
       
  5051 		iFinalItems->AddL(iSortedList->Id(i));
       
  5052 
       
  5053 	// Safe to do this now...
       
  5054 	delete iDb.iSortedItems;
       
  5055 	iDb.iSortedItems = iFinalItems;
       
  5056 	iFinalItems = NULL; // just so we don't delete it
       
  5057 
       
  5058 	if (iSortStarted)
       
  5059 		{
       
  5060 		// async Sort blocks Backup or Restore closing the database handles
       
  5061 		iDb.EndAsyncActivityL();
       
  5062 		iSortStarted = EFalse;
       
  5063 		}
       
  5064 
       
  5065 	// Set the sort order in the server.
       
  5066 	iDb.iCntSvr->SetSortPreferenceL(*iSortOrder);
       
  5067 	}
       
  5068 
       
  5069 
       
  5070 /**
       
  5071 Called as a result of a cancellation request by the CContactDatabase class.
       
  5072 */
       
  5073 void CCntIdleSorter::Cancel() 
       
  5074 	{
       
  5075 	iIdle->Cancel();
       
  5076 	CompleteRequest(KErrCancel);
       
  5077 	TRAP_IGNORE(ResetL());
       
  5078 	}
       
  5079 
       
  5080 
       
  5081 /**
       
  5082 Complete the client's request status with the specified error value (KErrNone by default).
       
  5083 */
       
  5084 void CCntIdleSorter::CompleteRequest(TInt aError)
       
  5085 	{
       
  5086 	if	(iStatus)
       
  5087 		User::RequestComplete(iStatus, aError);
       
  5088 	}
       
  5089 
       
  5090 
       
  5091 /**
       
  5092 if we have an observer, then we report progress as the sort is performed (in reality
       
  5093 we actually only report progress during the read stage, not the sort itself).
       
  5094 */
       
  5095 void CCntIdleSorter::ReportProgressL()
       
  5096 	{
       
  5097 	if	(iObserver && HasObserver())
       
  5098 		iObserver->HandleSortEventL(Max(TotalCount(), ReadSoFar()), TotalCount());
       
  5099 	}
       
  5100 
       
  5101 
       
  5102 /**
       
  5103 Idle object callback which performs appropriate action based on internal state machine.
       
  5104 */
       
  5105 TInt CCntIdleSorter::PeformSortStep()
       
  5106 	{
       
  5107 	TInt err = KErrNone;
       
  5108 	TBool moreToDo = EFalse;
       
  5109 
       
  5110 	// Based on the current state machine value we perform either a read or a sort
       
  5111 	switch (iState)
       
  5112 		{
       
  5113 	case EReadContacts:
       
  5114 		// Read all contacts & when complete move to next state
       
  5115 		TRAP(err, moreToDo = ReadContactsL())
       
  5116 		if	(err)
       
  5117 			{
       
  5118 			// There was an error sorting
       
  5119 			CompleteRequest(err);
       
  5120 			moreToDo = EFalse;
       
  5121 			}
       
  5122 		else if	(!moreToDo) 
       
  5123 			{
       
  5124 			// Indicate that the reading is complete
       
  5125 			iState = ESortContacts;
       
  5126 
       
  5127 			// Set this back to ETrue because we now have to do the sort...
       
  5128 			moreToDo = ETrue;
       
  5129 			}
       
  5130 
       
  5131 		break;
       
  5132 
       
  5133 	case ESortContacts:
       
  5134 		// Contact reading finished, now perform the sort
       
  5135 		TRAP(err, SortListAndSaveL());
       
  5136 		CompleteRequest(err);
       
  5137 		moreToDo = EFalse;
       
  5138 		break;
       
  5139 		}
       
  5140 
       
  5141 	// Return a boolean indicating whether we want the idle to call this dispatch
       
  5142 	// function again in future.
       
  5143 	return moreToDo;
       
  5144 	}
       
  5145 
       
  5146 
       
  5147 /**
       
  5148 Allocates and constructs a new contact database change notifier.
       
  5149 
       
  5150 @param aDatabase The contact database to observe.
       
  5151 @param aObserver The observer for aDatabase. Its HandleDatabaseEventL() function 
       
  5152 is called whenever a change occurs to the database.
       
  5153 
       
  5154 @return Pointer to the newly created contact database change notifier.
       
  5155 */
       
  5156 EXPORT_C CContactChangeNotifier* CContactChangeNotifier::NewL(CContactDatabase& aDatabase, MContactDbObserver* aObserver)
       
  5157 	{
       
  5158 	CContactChangeNotifier *self=new(ELeave) CContactChangeNotifier(aDatabase, aObserver);
       
  5159 	CleanupStack::PushL(self);
       
  5160 	self->ConstructL();
       
  5161 	CleanupStack::Pop(self);
       
  5162 	return(self);
       
  5163 	}
       
  5164 	
       
  5165 
       
  5166 CContactChangeNotifier::CContactChangeNotifier(CContactDatabase& aDatabase, MContactDbObserver *aObserver) :
       
  5167 	iDatabase(aDatabase), iObserver(aObserver)
       
  5168 	{}
       
  5169 
       
  5170 
       
  5171 /**
       
  5172 Removes the observer from the contact database.
       
  5173 */
       
  5174 EXPORT_C CContactChangeNotifier::~CContactChangeNotifier()
       
  5175 	{
       
  5176     if (iObserver)
       
  5177         {
       
  5178 	    iDatabase.RemoveObserver(*iObserver);
       
  5179         }
       
  5180 	}
       
  5181 
       
  5182 	
       
  5183 void CContactChangeNotifier::ConstructL()
       
  5184 	{
       
  5185     if (iObserver)
       
  5186         {
       
  5187 	    iDatabase.AddObserverL(*iObserver);
       
  5188         }
       
  5189 	}
       
  5190 
       
  5191 
       
  5192 /**
       
  5193 Deletes a contact item. 
       
  5194 See doDeleteContactL() for details
       
  5195 */
       
  5196 void CContactDatabase::DeleteContactSendEventActionL(TContactItemId aContactId, TCntSendEventAction aActionType)
       
  5197 	{
       
  5198 	iCntSvr->DeleteContactL(aContactId, aActionType);
       
  5199 	//Now we check if the contact belonged to the sort array, if so 
       
  5200 	//remove it from iSortedItems
       
  5201 	RemoveFromSortArray(aContactId);
       
  5202 	//Now we check if the contact belonged to the template list, if so 
       
  5203 	//remove it from iCardTemplateIds
       
  5204 	RemoveFromTemplateList(aContactId);
       
  5205 	//Now we check if the contact belonged to the Group Id list, if so 
       
  5206 	//remove it from iGroupIds	
       
  5207 	RemoveFromGroupIds(aContactId);
       
  5208 	}