plugins/contacts/symbian/contactsmodel/cntmodel/src/rcntmodel.cpp
changeset 0 876b1a06bc25
child 5 603d3f8b6302
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /*
       
     2 * Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 /**
       
    20  @file
       
    21  @internalComponent
       
    22  @released
       
    23 */
       
    24 
       
    25 #include <s32mem.h>
       
    26 #include <cntitem.h>
       
    27 #include <cntdb.h>
       
    28 #include <cntfilt.h>
       
    29 
       
    30 #include "rcntmodel.h"
       
    31 #include "persistencelayer.h" // for mlplcollection.
       
    32 #include "ccntnotificationmonitor.h"
       
    33 #include "ccontactprivate.h" // for mprogresseventhander.
       
    34 #include "ccntpackager.h"
       
    35 #include <cntviewstore.h>
       
    36 
       
    37 
       
    38 /** Contacts server version number. */ 
       
    39 const TInt KCntServerMajorVersionNumber=1;
       
    40 const TInt KCntServerMinorVersionNumber=1;
       
    41 const TInt KCntServerBuildVersionNumber=1;
       
    42 
       
    43 /** Number of attempts to try restart the server after premature termination. */
       
    44 const TInt KMaxTimesToRestartServer = 3;
       
    45 
       
    46 /** Maximum number of asynchronous IPC calls. */
       
    47 const TInt KAsyncMessageSlots=6;
       
    48 
       
    49 
       
    50 /**
       
    51 Unlock the last locked contact item on the server.  Used by OpenLX().  If any
       
    52 method which locks a contact item leaves thenccnt this method is called as the
       
    53 cleanup stack unwinds, removing the lock for the last locked contact item.
       
    54 
       
    55 @capability None
       
    56 */
       
    57 void CleanupUnlockRecord(TAny *aSession)
       
    58 	{
       
    59 	static_cast<RCntModel*>(aSession)->UnlockLastLockedContact();
       
    60 	}
       
    61 
       
    62 
       
    63 /**
       
    64 Unlock the last locked contact item on the server.  Used by OpenLX().
       
    65 
       
    66 @capability None
       
    67 */
       
    68 void RCntModel::UnlockLastLockedContact()
       
    69 	{
       
    70 	CloseContact(KNullContactId);
       
    71 	}
       
    72 
       
    73 
       
    74 /**
       
    75 Push a Contact item unlock cleanup item on the cleanup stack.
       
    76 */
       
    77 void RCntModel::PushUnlockL() const
       
    78 	{
       
    79 	CleanupStack::PushL( TCleanupItem(CleanupUnlockRecord, const_cast<RCntModel *>(this)));
       
    80 	}
       
    81 
       
    82 
       
    83 /**
       
    84 RCntModel constructor.
       
    85 
       
    86 Member variables must be initialised (zero'd) in the constructor since
       
    87 RCntModel does not derive from CBase.
       
    88 */
       
    89 RCntModel::RCntModel()
       
    90 	:
       
    91 	iDbNotifyMonitor(NULL), 
       
    92 	iPackager(NULL),
       
    93 	iConnectionId(0),
       
    94 	iNoOfSvrStartAttempts(0)
       
    95 	{
       
    96 	}
       
    97 
       
    98 
       
    99 /**
       
   100 Get the Contacts server version number.
       
   101 
       
   102 @return Contacts server version number.
       
   103 */
       
   104 TVersion RCntModel::Version() const
       
   105 	{
       
   106 	return(TVersion(KCntServerMajorVersionNumber,KCntServerMinorVersionNumber,KCntServerBuildVersionNumber));
       
   107 	}
       
   108 
       
   109 
       
   110 /** Name of the executable for the Contacts server. */
       
   111 _LIT(KCntServerExe,"CNTSRV.EXE");
       
   112 /** Name used to connect a session to the Contacts server. */
       
   113 _LIT(KCntServerName,"CNTSRV");
       
   114 
       
   115 
       
   116 /**
       
   117 Open a Contacts server session.
       
   118 */
       
   119 void RCntModel::ConnectL()
       
   120 	{
       
   121 	// Assume the server is already running and attempt to create a session
       
   122 	// with a maximum of KAsyncMessageSlots message slots.
       
   123 	TInt err = CreateSession(KCntServerName,Version(),KAsyncMessageSlots);
       
   124 	
       
   125 	if(err == KErrNotFound) // Server not running?
       
   126 		{
       
   127 		// Use the RProcess API to start the server.
       
   128 		RProcess server;
       
   129 		User::LeaveIfError(server.Create(KCntServerExe,KNullDesC));
       
   130 		
       
   131 		//Enforce server to be at system default priority EPriorityForeground
       
   132 		//Contact server used to set as EPriorityHigh and this caused client could
       
   133 		//not get control or responsive until sorting by the idle sorter in remote 
       
   134 		//view was done.
       
   135 		server.SetPriority(EPriorityForeground);
       
   136 		
       
   137 		// Synchronise with the server.
       
   138 		TRequestStatus reqStatus;
       
   139 		server.Rendezvous(reqStatus);
       
   140 		server.Resume();
       
   141 		
       
   142 		// Server will call the reciprocal static synchronisation call.
       
   143 		User::WaitForRequest(reqStatus);
       
   144 		server.Close();
       
   145 		User::LeaveIfError(reqStatus.Int());
       
   146 		
       
   147 		// Create the server session.
       
   148 		User::LeaveIfError(CreateSession(KCntServerName,Version(),KAsyncMessageSlots));
       
   149 		}
       
   150 	else
       
   151 		{
       
   152 		User::LeaveIfError(err);
       
   153 		}
       
   154 
       
   155 	// Create object packer/unpacker if it doesn't already exist.
       
   156 	if (iPackager == NULL)	
       
   157 		{
       
   158 		iPackager = CCntPackager::NewL();
       
   159 		}
       
   160 	
       
   161 	// Each session (client) will be given a unique ID known as the Connection
       
   162 	// ID.  This ID forms part of the database event notification message.  This
       
   163 	// ID is created during the connection to the server.
       
   164 	ConnectionId();
       
   165 	}
       
   166 
       
   167 	
       
   168 /**
       
   169 Close session.
       
   170 */
       
   171 void RCntModel::Close()
       
   172 	{
       
   173 	delete iPackager;
       
   174 	iPackager = NULL;
       
   175 	delete iDbNotifyMonitor;
       
   176 	iDbNotifyMonitor = NULL;
       
   177 	RHandleBase::Close();
       
   178 	}
       
   179 
       
   180 
       
   181 /**
       
   182 Open a named contact database.
       
   183 
       
   184 Opens the default contacts database if the default argument is used.  The given
       
   185 descriptor must not contain more than KCntMaxFilePath characters.
       
   186 
       
   187 @param aCntFile Filename (in the form drive:database).  Defaults to
       
   188 KCntDefaultDrive.
       
   189 
       
   190 @return KErrNone if success, KErrArgument if the given descriptor contains more than the 
       
   191         maximum length of 190 characters, otherwise one of the System error codes.
       
   192 
       
   193 @capability ReadUserData
       
   194 */
       
   195 TInt RCntModel::OpenDatabase(const TDesC& aCntFile) const
       
   196     {
       
   197     TInt err = SetFileName(aCntFile);
       
   198     if (err == KErrNone)
       
   199         {
       
   200         TIpcArgs args;
       
   201         args.Set(0,&aCntFile);
       
   202         err = SendReceive(ECntOpenDataBase, args);
       
   203         }
       
   204 
       
   205     return err;
       
   206     }
       
   207 
       
   208 
       
   209 /**
       
   210 Open a named contact database asynchronously.
       
   211 
       
   212 Opens the default contacts database if the default argument is used.  The given
       
   213 descriptor must not contain more than KCntMaxFilePath characters.
       
   214 
       
   215 @param aStatus Asynchronous request object.  Request is completed when database
       
   216 has been opened.
       
   217 @param aCntFile Contacts database filename (in the form drive:database).
       
   218 Defaults to KCntDefaultDrive.
       
   219 
       
   220 @capability ReadUserData
       
   221 */
       
   222 void RCntModel::OpenDatabaseAsyncL(TRequestStatus& aStatus, const TDesC& aCntFile)
       
   223     {
       
   224     User::LeaveIfError(SetFileName(aCntFile));
       
   225 
       
   226     TIpcArgs args;
       
   227     args.Set(0,&aCntFile);
       
   228     SendReceive(ECntOpenDataBase, args, aStatus);
       
   229     }
       
   230 
       
   231 
       
   232 /**
       
   233 Cancel last asynchronous database open request.
       
   234 
       
   235 @capability None
       
   236 */
       
   237 void RCntModel::CancelAsyncOpen() 
       
   238 	{
       
   239 	SendReceive(ECntCancelAsyncOpenDatabase);		
       
   240 	}
       
   241 
       
   242 
       
   243 /**
       
   244 Handle a premature termination of the contact server process by re-connecting
       
   245 the session and re-opening the database.
       
   246 
       
   247 @capability ReadUserData
       
   248 */
       
   249 void RCntModel::HandlePrematureServerTerminationL()
       
   250 	{
       
   251 	if (iNoOfSvrStartAttempts > KMaxTimesToRestartServer)
       
   252 		{
       
   253 		User::Leave(KErrServerTerminated);
       
   254 		}
       
   255 	ConnectL();
       
   256 	User::LeaveIfError(OpenDatabase(iFileName));
       
   257 	++iNoOfSvrStartAttempts;
       
   258 	}
       
   259 
       
   260 	
       
   261 /**
       
   262 Set the database filename. Used to re-open the database if the server is
       
   263 terminated prematurely.
       
   264 
       
   265 @param aCntFile Contacts database filename (in the form drive:database).
       
   266 @return KErrNone if success, KErrArgument if the given descriptor contains more than the 
       
   267         maximum length of 190 characters.         
       
   268 */
       
   269 TInt RCntModel::SetFileName(const TDesC& aCntFile) const
       
   270     {
       
   271     if(aCntFile.Length() > KCntMaxFilePath)
       
   272         {
       
   273         return KErrArgument;
       
   274         }
       
   275 
       
   276     iFileName = aCntFile;
       
   277     return KErrNone;
       
   278     }
       
   279 
       
   280 
       
   281 /**
       
   282 Close currently open database.
       
   283 
       
   284 @capability None
       
   285 */
       
   286 void RCntModel::CloseDatabase() const
       
   287 	{
       
   288 	(void)SendReceive(ECntCloseDataBase);
       
   289 	}
       
   290 
       
   291 
       
   292 /**
       
   293 Get the machine ID. 
       
   294 
       
   295 Note: This function can leave.
       
   296 
       
   297 @return Machine ID.
       
   298 
       
   299 @leave KErrNone The send operation is successful
       
   300 @leave KErrServerTerminated The server no longer present
       
   301 @leave KErrServerBusy There are no message slots available
       
   302 @leave KErrNoMemory There is insufficient memory available
       
   303 
       
   304 
       
   305 @capability None
       
   306 */
       
   307 TInt64 RCntModel::MachineId() const
       
   308 	{
       
   309 	TIpcArgs args;
       
   310 	TPckgBuf<TInt64> machineID;
       
   311 	args.Set(0, &machineID);
       
   312 	User::LeaveIfError(SendReceive(ECntMachineID, args)); // this can leave
       
   313 	return machineID();	
       
   314 	}
       
   315 
       
   316 
       
   317 /**
       
   318 Set the machine ID (debug only).
       
   319 
       
   320 @param aMachineUniqueId New machine ID.
       
   321 
       
   322 @capability None
       
   323 */
       
   324 void RCntModel::OverrideMachineUniqueId(TInt64 aMachineUniqueId)
       
   325 	{
       
   326 	TIpcArgs args;
       
   327 	TPckgBuf<TInt64> machineID(aMachineUniqueId);
       
   328 	args.Set(0, &machineID);
       
   329 	(void)SendReceive(ECntOverrideMachineID, args);	
       
   330 	}
       
   331 
       
   332 
       
   333 /**
       
   334 Replace a named contact database with an empty one, replacing any database with
       
   335 the same name.  Replaces the default contacts database if the default argument
       
   336 is used.  The given descriptor must not contain more than KCntMaxFilePath
       
   337 characters.
       
   338 
       
   339 @param aCntFile Contacts database filename (in the form drive:database).
       
   340 Defaults to KCntDefaultDrive.
       
   341 
       
   342 @return KErrNone if success, KErrArgument if the given descriptor contains more than the 
       
   343         maximum length of 190 characters, KErrInUse if the database is currently open, 
       
   344         otherwise one of the System error codes.
       
   345 
       
   346 @capability WriteUserData
       
   347 */
       
   348 TInt RCntModel::ReplaceDatabase(const TDesC& aCntFile) const
       
   349     {
       
   350     TInt err = SetFileName(aCntFile);
       
   351     if (err == KErrNone)
       
   352         {
       
   353         TIpcArgs args;
       
   354         args.Set(0,&aCntFile);
       
   355 
       
   356         err = SendReceive(ECntReplaceDatabase, args);
       
   357         }
       
   358 
       
   359     return err;
       
   360     }
       
   361 
       
   362 
       
   363 /**
       
   364 Returns an array of contact item IDs for all the contact items which may contain
       
   365 the specified telephone number in a telephone, fax or SMS type field.
       
   366 
       
   367 @see CContactDatabase::MatchPhoneNumberL() for more details on the match.
       
   368 
       
   369 @param aNumber Phone number string
       
   370 @param aMatchLengthFromRight Number of digits from the right of the phone number
       
   371 to use.  Up to 15 digits can be specified and it is recommended that at least 7
       
   372 match digits are specified.
       
   373 
       
   374 @return CContactIdArray of candidate matches.
       
   375 
       
   376 @capability ReadUserData
       
   377 */
       
   378 CContactIdArray* RCntModel::MatchPhoneNumberL(const TDesC& aNumber, const TInt aMatchLengthFromRight)
       
   379 	{
       
   380 	TIpcArgs args;
       
   381 	args.Set(0, &iPackager->GetReceivingBufferL());
       
   382 	args.Set(1, MLplCollection::EMatchPhoneNos);
       
   383 	args.Set(2, &aNumber);
       
   384 	args.Set(3, aMatchLengthFromRight);
       
   385 	
       
   386 	TInt newBuffSize = 0;
       
   387 	User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));
       
   388 	
       
   389 	if (newBuffSize > 0)
       
   390 		{
       
   391 		// If the buffer is not large enough resize the packager's internal
       
   392 		// buffer and make the call again.
       
   393 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
   394 		User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));		
       
   395 		}
       
   396 		
       
   397 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
   398 	CleanupStack::Pop(idArray);
       
   399 
       
   400 	return idArray;
       
   401 	}
       
   402 	
       
   403 	
       
   404 
       
   405 /**
       
   406 Create an empty named contact database.
       
   407 
       
   408 Creates the default contacts database if the default argument is used.  The
       
   409 given descriptor must not contain more than KCntMaxFilePath characters.
       
   410 
       
   411 @param aCntFile Contacts database filename (in the form drive:database).
       
   412 Defaults to KCntDefaultDrive.
       
   413 
       
   414 @return KErrNone if success, KErrArgument if the given descriptor contains more than the 
       
   415         maximum length of 190 characters, KErrAlreadyExists if the database already 
       
   416         exists otherwise one of the System error codes.
       
   417 
       
   418 @capability WriteUserData
       
   419 */
       
   420 TInt RCntModel::CreateDatabase(const TDesC& aCntFile) const
       
   421     {
       
   422     TInt err = SetFileName(aCntFile);
       
   423     if (err == KErrNone)
       
   424         {
       
   425         TIpcArgs args;
       
   426         args.Set(0,&aCntFile);
       
   427         err = SendReceive(ECntCreateDatabase, args);
       
   428         }
       
   429     return err;
       
   430     }
       
   431 
       
   432 
       
   433 /**
       
   434 Create the system template.
       
   435 
       
   436 @return KErrNone if success otherwise one of the System error codes.
       
   437 	
       
   438 @capability WriteUserData
       
   439 */
       
   440 TInt RCntModel::ReCreateTemplate() const
       
   441 	{
       
   442 	return SendReceive(ECntReCreateTemplate);
       
   443 	}
       
   444 
       
   445 
       
   446 /**
       
   447 Get the database file UID.
       
   448 
       
   449 @return Pointer to file UID.
       
   450 
       
   451 @capability None
       
   452 */
       
   453 TPtrC RCntModel::FileUidL() const
       
   454 	{
       
   455 	TIpcArgs args;
       
   456 	args.Set(0, &iFileUid);
       
   457 	User::LeaveIfError (SendReceive(ECntFileUniqueId, args));
       
   458     return iFileUid;
       
   459 	}
       
   460 
       
   461 
       
   462 /**
       
   463 Determine if the database is ready.  Ready in this context means that the
       
   464 database is open and readable/writable (i.e. the state machine is in
       
   465 CStateWritable).
       
   466 
       
   467 @capability None
       
   468 
       
   469 @return ETrue if the database is ready, EFalse if the database is not ready.
       
   470 */
       
   471 TBool RCntModel::DatabaseReadyL() const
       
   472     {
       
   473     TBool retVal = EFalse;
       
   474 
       
   475     // Although the ECntGetDatabaseReady msg. is completed with TBool values,
       
   476     // during message processing, it is possible that ServiceError() occurs,
       
   477     // causing the message to be completed with negative error codes.
       
   478     // LeaveIfError() would protect against such cases.
       
   479     User::LeaveIfError(retVal = SendReceive(ECntGetDatabaseReady));
       
   480 
       
   481     return retVal;
       
   482     }
       
   483 
       
   484 
       
   485 /**
       
   486 Tests whether a contact item's hint bit field matches a filter.
       
   487 
       
   488 @param aBitWiseFilter The filter to compare the item against.  This is a
       
   489 combination of TContactViewFilter values.
       
   490 @param aContactId The ID of the item in the database.
       
   491 
       
   492 @return ETrue if the item is of the correct type for inclusion in the database 
       
   493 and its hint bit field matches the specified filter, EFalse if either of these
       
   494 conditions are not met.
       
   495 
       
   496 @capability None
       
   497 */
       
   498 TBool RCntModel::ContactMatchesHintFieldL(TInt aBitWiseFilter, TContactItemId aContactId)
       
   499     {
       
   500     TIpcArgs args;
       
   501     args.Set(0, aBitWiseFilter);
       
   502     args.Set(1, aContactId);
       
   503     TBool retVal = EFalse;
       
   504 
       
   505     // Although the ECntMatchesHintField msg. is completed with TBool values,
       
   506     // during message processing, it is possible that ServiceError() occurs,
       
   507     // causing the message to be completed with negative error codes.
       
   508     // LeaveIfError() would protect against such cases.
       
   509     User::LeaveIfError (retVal = SendReceive(ECntMatchesHintField, args));
       
   510 
       
   511     return retVal;
       
   512     }
       
   513 
       
   514 
       
   515 /**
       
   516 Delete a named contact database.
       
   517 
       
   518 Deletes the default contacts database if the default argument is used.  The
       
   519 given descriptor must not contain more than KCntMaxFilePath characters.
       
   520 
       
   521 @param aCntFile Contacts database filename (in the form drive:database).
       
   522 Defaults to KCntDefaultDrive.
       
   523 
       
   524 @return KErrNone if success, KErrArgument if the given descriptor contains more 
       
   525         than the maximum length of 190 characters, KErrInUse if the database is 
       
   526         in use, KErrNotFound if the database does not exist otherwise one of the 
       
   527         System error codes.
       
   528 
       
   529 @capability WriteUserData
       
   530 */
       
   531 TInt RCntModel::DeleteDatabase(const TDesC& aCntFile) const
       
   532 	{
       
   533 	if(aCntFile.Length() > KCntMaxFilePath)
       
   534 		{
       
   535 		return KErrArgument;
       
   536 		}
       
   537 	TIpcArgs args;
       
   538 	args.Set(0,&aCntFile);
       
   539 	return SendReceive(ECntDeleteDatabase,args);
       
   540 	}
       
   541 
       
   542 
       
   543 /**
       
   544 Get the name of the default contact database file.
       
   545 
       
   546 The given descriptor must have room for minimum of KCntMaxFilePath characters.
       
   547 
       
   548 @param aCntFile Contains the default contact database name on return.
       
   549 
       
   550 @return KErrNone if success, KErrArgument if the given descriptor contains more 
       
   551         than the maximum length of 190 characters, otherwise one of the System 
       
   552         error codes.
       
   553 
       
   554 @capability None
       
   555 */
       
   556 TInt RCntModel::DefaultDatabase(TDes& aCntFile) const
       
   557 	{
       
   558 	TIpcArgs args;
       
   559 	args.Set(0,&aCntFile);
       
   560 	return SendReceive(ECntGetDefaultDatabaseName,args);
       
   561 	}
       
   562 
       
   563 
       
   564 /**
       
   565 Retrieve the current contact database drive.
       
   566 
       
   567 @param aDriveUnit Contains the current contact database drive unit on return.
       
   568 
       
   569 @return KErrNone if success otherwise one of the System error codes.
       
   570 
       
   571 @capability None
       
   572 */
       
   573 TInt RCntModel::DatabaseDrive(TDriveUnit& aDriveUnit) const
       
   574 	{
       
   575 	TInt ret = SendReceive(ECntDatabaseDrive);
       
   576 	if (ret >= KErrNone)
       
   577 		{
       
   578 		aDriveUnit = ret;	
       
   579 		}
       
   580 	return ret;
       
   581 	}
       
   582 
       
   583 
       
   584 /**
       
   585 Sets the contact database drive and optionally moves the default contact
       
   586 database from its current location to the new drive.  This function guarantees
       
   587 an all or nothing operation.  If the database is not successfully moved, the
       
   588 drive setting is not updated to reflect the change.
       
   589 
       
   590 @param aDriveUnit The drive to which to move the contact database.
       
   591 @param aCopy ETrue moves the existing file to the specified drive.  Deletion of
       
   592 the source file will fail if it is in use.  EFalse does not move the file.  The
       
   593 default argument value is ETrue.
       
   594 
       
   595 @return KErrNone if success, KErrInUse if destination file for copy is open,
       
   596 KErrNotFound found if source contact database (default) cannot be found,
       
   597 KErrAlreadyExists if the destination contact database file exists.
       
   598 
       
   599 @capability WriteUserData
       
   600 */
       
   601 void RCntModel::SetDatabaseDriveL(TDriveUnit aDriveUnit, TBool aCopy)
       
   602 	{
       
   603 	TIpcArgs args;
       
   604 	args.Set(0,aDriveUnit);
       
   605 	args.Set(1,aCopy);
       
   606 	User::LeaveIfError(SendReceive(ECntSetDatabaseDrive,args));
       
   607 	}
       
   608 
       
   609 /** 
       
   610 Gets the size of the database file in bytes.
       
   611 
       
   612 @return The size of the contact database in bytes.
       
   613 
       
   614 @capability None
       
   615 */
       
   616 TInt RCntModel::FileSize() const
       
   617 	{
       
   618 	return SendReceive(ECntFilesSize);	
       
   619 	}
       
   620 
       
   621 /**
       
   622 Determine if the named contact database file exists.
       
   623 
       
   624 If the aCntFile argument is the default, determines if default contact database
       
   625 file exists.
       
   626 
       
   627 @param aCntFile Contacts database filename (in the form drive:database).
       
   628 @leave KErrArgument if the given descriptor contains more than the maximum length 
       
   629        of 190 characters, otherwise one of the System error codes.
       
   630 @return ETrue if exists, EFalse does not exist. 
       
   631 @capability None
       
   632 */
       
   633 TBool RCntModel::DatabaseExistsL(const TDesC& aCntFile) const
       
   634     {
       
   635     if(aCntFile.Length() > KCntMaxFilePath)
       
   636         {
       
   637         User::Leave(KErrArgument);
       
   638         }
       
   639 
       
   640     TIpcArgs args;
       
   641     args.Set(0,&aCntFile);
       
   642     TBool ret = EFalse;
       
   643 
       
   644     // Although ECntDatabaseExists is normally completed with TBool values,
       
   645     // ServiceError() can occur which leads to a negative system error codes
       
   646     // being returned.  User::LeaveIfError will allow that to be properly handled.
       
   647     User::LeaveIfError(ret = SendReceive(ECntDatabaseExists,args));
       
   648 
       
   649     return ret;
       
   650     }
       
   651 
       
   652 
       
   653 /**
       
   654 List the contact database files for any given drive unit.  Lists all databases
       
   655 on all drives if aDriveUnit is set to NULL.
       
   656 
       
   657 @param aDriveUnit The drive unit to search.  Searches all drives if default
       
   658 argument is used.
       
   659 
       
   660 @return CDesCArray containing the database list.  Always returns list even if
       
   661 empty.
       
   662 
       
   663 @leave KErrNoMemory if not enough free memory, KErrNotReady if drive does not,
       
   664 otherwise one of the System error codes.
       
   665 
       
   666 @capability ReadUserData
       
   667 */
       
   668 CDesCArray* RCntModel::ListDatabasesL(TDriveUnit* aDriveUnit) const
       
   669 	{
       
   670 	// Convert the drive unit to an integer for IPC.  The TDriveUnit constructor
       
   671 	// does not allow values outside 0 - 25.
       
   672 	TInt driveNumber;
       
   673 	(aDriveUnit == NULL) ? (driveNumber = ECntAllDrives) : (driveNumber = *aDriveUnit);
       
   674 
       
   675 	// Provide a CBufFlat for receiving the list of databases from the server.
       
   676 	// Format is a (proprietary) serialized CDesCArray.
       
   677 	const TInt KInitialBufferSize = 200;
       
   678 	CBufFlat* listBuffer = CBufFlat::NewL(KInitialBufferSize);
       
   679 	CleanupStack::PushL(listBuffer);
       
   680 	listBuffer->ExpandL(0,KInitialBufferSize);
       
   681 
       
   682 	// IPC argument list is:
       
   683 	// 0 (Return param)	- Address of our receive buffer
       
   684 	// 1 (Param)		- The drive number 0 - 25 or ECntAllDrives
       
   685 	// 2 (Return param)	- The size of buffer required for the transfer
       
   686 	TIpcArgs args;
       
   687 	TPtr8 ptr(listBuffer->Ptr(0));
       
   688 	args.Set(0,&ptr);
       
   689 	args.Set(1,driveNumber);
       
   690 	TPckgBuf<TInt> size;
       
   691 	args.Set(2,&size);
       
   692 	User::LeaveIfError(SendReceive(ECntListDatabases,args));
       
   693 
       
   694 	// Check if our buffer was large enough by reading returned size argument.
       
   695 	// The server will not have written any data if our povided buffer was not
       
   696 	// big enough.
       
   697 	if(size() > KInitialBufferSize)
       
   698 		{
       
   699 		// Not big enough but now we know how big the buffer needs to be.
       
   700 		// Just allocate buffer again, reset the IPC args and call again.
       
   701 		CleanupStack::PopAndDestroy(listBuffer);
       
   702 		listBuffer = CBufFlat::NewL(size());
       
   703 		CleanupStack::PushL(listBuffer);
       
   704 		listBuffer->ExpandL(0,size());
       
   705 		ptr.Set(listBuffer->Ptr(0));
       
   706 		args.Set(0,&ptr);
       
   707 		args.Set(1,driveNumber);
       
   708 		args.Set(2,&size);
       
   709 		User::LeaveIfError(SendReceive(ECntListDatabases,args));
       
   710 		}
       
   711 
       
   712 	// Wrap the buffer in a read stream class to internalize.
       
   713 	RBufReadStream readStream;
       
   714 	readStream.Open(*listBuffer);
       
   715 	CleanupClosePushL(readStream);
       
   716 
       
   717 	// Number of array elements.
       
   718 	const TInt count = readStream.ReadUint32L();
       
   719 	// Use count if it is not zero.
       
   720 	CDesCArray* list = new(ELeave) CDesCArrayFlat(count ? count : 1);
       
   721 	CleanupStack::PushL(list);
       
   722 	for (TInt i=0; i<count; ++i)
       
   723 		{
       
   724 		TFileName path;
       
   725 		TInt length=readStream.ReadInt8L();
       
   726 		readStream.ReadL(path,length);
       
   727 		// Add to the list.
       
   728 		list->AppendL(path);
       
   729 		}
       
   730 
       
   731 	CleanupStack::Pop(list);
       
   732 	CleanupStack::PopAndDestroy(&readStream);
       
   733 	CleanupStack::PopAndDestroy(listBuffer);
       
   734 	
       
   735 	return list;
       
   736 	}
       
   737 
       
   738 
       
   739 /**
       
   740 Add a new contact to the database.
       
   741 
       
   742 @param aContact The contact to be added to the database.
       
   743 
       
   744 @capability WriteUserData
       
   745 */
       
   746 TContactItemId RCntModel::CreateContactL(CContactItem& aContact) const
       
   747 	{
       
   748 	// Pack the contact into the first IPC argument.
       
   749 	TIpcArgs args;
       
   750 	TPtr8 ptr(iPackager->PackL(aContact));
       
   751 	args.Set(0,&ptr);
       
   752 
       
   753 	TInt cntId = 0;
       
   754 	User::LeaveIfError(cntId = SendReceive(ECntItemCreate, args));
       
   755 
       
   756 	return cntId;
       
   757 	}
       
   758 
       
   759 
       
   760 /**
       
   761 Delete a contact from the database.
       
   762 
       
   763 @param aContact The contact to be deleted.
       
   764 @param aCntEventType The event type to pass on to the observers.
       
   765 @param aDecAccessCount If ETrue access count should be decremented prior to the
       
   766 deletion.
       
   767 
       
   768 @capability WriteUserData
       
   769 */
       
   770 void RCntModel::DeleteContactL(TContactItemId aCntId, TCntSendEventAction aCntEventType, TBool aDecAccessCount) const
       
   771 	{
       
   772 	TIpcArgs args(aCntId, aCntEventType, aDecAccessCount);
       
   773 	User::LeaveIfError(SendReceive(ECntItemDelete, args));
       
   774 	}
       
   775 
       
   776 /** 
       
   777 Open the database tables.
       
   778 
       
   779 @capability ReadUserData
       
   780 */
       
   781 void RCntModel::OpenTablesL()
       
   782 	{
       
   783 	User::LeaveIfError(SendReceive(ECntReOpenDbTables));
       
   784 	}
       
   785 
       
   786 
       
   787 /**
       
   788 Close the database tables.
       
   789 
       
   790 @capability None
       
   791 */
       
   792 void RCntModel::CloseTablesL()
       
   793 	{
       
   794 	User::LeaveIfError(SendReceive(ECntCloseDbTables));
       
   795 	}
       
   796 
       
   797 
       
   798 /**
       
   799 Update and unlock an existing contact in the database.
       
   800 
       
   801 @param aContact The contact to be updated and unlocked
       
   802 @param aSendChangedEvent If ETrue the changed event should be sent after the
       
   803 update/unlock.
       
   804 
       
   805 @capability WriteUserData
       
   806 */
       
   807 void RCntModel::CommitContactL(const CContactItem& aContact, TBool aSendChangedEvent) const
       
   808 	{
       
   809     //check what contacts were added/removed to a group
       
   810     if (aContact.Type() == KUidContactGroup)
       
   811         {
       
   812         const CContactGroup& group = static_cast<const CContactGroup&>(aContact);
       
   813         if (group.iInitialContactIds != NULL)
       
   814             {
       
   815             group.iAddedContactIds = CContactIdArray::NewL();
       
   816             group.iRemovedContactIds = CContactIdArray::NewL();
       
   817             for (int i = 0; i < group.iItems->Count(); i++)
       
   818                 {
       
   819                 if (group.iInitialContactIds->Find(group.iItems->operator[](i)) == KErrNotFound)
       
   820                     {
       
   821                     group.iAddedContactIds->AddL(group.iItems->operator[](i));
       
   822                     }
       
   823                 }
       
   824             for (int j = 0; j < group.iInitialContactIds->Count(); j++)
       
   825                 {
       
   826                 if (group.iItems->Find(group.iInitialContactIds->operator[](j)) == KErrNotFound)
       
   827                     {
       
   828                     group.iRemovedContactIds->AddL(group.iInitialContactIds->operator[](j));
       
   829                     }
       
   830                 }           
       
   831             }
       
   832         }	
       
   833 	
       
   834 	// Pack the contact into the first IPC argument.
       
   835 	TIpcArgs args; 
       
   836 	TPtr8 ptr(iPackager->PackL((const_cast<CContactItem&>(aContact))));
       
   837 	args.Set(0,&ptr);
       
   838 	
       
   839 	args.Set(1,aSendChangedEvent);
       
   840 
       
   841 	User::LeaveIfError(SendReceive(ECntItemCommit, args));
       
   842 	
       
   843     //clear list of contacts added/removed to a group
       
   844     if (aContact.Type() == KUidContactGroup)
       
   845         {
       
   846         const CContactGroup& group = static_cast<const CContactGroup&>(aContact);
       
   847         if (group.iAddedContactIds != NULL)
       
   848             {
       
   849             delete group.iAddedContactIds;
       
   850             group.iAddedContactIds = NULL;
       
   851             }
       
   852         if (group.iRemovedContactIds != NULL)
       
   853             {
       
   854             delete group.iRemovedContactIds;
       
   855             group.iRemovedContactIds = NULL;
       
   856             }
       
   857         if (group.iInitialContactIds != NULL)
       
   858             {
       
   859             delete group.iInitialContactIds;
       
   860             group.iInitialContactIds = NULL;
       
   861             }
       
   862         }	
       
   863 	}
       
   864 
       
   865 
       
   866 /**
       
   867 Unpacks a contact item contained within the Packager's internal buffer and
       
   868 creates a contact item object.  Within the server, the contact item has been
       
   869 written to the Packager's internal buffer by the RMessage2.
       
   870 
       
   871 If the buffer size was returned then the buffer was not large enough to hold a
       
   872 serialised contact item.  The buffer must be expanded to the size returned by
       
   873 the server (ie aBufferSize) and the read operation performed again. 
       
   874 
       
   875 @see CCntPackager::SetBufferFromMessageL()
       
   876 	
       
   877 @param aBufferSize The new buffer size.
       
   878 @param aArgs The argument buffer where the serialised contact item is written by
       
   879 the server.
       
   880 
       
   881 @return CContactItem unpacked from Packager's internal buffer.
       
   882 
       
   883 @capability ReadUserData
       
   884 */
       
   885 CContactItem* RCntModel::UnPackContactLC(TInt aBufferSize, TIpcArgs& aArgs) const
       
   886 	{
       
   887 	if(aBufferSize > 0) // Packager's internal buffer is not large enough.
       
   888 		{
       
   889 		// Set new extended receiving buffer.
       
   890 		aArgs.Set(1, &iPackager->GetReceivingBufferL(aBufferSize));
       
   891 		// Perform read operation again.
       
   892 		User::LeaveIfError(SendReceive(ECntItemRead, aArgs));
       
   893 		}
       
   894 	return iPackager->UnpackCntItemLC();
       
   895 	}
       
   896 
       
   897 
       
   898 /**
       
   899 Read an existing contact in the database.
       
   900 
       
   901 @param aCntItemVDef The view definition to use.
       
   902 @param aCntId Contact ID to read.
       
   903 
       
   904 @return CContactItem object with contact ID aCntId.
       
   905 */
       
   906 CContactItem* RCntModel::ReadContactL(const CContactItemViewDef* aCntItemVDef, TContactItemId aCntId) const
       
   907 	{
       
   908 	TIpcArgs args;
       
   909 
       
   910 	if (aCntItemVDef) 
       
   911 		{
       
   912 		iPackager->PackL(*(const_cast<CContactItemViewDef*>(aCntItemVDef)));
       
   913 		// Indicates that a user ContactItemViewDef is present in first IPC
       
   914 		// argument.
       
   915 		args.Set(3,TRUE);
       
   916 		}
       
   917 	else
       
   918 		{
       
   919 		iPackager->Clear();
       
   920 		// Indicates that no user ContactItemViewDef is present in first IPC
       
   921 		// argument.  The default view definition will be used instead.
       
   922 		args.Set(3,FALSE);
       
   923 		}
       
   924 
       
   925 	args.Set(0, &iPackager->GetTransmittingBuffer());
       
   926 	args.Set(1, &iPackager->GetReceivingBufferL());
       
   927 	args.Set(2, aCntId);
       
   928 
       
   929 	TInt newBuffSize = 0;
       
   930 	User::LeaveIfError(newBuffSize = SendReceive(ECntItemRead, args));
       
   931 	CContactItem* cntItem = UnPackContactLC(newBuffSize, args);
       
   932 	CleanupStack::Pop(cntItem);
       
   933 
       
   934 	return cntItem;
       
   935 	}
       
   936 	
       
   937 	
       
   938 /**
       
   939 Open and lock an existing contact in the database.  The contact item lock is
       
   940 pushed onto the cleanup stack.
       
   941 
       
   942 @param aCntItemVDef The view definition to use.
       
   943 @param aCntId Contact ID to read.
       
   944 
       
   945 @return Opened/locked CContactItem object.
       
   946 */
       
   947 CContactItem* RCntModel::OpenContactLX(const CContactItemViewDef* aCntItemVDef, TContactItemId aCntId) const
       
   948 	{
       
   949 	TIpcArgs args;
       
   950 	if (aCntItemVDef) 
       
   951 		{
       
   952 		iPackager->PackL(*(const_cast<CContactItemViewDef*>(aCntItemVDef)));
       
   953 		// Indicates that a user ContactItemViewDef is present in first IPC
       
   954 		// argument.
       
   955 		args.Set(3,TRUE);
       
   956 		}
       
   957 	else
       
   958 		{
       
   959 		iPackager->Clear();
       
   960 		// Indicates that no user ContactItemViewDef is present in first IPC
       
   961 		// argument.  The default view definition will be used instead.
       
   962 		args.Set(3,FALSE);
       
   963 		}
       
   964 
       
   965 	args.Set(0, &iPackager->GetTransmittingBuffer());
       
   966 	args.Set(1, &iPackager->GetReceivingBufferL());
       
   967 	args.Set(2, aCntId);
       
   968 
       
   969 	TInt newBuffSize = 0;
       
   970 	User::LeaveIfError(newBuffSize = SendReceive(ECntItemOpen, args));
       
   971 
       
   972 	// Push the contact item lock onto the cleanup stack.  If UnPackContactLC()
       
   973 	// (or any other RCntModel method leaves after this point) then the last
       
   974 	// contact to be locked will be unlocked (aka closed).  The method returns
       
   975 	// with the lock remaining on the cleanup stack.
       
   976 	PushUnlockL(); 
       
   977 
       
   978 	CContactItem* cntItem = UnPackContactLC(newBuffSize, args);
       
   979 	
       
   980     //save a list of contacts belonging to a group
       
   981     if (cntItem->Type() == KUidContactGroup)
       
   982         {
       
   983         CContactGroup* group = static_cast<CContactGroup*>(cntItem);
       
   984         delete group->iInitialContactIds;
       
   985         group->iInitialContactIds = NULL;
       
   986         group->iInitialContactIds = CContactIdArray::NewL(group->ItemsContained());
       
   987         }	
       
   988 	
       
   989 	CleanupStack::Pop(cntItem);
       
   990 	
       
   991 	return cntItem;		
       
   992 	}
       
   993 
       
   994 
       
   995 /**
       
   996 Close/unLock an existing contact in the database.
       
   997 
       
   998 @param aCntId The contact ID of the contact to close.
       
   999 
       
  1000 @return ETrue if the contact was opened before and closed after the call,
       
  1001 EFalse if there was no need to close the contact.
       
  1002 */
       
  1003 TBool RCntModel::CloseContact(TContactItemId aCntId)
       
  1004 	{
       
  1005 	TInt res = SendReceive(ECntItemClose, TIpcArgs(aCntId));
       
  1006 	if (res == KErrNone)
       
  1007 		{
       
  1008 		return ETrue;
       
  1009 		}
       
  1010 	return EFalse;
       
  1011 	}
       
  1012 
       
  1013 
       
  1014 /**
       
  1015 Start a database transaction.
       
  1016 */
       
  1017 TInt RCntModel::BeginDbTransaction() const
       
  1018 	{
       
  1019 	return SendReceive(EBeginDbTransaction);
       
  1020 	}
       
  1021 
       
  1022 	
       
  1023 /**
       
  1024 Commit a database transaction.
       
  1025 */
       
  1026 TInt RCntModel::CommitDbTransaction() const
       
  1027 	{
       
  1028 	return SendReceive(EEndDbTransaction);
       
  1029 	}
       
  1030 
       
  1031 	
       
  1032 /**
       
  1033 Rollback a database transaction.
       
  1034 */
       
  1035 TInt RCntModel::RollbackDbTransaction() const
       
  1036 	{
       
  1037 	return SendReceive(ERollbackDbTransaction);
       
  1038 	}
       
  1039 
       
  1040 
       
  1041 /**
       
  1042 Set the operation timeout value.  This value is the length of time that a
       
  1043 deferred request will remain in the request queue in the State Machine before
       
  1044 being completed with an error code.
       
  1045 
       
  1046 @param aMicroSeconds The operation timeout in microseconds.  This timeout will
       
  1047 only be applied to requests sent by clients of this database after this point in
       
  1048 time. 
       
  1049 */
       
  1050 void RCntModel::SetOperationTimeOutL(const TInt aMicroSeconds) const
       
  1051 	{
       
  1052 	TIpcArgs args;
       
  1053 	args.Set(0, aMicroSeconds);
       
  1054 	User::LeaveIfError(SendReceive(ECntOpsTimeOut, args));		
       
  1055 	}
       
  1056 
       
  1057 	
       
  1058 /**
       
  1059 Change the existing contact view definition on the server.
       
  1060 
       
  1061 @param aView The new contact view defintion.
       
  1062 */
       
  1063 void RCntModel::SetViewDefinitionL(const CContactViewDef& aView)
       
  1064 	{
       
  1065 	TPtr8 ptr(iPackager->PackL(aView));
       
  1066 	User::LeaveIfError(SendReceive(ECntChangeViewDef, TIpcArgs(&ptr)));	
       
  1067 	}
       
  1068 
       
  1069 
       
  1070 /**
       
  1071 Add a database event observer.
       
  1072 
       
  1073 @param aObserver Observer callback inteface used to send database event.
       
  1074 */
       
  1075 void RCntModel::AddObserverL(MContactDbObserver& aObserver)
       
  1076 	{
       
  1077 	// If this is the first observer to be added then required to create the
       
  1078 	// database event notification monitor (lazy initialisation).
       
  1079 	if (!iDbNotifyMonitor)
       
  1080 		{
       
  1081 		iDbNotifyMonitor = CCntDbNotifyMonitor::NewL(*this);
       
  1082 		}
       
  1083 	iDbNotifyMonitor->AddObserverL(aObserver);
       
  1084 	}
       
  1085 
       
  1086 	
       
  1087 /**
       
  1088 Remove a database event observer.
       
  1089 
       
  1090 @param aObserver Observer callback inteface to be removed.
       
  1091 */
       
  1092 void RCntModel::RemoveObserver(const MContactDbObserver& aObserver)
       
  1093 	{
       
  1094 	if (iDbNotifyMonitor)
       
  1095 		{
       
  1096 		iDbNotifyMonitor->RemoveObserver(aObserver);
       
  1097 		// If this is the last observer to be removed then dispose of the
       
  1098 		// database event notification monitor (no longer required).
       
  1099 		if (iDbNotifyMonitor->NumberOfListeners() == 0)
       
  1100 			{
       
  1101 			delete iDbNotifyMonitor;
       
  1102 			iDbNotifyMonitor = NULL;
       
  1103 			}
       
  1104 		}
       
  1105 	}
       
  1106 
       
  1107 /**
       
  1108 Add a database event observer.
       
  1109 
       
  1110 @param aObserver Observer callback inteface used to send database event.
       
  1111 */
       
  1112 void RCntModel::AddObserverV2L(MContactDbObserverV2& aObserver)
       
  1113     {
       
  1114     // If this is the first observer to be added then required to create the
       
  1115     // database event notification monitor (lazy initialisation).
       
  1116     if (!iDbNotifyMonitor)
       
  1117         {
       
  1118         iDbNotifyMonitor = CCntDbNotifyMonitor::NewL(*this);
       
  1119         }
       
  1120     iDbNotifyMonitor->AddObserverV2L(aObserver);
       
  1121     }
       
  1122 
       
  1123     
       
  1124 /**
       
  1125 Remove a database event observer.
       
  1126 
       
  1127 @param aObserver Observer callback inteface to be removed.
       
  1128 */
       
  1129 void RCntModel::RemoveObserverV2(const MContactDbObserverV2& aObserver)
       
  1130     {
       
  1131     if (iDbNotifyMonitor)
       
  1132         {
       
  1133         iDbNotifyMonitor->RemoveObserverV2(aObserver);
       
  1134         // If this is the last observer to be removed then dispose of the
       
  1135         // database event notification monitor (no longer required).
       
  1136         if (iDbNotifyMonitor->NumberOfListeners() == 0)
       
  1137             {
       
  1138             delete iDbNotifyMonitor;
       
  1139             iDbNotifyMonitor = NULL;
       
  1140             }
       
  1141         }
       
  1142     }
       
  1143 
       
  1144 /**
       
  1145 Request a database event from the server.
       
  1146 
       
  1147 @param aStatus Completed when database event is available.
       
  1148 @param aEvent When aStatus is completed contains the database event.
       
  1149 */
       
  1150 void RCntModel::StartNotificationTransfer(TRequestStatus& aStatus, TDes8& aEvent)
       
  1151 	{	
       
  1152 	SendReceive(ECntRequestEvent, TIpcArgs(&aEvent), aStatus);	
       
  1153 	}
       
  1154 
       
  1155 
       
  1156 /**
       
  1157 End (cancel) request for database event from server.
       
  1158 */
       
  1159 void RCntModel::EndNotificationTransfer()
       
  1160 	{	
       
  1161 	SendReceive(ECntCancelEventRequest);	
       
  1162 	}
       
  1163 	
       
  1164 /** 
       
  1165 Sets the ID of the current item and persists it in the database.  The current 
       
  1166 item is provided for use by clients who want to identify one contact item in the
       
  1167 database as the currently selected item.
       
  1168 
       
  1169 @param aContactId The ID of the current item. 
       
  1170 
       
  1171 @capability WriteUserData
       
  1172 */
       
  1173 void RCntModel::SetCurrentItem(TContactItemId aContactId) const
       
  1174 	{
       
  1175 	TIpcArgs args(aContactId);
       
  1176 	(void)SendReceive(ECntSetCurrentItem, args);	
       
  1177 	}
       
  1178 
       
  1179 	
       
  1180 /** 
       
  1181 Gets the ID of the current item, as set by SetCurrentItem().  The current item 
       
  1182 ID is initialised to KNullContactId when the database is opened.
       
  1183 
       
  1184 @return The ID of the current item. 
       
  1185 
       
  1186 @capability None
       
  1187 */
       
  1188 TContactItemId RCntModel::CurrentItem() const
       
  1189 	{		
       
  1190 	 TContactItemId id = SendReceive(ECntGetCurrentItem);
       
  1191 	 if (id < 0)
       
  1192 	 	{
       
  1193 		return KNullContactId;
       
  1194 		}
       
  1195 	 else
       
  1196 	 	{
       
  1197 		return id;
       
  1198 		}
       
  1199 	}
       
  1200 
       
  1201 
       
  1202 /** 
       
  1203 When there are multiple contact databases on a device this method can be used to
       
  1204 enquire which database is the current one.
       
  1205 
       
  1206 The current database functions are provided as part of current item
       
  1207 functionality.  In order to pass a current item from one contacts model client
       
  1208 to another, the receiving client needs to be using the same database.
       
  1209 
       
  1210 The current database is a path and filename, set using SetCurrentDatabase(),
       
  1211 which is persisted by the contacts server.
       
  1212 
       
  1213 @deprecated
       
  1214 
       
  1215 @param aDatabase The path and filename of the current database.  KNullDesC 
       
  1216 if no current database has been set.
       
  1217 
       
  1218 @return KErrNone if success otherwise one of the System error codes. 
       
  1219 
       
  1220 @capability None
       
  1221 */
       
  1222 TInt RCntModel::GetCurrentDatabase(TDes& aDatabase) const
       
  1223 	{
       
  1224 	TIpcArgs args(&aDatabase);
       
  1225 	return SendReceive(ECntGetCurrentDb, args);
       
  1226 	}
       
  1227 
       
  1228 
       
  1229 /** 
       
  1230 When there are multiple contact databases on a device this method can be used to
       
  1231 set a database as the current one.
       
  1232 
       
  1233 Note: this function simply updates a file name which is stored by the Contacts
       
  1234 server and its use is optional.  It is provided as part of current item
       
  1235 functionality. 
       
  1236 
       
  1237 In order to pass a current item from one contacts model client to another, 
       
  1238 the receiving client needs to be using the same database.
       
  1239 
       
  1240 @deprecated
       
  1241 
       
  1242 @param aDatabase The path and filename of the current database.
       
  1243 
       
  1244 @return KErrNone if success otherwise one of the System error codes. 
       
  1245 
       
  1246 @capability WriteUserData
       
  1247 */
       
  1248 TInt RCntModel::SetCurrentDatabase(const TDesC& aDatabase) const
       
  1249 	{
       
  1250 	TIpcArgs args(&aDatabase);
       
  1251 	return SendReceive(ECntSetCurrentDb, args);
       
  1252 	}
       
  1253 
       
  1254 
       
  1255 /** 
       
  1256 Returns the ID of the contact item whose telephone number field is mapped to 
       
  1257 the speed dial position specified.
       
  1258 
       
  1259 This function is provided so that information may be displayed about a contact
       
  1260 item whose telephone number is being dialled using speed dialling.
       
  1261 
       
  1262 The function also retrieves the telephone number stored in the field.
       
  1263 
       
  1264 @param aSpeedDialPosition The speed dial position.  This is an integer in the 
       
  1265 range 1 to 9 inclusive.  If outside this range, the function leaves with
       
  1266 KErrArgument.
       
  1267 @param aPhoneNumber On return contains the telephone number which is mapped to
       
  1268 the speed dial position specified.  Returns KNullDesC if the speed dial position
       
  1269 requested has not been set.
       
  1270 
       
  1271 @return The ID of the contact item to which the speed dial is mapped. 
       
  1272 
       
  1273 @capability ReadUserData
       
  1274 */
       
  1275 TContactItemId RCntModel::GetSpeedDialFieldL(TInt aSpeedDialPosition, TDes& aPhoneNumber)
       
  1276 	{
       
  1277 	__ASSERT_ALWAYS(aSpeedDialPosition >= KCntMinSpeedDialIndex && aSpeedDialPosition <= KCntMaxSpeedDialIndex , User::Leave(KErrArgument));	
       
  1278 	TPckgBuf<TContactItemId> contact(KNullContactId);
       
  1279 	TIpcArgs args(aSpeedDialPosition,&aPhoneNumber);
       
  1280 	return (TContactItemId)SendReceive(ECntGetSpeedDialContactIdAndPhoneNumber, args);
       
  1281 	}
       
  1282 
       
  1283 	
       
  1284 /**
       
  1285 Sets a field containing a telephone number as a speed dial field.  The field 
       
  1286 is identified by aFieldIndex within the contact item aItem.  It is assigned a 
       
  1287 speed dial position between 1 and 9 inclusive.
       
  1288 
       
  1289 The field's speed dial and user added attributes are set and the appropriate 
       
  1290 UID (KUidSpeedDialXxx) is added to the field's content type.  The changes are 
       
  1291 committed to the database.
       
  1292 
       
  1293 Notes:
       
  1294 
       
  1295 - If an item's telephone number field has already been assigned to position 
       
  1296 aSpeedDialPosition, that item is updated so that the speed dial attribute 
       
  1297 is removed from its field and the speed dial field type UID is removed from 
       
  1298 the field's content type, before the new speed dial field is set.
       
  1299 
       
  1300 - The speed dial attribute can be tested for using the
       
  1301 CContactItemField::IsSpeedDial() method.
       
  1302 
       
  1303 - The contact item passed to this function (aItem) must have been obtained using 
       
  1304 one of the variants of CContactDatabase::OpenContactL().  This is because it 
       
  1305 is modified and committed to the database by this function - no further 
       
  1306 commits are necessary.
       
  1307 
       
  1308 @param aItem The contact item containing the field to set as a speed dial 
       
  1309 field.
       
  1310 @param aFieldIndex Index of a field in aItem's field set to set as a speed dial
       
  1311 field.
       
  1312 @param aSpeedDialPosition The speed dial position.  This is an integer in the 
       
  1313 range 1 to 9 inclusive.  If outside this range, the function leaves with
       
  1314 KErrArgument. 
       
  1315 
       
  1316 @leave KErrDiskFull The disk does not have enough free space to perform the
       
  1317 operation.
       
  1318 
       
  1319 @capability ReadUserData
       
  1320 @capability WriteUserData
       
  1321 */
       
  1322 void RCntModel::SetFieldAsSpeedDialL(TContactItemId aContactId, TInt aFieldIndex, TInt aSpeedDialPosition)
       
  1323 	{
       
  1324 	__ASSERT_ALWAYS(aSpeedDialPosition >= KCntMinSpeedDialIndex && aSpeedDialPosition <= KCntMaxSpeedDialIndex , User::Leave(KErrArgument));
       
  1325 	TIpcArgs args(aSpeedDialPosition, aContactId, aFieldIndex);
       
  1326 	User::LeaveIfError(SendReceive(ECntSetSpeedDialIdForPosition, args));
       
  1327 	}
       
  1328 
       
  1329 
       
  1330 /** 
       
  1331 Removes the mapping between a contact item field and a speed dial position.
       
  1332 
       
  1333 Removes the KUidSpeedDialXxx UID from the field's content type, removes the 
       
  1334 field's speed dial attribute and commits the changes to the item.
       
  1335 
       
  1336 @param aContactId The ID of the contact item containing the speed dial field.
       
  1337 @param aSpeedDialPosition The speed dial position.  This is an integer in the 
       
  1338 range 1 to 9 inclusive.  If outside this range, the function leaves with
       
  1339 KErrArgument. 
       
  1340 
       
  1341 @leave KErrDiskFull The disk does not have enough free space to perform the operation.
       
  1342 
       
  1343 @capability ReadUserData
       
  1344 @capability WriteUserData
       
  1345 */
       
  1346 void RCntModel::RemoveSpeedDialFieldL(TContactItemId aContactId, TInt aSpeedDialPosition)
       
  1347 	{
       
  1348 	__ASSERT_ALWAYS(aSpeedDialPosition >= KCntMinSpeedDialIndex && aSpeedDialPosition <= KCntMaxSpeedDialIndex , User::Leave(KErrArgument));
       
  1349 	// Tell the server that this speed dial slot is now free.  Third argument
       
  1350 	// (i.e. field index) is not used.
       
  1351 	TIpcArgs args(aSpeedDialPosition, aContactId, -1);
       
  1352 	User::LeaveIfError(SendReceive(ECntSetSpeedDialIdForPosition, args));		
       
  1353 	}
       
  1354 
       
  1355 
       
  1356 /**
       
  1357 Returns the ID of the template that should be used with CContactICCEntry items.
       
  1358 If aPhonebookUid is set, the ID of the template belonging to the phonebook with 
       
  1359 TUid aPhonebookUid is returned.
       
  1360 
       
  1361 @param aPhonebookUid The phonebook ID with default KNullUid.
       
  1362 
       
  1363 @return A template ID.
       
  1364 */
       
  1365 TContactItemId RCntModel::ICCTemplateIdL(TUid aPhonebookUid)
       
  1366 	{
       
  1367 	TIpcArgs args(aPhonebookUid.iUid);
       
  1368 	return SendReceive(ECntICCTemplateId, args);
       
  1369 	}
       
  1370 
       
  1371 
       
  1372 /**
       
  1373 Returns the ID of the contacts model group which represents the ADN phonebook.
       
  1374 
       
  1375 @return ADN phonebook group ID.
       
  1376 */ 
       
  1377 TContactItemId RCntModel::PhonebookGroupIdL()
       
  1378 	{
       
  1379 	return SendReceive(ECntPhonebookGroupId);
       
  1380 	}
       
  1381 
       
  1382 
       
  1383 /** 
       
  1384 Sets an existing contact item to be the database's current own card.
       
  1385 
       
  1386 @param aContact The contact item to set as the database's current own card. 
       
  1387 It must already exist in the database.  It cannot be a group or a template.
       
  1388 
       
  1389 @leave KErrNotFound aContact does not exist in the database. 
       
  1390 @leave KErrDiskFull The disk does not have enough free space to perform the
       
  1391 operation.
       
  1392 
       
  1393 @capability None
       
  1394 */
       
  1395 void RCntModel::SetOwnCardL(const CContactItem& aContact)
       
  1396 	{
       
  1397 	TIpcArgs args; 
       
  1398 	TPtr8 ptr(iPackager->PackL(aContact));
       
  1399 	args.Set(0,&ptr);
       
  1400 	User::LeaveIfError(SendReceive(ECntSetOwnCard, args));	
       
  1401 	}
       
  1402 
       
  1403 
       
  1404 /**
       
  1405 Returns the ID of the database's current own card. 
       
  1406 
       
  1407 Having obtained this ID, the client may then open the own card in the same 
       
  1408 way as an ordinary contact card (using ReadContactL() or OpenContactL()).
       
  1409 
       
  1410 @return The ID of the database's current own card.  KNullContactId if the own 
       
  1411 card has been deleted or has not yet been set.
       
  1412 */
       
  1413 TContactItemId RCntModel::OwnCard() const
       
  1414 	{
       
  1415 	return static_cast<TContactItemId>(SendReceive(ECntGetOwnCard));
       
  1416 	}
       
  1417 
       
  1418 	
       
  1419 /**
       
  1420 Returns the connection ID of the current client session.
       
  1421 
       
  1422 @return Connection ID of the current client session.
       
  1423 */
       
  1424 TInt RCntModel::ConnectionId() const
       
  1425 	{
       
  1426 	// If asking for the connection ID the first time, then we ask the server
       
  1427 	// about the session id (lazy initialisation).
       
  1428 	if (!iConnectionId)
       
  1429 		{
       
  1430 		iConnectionId = SendReceive(ECntConnectionId); 	
       
  1431 		}
       
  1432 	return iConnectionId;		
       
  1433 	}
       
  1434 
       
  1435 
       
  1436 /** 
       
  1437 Debug only.
       
  1438 
       
  1439 @capability None
       
  1440 */
       
  1441 void RCntModel::SetHeapFailure(RHeap::TAllocFail aType, TInt aRate)
       
  1442 	{	
       
  1443 	TIpcArgs args(aType,aRate);
       
  1444 	SendReceive(ECntSetHeapFailure,args);
       
  1445 	}
       
  1446 
       
  1447 	
       
  1448 /** 
       
  1449 Debug only.
       
  1450 
       
  1451 @return The heap size usage of the server in debug mode, 0 in release mode.
       
  1452 
       
  1453 @capability None
       
  1454 */
       
  1455 TInt RCntModel::ResourceCount()
       
  1456 	{
       
  1457 	return(SendReceive(ECntResourceCount));
       
  1458 	}	
       
  1459 
       
  1460 	
       
  1461 /**
       
  1462 Returns the ID of the database's preferred template, as set by the method
       
  1463 SetPrefTemplateL().  The preferred template is for clients who may have 
       
  1464 multiple templates but want to identify one as preferred.
       
  1465 
       
  1466 @return The ID of the database's current preferred template.  KNullContactId if
       
  1467 not set.
       
  1468 */
       
  1469 TContactItemId RCntModel::PrefTemplateId() const
       
  1470 	{
       
  1471 	return(SendReceive(ECntGetPrefTemplateId));	
       
  1472 	}
       
  1473 
       
  1474 
       
  1475 /** 
       
  1476 Sets the database's preferred template.
       
  1477 
       
  1478 The preferred template's ID persists when the database is opened and closed. 
       
  1479 If the preferred template is subsequently deleted, the preferred template 
       
  1480 ID is set to KNullContactId.
       
  1481 
       
  1482 @param aContact The contact card template to set as the database's preferred 
       
  1483 template.
       
  1484 
       
  1485 @leave KErrNotSupported The item is not a template (i.e. is not of type
       
  1486 KUidContactCardTemplate).
       
  1487 @leave KErrDiskFull The disk does not have enough free space to perform the
       
  1488 operation.
       
  1489 
       
  1490 @capability WriteUserData
       
  1491 */
       
  1492 void RCntModel::SetPrefTemplateL(const TContactItemId aContactId)
       
  1493 	{
       
  1494 	TIpcArgs args(aContactId);
       
  1495 	User::LeaveIfError(SendReceive(ECntSetPrefTemplateId, args));
       
  1496 	}
       
  1497 
       
  1498 	
       
  1499 /**
       
  1500 Get a list of template IDs from the server.
       
  1501 
       
  1502 @return Array of template IDs.
       
  1503 */
       
  1504 CContactIdArray* RCntModel::FetchTemplateListIdsL()
       
  1505 {
       
  1506 	TIpcArgs args;
       
  1507 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1508 
       
  1509 	TInt newBuffSize;
       
  1510 	User::LeaveIfError(newBuffSize = SendReceive(ECntFetchTemplateIds, args));
       
  1511 	if (newBuffSize > 0)
       
  1512 		{
       
  1513 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1514 		User::LeaveIfError(newBuffSize = SendReceive(ECntFetchTemplateIds, args));		
       
  1515 		}
       
  1516 
       
  1517 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1518 	CleanupStack::Pop(idArray);
       
  1519 
       
  1520 	return idArray;	
       
  1521 }
       
  1522 
       
  1523 
       
  1524 /**
       
  1525 Get a list of group IDs from the server.
       
  1526 
       
  1527 @return Array of group IDs.
       
  1528 */
       
  1529 CContactIdArray* RCntModel::FetchGroupListIdsL()
       
  1530 {
       
  1531 	TIpcArgs args;
       
  1532 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1533 
       
  1534 	TInt newBuffSize;
       
  1535 	User::LeaveIfError(newBuffSize = SendReceive(ECntFetchGroupIdLists, args));
       
  1536 	if (newBuffSize > 0)
       
  1537 		{
       
  1538 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1539 		User::LeaveIfError(newBuffSize = SendReceive(ECntFetchGroupIdLists, args));		
       
  1540 		}
       
  1541 
       
  1542 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1543 	CleanupStack::Pop(idArray);
       
  1544 
       
  1545 	return idArray;	
       
  1546 }
       
  1547 
       
  1548 /**
       
  1549 Get a collection of contact IDs using the specified collection parameters.
       
  1550 
       
  1551 @param aCollectionType Type of collection.
       
  1552 @param aTime Used if collection type is "changed since".
       
  1553 @param aGuid Used if collection type is "find GUID".
       
  1554 
       
  1555 @return Contact ID array of those contacts which match the specified collection
       
  1556 parameters.
       
  1557 */
       
  1558 CContactIdArray* RCntModel::CollectionL(TInt aCollectionType, TTime aTime,const TDesC& aGuid)
       
  1559 	{
       
  1560 	CContactIdArray* idArray = NULL;
       
  1561 	switch(aCollectionType)
       
  1562 	{
       
  1563 	case MLplCollection::EChangedSince :		
       
  1564 		{
       
  1565 		idArray = DoGetCollectionChangedSinceL(aTime);
       
  1566 		}
       
  1567 		break;
       
  1568 	case MLplCollection::EDeleted :
       
  1569 	case MLplCollection::EUnfiled :
       
  1570 		{
       
  1571 		idArray = DoGetCollectionL(aCollectionType);
       
  1572 		}
       
  1573 		break;
       
  1574 	case MLplCollection::EFindGuid :
       
  1575 		{
       
  1576 		idArray = DoGetCollectionGuidL(aGuid);
       
  1577 		}
       
  1578 		break;
       
  1579 	default:
       
  1580 		{
       
  1581 		User::Leave(KErrNotFound);
       
  1582 		}
       
  1583 		break;
       
  1584 	}	
       
  1585 	return idArray;
       
  1586 	}
       
  1587 
       
  1588 
       
  1589 /**
       
  1590 Get a collection of contact IDs which have changed since the given time.
       
  1591 
       
  1592 @param aTime Changed since time.
       
  1593 
       
  1594 @return Contact ID array of those contacts which have changed since the given
       
  1595 time.
       
  1596 */
       
  1597 CContactIdArray* RCntModel::DoGetCollectionChangedSinceL(TTime aTime)
       
  1598 	{
       
  1599 	TIpcArgs args;
       
  1600 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1601 	args.Set(1,MLplCollection::EChangedSince);
       
  1602 	TPckgBuf<TTime> pckg(aTime);
       
  1603 	args.Set(2,&pckg);
       
  1604 
       
  1605 	TInt newBuffSize;
       
  1606 	User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));
       
  1607 	if (newBuffSize > 0)
       
  1608 		{
       
  1609 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1610 		User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));		
       
  1611 		}
       
  1612 
       
  1613 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1614 	CleanupStack::Pop(idArray);
       
  1615 
       
  1616 	return idArray;
       
  1617 	}
       
  1618 
       
  1619 	
       
  1620 /**
       
  1621 Get a collection of contact IDs for the given collection type.
       
  1622 
       
  1623 @param aCollectionType Collection type.
       
  1624 
       
  1625 @return Contact ID array of those contacts which meet the given collection type
       
  1626 criteria.
       
  1627 */
       
  1628 CContactIdArray* RCntModel::DoGetCollectionL(TInt aCollectionType)
       
  1629 	{
       
  1630 	TIpcArgs args;
       
  1631 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1632 	args.Set(1,aCollectionType);
       
  1633 
       
  1634 	TInt newBuffSize;
       
  1635 	User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));
       
  1636 	if (newBuffSize > 0)
       
  1637 		{
       
  1638 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1639 		User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));		
       
  1640 		}
       
  1641 
       
  1642 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1643 	CleanupStack::Pop(idArray);
       
  1644 
       
  1645 	return idArray;
       
  1646 	}
       
  1647 
       
  1648 
       
  1649 /**
       
  1650 Get a collection of contact IDs which have the given GUID.  Since GUIDs are
       
  1651 unique (i.e. no two contacts can have the same GUID) there will only ever be
       
  1652 one contact ID in this collection.
       
  1653 
       
  1654 @param aGuid Contact GUID.
       
  1655 
       
  1656 @return Contact ID array containing the contact with the given GUID.
       
  1657 */
       
  1658 CContactIdArray* RCntModel::DoGetCollectionGuidL(const TDesC& aGuid)
       
  1659 	{
       
  1660 	TIpcArgs args;
       
  1661 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1662 	args.Set(1,MLplCollection::EFindGuid);
       
  1663 	args.Set(2,&aGuid);
       
  1664 
       
  1665 	TInt newBuffSize;
       
  1666 	User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));
       
  1667 	if (newBuffSize > 0)
       
  1668 		{
       
  1669 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1670 		User::LeaveIfError(newBuffSize = SendReceive(ECntGetCollection, args));		
       
  1671 		}
       
  1672 
       
  1673 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1674 	CleanupStack::Pop(idArray);
       
  1675 
       
  1676 	return idArray;
       
  1677 	}
       
  1678 
       
  1679 
       
  1680 /**
       
  1681 Set the sort preferences in the server.
       
  1682 
       
  1683 @param aSortOrder Sort order preferences.
       
  1684 */
       
  1685 void RCntModel::SetSortPreferenceL(const CArrayFix<CContactDatabase::TSortPref>& aSortOrder)
       
  1686 	{
       
  1687 	TPtr8 ptr(iPackager->PackL(aSortOrder));
       
  1688 	TIpcArgs args;
       
  1689 	args.Set(0,&ptr);
       
  1690 	User::LeaveIfError(SendReceive(ECntSetSortPrefs,args));	
       
  1691 	}
       
  1692 
       
  1693 
       
  1694 /**
       
  1695 Get the sort preferences from the server.
       
  1696 
       
  1697 @return Sort order preferences.
       
  1698 */
       
  1699 CArrayFix<CContactDatabase::TSortPref>* RCntModel::GetSortPreferenceL() const
       
  1700 	{
       
  1701 	TIpcArgs args;
       
  1702 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1703 
       
  1704 	TInt newBuffSize;
       
  1705 	User::LeaveIfError(newBuffSize = SendReceive(ECntGetSortPrefs, args));
       
  1706 	if (newBuffSize > 0)
       
  1707 		{
       
  1708 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1709 		User::LeaveIfError(newBuffSize = SendReceive(ECntGetSortPrefs, args));		
       
  1710 		}
       
  1711 
       
  1712 	CArrayFix<CContactDatabase::TSortPref>* prefs = iPackager->UnpackCArrayFixLC();	
       
  1713 	CleanupStack::Pop(prefs);
       
  1714 
       
  1715 	return prefs;
       
  1716 	}
       
  1717 
       
  1718 
       
  1719 /**
       
  1720 Get the number of contacts in the database.
       
  1721 
       
  1722 @return Number of contacts in the database if successful, otherwise it leaves.
       
  1723 */
       
  1724 TInt RCntModel::ContactCountL() const
       
  1725 	{
       
  1726     TInt numContacts = SendReceive( ECntDbContactCount );
       
  1727     User::LeaveIfError( numContacts );
       
  1728     return numContacts;
       
  1729 	}
       
  1730 
       
  1731 /**
       
  1732 Seek to the given contact ID.
       
  1733 
       
  1734 @param aContactId Contact ID to seek to.
       
  1735 @param aId On return the contact ID that the seek found.  This will be the
       
  1736 nearest contact ID if the given aContactID cannot be found.
       
  1737 @param aContactType On return the contact type of the contact that the seek
       
  1738 found.
       
  1739 @param aDeleted On return ETrue if the contact that the seek found is marked as
       
  1740 deleted, EFalse otherwise.
       
  1741 
       
  1742 @return ETrue if the seek was successful, EFalse otherwise.
       
  1743 */
       
  1744 TBool RCntModel::SeekContactL(TContactItemId aContactId,TContactItemId& aId,TUid& aContactType, TBool& aDeleted)
       
  1745     {
       
  1746     TPckgBuf<TInt> id;
       
  1747     TPckgBuf<TUid> type;
       
  1748     TPckgBuf<TBool> deleted;
       
  1749     TIpcArgs args(aContactId,&id,&type,&deleted);
       
  1750     TInt ret = SendReceive(ECntSeekContactInCollection,args);
       
  1751 
       
  1752     // Although ECntSeekContact/ECntSeekContactInCollection is normally completed
       
  1753     // with TBool values, ServiceError() can occur which leads to a negative system
       
  1754     // error codes being returned.  User::LeaveIfError will allow that to be properly
       
  1755     // handled.
       
  1756     User::LeaveIfError(ret);
       
  1757 
       
  1758     if(ret)
       
  1759         {
       
  1760         aContactType = type();
       
  1761         aId = id();
       
  1762         aDeleted = deleted();
       
  1763         return ETrue;
       
  1764         }
       
  1765     else
       
  1766         {
       
  1767         return EFalse;
       
  1768         }
       
  1769     }
       
  1770 
       
  1771 
       
  1772 void RCntModel::TextFieldL(TInt aCntItemId,TFieldType aFieldType, TDes& aText)
       
  1773 	{
       
  1774 	TPckgBuf<TFieldType> fieldType(aFieldType);
       
  1775 	TIpcArgs args(aCntItemId,&fieldType,&aText);
       
  1776 	User::LeaveIfError(SendReceive(ECntTextField,args));
       
  1777 	}
       
  1778 
       
  1779 
       
  1780 void RCntModel::ReadContactTextDefL(TContactItemId aContactId, TDes &aResult,const CContactTextDef& aTextDef)
       
  1781 	{
       
  1782 	iPackager->PackL( const_cast<CContactTextDef&>(aTextDef));
       
  1783 	TIpcArgs args(&iPackager->GetTransmittingBuffer(), &aResult,aContactId);
       
  1784 	User::LeaveIfError(SendReceive(ECntReadContactTextDef, args));
       
  1785 	}
       
  1786 
       
  1787 
       
  1788 CContactIdArray* RCntModel::FindL(const TDesC& aText,const CContactItemFieldDef* aFieldDef)
       
  1789 	{
       
  1790 	TIpcArgs args;
       
  1791 
       
  1792 	// Parameter can be NULL so send down an empty descriptor to the server.
       
  1793 	// Server can detect this and pass NULL parameter to the Persistence Layer
       
  1794 	// FindL() method.
       
  1795 	if(aFieldDef != NULL)
       
  1796 		{
       
  1797 		// Packager's sending buffer in slot 1 (contains packed field
       
  1798 		// definition).
       
  1799 		iPackager->PackL(*aFieldDef);
       
  1800 		args.Set(1,&iPackager->GetTransmittingBuffer());
       
  1801 		}
       
  1802 	else
       
  1803 		{
       
  1804 		// Frigged NULL.
       
  1805 		args.Set(1,&KNullDesC);
       
  1806 		}
       
  1807 
       
  1808 	// Packager's receiving buffer in slot 0.
       
  1809 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1810 
       
  1811 	// Text in slot 2.
       
  1812 	args.Set(2,&aText);
       
  1813 
       
  1814 	// Ensure receiving buffer is big enough.
       
  1815 	TInt newBuffSize;
       
  1816 	User::LeaveIfError(newBuffSize = SendReceive(ECntFind, args));
       
  1817 	if (newBuffSize > 0)
       
  1818 		{
       
  1819 		// Not big enough so resize and call again.
       
  1820 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  1821 		User::LeaveIfError(newBuffSize = SendReceive(ECntFind, args));
       
  1822 		}
       
  1823 
       
  1824 	CContactIdArray* idArray = iPackager->UnpackCntIdArrayLC();	
       
  1825 	CleanupStack::Pop(idArray);
       
  1826 
       
  1827 	return idArray;	
       
  1828 	}
       
  1829 
       
  1830 
       
  1831 void RCntModel::SetDbViewContactType(const TUid aUid)
       
  1832 	{
       
  1833 	TIpcArgs args(aUid.iUid);
       
  1834 	(void)SendReceive(ECntSetDbViewContactType,args);
       
  1835 	}
       
  1836 
       
  1837 
       
  1838 TUid RCntModel::GetDbViewContactType() const
       
  1839 	{
       
  1840 	TPckgBuf<TUid> type;
       
  1841 	TIpcArgs args(&type);
       
  1842 	(void)SendReceive(ECntSetDbViewContactType,args);
       
  1843 	return type();	
       
  1844 	}
       
  1845 
       
  1846 
       
  1847 /**
       
  1848 Initialise the Persistence Layer collection class ready for iterative calls to
       
  1849 the FindAsyncL() method.  This form of initialisation is for an asynchronous
       
  1850 find which uses a text definition and an array of "find words".
       
  1851 
       
  1852 @param aWords "Find words" array.
       
  1853 @param aTextDef Text definition to use in find.
       
  1854 */
       
  1855 void RCntModel::FindAsyncTextDefInitL(const CDesCArray& aWords,CContactTextDef* aTextDef)
       
  1856 	{
       
  1857 	TIpcArgs args;
       
  1858 	if(aTextDef != NULL)
       
  1859 		{
       
  1860 		// Pack the text definition.
       
  1861 		iPackager->PackL(*aTextDef);
       
  1862 		args.Set(1,&iPackager->GetTransmittingBuffer());
       
  1863 		}
       
  1864 	else
       
  1865 		{
       
  1866 		// No user supplied text definition.
       
  1867 		args.Set(1, &KNullDesC);
       
  1868 		}
       
  1869 	
       
  1870 	// Do the CDesCArray manually as Packager can't do both.
       
  1871 	RBufWriteStream writeStream;
       
  1872 	CBufFlat* buf = CBufFlat::NewL(1 << 8);
       
  1873 	CleanupStack::PushL(buf);
       
  1874 
       
  1875 	writeStream.Open(*buf);
       
  1876 	TInt count = aWords.Count();
       
  1877 	writeStream.WriteInt32L(count);	
       
  1878 	TInt length = 0;
       
  1879 	for(TInt i=0; i<count;++i)
       
  1880 		{
       
  1881 		length = aWords[i].Length();
       
  1882 		writeStream.WriteInt32L(length);		
       
  1883 		writeStream.WriteL(aWords[i],length);
       
  1884 		}
       
  1885 	writeStream.CommitL();
       
  1886 	writeStream.Close();
       
  1887 
       
  1888 	TPtr8 ptr8(buf->Ptr(0));
       
  1889 	args.Set(0,&ptr8);
       
  1890 
       
  1891 	User::LeaveIfError(SendReceive(ECntFindAsyncTextDefInit,args));
       
  1892 
       
  1893 	CleanupStack::PopAndDestroy(buf);
       
  1894 	}
       
  1895 
       
  1896 
       
  1897 /**
       
  1898 Initialise the Persistence Layer collection class ready for iterative calls to
       
  1899 the FindAsyncL() method.  This form of initialisation is for an asynchronous
       
  1900 find which uses text and a field definition.
       
  1901 
       
  1902 @param aText Find text.
       
  1903 @param aFieldDef Field definition to use in find.
       
  1904 */
       
  1905 void RCntModel::FindAsyncInitL(const TDesC& aText,CContactItemFieldDef* aFieldDef)
       
  1906 	{
       
  1907 	TIpcArgs args;
       
  1908 	args.Set(0,&aText);
       
  1909 	if(aFieldDef != NULL)
       
  1910 		{
       
  1911 		// Pack the field definition.
       
  1912 		iPackager->PackL(*aFieldDef);
       
  1913 		args.Set(1,&iPackager->GetTransmittingBuffer());
       
  1914 		}
       
  1915 	else
       
  1916 		{
       
  1917 		// No user supplied field definition.
       
  1918 		args.Set(1, &KNullDesC);
       
  1919 		}
       
  1920 
       
  1921 	User::LeaveIfError(SendReceive(ECntFindAsyncInit,args));
       
  1922 	}
       
  1923 
       
  1924 
       
  1925 /**
       
  1926 Perform an asynchronous find iteration.  Either the FindAsyncTextDefInitL() or
       
  1927 the FindAsyncInitL() method above must have first been called.
       
  1928 
       
  1929 @param aOrigIdArray Set of contacts IDs from previous calls to FindAsyncL().
       
  1930 Will be NULL if this is the first iteration.
       
  1931 
       
  1932 @return ETrue if further find iterations are required, EFalse otherwise.
       
  1933 */
       
  1934 TBool RCntModel::FindAsyncL(CContactIdArray*& aOrigIdArray)
       
  1935 	{
       
  1936 	TBool moreToGo;
       
  1937 	TPckg<TBool> pckg(moreToGo);
       
  1938 	// Iterations can't fail so expand buffer to 4Kb.  4096 contacts should be
       
  1939 	// enough.  Rather than this brutal approach we could call ContactCountL()
       
  1940 	// and add a contingency in case another client adds some.
       
  1941 	TIpcArgs args(&iPackager->GetReceivingBufferL(4096),&pckg);
       
  1942 
       
  1943 	User::LeaveIfError(SendReceive(ECntFindAsync,args));
       
  1944 
       
  1945 	CContactIdArray* newIdArray = iPackager->UnpackCntIdArrayLC();	
       
  1946 	if(aOrigIdArray != NULL)
       
  1947 		{
       
  1948 		// Append to the old array if it was not NULL.
       
  1949 		for(TInt i=0;i<newIdArray->Count();++i)
       
  1950 			{
       
  1951 			aOrigIdArray->AddL((*newIdArray)[i]);
       
  1952 			}
       
  1953 		CleanupStack::PopAndDestroy(newIdArray);
       
  1954 		}
       
  1955 	else
       
  1956 		{
       
  1957 		CleanupStack::Pop(newIdArray);
       
  1958 		aOrigIdArray = newIdArray;
       
  1959 		}
       
  1960 
       
  1961 	return pckg();
       
  1962 	}
       
  1963 
       
  1964 
       
  1965 /**
       
  1966 Set the asynchronous activity flag in the server.  Any asynchronous activity
       
  1967 such as asynchronous find or asynchronous sort prevent the database from
       
  1968 being closed and should set this flag.  When all asynchronous activites are
       
  1969 finished this flag should be cleared.
       
  1970 
       
  1971 @capability None
       
  1972 
       
  1973 @param aAsyncActivity ETrue if at least one asynchronous activity, EFalse if
       
  1974 no asynchronous activities.
       
  1975 */
       
  1976 void RCntModel::SetAsyncActivityL(TBool aAsyncActivity)
       
  1977 	{
       
  1978 	TIpcArgs args;
       
  1979 	args.Set(0,aAsyncActivity);
       
  1980 	User::LeaveIfError(SendReceive(ECntSetAsyncActivity,args));
       
  1981 	}
       
  1982 
       
  1983 
       
  1984 /**
       
  1985 Filter the database using the given filter.
       
  1986 
       
  1987 @param aFilter Filter to use.  On return the contact IDs in this filter will be
       
  1988 augmented with those contact IDs which match the given filter.
       
  1989 */
       
  1990 void RCntModel::FilterDatabaseL(CCntFilter& aFilter)
       
  1991 	{
       
  1992 	CContactIdArray* origIdArray = aFilter.iIds;
       
  1993 	aFilter.iIds = NULL;
       
  1994 
       
  1995 	TIpcArgs args;
       
  1996 	iPackager->PackL(aFilter);
       
  1997 	args.Set(1,&iPackager->GetTransmittingBuffer());	
       
  1998 	args.Set(0, &iPackager->GetReceivingBufferL());
       
  1999 
       
  2000 	TInt newBuffSize(0);
       
  2001 	User::LeaveIfError(newBuffSize = SendReceive(ECntFilterDatabase, args));
       
  2002 	if (newBuffSize > 0)
       
  2003 		{
       
  2004 		// Not big enough so resize and call again.
       
  2005 		args.Set(0, &iPackager->GetReceivingBufferL(newBuffSize));
       
  2006 		User::LeaveIfError(newBuffSize = SendReceive(ECntFilterDatabase, args));
       
  2007 		}
       
  2008 	
       
  2009 	CContactIdArray* newIdArray = iPackager->UnpackCntIdArrayLC();
       
  2010 	if(origIdArray != NULL)
       
  2011 		{
       
  2012 		for(TInt i=0;i<newIdArray->Count();++i)
       
  2013 			{
       
  2014 			origIdArray->AddL((*newIdArray)[i]);
       
  2015 			}
       
  2016 		aFilter.iIds = origIdArray;
       
  2017 		CleanupStack::PopAndDestroy(newIdArray);
       
  2018 		}
       
  2019 	else
       
  2020 		{
       
  2021 		CleanupStack::Pop(newIdArray);
       
  2022 		aFilter.iIds = newIdArray;
       
  2023 		}
       
  2024 	}
       
  2025 
       
  2026 	
       
  2027 TInt RCntModel::OpenViewL(const CContactTextDef& aTextDef, const TInt aViewPrefs)
       
  2028 	{
       
  2029 	TPckgBuf<TInt> viewSessionId;
       
  2030 	iPackager->PackL(const_cast<CContactTextDef&>(aTextDef));
       
  2031 	TIpcArgs args(&iPackager->GetTransmittingBuffer(), aViewPrefs, &viewSessionId);
       
  2032 	
       
  2033 	TInt ret = SendReceive(ECntOpenViewSession,args);
       
  2034 	User::LeaveIfError(ret);
       
  2035 	
       
  2036 	return 	viewSessionId();
       
  2037 	}
       
  2038 	
       
  2039 	
       
  2040 void RCntModel::CloseView(TInt aViewId)
       
  2041 	{
       
  2042 	TIpcArgs args(aViewId);
       
  2043 	SendReceive(ECntCloseViewSession,args);
       
  2044 	}
       
  2045 	
       
  2046 	
       
  2047 void RCntModel::ChangeSortOrderL(TInt aViewId, const CContactTextDef& aTextDef)
       
  2048 	{
       
  2049 	// Serialize the text def using packager overload.
       
  2050 	iPackager->PackL( const_cast<CContactTextDef&>(aTextDef));
       
  2051 	
       
  2052 
       
  2053 	TIpcArgs args(aViewId, &iPackager->GetTransmittingBuffer());
       
  2054 	TInt ret = SendReceive(ECntViewChangeSortOrderL, args);
       
  2055 	
       
  2056 	User::LeaveIfError(ret);
       
  2057 	}
       
  2058 	
       
  2059 	
       
  2060 void RCntModel::BeginIterateL(TInt aViewId)
       
  2061 	{
       
  2062 	TIpcArgs args(aViewId);
       
  2063 	TInt ret = SendReceive(ECntViewBeginIterate,args);
       
  2064 	User::LeaveIfError(ret);
       
  2065 	}
       
  2066 	
       
  2067 	
       
  2068 void RCntModel::EndIterateL(TInt aViewId)
       
  2069 	{
       
  2070 	TIpcArgs args(aViewId);
       
  2071 	TInt ret = SendReceive(ECntViewEndIterate,args);
       
  2072 	User::LeaveIfError(ret);
       
  2073 	}
       
  2074 	
       
  2075 	
       
  2076 CViewContact* RCntModel::NextItemL(TInt aViewId, const TInt aViewPrefs)
       
  2077 	{
       
  2078 	TIpcArgs args(aViewId, aViewPrefs, &iPackager->GetReceivingBufferL());
       
  2079 	TInt size = SendReceive(ECntViewNextItemL, args);
       
  2080 
       
  2081 	// KErrNotFound is returned if Persistence Layer view item manager 
       
  2082 	// can't reach end of the contacts.
       
  2083 	if(size == KErrNotFound)
       
  2084 		{
       
  2085 		// Not an error just no match.
       
  2086 		return NULL;
       
  2087 		}
       
  2088 
       
  2089 	// Leave on genuine errors.
       
  2090 	User::LeaveIfError(size);
       
  2091 
       
  2092 	if(size != 0) // Server session requires larger packager buffer.
       
  2093 		{
       
  2094 		// Increase the buffer size and call again.  Just in case some other
       
  2095 		// client has deleted in between calls do the KErrNotFound check.
       
  2096 		TIpcArgs args(aViewId, aViewPrefs, &iPackager->GetReceivingBufferL(size));
       
  2097 		TInt ret = SendReceive(ECntViewNextItemL, args);
       
  2098 		if(ret == KErrNotFound)
       
  2099 			{
       
  2100 			return NULL;
       
  2101 			}
       
  2102 		// Leave on genuine errors
       
  2103 		User::LeaveIfError(ret);
       
  2104 		}
       
  2105 
       
  2106 	// Got it so unpack and return.
       
  2107 	CViewContact* viewContact = iPackager->UnpackViewContactLC();
       
  2108 
       
  2109 	CleanupStack::Pop(viewContact);
       
  2110 
       
  2111 	return viewContact;
       
  2112 	}
       
  2113 
       
  2114 	
       
  2115 CViewContact* RCntModel::ItemAtL(TContactItemId aContactId, TInt aViewId)
       
  2116 	{
       
  2117 	TIpcArgs args(aContactId, aViewId, &iPackager->GetReceivingBufferL());
       
  2118 	TInt size = SendReceive(ECntItemAtL, args);
       
  2119 
       
  2120 	// KErrNotFound is returned if Persistence Layer view item manager cannot 
       
  2121 	// find the view contact by given aContactId.
       
  2122 	if(size == KErrNotFound)
       
  2123 		{
       
  2124 		// Not an error just no match.
       
  2125 		return NULL;
       
  2126 		}
       
  2127 
       
  2128 	// Leave on genuine errors.
       
  2129 	User::LeaveIfError(size);
       
  2130 
       
  2131 	if(size != 0) // Server session requires larger packager buffer.
       
  2132 		{
       
  2133 		// Increase the buffer size and call again.  Just in case some other
       
  2134 		// client has deleted in between calls do the KErrNotFound check.
       
  2135 		TIpcArgs args(aContactId, aViewId, &iPackager->GetReceivingBufferL(size));
       
  2136 		TInt ret = SendReceive(ECntItemAtL, args);
       
  2137 		if(ret == KErrNotFound)
       
  2138 			{
       
  2139 			return NULL;
       
  2140 			}
       
  2141 		// Leave on genuine errors
       
  2142 		User::LeaveIfError(ret);
       
  2143 		}
       
  2144 
       
  2145 	// Got it so unpack and return.
       
  2146 	CViewContact* viewContact = iPackager->UnpackViewContactLC();
       
  2147 
       
  2148 	CleanupStack::Pop(viewContact);
       
  2149 
       
  2150 	return viewContact;
       
  2151 	}
       
  2152 	
       
  2153 
       
  2154 #if defined(_DEBUG)	
       
  2155 void RCntModel::GetDefinitionsOfExistingViewsL(const TDesC& aDbName, RPointerArray<CContactDefaultViewDefinition>& aViewDefs)
       
  2156 	{
       
  2157 	RBuf8 buf;
       
  2158 	CleanupClosePushL(buf);
       
  2159 	buf.Create(256);
       
  2160 	TIpcArgs args(&aDbName, &buf);
       
  2161 
       
  2162 	TInt newBufSize;
       
  2163 	User::LeaveIfError(newBufSize = SendReceive(ECntGetDefinitionsForExistingView, args));
       
  2164 	if (newBufSize > 0)
       
  2165 		{
       
  2166 		buf.ReAllocL(newBufSize);
       
  2167 		args.Set(1, &buf);
       
  2168 		User::LeaveIfError(newBufSize = SendReceive(ECntGetDefinitionsForExistingView, args));		
       
  2169 		}
       
  2170 
       
  2171 	RDesReadStream readStream(buf);
       
  2172 	CleanupClosePushL(readStream);
       
  2173 	TInt32 count;
       
  2174 	readStream >> count;
       
  2175 	CContactDefaultViewDefinition* view;
       
  2176 	for (TInt i = 0; i < count; i++)
       
  2177 		{
       
  2178 		view = CContactDefaultViewDefinition::NewLC(readStream);
       
  2179 		aViewDefs.AppendL(view);
       
  2180 		CleanupStack::Pop(view);
       
  2181 		}
       
  2182 		
       
  2183 	CleanupStack::PopAndDestroy(2); // readStream, buf	
       
  2184 	}
       
  2185 #else
       
  2186 void RCntModel::GetDefinitionsOfExistingViewsL(const TDesC& /*aDbName*/, RPointerArray<CContactDefaultViewDefinition>& /*aViewDefs*/)
       
  2187 	{	
       
  2188 	}
       
  2189 #endif // _DEBUG