--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/contacts/symbian/contactsmodel/cntmodel/src/ccontactdatabase.cpp Wed Aug 25 15:49:42 2010 +0300
@@ -0,0 +1,5240 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <cntitem.h>
+#include <f32file.h>
+#include <cntfldst.h> //for ccontactfieldstorage used in setfieldasspeeddiall
+#include <phbksync.h>
+#include <cntdb.h>
+
+#include "cntstd.h"
+#include "rcntmodel.h"
+#include "ccontactprivate.h"
+
+#include "clplproxyfactory.h"
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "cntdb_internal.h"
+#include "cntsyncecom.h"
+
+const TInt KMajorVersion=1;
+
+const TInt KMinorVersion=0;
+
+const TInt KBuildNumber=40;
+#endif
+
+CContactDatabase::CContactDatabase():
+ iDbConnectionState(EDbConnectionNotReady),
+ iTablesOpen(EFalse),
+ iDbViewContactType(KUidContactItem),
+ iContactSynchroniser(NULL)
+ {
+ // Needed to ensure unicode sorting / inserting into sorted lists works the
+ // same as er5 i.e. that it encludes all spaces and punctuation.
+ iCollateMethod = *Mem::CollationMethodByIndex(0);
+ iCollateMethod.iFlags|=TCollationMethod::EIgnoreNone;
+ }
+
+
+/**
+Frees all resources owned by the contact database, prior to its destruction.
+*/
+EXPORT_C CContactDatabase::~CContactDatabase()
+ {
+ delete iConv;
+ delete iProxyFactory;
+ delete iView;
+ delete iAllFieldsView;
+ delete iCardTemplateIds;
+ delete iGroupIds;
+ delete iTemplateCache;
+ delete iTextDef;
+ if (iCntSvr)
+ {
+ iCntSvr->RemoveObserver(*iDataBaseObserver);
+ iCntSvr->Close();
+ }
+ if (iContactSynchroniser)
+ {
+ iContactSynchroniser->Release();
+ iContactSynchroniser = NULL;
+ }
+ delete iDataBaseObserver;
+ delete iCntSvr;
+ delete iIdleSorter;
+ delete iSortedItems;
+ delete iSortOrder;
+ REComSession::FinalClose();
+ }
+
+
+/**
+Create a new CContactDatabase object
+*/
+CContactDatabase* CContactDatabase::NewLC()
+ {
+ CContactDatabase* db =new(ELeave) CContactDatabase();
+ CleanupStack::PushL(db);
+ db->ConstructL();
+ return db;
+ }
+
+
+void CContactDatabase::ConstructL()
+ {
+ iCntSvr = new (ELeave) RCntModel;
+ iCntSvr->ConnectL();
+ iProxyFactory = CProxyFactory::NewL(*this);
+ CreateViewDefL();
+ iTemplateCache = CCntTemplateCache::NewL(*iCntSvr);
+ iDataBaseObserver = CDataBaseChangeObserver::NewL(*this);
+ iCntSvr->AddObserverL(*iDataBaseObserver);
+ iIdleSorter = CCntIdleSorter::NewL(*this);
+ }
+
+
+void CContactDatabase::CreateViewDefL()
+ {
+ // The exact same object is created in the Session on the server. If
+ // it is changed here it must also be changed in the server code.
+ CContactItemViewDef* itemDef = CContactItemViewDef::NewLC(CContactItemViewDef::EIncludeFields,CContactItemViewDef::EMaskHiddenFields);
+ itemDef->AddL(KUidContactFieldMatchAll);
+ iView = CContactViewDef::NewL(itemDef);
+ CleanupStack::Pop(itemDef);
+
+ // iAllFieldView is not created on the server code - an exported getter method
+ // allows the user to modify this member and so it cannot be mirrored on the
+ // server
+ iAllFieldsView = CContactItemViewDef::NewL(CContactItemViewDef::EMaskFields,CContactItemViewDef::EIncludeHiddenFields);
+ }
+
+
+/**
+For BC.
+
+@internalComponent
+*/
+EXPORT_C CContactDatabase* CContactDatabase::LockServerConnectL(const TDesC& /*aFileName*/)
+ {
+ return NULL;
+ }
+
+
+/**
+For BC.
+
+@internalComponent
+*/
+EXPORT_C CContactDatabase* CContactDatabase::LockServerConnectL(const TDesC& /*aFileName*/, TInt /*aOperation*/)
+ {
+ return NULL;
+ }
+
+
+/**
+For BC.
+
+@internalComponent
+*/
+EXPORT_C TInt CContactDatabase::LockServerCallBackL(TUint /*aServerOperation*/)
+ {
+ return NULL;
+ }
+
+
+/**
+For BC.
+
+@internalComponent
+*/
+EXPORT_C void CContactDatabase::LockServerCleanup()
+ {
+ }
+
+
+/**
+Gets the file name of the default contact database.
+
+By default it is on drive C: but this can be changed using SetDatabaseDriveL().
+
+@capability None
+
+@param aDes On return, contains the drive and filename of the default
+contact database. From v9.0 onwards, this has the form driveletter:filename,
+in other words, it does not include a path.
+
+@see CContactDatabase::SetDatabaseDriveL()
+@see CContactDatabase::DatabaseDrive()
+@see CContactDatabase::DefaultContactDatabaseExistsL()
+*/
+EXPORT_C void CContactDatabase::GetDefaultNameL(TDes& aDes)
+ {
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->DefaultDatabase(aDes));
+ CleanupStack::PopAndDestroy(db);
+ }
+
+
+/**
+Deletes the default contact database.
+
+@capability WriteUserData
+
+@leave KErrInUse Another client has the database open.
+@leave KErrNotFound The database file was not found or it did not have the correct UIDs.
+
+@see CContactDatabase::DeleteDatabaseL()
+@see CContactDatabase::GetDefaultNameL()
+@see CContactDatabase::DefaultContactDatabaseExistsL()
+*/
+EXPORT_C void CContactDatabase::DeleteDefaultFileL()
+ {
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->DeleteDatabase(KNullDesC));
+ CleanupStack::PopAndDestroy(db);
+ }
+
+
+/**
+Gets the current database drive. The database drive is the drive on which
+the default contact database is located. Note: this function can leave.
+
+@capability None
+
+@param aDriveUnit On return, contains the database drive.
+
+@return ETrue if the database drive has been set using SetDatabaseDriveL().
+Otherwise EFalse and in this case, the function returns drive c: in aDriveUnit
+as the current drive.
+
+@leave KErrNoMemory Out of memory.
+
+@see CContactDatabase::SetDatabaseDrive()
+@see CContactDatabase::GetDefaultNameL()
+*/
+EXPORT_C TBool CContactDatabase::DatabaseDrive(TDriveUnit& aDriveUnit)
+ {
+ CContactDatabase* db = NewLC(); // this can leave
+ TBool ret = db->iCntSvr->DatabaseDrive(aDriveUnit);
+ CleanupStack::PopAndDestroy(db);
+ return ret;
+ }
+
+
+/**
+Sets the contact database drive and optionally moves the default contact database
+from its current location to the new drive. This function guarantees an all
+or nothing operation. If the database is not successfully moved, the drive
+setting is not updated to reflect the change.
+
+In v8.1 when copying the file is moved to \\system\\data on the specified
+drive, and if the destination file already exists it is replaced.
+
+From v9.0 onwards the file copying goes to the correct data caged directory
+on the destination drive. If the destination file already exists the copy
+fails.
+
+@capability WriteUserData
+
+@param aDriveUnit
+ The drive to which to move the database.
+@param aCopy
+ ETrue moves the existing file to the specified drive. Deletion of
+ the source file will fail if it is in use.
+ EFalse does not move the file.
+
+@leave KErrNotReady There is no media present in the drive.
+@leave KErrInUse The destination file for the copy is already open.
+@leave KErrNotFound The source file for the copy was not found.
+@leave KErrAlreadyExists The destination file for the copy already exists, (v9.0).
+
+@see CContactdatabase::DatabaseDrive()
+@see CContactDatabase::GetDefaultNameL()
+@see CContactDatabase::DefaultContactDatabaseExistsL()
+*/
+EXPORT_C void CContactDatabase::SetDatabaseDriveL(TDriveUnit aDriveUnit, TBool aCopy)
+ {
+ CContactDatabase* db = NewLC();
+ db->iCntSvr->SetDatabaseDriveL(aDriveUnit, aCopy);
+ CleanupStack::PopAndDestroy(db);
+ }
+
+
+/**
+Opens the default contact database.
+
+Note: clients should not assume any knowledge of the default database name or location
+because they may be changed in future releases.
+
+@capability ReadUserData
+
+@param aAccess The default (ESingleThread) allows access to the session with the
+database server from a single client thread only (as in v5 and v5.1). EMultiThread
+allows multiple client threads to share the same session with the server. As
+multi-threaded programs are uncommon in Symbian OS, this argument can be ignored
+by most C++ developers
+
+@return Pointer to the open contact database.
+
+@leave KErrNotFound The database file was not found or it did not have the correct UIDs.
+@leave KErrLocked Another client is writing to the database.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C CContactDatabase* CContactDatabase::OpenL(TThreadAccess aAccess)
+ {
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->OpenDatabase(KNullDesC));
+ if( aAccess == EMultiThread )
+ {
+ db->iCntSvr->ShareAuto();
+ }
+ db->FetchGroupAndTemplateListsL();
+ CleanupStack::Pop(db);
+ return db;
+ }
+
+EXPORT_C CContactDatabase* CContactDatabase::OpenV2L(TThreadAccess aAccess)
+ {
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->OpenDatabase(KNullDesC));
+ if( aAccess == EMultiThread )
+ {
+ db->iCntSvr->ShareAuto();
+ }
+ CleanupStack::Pop(db);
+ return db;
+ }
+
+/**
+Opens a named contact database.
+
+From v9.0 onwards, contact databases can only be located in the correct data caged
+subdirectory. The filenames must have no path, for example c:contacts.cdb.
+The maximum length for the drive, filename and extension is 190 characters, and empty
+string is not accepted.
+
+@capability ReadUserData
+
+@param aFileName The filename of the database to open.
+@param aAccess The default (ESingleThread) allows access to the session with the
+database server from a single client thread only (as in v5 and v5.1). EMultiThread
+allows multiple client threads to share the same session with the server. As
+multi-threaded programs are uncommon in Symbian OS, this argument can be ignored
+by most C++ developers
+
+@leave KErrNotFound The database file was not found or it did not have the correct UIDs.
+@leave KErrLocked Another client is writing to the database.
+@leave KErrBadName The filename is invalid; for example it contains
+wildcard characters or the drive is missing.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+@leave KErrArgument if the given descriptor contains more than the maximum length
+ of 190 characters.
+
+@return A pointer to the open contact database.
+*/
+EXPORT_C CContactDatabase* CContactDatabase::OpenL(const TDesC& aFileName, TThreadAccess aAccess)
+ {
+ __ASSERT_ALWAYS(aFileName.Length() != 0, User::Leave(KErrBadName) );
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->OpenDatabase(aFileName));
+ if( aAccess == EMultiThread )
+ {
+ db->iCntSvr->ShareAuto();
+ }
+ db->FetchGroupAndTemplateListsL();
+ CleanupStack::Pop(db);
+ return db;
+ }
+
+
+/**
+Creates and opens an empty contact database, replacing the existing default
+database.
+
+@capability WriteUserData
+
+@param aAccess The default (ESingleThread) allows access to the session with the
+database server from a single client thread only (as in v5 and v5.1). EMultiThread
+allows multiple client threads to share the same session with the server. As
+multi-threaded programs are uncommon in Symbian OS, this argument can be ignored
+by most C++ developers
+
+@return Pointer to the new contact database.
+
+@leave KErrInUse Another client has an open connection to the database.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+@leave KErrNoMemory There is no memory to perform the operation.
+*/
+EXPORT_C CContactDatabase* CContactDatabase::ReplaceL(TThreadAccess aAccess)
+ {
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->ReplaceDatabase(KNullDesC));
+ if( aAccess == EMultiThread )
+ {
+ db->iCntSvr->ShareAuto();
+ }
+ db->FetchGroupAndTemplateListsL();
+ CleanupStack::Pop(db);
+ return db;
+ }
+
+
+/**
+Creates and opens an empty contact database, replacing any existing file with
+the same name.
+
+From v9.0 onwards, contact databases can only be located in the correct data caged
+subdirectory. The filenames must have no path, for example c:contacts.cdb.
+The maximum length for the drive, filename and extension is 190 characters.
+
+@capability WriteUserData
+
+@param aFileName The filename of the database to replace.
+@param aAccess The default (ESingleThread) allows access to the session with the
+database server from a single client thread only (as in v5 and v5.1). EMultiThread
+allows multiple client threads to share the same session with the server. As
+multi-threaded programs are uncommon in Symbian OS, this argument can be ignored
+by most C++ developers
+
+@leave KErrBadName The filename is invalid; for example it contains wildcard characters
+or the drive letter is missing.
+@leave KErrInUse Another client has an open connection to the database.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+@leave KErrNoMemory There is no memory to perform the operation.
+@leave KErrArgument if the given descriptor contains more than the maximum length
+ of 190 characters.
+
+@return A pointer to the new contact database.
+*/
+EXPORT_C CContactDatabase* CContactDatabase::ReplaceL(const TDesC& aFileName, TThreadAccess aAccess)
+ {
+ __ASSERT_ALWAYS(aFileName.Length() != 0, User::Leave(KErrBadName) );
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->ReplaceDatabase(aFileName));
+ if( aAccess == EMultiThread )
+ {
+ db->iCntSvr->ShareAuto();
+ }
+ db->FetchGroupAndTemplateListsL();
+ CleanupStack::Pop(db);
+ return db;
+ }
+
+
+/**
+Creates and opens an empty contact database using the default database name.
+
+@capability WriteUserData
+
+@param aAccess The default (ESingleThread) allows access to the session with the
+database server from a single client thread only (as in v5 and v5.1). EMultiThread
+allows multiple client threads to share the same session with the server. As
+multi-threaded programs are uncommon in Symbian OS, this argument can be ignored
+by most C++ developers
+
+@return A pointer to the new contact database.
+
+@leave KErrAlreadyExists The database already exists.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C CContactDatabase* CContactDatabase::CreateL(TThreadAccess aAccess)
+ {
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->CreateDatabase(KNullDesC));
+ if( aAccess == EMultiThread )
+ {
+ db->iCntSvr->ShareAuto();
+ }
+ db->FetchGroupAndTemplateListsL();
+ CleanupStack::Pop (db);
+ return db;
+ }
+
+EXPORT_C CContactDatabase* CContactDatabase::CreateV2L(TThreadAccess aAccess)
+ {
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->CreateDatabase(KNullDesC));
+ if( aAccess == EMultiThread )
+ {
+ db->iCntSvr->ShareAuto();
+ }
+ CleanupStack::Pop (db);
+ return db;
+ }
+
+
+/**
+Creates and opens a named contact database.
+
+From v9.0 onwards, contact databases can only be located in the correct data caged
+subdirectory. The filenames must have no path, for example c:contacts.cdb.
+The maximum length for the drive, filename and extension is 190 characters.
+
+@capability WriteUserData
+
+@param aFileName The filename of the database to create.
+@param aAccess The default (ESingleThread) allows access to the session with the
+database server from a single client thread only (as in v5 and v5.1). EMultiThread
+allows multiple client threads to share the same session with the server. As
+multi-threaded programs are uncommon in Symbian OS, this argument can be ignored
+by most C++ developers
+
+@leave KErrAlreadyExists The database already exists.
+@leave KErrBadName The filename is invalid; for example it contains wildcard characters
+or the drive letter is missing.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+@leave KErrArgument if the given descriptor contains more than the maximum length
+ of 190 characters.
+
+@return A pointer to the new contact database.
+*/
+EXPORT_C CContactDatabase* CContactDatabase::CreateL(const TDesC& aFileName,TThreadAccess aAccess)
+ {
+ __ASSERT_ALWAYS(aFileName.Length() != 0, User::Leave(KErrBadName) );
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->CreateDatabase(aFileName));
+ if( aAccess == EMultiThread )
+ {
+ db->iCntSvr->ShareAuto();
+ }
+ db->FetchGroupAndTemplateListsL();
+ CleanupStack::Pop (db);
+ return db;
+ }
+
+
+/**
+This method is no longer required and should not be called.
+
+Closes all database tables. After a rollback and recover all tables need to
+be closed and re-opened before the database can be accessed again.
+
+@capability WriteUserData
+@deprecated
+*/
+EXPORT_C void CContactDatabase::CloseTables()
+ {
+ TRAP_IGNORE( iCntSvr->CloseTablesL() );
+ }
+
+
+/**
+This method is no longer required and should not be called.
+
+Opens all database tables. After a rollback and recover all tables need to
+be closed and re-opened before the database can be accessed again.
+
+@capability ReadUserData
+@deprecated
+*/
+EXPORT_C void CContactDatabase::OpenTablesL()
+ {
+ iCntSvr->OpenTablesL();
+ }
+
+
+/**
+A static method to recreate the system template.
+
+From v9.0 onwards, contact databases can only be located in the correct data caged
+subdirectory. The filenames must have no path, for example c:contacts.cdb.
+The maximum length for the drive, filename and extension is 190 characters.
+
+@publishedPartner
+@released
+@capability ReadUserData
+@capability WriteUserData
+
+@param aFileName The contact database filename.
+
+@leave KErrBadName The filename is invalid; for example it contains wildcard characters
+or the drive letter is missing.
+@leave KErrArgument if the given descriptor contains more than the maximum length
+ of 190 characters.
+*/
+EXPORT_C void CContactDatabase::RecreateSystemTemplateL(const TDesC& aFileName)
+ {
+ // Workaround for dynamic language switching because the system template may need to be recreated in a different language.
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->OpenDatabase(aFileName));
+ User::LeaveIfError(db->iCntSvr->ReCreateTemplate());
+ CleanupStack::PopAndDestroy(db);
+ }
+
+
+/**
+Sets the default view definition. The contact database takes ownership of the
+view definition specified. The default view definition is used in calls to
+ReadContactL(), ReadContactLC() and ReadContactAndAgentL() when no view definition
+is explicitly specified.
+
+@capability WriteUserData
+
+@param aView The view definition. This method does nothing if this is null.
+*/
+EXPORT_C void CContactDatabase::SetViewDefinitionL(CContactViewDef* aView)
+ {
+ if (aView)
+ {
+ iCntSvr->SetViewDefinitionL(*aView);
+ // We also need to hold the ViewDef here - it is used in merging
+ delete iView;
+ iView = aView;
+ }
+ }
+
+
+/**
+Sets the text definition. The contact database takes ownership of the
+text definition specified.
+
+@param aTextDef The new text definition.
+*/
+EXPORT_C void CContactDatabase::SetTextDefinitionL(CContactTextDef* aTextDef)
+ {
+ delete iTextDef;
+ iTextDef = aTextDef;
+ }
+
+
+/**
+Gets a pointer to the text definition.
+
+@return A pointer to the text definition.
+*/
+EXPORT_C const CContactTextDef* CContactDatabase::TextDefinition() const
+ {
+ return iTextDef;
+ }
+
+
+void CContactDatabase::CleanupDatabaseRollback(TAny *aDatabase)
+ {
+ ASSERT(aDatabase);
+ CContactDatabase* db = static_cast<CContactDatabase*>(aDatabase);
+ db->DatabaseRollback();
+ }
+
+
+/**
+Starts a new transaction. Places and leaves a cleanup item to rollback
+the database on the cleanupstack.
+
+@publishedPartner
+@released
+
+@param aIsInTransaction Used to determine whether or not to start the transaction depending on if a transaction is currently in progress.
+@leave KErrDiskFull There is insufficient disk space.
+*/
+EXPORT_C void CContactDatabase::DatabaseBeginLC(TBool aIsInTransaction)
+ {
+ if (!aIsInTransaction)
+ {
+ User::LeaveIfError(iCntSvr->BeginDbTransaction());
+ CleanupStack::PushL(TCleanupItem(CleanupDatabaseRollback, this));
+ }
+ }
+
+
+/**
+Commits an existing transaction, pops the rollback cleanup item off the CleanupStack.
+Closes the database if the connection state is EDbConnectionNeedToCloseForRestore.
+
+@publishedPartner
+@released
+
+@param aIsInTransaction Used to determine whether or not to commit the transaction depending on whether a transaction is currently in progress.
+*/
+EXPORT_C void CContactDatabase::DatabaseCommitLP(TBool aIsInTransaction)
+ {
+ if (!aIsInTransaction)
+ {
+ User::LeaveIfError(iCntSvr->CommitDbTransaction());
+ CleanupStack::Pop(); // CleanupDatabaseRollback
+ }
+ }
+
+
+/**
+This function is not currently supported.
+@deprecated
+*/
+EXPORT_C void CContactDatabase::StoreSortOrderL()
+ {
+ // Does nothing in the new architecture.
+ }
+
+
+/**
+This function is not currently supported.
+@deprecated
+*/
+EXPORT_C void CContactDatabase::RestoreSortOrderL()
+ {
+ //Does nothing in the new architecture
+ }
+
+
+/**
+ Gets the array of sort preferences.
+
+ Note: This method can leave.
+
+ @deprecated
+ @capability None
+ @return A pointer to an array of sort preferences of the contact database.
+*/
+EXPORT_C const CArrayFix<CContactDatabase::TSortPref>* CContactDatabase::SortOrder() const
+ {
+ return iCntSvr->GetSortPreferenceL(); // this can leave
+ }
+
+
+/**
+Adds a new contact item to the database and returns its ID.
+
+@capability WriteUserData
+
+@param aContact The contact item to add to the database.
+
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+
+@return The ID of the new contact item.
+*/
+EXPORT_C TContactItemId CContactDatabase::AddNewContactL(CContactItem& aContact)
+ {
+ return doAddNewContactL(aContact, EFalse, EFalse);
+ }
+
+
+/**
+Adds a new contact item to the database and returns its ID.
+
+@capability WriteUserData
+
+@param aContact The contact item to add to the database.
+@param aIsTemplate This argument should be ignored by developers.
+@param aIsInTransaction This argument should be ignored by developers.
+
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+
+@return The ID of the new contact item.
+*/
+EXPORT_C TContactItemId CContactDatabase::doAddNewContactL(CContactItem& aContact,TBool /*aIsTemplate*/,TBool /*aIsInTransaction*/)
+ {
+ if (aContact.Type() == KUidContactICCEntry)
+ {
+ LoadSyncPluginL();
+ }
+
+ aContact.iId = iCntSvr->CreateContactL(aContact);
+
+ if (CheckType(aContact.Type()))
+ {
+ InsertInSortArray(aContact);
+ }
+
+ return aContact.iId;
+ }
+
+
+CContactItem* CContactDatabase::doCreateContactGroupLC(const TDesC& aGroupLabel)
+ {
+ CContactItem* newGroup = CContactGroup::NewLC();
+ newGroup->AddLabelFieldL();
+ if (aGroupLabel != KNullDesC)
+ STATIC_CAST(CContactGroup*, newGroup)->SetGroupLabelL(aGroupLabel);
+
+ newGroup->iId = AddNewContactL(*newGroup);
+ RespondToEventL(EContactDbObserverEventGroupAdded, newGroup->iId);
+ return newGroup;
+ }
+
+
+/**
+Creates a new contact group with a default label of 'Group Label' and
+adds it to the database.
+
+The caller takes ownership of the returned object.
+
+@capability WriteUserData
+
+@param aInTransaction This argument should be ignored by developers.
+
+@return Pointer to the newly created contact group.
+*/
+EXPORT_C CContactItem* CContactDatabase::CreateContactGroupL(TBool aInTransaction)
+ {
+ CContactItem* newGroup = CContactDatabase::CreateContactGroupLC(aInTransaction);
+ CleanupStack::Pop(newGroup);
+ return newGroup;
+ }
+
+
+/**
+Creates a new contact group with a default label of 'Group Label' and
+adds it to the database.
+
+The caller takes ownership of the returned object.
+
+@capability WriteUserData
+
+@param aInTransaction This argument should be ignored by developers.
+
+@return Pointer to the newly created contact group.
+*/
+EXPORT_C CContactItem* CContactDatabase::CreateContactGroupLC(TBool /*aInTransaction*/)
+ {
+ return doCreateContactGroupLC();
+ }
+
+
+/**
+Creates a new contact group with a specified label and adds it to the database.
+
+The pointer to the group is left on the cleanup stack. The caller takes
+ownership of the returned object.
+
+@capability WriteUserData
+
+@param aGroupLabel The string to set as the group label.
+@param aInTransaction This argument should be ignored by developers.
+
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+
+@return Pointer to the newly created contact group.
+*/
+EXPORT_C CContactItem* CContactDatabase::CreateContactGroupLC(const TDesC& aGroupLabel, TBool /*aInTransaction*/)
+ {
+ return doCreateContactGroupLC(aGroupLabel);
+ }
+
+
+/**
+Creates a new contact group with a specified label and adds it to the database.
+
+The caller takes ownership of the returned object.
+
+@capability WriteUserData
+
+@param aGroupLabel The string to set as the group label.
+@param aInTransaction This argument should be ignored by developers.
+
+@return Pointer to the newly created contact group.
+*/
+EXPORT_C CContactItem* CContactDatabase::CreateContactGroupL(const TDesC& aGroupLabel,TBool aInTransaction)
+ {
+ CContactItem* newGroup = CContactDatabase::CreateContactGroupLC(aGroupLabel, aInTransaction);
+ CleanupStack::Pop(newGroup);
+ return newGroup;
+ }
+
+
+/**
+Creates a contact card template based on the system template and adds it to the database.
+
+A template label must be specifed. This can be changed later using CContactCardTemplate::SetTemplateLabelL().
+
+The pointer to the template is left on the cleanup stack. The caller takes ownership of the returned object.
+
+@capability WriteUserData
+
+@param aTempLabel The string to set as the template label.
+@param aInTransaction This argument should be ignored by developers.
+
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+
+@return Pointer to the contact card template.
+*/
+EXPORT_C CContactItem* CContactDatabase::CreateContactCardTemplateLC(const TDesC& aTempLabel, TBool aInTransaction)
+ {
+ return CreateContactCardTemplateLC(&iTemplateCache->SystemTemplateL(), aTempLabel, aInTransaction);
+ }
+
+
+/**
+Creates a contact card template based on the system template and adds it to the database.
+
+A template label must be specifed. This can be changed later using CContactCardTemplate::SetTemplateLabelL().
+
+The caller takes ownership of the returned object.
+
+@capability WriteUserData
+
+@param aTempLabel The string to set as the template label.
+@param aInTransaction This argument should be ignored by developers.
+
+@return Pointer to the contact card template.
+*/
+EXPORT_C CContactItem* CContactDatabase::CreateContactCardTemplateL(const TDesC& aTempLabel, TBool aInTransaction)
+ {
+ CContactItem *cntItem = CreateContactCardTemplateLC(&iTemplateCache->SystemTemplateL(), aTempLabel, aInTransaction);
+ CleanupStack::Pop(cntItem);
+ return cntItem;
+ }
+
+
+/**
+Creates a contact card template and adds it to the database.
+
+The new template's field set is based on the specified contact item. This could be a
+contact card, an own card, another template or even a group. Note that no field data
+is copied into the new template. All of the new template's fields are marked as template
+fields.
+
+A template label must be specifed. This can be changed later using CContactCardTemplate::SetTemplateLabelL().
+
+The caller takes ownership of the returned object.
+
+@capability WriteUserData
+
+@param aTemplate Pointer to an instance of a CContactItem-derived class. This
+is used to initialise the new template's field set.
+@param aTemplateLabel The string to set as the template label.
+@param aInTransaction This argument should be ignored by developers.
+
+@return Pointer to the contact card template.
+*/
+EXPORT_C CContactItem* CContactDatabase::CreateContactCardTemplateL(const CContactItem* aTemplate,const TDesC& aTempLabel,TBool aInTransaction)
+ {
+ CContactItem *cntItem = CreateContactCardTemplateLC(aTemplate, aTempLabel, aInTransaction);
+ CleanupStack::Pop(cntItem);
+ return cntItem;
+ }
+
+
+/**
+Creates a contact card template and adds it to the database.
+
+The new template's field set is based on the specified contact item. This could be a
+contact card, an own card, another template or even a group. Note that no field data
+is copied into the new template. All of the new template's fields are marked as template
+fields.
+
+A template label must be specifed. This can be changed later using CContactCardTemplate::SetTemplateLabelL().
+
+The pointer to the object is left on the cleanup stack. The caller takes ownership of it.
+
+@capability WriteUserData
+
+@param aTemplate Pointer to an instance of a CContactItem-derived class. This
+is used to initialise the new template's field set.
+@param aTemplateLabel The string to set as the template label.
+@param aInTransaction This argument should be ignored by developers.
+
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+
+@return Pointer to the contact card template.
+*/
+EXPORT_C CContactItem* CContactDatabase::CreateContactCardTemplateLC(const CContactItem* aTemplate, const TDesC& aLabel, TBool /*aInTransaction*/)
+ {
+ CContactItem* newTemplate = CContactCardTemplate::NewLC(aTemplate);
+ // Clear all data from the new template
+ newTemplate->ClearFieldContent();
+
+ // Add label field
+ newTemplate->AddLabelFieldL();
+ static_cast<CContactCardTemplate*>(newTemplate)->SetTemplateLabelL(aLabel);
+
+ // Create the contact in the database
+ newTemplate->iId = AddNewContactL(*newTemplate);
+ AddToTemplateListL(newTemplate->Id());
+ return newTemplate;
+ }
+
+
+void CContactDatabase::AddToTemplateListL(const TContactItemId aNewTemplateId)
+ {
+ if (!iCardTemplateIds)
+ {
+ iCardTemplateIds = CContactIdArray::NewL();
+ }
+ RespondToEventL(EContactDbObserverEventTemplateAdded, aNewTemplateId);
+ }
+
+
+void CContactDatabase::RemoveFromTemplateList(const TContactItemId aTemplateId)
+ {
+ if (iCardTemplateIds)
+ {
+ TInt templatePos = iCardTemplateIds->Find(aTemplateId);
+ if (templatePos != KErrNotFound)
+ {
+ iCardTemplateIds->Remove(templatePos);
+ }
+ }
+ }
+
+
+/**
+Gets a copy of the database's template ID list. This is a list of the IDs
+of all contact card templates which have been added to the database. The caller
+takes ownership of the returned object.
+
+@return Pointer to a copy of the database's template ID list. This does
+not include the system template. NULL if there are no templates in the database.
+*/
+EXPORT_C CContactIdArray* CContactDatabase::GetCardTemplateIdListL() const
+ {
+ if (iCardTemplateIds)
+ {
+ CContactIdArray* copyArray = CContactIdArray::NewL(iCardTemplateIds);
+ return copyArray;
+ }
+ else
+ return NULL;
+ }
+
+
+void CContactDatabase::ReadTemplateIdsL()
+ {
+ const_cast<CContactDatabase*>(this)->FetchGroupAndTemplateListsL();
+ }
+
+
+/** Determines if the System template fields are valid. Valid means that no
+fields contain data.
+@internalTechnology
+@released
+@capability None
+@param aContact Contact item representing the System template.
+@return ETrue if the System template fields are valid, EFalse otherwise.
+*/
+TBool CContactDatabase::SystemTemplateFieldsValid( const CContactItem& aContact )
+ {
+ // Precondition: aContact's ID must match the System template's ID.
+ __ASSERT_ALWAYS( aContact.Id() == TemplateId(), Panic(ECntPanicSystemTemplate) );
+
+ TBool fieldsValid = ETrue;
+ CContactItemFieldSet& fieldSet = aContact.CardFields();
+
+ for( TInt ii = 0; ii < fieldSet.Count(); ii++ )
+ {
+ CContactItemField& field = fieldSet[ii];
+ CContactFieldStorage* fieldStorage = field.Storage();
+ //
+ // If the field contains data (is "full") then the System template
+ // fields are not valid.
+ //
+ if( fieldStorage->IsFull() )
+ {
+ fieldsValid = EFalse;
+ break;
+ }
+ }
+
+ return fieldsValid;
+ }
+
+
+/**
+Returns a copy of the database's group ID list. This is a list which contains
+the contact item IDs for each group in the database. The caller takes ownership
+of the returned object.
+
+@return Pointer to an array containing the contact item IDs for each group
+in the database. NULL if there are no groups in the database.
+*/
+EXPORT_C CContactIdArray* CContactDatabase::GetGroupIdListL() const
+ {
+ const_cast<CContactDatabase*>(this)->FetchGroupAndTemplateListsL();
+ CContactIdArray* copyArray = CContactIdArray::NewL(iGroupIds);
+ return copyArray;
+ }
+
+
+/**
+Sets a contact item in the database to be a member of a contact group.
+
+The item and group are identified by their IDs.
+
+@capability WriteUserData
+
+@param aItemId The ID of the item to add to the group.
+@param aGroupId The ID of the group to which the item should be added.
+
+@leave KErrNotFound Either the group or the item does not exist.
+@leave KErrNotSupported The group is not of type KUidContactGroup.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::AddContactToGroupL(TContactItemId aItemId, TContactItemId aGroupId)
+ {
+ //Remember if the group was already opened, if so open it at the end of the method
+ TBool isAlreadyOpened = iCntSvr->CloseContact(aGroupId);
+
+ CContactItem* cntGroup = OpenNoMergeLCX(aGroupId); //double push
+
+ if (cntGroup->Type() != KUidContactGroup)
+ User::Leave(KErrNotSupported);
+ AddCntToOpenedGroupL(aItemId, *cntGroup);
+
+ CleanupStack::PopAndDestroy(cntGroup); // cntGroup
+ CleanupStack::Pop(); // Pop the lock
+ cntGroup = NULL;
+ if (isAlreadyOpened)
+ {
+ CContactItem* dummy = OpenContactL(aGroupId);
+ delete dummy;
+ }
+ }
+
+
+/**
+Sets a contact item in the database to be a member of a contact group.
+
+The item and group are identified by their IDs.
+
+@capability WriteUserData
+
+@param aItemId The ID of the item to add to the group.
+@param aGroupId The ID of the group to which the item should be added.
+@param aInTransaction This argument should be ignored by developers.
+
+@leave KErrNotFound Either the group or the item does not exist.
+@leave KErrNotSupported The group is not of type KUidContactGroup.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::AddContactToGroupL(TContactItemId aItemId, TContactItemId aGroupId, TBool /*aInTransaction*/)
+ {
+ AddContactToGroupL(aItemId, aGroupId);
+ }
+
+
+/**
+Sets a contact item in the database to be a member of a contact group.
+
+@capability WriteUserData
+
+@param aItem The item to add to the group.
+@param aGroup The group to which the item should be added.
+
+@leave KErrNotFound Either the group or the item does not exist in the database.
+@leave KErrNotSupported The group is not of type KUidContactGroup.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::AddContactToGroupL(CContactItem& aItem, CContactItem& aGroup)
+ {
+ if (aGroup.Type() != KUidContactGroup)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ AddContactToGroupL(aItem.Id(), aGroup.Id());
+
+ //Update client's group object
+ static_cast<CContactGroup&>(aGroup).AddContactL(aItem.Id());
+
+ //Update client's contacts item object
+ CContactItemPlusGroup& item = static_cast<CContactItemPlusGroup&>(aItem);
+ if (!item.iGroups)
+ {
+ item.iGroups = CContactIdArray::NewL();
+ }
+ item.iGroups->AddL(aGroup.Id());
+ }
+
+
+/**
+Removes the association between a contact item and a group.
+
+@capability WriteUserData
+
+@param aItem The item to remove.
+@param aGroup The group from which the item should be removed.
+
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::RemoveContactFromGroupL(CContactItem& aItem, CContactItem& aGroup)
+ {
+ if (aGroup.Type() != KUidContactGroup)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ RemoveContactFromGroupL(aItem.Id(), aGroup.Id()); //Perform the change in the database
+
+ //Update client's group object
+ static_cast<CContactGroup&>(aGroup).RemoveContactL(aItem.Id());
+
+ //Update client's contacts item object
+ CContactItemPlusGroup& item = static_cast<CContactItemPlusGroup&>(aItem);
+ if (item.iGroups)
+ {
+ const TInt groupIndex = item.iGroups->Find(aGroup.Id());
+ if (groupIndex>=0)
+ {
+ item.iGroups->Remove(groupIndex);
+ }
+ }
+ }
+
+
+void CContactDatabase::AddCntToOpenedGroupL(TContactItemId aItemId, CContactItem& aGroup)
+ {
+ CContactGroup& group = static_cast<CContactGroup&>(aGroup);
+ if (!group.ContainsItem(aItemId))
+ {
+ group.AddContactL(aItemId);
+ iCntSvr->CommitContactL(aGroup);
+ }
+ else
+ {
+ iCntSvr->CloseContact(aGroup.Id());
+ }
+ }
+
+
+/**
+Removes the association between a contact item and a group.
+
+The item and group are identified by their IDs.
+
+@capability WriteUserData
+
+@param aItemId The ID of the item to remove.
+@param aGroupId The ID of the group from which the item should be removed.
+
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::RemoveContactFromGroupL(TContactItemId aItemId, TContactItemId aGroupId)
+ {
+ //Remember if the group was already opened, if so open it at the end of the method
+ TBool isAlreadyOpened = iCntSvr->CloseContact(aGroupId);
+ CContactItem* cntGroup = OpenNoMergeLCX(aGroupId); //double push
+
+ if (cntGroup->Type() != KUidContactGroup)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ CContactGroup* group = static_cast<CContactGroup*>(cntGroup);
+ if (group->ContainsItem(aItemId))
+ {
+ group->RemoveContactL(aItemId);
+ iCntSvr->CommitContactL(*cntGroup);
+ }
+ else
+ {
+ iCntSvr->CloseContact(cntGroup->Id());
+ }
+
+ CleanupStack::PopAndDestroy(2); // cntGroup, CntItemClose
+ cntGroup = NULL;
+
+ if (isAlreadyOpened)
+ {
+ CContactItem* dummy = OpenContactL(aGroupId);
+ delete dummy;
+ }
+
+ }
+
+
+/**
+Sets a field containing a telephone number as a speed dial field. The field
+is identified by aFieldIndex within the contact item aItem. It is assigned a
+speed dial position between 1 and 9 inclusive.
+
+The field's speed dial and user added attributes are set and the appropriate
+UID (KUidSpeedDialXxx) is added to the field's content type. The changes are
+committed to the database.
+
+Notes:
+
+If an item's telephone number field has already been assigned to position
+aSpeedDialPosition, that item is updated so that the speed dial attribute
+is removed from its field and the speed dial field type UID is removed from
+the field's content type, before the new speed dial field is set.
+
+The speed dial attribute can be tested for using the CContactItemField::IsSpeedDial()
+function.
+
+The contact item passed to this function (aItem) must have been obtained using
+one of the variants of CContactDatabase::OpenContactL(). This is because it
+is modified and committed to the database by this function - no further
+commits are necessary.
+
+@capability ReadUserData
+@capability WriteUserData
+
+@param aItem The contact item containing the field to set as a speed dial
+field.
+@param aFieldIndex Index of a field in aItem's field set to set as a speed dial field.
+@param aSpeedDialPosition The speed dial position. This is an integer in the
+range 1 to 9 inclusive. If outside this range, the function leaves with KErrArgument.
+
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::SetFieldAsSpeedDialL(CContactItem& aItem, TInt aFieldIndex, TInt aSpeedDialPosition)
+ {
+ //
+ // aItem has been merged with the appropriate template. On the server when
+ // the contact is read it is not merged with the template. Therefore we
+ // need to determine an equivalent field index for the server. The index
+ // on the client's side takes account of the template fields so to compute
+ // the equivalent index iterate through the contact fields up to and
+ // including aFieldIndex and count the number of non-empty (i.e. non-
+ // template) fields. The total number is the equivalent index.
+ //
+ CContactItemFieldSet &fieldSet = aItem.CardFields();
+ TInt svrFieldIndex = -1;
+ if(fieldSet.Count() == 0)
+ {
+ User::Leave(KErrArgument);
+ }
+ for( TInt fieldIndex = 0; fieldIndex <= aFieldIndex; fieldIndex++ )
+ {
+ CContactItemField& field = fieldSet[fieldIndex];
+ if( field.Storage()->IsFull() )
+ {
+ svrFieldIndex++;
+ }
+ }
+
+
+ CContactItemField& field = fieldSet[aFieldIndex];
+ if (field.StorageType() == KStorageTypeText)
+ {
+ iCntSvr->SetFieldAsSpeedDialL(aItem.Id(), svrFieldIndex, aSpeedDialPosition);
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+
+
+ //
+ // The contact has been read from the database and modified on the server.
+ // These changes have not been made to the CContactItem passed in to this
+ // function. We need to make these changes here for consistency with the
+ // old model. A future BC break will disallow this behaviour by changing
+ // the parameter from CContactItem& to const CContactItem& thus forcing the
+ // client to pass a constant object.
+ //
+
+ // Get the field containing the number to be associated with the
+ // speed dial. Note that we use the original index passed in not the
+ // equivalent server index.
+ CContactItemField& speedDialField = aItem.CardFields()[aFieldIndex];
+ // Add speed dial attributes to the contact item field.
+ TUid fieldTypeUid = CContactDatabase::SpeedDialFieldUidFromSpeedDialPosition(aSpeedDialPosition);
+ if (!speedDialField.ContentType().ContainsFieldType(fieldTypeUid))
+ {
+ speedDialField.AddFieldTypeL(fieldTypeUid);
+ }
+ speedDialField.SetUserAddedField(ETrue);
+ speedDialField.SetSpeedDial(ETrue);
+ }
+
+
+/**
+Returns the field UID for the given speed dial position. This method is
+copied from CCntServerSpeedDialManager::SpeedDialFieldUidFromSpeedDialPosition()
+rather than export this method for use here and on the server. Once the BC
+break referred to in SetFieldAsSpeedDialL() has been made this method should be
+removed.
+
+@internalTechnology
+@released
+
+@param aSpeedDialPosition The speed dial position for which we want the field
+UID.
+
+@return The field UID corresponding to aSpeedDialPosition.
+*/
+TUid CContactDatabase::SpeedDialFieldUidFromSpeedDialPosition(TInt aSpeedDialPosition)
+ {
+ __ASSERT_ALWAYS(aSpeedDialPosition >= KCntMinSpeedDialIndex && aSpeedDialPosition <= KCntMaxSpeedDialIndex, Panic(ECntPanicInvalidSpeedDialIndex));
+
+ TUid fieldTypeUid = KNullUid;
+ switch (aSpeedDialPosition)
+ {
+ case 1:
+ fieldTypeUid = KUidSpeedDialOne;
+ break;
+ case 2:
+ fieldTypeUid = KUidSpeedDialTwo;
+ break;
+ case 3:
+ fieldTypeUid = KUidSpeedDialThree;
+ break;
+ case 4:
+ fieldTypeUid = KUidSpeedDialFour;
+ break;
+ case 5:
+ fieldTypeUid = KUidSpeedDialFive;
+ break;
+ case 6:
+ fieldTypeUid = KUidSpeedDialSix;
+ break;
+ case 7:
+ fieldTypeUid = KUidSpeedDialSeven;
+ break;
+ case 8:
+ fieldTypeUid = KUidSpeedDialEight;
+ break;
+ case 9:
+ fieldTypeUid = KUidSpeedDialNine;
+ break;
+ }
+
+ return fieldTypeUid;
+ }
+
+
+/**
+Returns the ID of the contact item whose telephone number field is mapped to
+the speed dial position specified. This function is provided so that information
+may be displayed about a contact item whose telephone number is being dialled
+using speed dialling.
+
+The function also retrieves the telephone number stored in the field.
+
+@capability ReadUserData
+
+@param aSpeedDialPosition The speed dial position. This is an integer in the
+range 1 to 9 inclusive. If outside this range, the function leaves with KErrArgument.
+@param aPhoneNumber On return, contains the telephone number which is mapped
+to the speed dial position specified. Returns KNullDesC if the speed dial
+position requested has not been set.
+
+@return The ID of the contact item for which the speed dial has been set.
+*/
+EXPORT_C TContactItemId CContactDatabase::GetSpeedDialFieldL(TInt aSpeedDialPosition, TDes& aPhoneNumber)
+ {
+ return iCntSvr->GetSpeedDialFieldL(aSpeedDialPosition, aPhoneNumber);
+ }
+
+
+/**
+Removes the mapping between a contact item field and a speed dial position.
+
+Removes the KUidSpeedDialXxx UID from the field's content type, removes the
+field's speed dial attribute and commits the changes to the item.
+
+@capability ReadUserData
+@capability WriteUserData
+
+@param aContactId The ID of the contact item containing the speed dial field.
+@param aSpeedDialPosition The speed dial position. This is an integer in the
+range 1 to 9 inclusive. If outside this range, the function leaves with KErrArgument.
+
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::RemoveSpeedDialFieldL(TContactItemId aContactId, TInt aSpeedDialPosition)
+ {
+ iCntSvr->RemoveSpeedDialFieldL(aContactId, aSpeedDialPosition);
+ }
+
+
+/**
+Reads a contact item without locking it.
+
+This function uses the default view definition (as set by SetViewDefinitionL()). The
+caller takes ownership of the returned object.
+
+@capability ReadUserData
+
+@param aContactId The ID of the contact item to read.
+
+@return Pointer to the contact item.
+
+@leave KErrNotFound The specified contact item does not exist in the database. */
+EXPORT_C CContactItem* CContactDatabase::ReadContactL(TContactItemId aContactId)
+ {
+ CContactItem* cntItem = ReadContactLC(aContactId);
+ CleanupStack::Pop(cntItem);
+ return cntItem;
+ }
+
+
+/**
+Reads a contact item without locking it.
+
+This function uses the view definition specified. The caller takes ownership
+of the returned object.
+
+@capability ReadUserData
+
+@param aContactId The ID of the contact item to read.
+@param aViewDef The view definition to use.
+
+@return Pointer to the contact item.
+
+@leave KErrNotFound The specified contact item does not exist in the database. */
+EXPORT_C CContactItem* CContactDatabase::ReadContactL(TContactItemId aContactId, const CContactItemViewDef& aViewDef)
+ {
+ CContactItem* cntItem = ReadContactLC(aContactId, aViewDef);
+ CleanupStack::Pop(cntItem);
+ return cntItem;
+ }
+
+
+/**
+Reads a contact item without locking it.
+
+This function uses the default view definition (as set by SetViewDefinitionL()). The
+caller takes ownership of the returned object.
+
+@capability ReadUserData
+
+@param aContactId The ID of the contact item to read.
+
+@return Pointer to the contact item. This is left on the cleanup stack.
+
+@leave KErrNotFound The specified contact item does not exist in the database.
+*/
+EXPORT_C CContactItem* CContactDatabase::ReadContactLC(TContactItemId aContactId)
+ {
+ CContactItem* cntItem = iCntSvr->ReadContactL(&iView->ItemDef(), aContactId);
+ CleanupStack::PushL(cntItem);
+
+ iTemplateCache->MergeWithTemplateL(*cntItem, &iView->ItemDef());
+
+ return cntItem;
+ }
+
+
+/**
+Reads a contact item without locking it.
+
+This function uses the view definition specified. The caller takes ownership
+of the returned object.
+
+@capability ReadUserData
+
+@param aContactId The ID of the contact item to read.
+@param aViewDef The view definition to use.
+
+@return Pointer to the contact item. This is left on the cleanup stack.
+
+@leave KErrNotFound The specified contact item does not exist in the database.
+*/
+EXPORT_C CContactItem* CContactDatabase::ReadContactLC(TContactItemId aContactId,const CContactItemViewDef& aViewDef)
+ {
+ CContactItem* cntItem = iCntSvr->ReadContactL(&aViewDef, aContactId);
+ CleanupStack::PushL(cntItem);
+ iTemplateCache->MergeWithTemplateL(*cntItem, &aViewDef);
+ return cntItem;
+ }
+
+
+/**
+Reads a contact item and an agent if the item has an agent field. The item
+and agent (if present) are returned in an array. The function uses the database's
+default view definition (as set by SetViewDefinitionL()). The caller takes
+ownership of the returned object.
+
+@capability ReadUserData
+
+@param aContactId The ID of the contact item to read.
+@leave KErrNotFound The specified contact item cannot be found in the database.
+
+@return Pointer to an array containing the contact item and agent, if present.
+*/
+EXPORT_C CArrayPtr<CContactItem>* CContactDatabase::ReadContactAndAgentL(TContactItemId aContactId)
+ {
+ CArrayPtr<CContactItem>* cntItemsArray = new (ELeave)CArrayPtrFlat<CContactItem>(4);
+ CleanupStack::PushL(cntItemsArray);
+ CContactItem* contactItem = ReadContactLC(aContactId);
+ cntItemsArray->AppendL(contactItem);
+ CleanupStack::Pop(contactItem); // from ReadContactLC
+
+ // Determine whether the contactItem needs an agent
+ TInt agentIndex = (*cntItemsArray)[0]->Agent();
+ if (agentIndex != KErrNotFound)
+ {
+ CContactItem* contactItemAgent = ReadContactLC(agentIndex);
+ cntItemsArray->AppendL(contactItemAgent); // Will use the Viewdef on the server - no need to marshal ViewDef
+ CleanupStack::Pop(contactItemAgent);// from ReadContactLC
+ }
+ CleanupStack::Pop(cntItemsArray); // cntItemsArray
+ return cntItemsArray;
+ }
+
+
+/**
+Reads a contact item (contact card, own card, template, or contact group),
+but does not read the group or template information.
+
+This function is identical to the variant of ReadContactL() which uses the database's
+default view definition, except that this function does not read:
+
+- the list of group members and the group label (if the item is a CContactGroup)
+- the template label (if the item is a CContactCardTemplate)
+- the list of groups to which the item belongs, if any (not applicable to templates)
+- any fields inherited from a non-system template, if any (not applicable if
+the item is a CContactCardTemplate)
+
+Notes:
+
+This function is faster than the standard reading function (ReadContactL()),
+which needs to match the template fields and groups etc.
+
+The caller takes ownership of the returned object.
+
+@capability ReadUserData
+
+@param aContactId The ID of the contact to read.
+
+@leave KErrNotFound The specified contact item cannot be found in the database.
+
+@return Pointer to the contact whose ID is aContactId.
+*/
+EXPORT_C CContactItem* CContactDatabase::ReadMinimalContactL(TContactItemId aContactId)
+ {
+ return iCntSvr->ReadContactL(NULL, aContactId);
+ }
+
+
+/**
+Reads a contact item (contact card, own card, template, or contact group),
+but does not read the group or template information.
+
+This function is identical to the variant of ReadContactLC() which uses the server's
+default view definition, except that this function does not read:
+
+- the list of group members and the group label (if the item is a CContactGroup)
+- the template label (if the item is a CContactCardTemplate)
+- the list of groups to which the item belongs, if any (not applicable to templates)
+- any fields inherited from a non-system template, if any (not applicable if
+the item is a CContactCardTemplate)
+
+Notes:
+
+This function is faster than the standard reading function (ReadContactLC()),
+which needs to match the template fields and groups etc.
+
+The caller takes ownership of the returned object.
+
+@capability ReadUserData
+
+@param aContactId The ID of the contact to read.
+
+@leave KErrNotFound The specified contact item cannot be found in the database.
+
+@return Pointer to the contact whose ID is aContactId. The contact is left
+on the cleanup stack.
+*/
+EXPORT_C CContactItem* CContactDatabase::ReadMinimalContactLC(TContactItemId aContactId)
+ {
+ CContactItem* cntItem = iCntSvr->ReadContactL(NULL, aContactId);
+ CleanupStack::PushL(cntItem);
+ return cntItem;
+ }
+
+
+/**
+Gets the content type of the template field which a specified field maps onto.
+If the field does not map onto a field in a template, then its own content
+type is returned.
+
+Note: this function can leave.
+
+@param aField The field of interest.
+
+@return The content type of the field.
+*/
+EXPORT_C const CContentType& CContactDatabase::TemplateContentType(const CContactItemField& aField) const
+ {
+ return(aField.TemplateContentType(iTemplateCache->SystemTemplateL().CardFields())); // this can leave
+ }
+
+
+//
+// Logic cut and paste with minor edit from old CContactTables.
+// Create a descriptor with field values separated by the 'separator' from a
+// CContactItemFieldSet.
+// No database read.
+//
+void CContactDatabase::DoReadContactTextDefL(const CContactItemFieldSet* aFieldSet,TDes& aResult,CContactTextDef* aTextDef)
+ {
+ TBool firstText=ETrue;
+ if (aTextDef)
+ {
+ TBuf<KMaxContactTextSeperator> nextSeperator;
+ for(TInt loop=0;loop<aTextDef->Count();loop++)
+ {
+ CContactDatabase::TTextFieldMinimal textFieldMin;
+ TContactTextDefItem textDefItem=(*aTextDef)[loop];
+ const TInt startOfFieldSet=0;
+ aFieldSet->FieldText(textDefItem.iFieldType,textFieldMin,startOfFieldSet);
+ if (textFieldMin.Length()>0)
+ {
+ if (!firstText && aResult.MaxLength()>aResult.Length())
+ aResult.Append(nextSeperator.Left(Min(aResult.MaxLength()-aResult.Length(),nextSeperator.Length())));
+ aResult.Append(textFieldMin.Left(Min(aResult.MaxLength()-aResult.Length(),textFieldMin.Length())));
+ firstText=EFalse;
+ }
+ nextSeperator=textDefItem.iSeperator;
+ }
+ }
+ if (firstText)
+ {
+ if(aTextDef && aTextDef->ExactMatchOnly()!=EFalse)
+ return;//text def specifies an exact match only
+ CContactDatabase::TTextFieldMinimal textFieldMin;
+ if (aTextDef)
+ {
+ TFieldType fieldType=aTextDef->iFallbackFieldType;
+ if (fieldType!=KUidContactFieldNone)
+ {
+ const TInt startOfFieldSet=0;
+ aFieldSet->FieldText(fieldType,textFieldMin,startOfFieldSet);
+ }
+ }
+ if (textFieldMin.Length()==0)
+ {
+ TInt findPos=KContactFieldSetSearchAll;
+ do
+ {
+ findPos=aFieldSet->FindNext(KUidContactFieldMatchAll,findPos+1);
+ if (findPos<0)
+ break;
+ (*aFieldSet)[findPos].GetFieldText(textFieldMin);
+ } while(textFieldMin.Length()==0);
+ }
+ aResult.Append(textFieldMin.Left(Min(aResult.MaxLength(),textFieldMin.Length())));
+ }
+ }
+
+
+/**
+Reads text into a descriptor from a pre-loaded contact item.
+
+This function uses the database's current text definition (as set using
+CContactDatabase::SetTextDefinitionL()).
+
+@capability ReadUserData
+
+@param aItem The contact item to read.
+@param aResult On return, contains the text read from the contact item aItem,
+using the database's current text definition.
+*/
+EXPORT_C void CContactDatabase::ReadContactTextDefL(const CContactItem& aItem, TDes& aResult)
+ {
+ DoReadContactTextDefL(&aItem.CardFields(),aResult,iTextDef);
+ }
+
+
+/**
+Reads text into a descriptor from a pre-loaded contact item, using the specified
+text definition.
+
+@capability ReadUserData
+
+@param aItem The contact item to read.
+@param aResult On return, contains the text read from the contact item aItem,
+using the text definition specified in aTextDef.
+@param aTextDef The text definition to use.
+*/
+EXPORT_C void CContactDatabase::ReadContactTextDefL(const CContactItem& aItem, TDes& aResult,CContactTextDef* aTextDef)
+ {
+ DoReadContactTextDefL(&aItem.CardFields(),aResult,aTextDef);
+ }
+
+
+/**
+Reads text from a contact item stored in the database into a descriptor.
+
+This function uses the database's currently set text definition (as set using
+CContactDatabase::SetTextDefinitionL()).
+
+@capability ReadUserData
+
+@param aContactId The ID of the contact to read.
+@param aResult On return, contains the text read from the contact item identified by aContactId, using
+the database's current text definition.
+
+@leave KErrNotFound The specified contact item cannot be found in the database.
+*/
+EXPORT_C void CContactDatabase::ReadContactTextDefL(TContactItemId aContactId, TDes& aResult)
+ {
+ ReadContactTextDefL(aContactId,aResult,iTextDef);
+ }
+
+
+/**
+Reads text from a contact item stored in the database into a descriptor
+using the specified text definition.
+
+@capability ReadUserData
+
+@param aContactId The ID of the contact to read.
+@param aResult On return, contains the text read from the contact item identified by aContactId, using
+the text definition specified in aTextDef.
+@param aTextDef The text definition to use.
+
+@leave KErrNotFound The specified contact item cannot be found in the database.
+*/
+EXPORT_C void CContactDatabase::ReadContactTextDefL(TContactItemId aContactId, TDes& aResult,CContactTextDef* aTextDef)
+ {
+ CContactTextDef* textDef = NULL;
+ if(aTextDef == NULL)
+ {
+ textDef = CContactTextDef::NewLC();
+ }
+ else
+ {
+ textDef = aTextDef;
+ }
+ MLplViewIteratorManager& manager = FactoryL()->GetViewIteratorManagerL();
+ manager.ReadContactTextDefL(aContactId,aResult,*textDef);
+ if(aTextDef == NULL)
+ {
+ CleanupStack::PopAndDestroy(textDef);
+ }
+ }
+
+
+CContactIdArray* CContactDatabase::SortLC(const CArrayFix<CContactDatabase::TSortPref>* aSortOrder, const CContactIdArray* aIdArray)
+ {
+ CContactIdArray* sortedItems=CContactIdArray::NewLC();
+ if (aSortOrder->Count()==0)
+ {
+ TContactItemId currentId(1);
+ TContactItemId actualId;
+ TUid contactType;
+ TBool deleted;
+ MLplCollection& collection = FactoryL()->GetCollectorL();
+ while(collection.SeekContactL(currentId,actualId,contactType,deleted))
+ {
+ if(CheckType(contactType) && !deleted)
+ {
+ sortedItems->AddL(actualId);
+ }
+ currentId = actualId+1;
+ }
+ }
+ else
+ {
+ CContactTextDef* textDef;
+ TUid fieldType=(*aSortOrder)[0].iFieldType;
+ if (fieldType==KUidContactFieldDefinedText)
+ {
+ textDef=iTextDef;
+ }
+ else
+ {
+ //We are sorting on aSortOrder.
+ textDef=CContactTextDef::NewLC();
+ TInt sortOrderCount=aSortOrder->Count();
+ for (TInt sortIndex=0;sortIndex<sortOrderCount;sortIndex++)
+ {
+ textDef->AppendL(TContactTextDefItem((*aSortOrder)[sortIndex].iFieldType));
+ }
+ }
+ CSortArray* sortedList=new(ELeave) CSortArray;
+ CleanupStack::PushL(sortedList);
+ TContactItemId currentId(1);
+ TInt arrayIndex(0);
+ for(;;)
+ {
+ TUid contactType;
+ TContactItemId actualId;
+ TBool deleted;
+ if(aIdArray)
+ {
+ if (arrayIndex==aIdArray->Count())
+ break;
+ MLplCollection& collection = FactoryL()->GetCollectorL();
+ if(!collection.SeekContactL((*aIdArray)[arrayIndex],actualId,contactType,deleted) || actualId != (*aIdArray)[arrayIndex])
+ {
+ User::Leave(KErrNotFound);
+ }
+ ++arrayIndex;
+ }
+ else
+ {
+ MLplCollection& collection = FactoryL()->GetCollectorL();
+ if(!collection.SeekContactL(currentId,actualId,contactType,deleted))
+ {
+ break;
+ }
+ currentId = actualId+1;
+ }
+ if(CheckType(contactType) && !deleted)
+ {
+ CContactDatabase::TTextFieldMinimal textFieldMin;
+ ReadContactTextDefL(actualId,textFieldMin,textDef);
+ sortedList->AppendL(textFieldMin,actualId);
+ }
+ }
+ sortedList->SortL((*aSortOrder)[0].iOrder);
+ SortDuplicatesL(*aSortOrder,*sortedList,1);
+ const TInt count=sortedList->Count();
+ for (TInt ii=0;ii<count;ii++)
+ sortedItems->AddL(sortedList->Id(ii));
+ CleanupStack::PopAndDestroy(); // sortedList ,
+ if (fieldType!=KUidContactFieldDefinedText)
+ {
+ CleanupStack::PopAndDestroy();//textdef
+ }
+ }
+ CContactIdArray* newSortedItems=CContactIdArray::NewL(sortedItems);
+ CleanupStack::PopAndDestroy(sortedItems);
+ CleanupStack::PushL(newSortedItems);
+ User::Heap().Compress();
+ return(newSortedItems);
+ }
+
+
+void CContactDatabase::ReSortL(CArrayFix<TSortPref>* aSortOrder)
+ {
+ CContactIdArray* sortedItems=SortLC(aSortOrder,NULL);
+ delete iSortedItems;
+ iSortedItems=sortedItems;
+ CleanupStack::Pop(sortedItems);
+ }
+
+
+void CContactDatabase::SortDuplicatesL(const CArrayFix<TSortPref>& aSortOrder,
+ CSortArray& aList,TInt aSortIndex)
+ { // is this too heavy on stack usage to be called recursively ???
+ __ASSERT_DEBUG(&aSortOrder!=NULL,Panic(ECntPanicNullPointer));
+ __ASSERT_DEBUG(&aList!=NULL,Panic(ECntPanicNullPointer));
+ if (aSortIndex<aSortOrder.Count())
+ {
+ const TInt count=aList.Count();
+ if (count<=1)
+ return;
+ TInt ii=0;
+ HBufC *text1=aList.Text(ii);
+ TInt startPos=KErrNotFound;
+ TBool checkedList=EFalse;
+ while (!checkedList)
+ {
+ checkedList=(++ii==count-1);
+ HBufC *text2=aList.Text(ii);
+ const TInt compare=text1->CompareC(*text2,3,&iCollateMethod);
+ if (compare==0)
+ {
+ if (startPos==KErrNotFound)
+ startPos=ii-1;
+ }
+ else if (startPos!=KErrNotFound)
+ {
+ SortDuplicatesL(aSortOrder,aList,aSortIndex,startPos,ii);
+ startPos=KErrNotFound;
+ }
+ text1=text2;
+ }
+ if (startPos!=KErrNotFound)
+ SortDuplicatesL(aSortOrder,aList,aSortIndex,startPos,ii+1);
+ }
+ }
+
+
+void CContactDatabase::SortDuplicatesL(const CArrayFix<TSortPref>& /*aSortOrder*/,CSortArray& /*aList*/,
+ TInt /*aIndex*/,TInt /*aStartPos*/,TInt /*aEndPos*/)
+ {
+ }
+
+
+TBool CContactDatabase::CheckType(TUid aUid) const
+ {
+ // checks the view on the db whether the uid supplied complies to the rules below
+ if (aUid == KUidContactTemplate) // do not include golden template;
+ return EFalse;
+ if (iDbViewContactType == KUidContactItem) // any type of contact;
+ return ETrue;
+ if (iDbViewContactType == KUidContactCardOrGroup &&
+ (aUid == KUidContactCard || aUid == KUidContactGroup)) // cards and/or groups
+ return ETrue;
+ if (iDbViewContactType == KUidContactCard && aUid == KUidContactOwnCard)
+ // if the card being checked is an own card - allow it to be included
+ return ETrue;
+ else if (aUid == iDbViewContactType) // only a specific match
+ return ETrue;
+ return EFalse;
+ }
+
+
+/**
+Sets the template id on the contact item to that of the SystemTemplate
+after each update or commit operation.
+*/
+void CContactDatabase::CheckTemplateField(CContactItem& aCnt)
+ {
+ if (aCnt.iTemplateRefId == KNoValueSet)
+ {
+ aCnt.iTemplateRefId = KGoldenTemplateId;
+ }
+ if (aCnt.iAccessCount == (TUint32)KNoValueSet)
+ {
+ aCnt.iAccessCount = 0;
+ }
+ }
+
+
+/**
+Opens a contact item for editing using a specified view definition.
+
+The returned contact item is locked and left open until either CommitContactL() or CloseContactL()
+is called.
+
+Note: care should be taken when specifying a view definition because when committing
+the contact item, any fields not loaded by the view definition are deleted
+from the item.
+
+The caller takes ownership of the returned object.
+
+@deprecated
+@capability WriteUserData
+
+@param aContactId The ID of the contact item to open.
+
+@leave KErrInUse The contact item is already open.
+@leave KErrNotFound The contact item is not present in the database.
+
+@return The open, locked contact.
+*/
+EXPORT_C CContactItem* CContactDatabase::OpenContactLX(TContactItemId aContactId)
+ {
+ // Since the AllFieldsView method returns a modifiable ptr to the iAllFieldsView
+ // we must always send it across the IPC as it may have changed.
+ return OpenContactLX(aContactId, *iAllFieldsView);
+ }
+
+
+/**
+Opens a contact item for editing.
+
+The returned contact item is locked and left open until either CommitContactL()
+or CloseContactL() is called.
+
+This function uses a view definition that loads every field. If you need to
+specify your own view definition use the other overload of this function.
+
+The caller takes ownership of the returned object.
+
+@capability WriteUserData
+
+@param aContactId The ID of the contact item to open.
+
+@return The open, locked contact.
+
+@leave KErrInUse The contact item is already open.
+@leave KErrNotFound The contact item is not present in the database.
+*/
+EXPORT_C CContactItem* CContactDatabase::OpenContactL(TContactItemId aContactId)
+ {
+ CContactItem* cntItem = OpenContactLX(aContactId);
+ CleanupStack::Pop(); // Pop the lock
+ return cntItem;
+ }
+
+
+/**
+Opens a contact item for editing, leaving the lock record on the cleanup stack.
+
+The returned item is locked and left open until either CommitContactL() or
+CloseContactL() is called.
+
+This function uses the specified view definition. Note: Care should be taken
+when specifying a view definition because when committing the contact item
+any fields not loaded by the view definition are deleted from the item.
+
+The caller takes ownership of the returned object.
+
+@deprecated
+@capability WriteUserData
+
+@param aContactId The ID of the contact item to open.
+@param aViewDef The view definition.
+
+@return The open, locked contact item.
+
+@leave KErrInUse The contact item is already open
+@leave KErrNotFound The contact item is not present in the database.
+*/
+EXPORT_C CContactItem* CContactDatabase::OpenContactL(TContactItemId aContactId, const CContactItemViewDef& aViewDef)
+ {
+ CContactItem* cntItem = OpenContactLX(aContactId, aViewDef);
+ CleanupStack::Pop();
+ return cntItem;
+ }
+
+
+/**
+Opens a contact item for editing, leaving the lock record on the cleanup stack.
+
+The returned item is locked and left open until either CommitContactL() or
+CloseContactL() is called.
+
+This function uses the specified view definition. Note: Care should be taken
+when specifying a view definition because when committing the contact item
+any fields not loaded by the view definition are deleted from the item.
+
+The caller takes ownership of the returned object.
+
+@deprecated
+@capability WriteUserData
+
+@param aContactId The ID of the contact item to open.
+@param aViewDef The view definition.
+
+@return The open, locked contact item.
+
+@leave KErrInUse The contact item is already open
+@leave KErrNotFound The contact item is not present in the database.
+*/
+EXPORT_C CContactItem* CContactDatabase::OpenContactLX(TContactItemId aContactId, const CContactItemViewDef& aViewDef)
+ {
+ CContactItem* cntItem = iCntSvr->OpenContactLX(&aViewDef, aContactId);
+
+ CleanupStack::PushL(cntItem);
+ iTemplateCache->MergeWithTemplateL(*cntItem, &aViewDef);
+
+ CleanupStack::Pop(cntItem);
+ return cntItem;
+ }
+
+
+CContactItem* CContactDatabase::OpenNoMergeLCX(TContactItemId aContactId)
+ {
+ CContactItem* cntItem = iCntSvr->OpenContactLX(NULL, aContactId);
+ CleanupStack::PushL(cntItem);
+
+ return cntItem;
+ }
+
+
+/**
+Gets the ID of the system template. This can then be read, opened and committed
+like any other contact item.
+
+@return ID of the system template.
+*/
+EXPORT_C TContactItemId CContactDatabase::TemplateId() const
+ {
+ return iTemplateCache->TemplateId();
+ }
+
+
+/**
+Creates a default own card based on the system template and adds it to the
+database. This is set as the database's current own card, replacing any existing
+current own card. The caller takes ownership of the returned object.
+
+@capability WriteUserData
+
+@return Pointer to the new default own card. The pointer is left on the cleanup
+stack.
+*/
+EXPORT_C CContactItem* CContactDatabase::CreateOwnCardLC()
+ {
+ CContactCard* ownCard = CContactCard::NewLC(&iTemplateCache->SystemTemplateL());
+ TInt cntId = AddNewContactL(*ownCard);
+ ownCard->iId = cntId;
+ // set and persist newowncard id
+ iCntSvr->SetOwnCardL(*ownCard);
+ CleanupStack::PopAndDestroy(ownCard);
+ return ReadContactLC(cntId);
+ }
+
+
+/**
+Creates a default own card based on the system template and adds it to the
+database. This is set as the database's current own card, replacing any existing
+current own card. The caller takes ownership of the returned object.
+
+@capability WriteUserData
+
+@return Pointer to the new default own card.
+*/
+EXPORT_C CContactItem* CContactDatabase::CreateOwnCardL()
+ {
+ CContactItem* ownCard = CreateOwnCardLC();
+ CleanupStack::Pop(ownCard);
+ return ownCard;
+ }
+
+
+/**
+Returns the ID of the database's current own card.
+
+Having obtained this ID, the client may then open the own card in the same
+way as an ordinary contact card (using ReadContactL() or OpenContactL()).
+
+@capability None
+
+@return The ID of the database's current own card. KNullContactId if the own
+card has been deleted or has not yet been set.
+*/
+EXPORT_C TContactItemId CContactDatabase::OwnCardId() const
+ {
+ return iCntSvr->OwnCard();
+ }
+
+
+/**
+Returns the ID of the database's preferred template, as set by SetPrefTemplateL().
+KNullContactId if not set. The preferred template is for clients who may have
+multiple templates but want to identify one as preferred.
+
+@capability None
+
+@return The ID of the database's current preferred template.
+*/
+EXPORT_C TContactItemId CContactDatabase::PrefTemplateId() const
+ {
+ return(iCntSvr->PrefTemplateId());
+ }
+
+
+/**
+Sets an existing contact item to be the database's current own card.
+
+@capability WriteUserData
+
+@param aContact The contact item to set as the database's current own card.
+It must already exist in the database. It cannot be a group or a template.
+
+@leave KErrNotFound aContact does not exist in the database.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::SetOwnCardL(const CContactItem& aContact)
+ {
+ iCntSvr->SetOwnCardL(aContact);
+ }
+
+
+/**
+Sets the time out of operations on the database server.
+
+This API allows the behaviour of the Contacts Model to be tuned for scenarios
+where clients either expect to encounter or know they will encounter operations
+failing primarily due to the database being locked.
+
+Not all clients will find they need to use this API. By default the operation
+timeout is 1 second.
+
+The timeout only needs to be set once per session. Multiple clients using the
+same database can specify independent values for the operation timeout.
+
+@capability None
+
+@publishedPartner
+
+@released
+
+@param aMicroSeconds The operation timeout in microseconds. This timeout will
+only be applied to requests sent by clients of this database after this point in
+time.
+
+@leave KErrArgument If aMicroSeconds is less than 0 or is greater than 300000000
+(equivalent to 5 minutes).
+*/
+EXPORT_C void CContactDatabase::SetOperationTimeOutL(const TInt aMicroSeconds) const
+ {
+ if (aMicroSeconds < 0 || aMicroSeconds > KFiveMins)
+ {
+ User::Leave(KErrArgument);
+ }
+ iCntSvr->SetOperationTimeOutL(aMicroSeconds);
+ }
+
+
+/**
+Sets the database's preferred template.
+
+The preferred template's ID persists when the database is opened and closed.
+If the preferred template is subsequently deleted, the preferred template
+ID is set to KNullContactId.
+
+@capability WriteUserData
+
+@param aContact The contact card template to set as the database's preferred
+template.
+
+@leave KErrNotSupported The item is not a template (of type KUidContactCardTemplate).
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::SetPrefTemplateL(const CContactItem& aContact)
+ {
+ TUid aContactType = aContact.Type();
+ __ASSERT_ALWAYS(aContactType==KUidContactCardTemplate,User::Leave(KErrNotSupported));
+ if (aContact.Id()==PrefTemplateId())
+ {
+ // leave quietly if already set as the preferred template
+ return;
+ }
+ iCntSvr->SetPrefTemplateL(aContact.Id());
+ }
+
+
+/**
+Sets the ID of the current item and persists it in the database. The current
+item is provided for use by clients who want to identify one contact item
+in the database as the currently selected item.
+
+@capability WriteUserData
+
+@param aContactId The ID of the current item.
+*/
+EXPORT_C void CContactDatabase::SetCurrentItem(const TContactItemId aContactId)
+ {
+ iCntSvr->SetCurrentItem(aContactId);
+ }
+
+
+/**
+Gets the ID of the current item, as set by SetCurrentItem(). The current item
+ID is initialised to KNullContactId when the database is opened.
+
+@capability None
+
+@return The ID of the current item.
+*/
+EXPORT_C TContactItemId CContactDatabase::GetCurrentItem() const
+ {
+ return iCntSvr->CurrentItem();
+ }
+
+
+/**
+Updates a contact identified by aContactId with the data in aNewContact.
+All empty fields are deleted.
+
+@deprecated
+@publishedPartner
+
+@capability WriteUserData
+@capability ReadUserData
+
+@param aContactId This argument should be ignored by developers.
+@param aNewContact The contact item to replace it with.
+
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+
+@return The contact item after the update.
+*/
+EXPORT_C CContactItem* CContactDatabase::UpdateContactLC(TContactItemId aContactId,CContactItem* aNewContact)
+ {
+ CContactItemViewDef* viewDef = CContactItemViewDef::NewLC(CContactItemViewDef::EIncludeFields,CContactItemViewDef::EIncludeHiddenFields);
+ viewDef->AddL(KUidContactFieldMatchAll);
+
+ CContactItem* cntItem = OpenContactLX(aContactId, *viewDef);
+ CleanupStack::PushL(cntItem);
+
+ CContactItemFieldSet& newfieldSet = aNewContact->CardFields();
+
+ TInt count=newfieldSet.Count();
+ for (TInt ii=0; ii<count; ++ii)
+ {
+ //In the case there are duplicate fields in the field Set
+ //matchCount need to be increased, so the previous field won't be
+ //overwritten by the later one.
+ TInt matchCount =1;
+ for (TInt jj=ii-1; jj>=0; jj--)
+ {
+ if(newfieldSet[ii].ContentType()==newfieldSet[jj].ContentType())
+ matchCount++;
+ }
+
+ cntItem->CardFields().UpdateFieldL(newfieldSet[ii],matchCount);
+ }
+
+ doCommitContactL(*cntItem,ETrue,ETrue);
+ if (!count)
+ {
+ doDeleteContactL(aContactId,ETrue,ETrue);
+ delete cntItem;
+ cntItem = NULL;
+ }
+
+ if(cntItem != NULL)
+ {
+ CleanupStack::Pop(cntItem);
+ CleanupStack::Pop(); // Pop the lock
+ CleanupStack::PopAndDestroy(viewDef);
+ CheckTemplateField(*cntItem);
+
+ CleanupStack::PushL(cntItem);
+ }
+ return(cntItem);
+ }
+
+
+/**
+Closes the contact item, allowing other applications to access it. Specifying
+a contact item that is not open, or cannot be found, is harmless. This function
+does not commit any changes made to the item. Despite the trailing L in the
+function's name, this function cannot leave.
+
+@capability None
+
+@param aContactId The ID of the contact to close.
+*/
+EXPORT_C void CContactDatabase::CloseContactL(TContactItemId aContactId)
+ {
+ iCntSvr->CloseContact(aContactId);
+ }
+
+
+/**
+Overwrites a contact item with the values contained in aContact. The contact
+item is also closed by this call.
+
+@capability ReadUserData
+@capability WriteUserData
+
+@param aContact Contains the new values for the contact item.
+
+@leave KErrAccessDenied The contact item is not locked by the caller.
+@leave KErrNotFound The contact item's ID is not present in the database.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+@leave KErrNotSupported The contact item cannot be committed because it contains
+invalid data.
+*/
+EXPORT_C void CContactDatabase::CommitContactL(const CContactItem& aContact)
+ {
+ // If the contact item being committed is the System template then check if
+ // the fields are valid.
+ if (aContact.Id()==TemplateId())
+ {
+ if (!SystemTemplateFieldsValid(aContact))
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+ iCntSvr->CommitContactL(aContact);
+ RespondToEventL(EContactDbObserverEventTemplateChanged, aContact.Id());
+ }
+
+
+/** Updates the existing contact information.
+@publishedPartner
+@released
+
+@capability ReadUserData
+@capability WriteUserData
+
+@param aContact Contains the new values for the contact item.
+@param aIsInTransaction This argument should be ignored by developers.
+@param aSendChangedEvent This argument should be ignored by developers.
+
+@leave KErrAccessDenied The contact item is not locked by the caller.
+@leave KErrNotFound The contact item's ID is not present in the database.
+@leave KErrNotSupported The contact item cannot be committed because it contains
+invalid data.
+*/
+EXPORT_C void CContactDatabase::doCommitContactL(const CContactItem& aContact,TBool /*aIsInTransaction*/, TBool aSendChangedEvent)
+ {
+ // If the contact item being committed is the System template then check if
+ // the fields are valid.
+ if (aContact.Id()==TemplateId())
+ {
+ if (!SystemTemplateFieldsValid(aContact))
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+ iCntSvr->CommitContactL(aContact, aSendChangedEvent);
+ MoveInSortArray(aContact);
+ }
+
+
+/**
+Deletes an array of contacts.
+
+The function commits the changes for every 32 (for 9.5 onwards it commits after every 50)
+contacts deleted, and compresses the database as required. A changed message
+is not sent for every contact deleted, instead a single unknown change event
+message (EContactDbObserverEventUnknownChanges) is sent after all the contacts
+have been deleted and the changes committed.
+
+@capability WriteUserData
+@capability ReadUserData
+
+@param aContactIds An array of contacts to delete.
+
+@leave KErrNotFound A contact item ID contained in the array is not present
+in the database.
+@leave KErrInUse One or more of the contact items is open.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::DeleteContactsL(const CContactIdArray& aContactIds)
+ {
+ const TInt KDeleteTransactionGranularity = 50;
+ TInt count = aContactIds.Count();
+ if (count == 0)
+ {
+ return;
+ }
+
+ // Clone the ContactIdArray so it can be sorted into ascending order
+ CContactIdArray* sortedIdArray = CContactIdArray::NewLC(&aContactIds);
+ sortedIdArray->Sort();
+
+ if (count > 1)
+ {
+ for(TInt ii = 0; ii < count-1; ++ii)
+ {
+ if ((ii % KDeleteTransactionGranularity) == 0)
+ {
+ if (ii > 0)
+ {
+ DatabaseCommitLP(EFalse);
+ }
+ DatabaseBeginLC(EFalse);
+ }
+ // Delete the contact but do not trigger any event
+ DeleteContactSendEventActionL((*sortedIdArray)[ii], EDeferEvent);
+ }
+ }
+ else
+ { // edge case
+ DatabaseBeginLC(EFalse);
+ }
+
+ // Delete the last item and trigger EContactDbObserverEventUnknownChanges
+ DeleteContactSendEventActionL((*sortedIdArray)[count-1], ESendUnknownChangesEvent);
+
+ DatabaseCommitLP(EFalse);
+
+ CleanupStack::PopAndDestroy(sortedIdArray);
+ }
+
+
+/**
+Deletes a contact item.
+
+Note: if the contact's access count is greater than zero, the contact is not fully
+deleted from the database. A 'skeleton' of the contact is left, containing only
+basic information, and no field data. The skeleton contact can still be accessed
+if a record of its contact ID has been retained (or call DeletedContactsLC()).
+The skeleton is removed when the access count is zero.
+
+@capability ReadUserData
+@capability WriteUserData
+
+@param aContactId The contact item ID of the contact to delete.
+
+@leave KErrNotFound aContactId is not present in the database.
+@leave KErrInUse The contact item is open.
+@leave KErrDiskFull The disk does not have enough free space to perform the operation.
+*/
+EXPORT_C void CContactDatabase::DeleteContactL(TContactItemId aContactId)
+ {
+ iCntSvr->DeleteContactL(aContactId, ESendEvent);
+ //Now we check if the contact belonged to the sort array, if so
+ //remove it from iSortedItems
+ RemoveFromSortArray(aContactId);
+ //Now we check if the contact belonged to the template list, if so
+ //remove it from iCardTemplateIds
+ RemoveFromTemplateList(aContactId);
+ //Now we check if the contact belonged to the Group Id list, if so
+ //remove it from iGroupIds
+ RemoveFromGroupIds(aContactId);
+ }
+
+
+/**
+Deletes a contact item.
+
+Note: if the contact's access count is greater than zero, the contact is not fully
+deleted from the database. A 'skeleton' of the contact is left, containing only
+basic information, and no field data. The skeleton contact can still be accessed
+if a record of its contact ID has been retained (or call DeletedContactsLC()).
+The skeleton is removed when the access count is zero.
+
+@publishedPartner
+@released
+
+@capability ReadUserData
+@capability WriteUserData
+
+@param aContactId The contact item ID of the contact to delete.
+@param aIsInTransaction This argument should be ignored by developers.
+@param aSendChangedEvent This argument should be ignored by developers.
+@param aDecAccessCount This argument should be ignored by developers.
+
+@leave KErrNotSupported An attempt has been made to delete the system template.
+@leave KErrNotFound aContactId is not present in the database.
+@leave KErrInUse The contact item is open.
+*/
+EXPORT_C void CContactDatabase::doDeleteContactL(TContactItemId aContactId, TBool /*aIsInTransaction*/, TBool aSendChangedEvent, TBool aDecAccessCount)
+ {
+ TCntSendEventAction action = aSendChangedEvent ? ESendEvent : EDeferEvent;
+ iCntSvr->DeleteContactL(aContactId, action, aDecAccessCount);
+ //Now we check if the contact belonged to the sort array, if so
+ //remove it from iSortedItems
+ RemoveFromSortArray(aContactId);
+ //Now we check if the contact belonged to the template list, if so
+ //remove it from iCardTemplateIds
+ RemoveFromTemplateList(aContactId);
+ //Now we check if the contact belonged to the Group Id list, if so
+ //remove it from iGroupIds
+ RemoveFromGroupIds(aContactId);
+ }
+
+
+/**
+Returns the full view definition, that loads every field,
+the returned pointer is owned by the CContactDatabase object.
+
+@publishedPartner
+@released
+
+@capability None
+
+@return The definition for a full view with all the contact item fields.
+*/
+EXPORT_C CContactItemViewDef* CContactDatabase::AllFieldsView()
+ {
+ return iAllFieldsView;
+ }
+
+
+/**
+Imports one or more vCards from a read stream. The vCards are converted into
+contact items, and added to the database. If at least one contact item was
+successfully imported, aImportSuccessful is set to ETrue. If EImportSingleContact
+is specified in aOption, the read stream marker is left at the next position,
+ready to read the next contact item. The caller takes ownership of the returned
+object.
+
+@capability WriteUserData
+
+@param aFormat Indicates the format for imported and exported contacts. Its
+value must be KUidVCardConvDefaultImpl.
+@param aReadStream The stream to read from.
+@param aImportSuccessful On return, ETrue if at least one contact was successfully
+imported. EFalse if not.
+@param aOption Indicates the options for import and export. See the TOptions
+enum.
+
+@leave KErrNotSupported aFormat.iUid is not KUidVCardConvDefaultImpl.
+
+@return The array of contact items imported.
+*/
+EXPORT_C CArrayPtr<CContactItem>* CContactDatabase::ImportContactsL(const TUid& aFormat,RReadStream& aReadStream,TBool& aImportSuccessful,TInt aOption)
+ {
+ const TBool importSingleContact= aOption & EImportSingleContact;
+ return ConverterL(aFormat).ImportL(*this,aReadStream,aImportSuccessful,aOption,importSingleContact);
+ }
+
+
+/**
+Converts an array of contact items to vCards and exports them to a write stream.
+
+The default character set CVersitParser::EUTF8CharSet is used to convert into. If
+you need a different character set, use the other overload of this function.
+
+@capability ReadUserData
+
+@param aFormat Indicates the format for imported and exported contacts. Must
+have a value of KUidVCardConvDefaultImpl.
+@param aSelectedContactIds Array of contact IDs to export.
+@param aWriteStream The stream to write to.
+@param aOption Indicates the options for import and export. See the TOptions
+enum.
+@param aExportPrivateFields ETrue exports fields marked as private. EFalse
+does not export fields marked as private. See CContactItemField::SetPrivate().
+
+@leave KErrNotSupported aFormat.iUid is not KUidVCardConvDefaultImpl.
+@leave KErrNotFound One or more of the contact items does not exist in the
+database.
+*/
+EXPORT_C void CContactDatabase::ExportSelectedContactsL(const TUid& aFormat,const CContactIdArray& aSelectedContactIds, RWriteStream& aWriteStream, TInt aOption, TBool aExportPrivateFields)
+ {
+ ExportSelectedContactsL(aFormat,aSelectedContactIds,aWriteStream,aOption,Versit::EUTF8CharSet,aExportPrivateFields);
+ }
+
+
+/**
+Converts an array of contact items to vCards and exports them to a write
+stream using the specified character set.
+
+@capability ReadUserData
+
+@param aFormat Indicates the format for imported and exported contacts. Must
+have a value of KUidVCardConvDefaultImpl.
+@param aSelectedContactIds Array of contact IDs to export.
+@param aWriteStream The stream to write to.
+@param aOption Indicates the options for import and export. See the TOptions
+enum.
+@param aCharSet The character set to convert into.
+@param aExportPrivateFields ETrue exports fields marked as private. EFalse
+does not export fields marked as private. See CContactItemField::SetPrivate().
+
+@leave KErrNotSupported aFormat.iUid is not KUidVCardConvDefaultImpl.
+@leave KErrNotFound One or more of the contact items does not exist in the
+database.
+*/
+EXPORT_C void CContactDatabase::ExportSelectedContactsL(const TUid& aFormat,const CContactIdArray& aSelectedContactIds, RWriteStream& aWriteStream,TInt aOption,const Versit::TVersitCharSet aCharSet, TBool aExportPrivateFields)
+ {
+ ConverterL(aFormat).ExportL(*this,aSelectedContactIds,aWriteStream,aOption,aCharSet,aExportPrivateFields);
+ }
+
+
+/**
+Converts an array of contact items to PBAP compliant vCards following vCard2.1 and vCard3.0 specifications and exports them to a write
+stream using UTF-8 as the character set. It also provides support for exporting contacts as standard vCard2.1.
+
+@capability ReadUserData
+@internalTechnology
+@released
+
+@param aFormat Indicates the format for imported and exported contacts. It should have a value of KUidPBAPVCardConvImpl if user
+wants to export contacts as PBAP specific vCards and KUidVCardConvDefaultImpl for standard vCard2.1.
+@param aSelectedContactIds Array of contact IDs to export.
+@param aWriteStream The stream to write to.
+@param aOption Indicates the options for import and export. See the TOptions
+enum.
+@param aContactFieldFilter 64-bit filter,specifies the contact fields to export, argument value not considered for standard vCard2.1 export.
+@param aCallback Calls client which has to implement class MConverterCallBack, used to add intra-contact properties,
+argument value not considered for standard vCard2.1 export.
+@param aVersion TVCardVersion specifies vCard version to which contacts should be exported.
+@param aExportTel If TEL property should be exported, it should be set to ETrue, argument value not considered for standard vCard2.1 export.
+@param aCharSet The character set to convert into.Must be UTF-8 for PBAP export, provided as default value.
+@param aExportPrivateFields ETrue exports fields marked as private. EFalse does not export fields marked as private. See CContactItemField::SetPrivate().
+
+@leave KErrNotSupported aFormat.iUid is not KUidPBAPVCardConvImpl for PBAP export.
+@leave KErrNotSupported aFormat.iUid is not KUidVCardConvDefaultImpl for standard vCard2.1 export.
+@leave KErrNotSupported aCharSet is other than UTF-8 for PBAP export.
+@leave KErrNotFound One or more of the contact items does not exist in the database.
+*/
+EXPORT_C void CContactDatabase::ExportSelectedContactsL(const TUid& aFormat, const CContactIdArray& aSelectedContactIds, RWriteStream& aWriteStream, TInt aOption, const TInt64 aContactFieldFilter, MConverterCallBack* aCallback, const TVCardVersion aVersion, const TBool aExportTel, Versit::TVersitCharSet aCharSet, TBool aExportPrivateFields)
+ {
+ if(aVersion == EVCard21)
+ {
+ //client wants to export contacts as standard vCard2.1.
+ ConverterL(aFormat).ExportL(*this, aSelectedContactIds, aWriteStream, aOption, aCharSet, aExportPrivateFields);
+ }
+ else
+ {
+ if(aCharSet != Versit::EUTF8CharSet)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ ConverterL(aFormat, aContactFieldFilter, aCallback, aVersion, aExportTel).ExportL(*this, aSelectedContactIds, aWriteStream, aOption, aCharSet, aExportPrivateFields);
+ }
+ }
+
+CContactConverter& CContactDatabase::ConverterL(const TUid& aFormat, const TInt64 aContactFieldFilter, MConverterCallBack* aCallback, const TVCardVersion aVersion, const TBool aExportTel)
+ {
+ if(aFormat.iUid != KUidPBAPVCardConvImpl)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ //since version, filter and boolean TEL are initialised only when PBAP plug-in is created,
+ //if there is any change in these arguments provided by Client, The plugin should be loaded once again.
+ if(iConv && (iConv->GetCurrentVersion() != aVersion || iConv->GetPBAPFilter() != aContactFieldFilter || iConv->GetExportTel() != aExportTel) )
+ {
+ delete iConv;
+ iConv = NULL;
+ }
+ if(!iConv)
+ {
+ iConv = CPrivConverter::NewL(aFormat, aContactFieldFilter, aCallback, aVersion, aExportTel);
+ }
+ return *iConv->Converter();
+ }
+
+
+CContactConverter& CContactDatabase::ConverterL(const TUid& aFormat)
+ {
+ if(iConv && iConv->GetCurrentVersion() != EVCard21)
+ {
+ delete iConv;
+ iConv = NULL;
+ }
+
+ switch (aFormat.iUid)
+ {
+ case KVersitEntityUidVCard:
+ case KUidVCardConvDefaultImpl:
+ if (!iConv)
+ {
+ if(aFormat.iUid == KVersitEntityUidVCard)
+ {
+ iConv=CPrivConverter::NewL( TUid::Uid(KUidVCardConvDefaultImpl));
+ }
+ else
+ {
+ iConv=CPrivConverter::NewL(aFormat);
+ }
+ }
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ };
+
+ return *iConv->Converter();
+ }
+
+
+/**
+Searches the contact tables for the contact described by aGuid.
+
+@publishedPartner
+@released
+@capability ReadUserData
+
+@param aGuid Describes the contact item to be found.
+
+@leave KErrNotReady The database is not yet ready to read from, could be because an asynchronous open is in progress
+or because a recover is required after a rollback.
+@leave KErrBadHandle An asynchronous open either failed or was cancelled.
+@leave KErrLocked The database has been closed for a restore.
+
+@return The unique id of the contact item within the database.
+*/
+EXPORT_C TContactItemId CContactDatabase::ContactIdByGuidL(const TDesC& aGuid)
+ {
+ TTime time(0);
+ MLplCollection& collection = FactoryL()->GetCollectorL();
+ CContactIdArray* idArray = collection.CollectionL(MLplCollection::EFindGuid,time,aGuid);
+ // Assume a contact with aGuid will not be found.
+ TContactItemId id = KNullContactId;
+ // Check there is an entry in idArray before attempting to access it.
+ if(idArray->Count() > 0)
+ {
+ // Since aGuid is unique only one contact can match it therefore always
+ // expect one and only one entry in the array.
+ id = (*idArray)[0];
+ }
+ delete idArray;
+ return id;
+ }
+
+
+/**
+Returns a pointer to the array of contact items which have been sorted by either
+SortByTypeL() or SortL(). This pointer is valid until a change is made to
+the database or until the database's active object is allowed to run. If
+the array is required after one of the above two events has occurred, a copy
+of the array must first be made.
+
+@deprecated
+@capability None
+
+@return A pointer to the array of sorted items. The caller does not take ownership
+of this object.
+*/
+EXPORT_C const CContactIdArray* CContactDatabase::SortedItemsL()
+ {
+ if(!iSortedItems)
+ {
+ CArrayFix<TSortPref>* sortPref = iCntSvr->GetSortPreferenceL();
+ CleanupStack::PushL(sortPref);
+ iSortedItems = SortLC(sortPref,NULL);
+ CleanupStack::Pop(iSortedItems);
+ CleanupStack::PopAndDestroy(sortPref);
+ }
+ return iSortedItems;
+ }
+
+
+/**
+Gets the database's UID. This value is used to identify a particular contact
+database. The database UID is generated when the database is first created.
+
+Note: This method can leave.
+
+@capability None
+
+@return Descriptor containing the database UID.
+*/
+EXPORT_C TPtrC CContactDatabase::FileUid()
+ {
+ return iCntSvr->FileUidL(); // this can leave
+ }
+
+
+/**
+Sorts an array of contact IDs. The sort uses the same logic as SortL(). The
+caller takes ownership of the returned object.
+
+@deprecated
+@capability None
+
+@param aIdArray Pointer to array of contact IDs to sort.
+@param aSortOrder Sort order array.
+
+@return Pointer to sorted array of contact IDs.
+*/
+EXPORT_C CContactIdArray* CContactDatabase::SortArrayL(const CContactIdArray* aIdArray, const CArrayFix<TSortPref>* aSortOrder)
+ {
+ CContactIdArray* sortedItems = SortArrayLC(aIdArray, aSortOrder);
+ CleanupStack::Pop(sortedItems);
+ return (sortedItems);
+ }
+
+
+/**
+Sorts an array of contact IDs. The sort uses the same logic as SortL(). The
+returned array is left on the cleanup stack. The caller takes ownership of
+the returned object.
+
+@deprecated
+@capability None
+
+@param aIdArray Pointer to array of contact IDs to sort.
+@param aSortOrder Sort order array.
+
+@return Pointer to sorted array of contact IDs.
+*/
+EXPORT_C CContactIdArray* CContactDatabase::SortArrayLC(const CContactIdArray* aIdArray, const CArrayFix<TSortPref>* aSortOrder)
+ {
+ return SortLC(aSortOrder,aIdArray);
+ }
+
+
+/**
+Sorts the database using the view type value set by SetDbViewContactType().
+The database takes ownership of the sort order array passed in.
+
+The sort uses the same logic as SortL(). The two functions have the same
+effect.
+
+After calling this function, use CContactDatabase::SortedItemsL() to retrieve
+the sorted array of contact IDs.
+
+@deprecated
+@capability None
+
+@param aSortOrder Sort order array.
+*/
+EXPORT_C void CContactDatabase::SortByTypeL(CArrayFix<TSortPref>* aSortOrder)
+ {
+ CContactIdArray* sortedItems=SortLC(aSortOrder,NULL);
+ CleanupStack::Pop(sortedItems);
+ delete iSortedItems;
+ iSortedItems=sortedItems;
+ iCntSvr->SetSortPreferenceL(*aSortOrder);
+ delete aSortOrder;
+ }
+
+
+/**
+Sorts the database. The sort only includes items of the type set by SetDbViewContactType().
+The database takes ownership of the sort order array passed in. Contacts are
+sorted using the first TSortPref in the array. Any identical matches are then
+sorted using the next TSortPref and so on. When there are no more TSortPrefs
+to use, any remaining unsorted contacts are left in the original database order.
+
+Note: after calling this function, use CContactDatabase::SortedItemsL() to retrieve
+the sorted array of contact IDs.
+
+@deprecated
+@capability None
+
+@param aSortOrder Sort order array. If the array's count is zero, no sorting
+takes place.
+*/
+EXPORT_C void CContactDatabase::SortL(CArrayFix<TSortPref>* aSortOrder)
+ {
+ TBool reverse=ETrue;
+ CArrayFix<TSortPref>* sortPref = iCntSvr->GetSortPreferenceL();
+ CleanupStack::PushL(sortPref);
+ if (aSortOrder->Count()!=sortPref->Count())
+ reverse=EFalse;
+ else for(TInt loop=0;loop<aSortOrder->Count();loop++)
+ {
+ TSortPref oldSort=(*sortPref)[loop];
+ TSortPref newSort=(*aSortOrder)[loop];
+ if (oldSort.iFieldType!=newSort.iFieldType || oldSort.iOrder==newSort.iOrder)
+ {
+ reverse=EFalse;
+ break;
+ }
+ }
+ if (reverse)
+ {
+ if (iSortedItems)
+ iSortedItems->ReverseOrder();
+ }
+ else
+ {
+ ReSortL(aSortOrder);
+ }
+
+ iCntSvr->SetSortPreferenceL(*aSortOrder);
+ CleanupStack::PopAndDestroy(sortPref);
+
+ // Having taken ownership, we deleted aSortOrder here after storing the sort
+ // preferences in iCntSrv. Earlier versions of cntmodel stored it in
+ // iSortOrder. Some 3rd party apps wrongly use aSortOrder after calling us.
+ // As it was held until deletion in the destructor, they used to get away
+ // with it. Since the new way broke these apps, we've reverted to the old
+ // delayed deletion to maintain compatibility, reinstating iSortOrder.
+ delete iSortOrder;
+ iSortOrder = aSortOrder;
+ }
+
+
+/**
+Gets the number of CContactItems in the database. The count includes non-system
+template items. It does not include items marked as deleted.
+
+@deprecated
+@capability None
+
+@return The number of contact items in the database.
+*/
+EXPORT_C TInt CContactDatabase::CountL()
+ {
+ MLplCollection& collection = FactoryL()->GetCollectorL();
+ return collection.ContactCountL();
+ }
+
+
+/**
+Sets the type of contact items to be included in sorted views of the database.
+
+See also SortL() and SortByTypeL().
+
+This value is initialised to KUidContactItem when the database is opened.
+This means that all CContactItem-derived types (cards, non-system templates,
+groups, own cards) are included in database views.
+
+@deprecated
+@capability None
+
+@param aUid Specifies a contact type. One of the following: KUidContactCard
+(contact cards), KUidContactGroup (contact item groups), KUidContactOwnCard
+(own cards), KUidContactCardTemplate (templates which are not system templates,
+in other words, which have been added to the database), KUidContactItem (all of the above)
+*/
+EXPORT_C void CContactDatabase::SetDbViewContactType(const TUid aUid)
+ {
+ iDbViewContactType = aUid;
+ iCntSvr->SetDbViewContactType(aUid);
+ }
+
+
+/**
+Gets the type of contact items which are included in sorted views of the database,
+as set by SetDbViewContactType().
+
+@deprecated
+
+@return Specifies a contact type. One of the following: KUidContactCard
+(contact cards), KUidContactGroup (contact item groups), KUidContactOwnCard
+(own cards), KUidContactCardTemplate (templates which are not system, in other words,
+which have been added to the database), KUidContactItem (all of the above)
+*/
+EXPORT_C TUid CContactDatabase::GetDbViewContactType() const
+ {
+ return iDbViewContactType;
+ }
+
+
+/**
+This function does nothing and has been deprecated.
+
+@capability WriteUserData
+@deprecated
+*/
+EXPORT_C void CContactDatabase::CompactL()
+ {
+ }
+
+
+/**
+This function is deprecated. It returns an object whose functions do nothing.
+
+@capability WriteUserData
+@return Pointer to an active compressor.
+@deprecated
+*/
+EXPORT_C CContactActiveCompress* CContactDatabase::CreateCompressorLC()
+ {
+ CContactActiveCompress* compressor = new (ELeave) CContactActiveCompress;
+ CleanupStack::PushL(compressor);
+ return compressor;
+ }
+
+
+/**
+This function is deprecated. It returns an object whose functions do nothing.
+
+@capability WriteUserData
+@return Pointer to an active recoverer.
+@deprecated
+*/
+EXPORT_C CContactActiveRecover* CContactDatabase::CreateRecoverLC()
+ {
+ CContactActiveRecover* recover = new(ELeave) CContactActiveRecover;
+ CleanupStack::PushL(recover);
+ return recover;
+ }
+
+
+/**
+Recovers the database from a rollback. It first closes all tables and then reopens
+them after the recover.
+
+@capability WriteUserData
+*/
+EXPORT_C void CContactDatabase::RecoverL()
+ {
+ }
+
+
+/**
+This function is deprecated. It always returns EFalse.
+
+@capability None
+@return EFalse
+@deprecated
+*/
+EXPORT_C TBool CContactDatabase::CompressRequired()
+ {
+ return EFalse;
+ }
+
+
+/**
+This function is deprecated. It always returns EFalse.
+
+@capability None
+@return EFalse
+@deprecated
+*/
+EXPORT_C TBool CContactDatabase::IsDamaged() const
+ {
+ return EFalse;
+ }
+
+
+/**
+Debug Only
+
+@internalTechnology
+@released
+@capability WriteUserData
+*/
+EXPORT_C void CContactDatabase::DamageDatabaseL(TInt /*aSecretCode*/)
+ {
+ }
+
+
+/**
+Gets the size of the database file in bytes.
+
+@capability None
+
+@return The size of the contact database.
+*/
+EXPORT_C TInt CContactDatabase::FileSize() const
+ {
+ return iCntSvr->FileSize();
+ }
+
+
+/**
+This function is deprecated and always returns 0.
+
+@capability None
+@return The wasted space in the contacts database.
+@deprecated
+*/
+EXPORT_C TInt CContactDatabase::WastedSpaceInBytes() const
+ {
+ return 0;
+ }
+
+
+/**
+Filters the database. On return, aFilter contains an array of filtered contact
+item IDs.
+
+@capability ReadUserData
+
+@param aFilter The filter to use. On return, contains a filtered array of
+contact item IDs.
+*/
+EXPORT_C void CContactDatabase::FilterDatabaseL(CCntFilter& aFilter)
+ {
+ iCntSvr->FilterDatabaseL(aFilter);
+ }
+
+
+/**
+Gets an array of contacts modified since the specified date/time. The array
+includes those contacts that have changed since the beginning of the specified
+micro-second. The caller takes ownership of the returned object.
+
+@capability ReadUserData
+
+@param aTime The date/time of interest.
+
+@return Pointer to the array of contacts modified since the specified time.
+*/
+EXPORT_C CContactIdArray* CContactDatabase::ContactsChangedSinceL(const TTime& aTime)
+ {
+ MLplCollection& collection = FactoryL()->GetCollectorL();
+ return collection.CollectionL(MLplCollection::EChangedSince,aTime);
+ }
+
+
+/**
+Sets the date/time the database was last synchronised.
+
+This overload sets the last synchronised date/time where the sync ID is not
+known, and returns the sync ID that was created (a sync ID identifies a machine
+with which the database has been synchronised).
+
+@deprecated
+
+@param aSyncDate The database's new last synchronised date/time.
+
+@return The sync ID created by the function.
+*/
+EXPORT_C TContactSyncId CContactDatabase::SetLastSyncDateL(const TTime& aSyncDate)
+ {
+ //
+ // Quick workaround for these APIs rather than implement IPC call to server
+ // and a Sync table class. If we can establish that these APIs are never
+ // used (they have been deprecated for a long time) then this workaround can
+ // be made permanent.
+ //
+ iSyncDate = aSyncDate;
+ return 0;
+ }
+
+
+/**
+Sets the date/time the database was last synchronised.
+
+This overload is for a known sync ID and updates the database's last
+synchronised date/time for that ID.
+
+@deprecated
+
+@param aSyncId This argument should be ignored by developers.
+@param aSyncDate The database's new last synchronised date/time.
+
+@leave KErrNotFound The specified sync ID is not found.
+*/
+EXPORT_C void CContactDatabase::SetLastSyncDateL(TContactSyncId /*aSyncId*/, const TTime& aSyncDate)
+ {
+ //
+ // Quick workaround for these APIs rather than implement IPC call to server
+ // and a Sync table class. If we can establish that these APIs are never
+ // used (they have been deprecated for a long time) then this workaround can
+ // be made permanent.
+ //
+ iSyncDate = aSyncDate;
+ }
+
+
+/**
+Gets the date/time the database was last synchronised with a particular
+sync ID, as set by SetLastSyncDateL().
+
+@deprecated
+
+@param aSyncId This argument should be ignored by developers.
+@param aSyncDate On return contains the date/time the database was last
+synchronised with the sync ID specified.
+
+@leave KErrNotFound The ID cannot be found in the database.
+*/
+EXPORT_C void CContactDatabase::GetLastSyncDateL(TContactSyncId /*aSyncId*/, TTime& aSyncDate)
+ {
+ //
+ // Quick workaround for these APIs rather than implement IPC call to server
+ // and a Sync table class. If we can establish that these APIs are never
+ // used (they have been deprecated for a long time) then this workaround can
+ // be made permanent.
+ //
+ aSyncDate = iSyncDate;
+ }
+
+
+/**
+Gets the ID of the connection to the Contacts server.
+
+This can be compared with the connection IDs of incoming messages to identify
+which connection generated the message.
+
+@capability None
+
+@return The ID of the connection to the Contacts server.
+*/
+EXPORT_C TUint CContactDatabase::ConnectionId() const
+ {
+ return iCntSvr->ConnectionId();
+ }
+
+
+/**
+Debug only.
+
+@internalTechnology
+@released
+
+@capability None
+
+@return return the heap size usage of the server in debug mode, 0 in release mode.
+*/
+EXPORT_C TInt CContactDatabase::CntServerResourceCount()
+ {
+ return(iCntSvr->ResourceCount());
+ }
+
+
+/**
+Debug only.
+
+@internalTechnology
+@released
+
+@capability None
+*/
+EXPORT_C void CContactDatabase::SetCntServerHeapFailure(TInt aTAllocFailType, TInt aRate)
+ {
+ iCntSvr->SetHeapFailure((RHeap::TAllocFail)aTAllocFailType,aRate);
+ }
+
+
+/**
+Debug only.
+
+@internalTechnology
+@released
+
+@capability None
+
+@param aMachineUniqueId The Machine ID to set.
+*/
+EXPORT_C void CContactDatabase::OverrideMachineUniqueId(TInt64 aMachineUniqueId)
+ {
+ iCntSvr->OverrideMachineUniqueId(aMachineUniqueId);
+ }
+
+
+/**
+Gets the contact model's version number.
+
+@return The version number of the contacts model.
+*/
+EXPORT_C TVersion CContactDatabase::Version() const
+ {
+ return(TVersion(KMajorVersion,KMinorVersion,KBuildNumber));
+ }
+
+
+/**
+Returns a number unique to the contacts database. This value may be passed
+to CContactItem::UidStringL().
+
+@capability None
+
+@return The database's unique ID.
+*/
+EXPORT_C TInt64 CContactDatabase::MachineId() const
+ {
+ return iCntSvr->MachineId();
+ }
+
+
+/**
+Gets an array of IDs for contact items that still exist in the database, but
+are marked as deleted. These are contact items which have been deleted, but
+which have a non-zero access count. The caller takes ownership of the returned
+object.
+
+Debug only.
+
+@internalTechnology
+@released
+@capability ReadUserData
+
+@return Pointer to the array of contacts marked as deleted.
+*/
+EXPORT_C CContactIdArray* CContactDatabase::DeletedContactsLC()
+ {
+#if defined(_DEBUG)
+ MLplCollection& collection = FactoryL()->GetCollectorL();
+ CContactIdArray* deletedContactsIdArray =
+ collection.CollectionL(MLplCollection::EDeleted);
+ CleanupStack::PushL(deletedContactsIdArray);
+ return deletedContactsIdArray;
+#else
+ // Do nothing (except avoid compiler errors)
+ return NULL;
+#endif
+ }
+
+
+/**
+Requests that the server reset all its speed dials to a NULL state.
+Needed so that T_NOMACH works (since deleting the db no longer resets the speed dials)
+
+Debug only.
+
+@internalTechnology
+@released
+@capability WriteUserData
+*/
+EXPORT_C void CContactDatabase::ResetServerSpeedDialsL()
+ {
+#if defined(_DEBUG)
+ for(TInt i = KCntMinSpeedDialIndex; i <= KCntMaxSpeedDialIndex; i++)
+ {
+ // Pass -1 as field index to indicate that speed dial position is to
+ // be reset.
+ iCntSvr->SetFieldAsSpeedDialL(KNullContactId, -1, i);
+ }
+#endif
+ }
+
+
+/**
+Where there are multiple contact databases on a device, this function can be
+used to enquire which database is the current one. The current database functions
+are provided as part of current item functionality. In order to pass a current
+item from one contacts model client to another, the receiving client needs
+to be using the same database.
+
+The current database is a path and filename, set using SetCurrentDatabase()
+which is persisted by the contacts server.
+
+@deprecated
+@capability None
+
+@param aDatabase The path and filename of the current database. KNullDesC
+if no current database has been set.
+
+@return KErrNone if the function completed successfully, otherwise one of the
+standard error codes.
+*/
+EXPORT_C TInt CContactDatabase::GetCurrentDatabase(TDes& aDatabase) const
+ {
+ return iCntSvr->GetCurrentDatabase(aDatabase);
+ }
+
+
+/**
+Where there are multiple contact databases on a device, this function can be
+used to set a database as the current one.
+
+Note: this function simply updates a file name which is stored by the contacts server
+and its use is optional. It is provided as part of current item functionality.
+In order to pass a current item from one contacts model client to another,
+the receiving client needs to be using the same database.
+
+@deprecated
+@capability WriteUserData
+
+@param aDatabase The path and filename of the current database.
+
+@return KErrNone if the function completed successfully, otherwise one of the
+standard error codes.
+*/
+EXPORT_C TInt CContactDatabase::SetCurrentDatabase(const TDesC& aDatabase) const
+ {
+ return iCntSvr->SetCurrentDatabase(aDatabase);
+ }
+
+
+/**
+Starts a new transaction, without placing a cleanup item to rollback
+the database onto the cleanupstack. This is to enable clients to call
+contacts methods from an active object.
+
+@publishedPartner
+@released
+@capability WriteUserData
+
+@param aIsInTransaction ETrue if transaction already started
+
+@leave KErrDiskFull if used storage space above threshold
+*/
+EXPORT_C void CContactDatabase::DatabaseBeginL(TBool aIsInTransaction)
+ {
+ if (!aIsInTransaction)
+ {
+ User::LeaveIfError(iCntSvr->BeginDbTransaction());
+ }
+ }
+
+
+/**
+Commits an existing transaction, without popping a cleanup item.
+
+@publishedPartner
+@released
+@capability WriteUserData
+
+@param aIsInTransaction ETrue if transaction already started
+*/
+EXPORT_C void CContactDatabase::DatabaseCommitL(TBool aIsInTransaction)
+ {
+ if (!aIsInTransaction)
+ {
+ User::LeaveIfError(iCntSvr->CommitDbTransaction());
+ }
+ }
+
+
+/**
+Force a rollback of the database.
+
+@publishedPartner
+@released
+@capability WriteUserData
+*/
+EXPORT_C void CContactDatabase::DatabaseRollback()
+ {
+ iCntSvr->RollbackDbTransaction();
+ }
+
+
+/**
+This method allows clients of contacts model to set the sorted item list
+and sort order from a default sort order server as proposed for Crystal 6.0
+
+Note: This method can leave.
+
+@param aSortedItems Specifies an array sorted items
+@param aSortOrder Specifies the sort order
+@deprecated
+@capability None
+*/
+EXPORT_C void CContactDatabase::SetSortedItemsList(CContactIdArray* aSortedItems, CArrayFix<TSortPref>* aSortOrder)
+ {
+ __ASSERT_DEBUG(aSortedItems!=NULL,Panic(ECntPanicNullPointer));
+ __ASSERT_DEBUG(aSortOrder!=NULL,Panic(ECntPanicNullPointer));
+
+ delete iSortedItems;
+ iSortedItems=aSortedItems;
+ iCntSvr->SetSortPreferenceL(*aSortOrder); // this can leave
+ delete aSortOrder;
+ }
+
+
+/**
+aSortOrder is owned by the idle sorter.
+@param aSortOrder Specifies the sort order
+@param aStatus The request status for the asynchronous phase request.
+@deprecated
+*/
+EXPORT_C void CContactDatabase::SortAsyncL(CArrayFix<TSortPref>* aSortOrder, TRequestStatus& aStatus)
+ {
+ iIdleSorter->ResetL();
+ iIdleSorter->StartSortingL(aSortOrder, aStatus);
+ }
+
+
+/**
+aSortOrder is owned by the idle sorter.
+@param aSortOrder Specifies the sort order
+@param aStatus The request status for the asynchronous phase request.
+@deprecated
+*/
+EXPORT_C void CContactDatabase::SortAsyncL(CArrayFix<TSortPref>* aSortOrder, TRequestStatus& aStatus, MContactSortObserver& aObserver)
+ {
+ iIdleSorter->ResetL();
+ iIdleSorter->StartSortingL(aSortOrder, aStatus, aObserver);
+ }
+
+
+/**
+Cancel the CCntIdleSorter object and clean up resources.
+
+@deprecated
+*/
+EXPORT_C void CContactDatabase::CancelAsyncSort()
+ {
+ iIdleSorter->Cancel();
+ }
+
+
+/**
+Tests whether a contact item's hint bit field matches a filter.
+
+For a match to occur, the item must be of the correct type for inclusion in
+the database (as returned by GetDbViewContactType()) and its hint bit field
+(which indicates whether the item contains a work or home telephone number,
+fax number or email address) must match the filter, according to the rules
+described in TContactViewFilter.
+
+@internalTechnology
+@capability None
+
+@param aBitWiseFilter The filter to compare the item against. This is a combination
+of TContactViewFilter values.
+@param aContactId The ID of the item in the database.
+
+@return ETrue if the item is of the correct type for inclusion in the database,
+and its hint bit field matches the specified filter, EFalse if either of these
+conditions are not met.
+*/
+EXPORT_C TBool CContactDatabase::ContactMatchesHintFieldL(TInt aBitWiseFilter,TContactItemId aContactId)
+ {//Returns ETrue if the contact Hint field matches any of the aBitWiseFilter fields
+ return iCntSvr->ContactMatchesHintFieldL(aBitWiseFilter,aContactId);
+ }
+
+
+/**
+Returns the ID of the template that should be used with CContactICCEntry items.
+
+@capability None
+
+@return A template ID.
+*/
+EXPORT_C TContactItemId CContactDatabase::ICCTemplateIdL()
+ {
+ LoadSyncPluginL();
+ return iCntSvr->ICCTemplateIdL(KUidIccGlobalAdnPhonebook);
+ }
+
+
+/**
+Returns the ID of the template that should be used with CContactICCEntry items
+belonging to the phonebook with TUid aPhonebookUid.
+
+@capability None
+
+@param aPhonebookUid The phonebook ID.
+
+@return A template ID.
+*/
+EXPORT_C TContactItemId CContactDatabase::ICCTemplateIdL(TUid aPhonebookUid)
+ {
+ LoadSyncPluginL();
+ return iCntSvr->ICCTemplateIdL(aPhonebookUid);
+ }
+
+
+/**
+Returns the ID of the contacts model group which represents the ADN phonebook.
+
+@capability None
+
+@return Group ID.
+*/
+EXPORT_C TContactItemId CContactDatabase::PhonebookGroupIdL()
+ {
+ LoadSyncPluginL();
+ return iCntSvr->PhonebookGroupIdL();
+ }
+
+
+/**
+Returns a list of 'unfiled' contacts. These are contacts which do not belong to any group.
+
+@publishedPartner
+@released
+@capability ReadUserData
+
+@return The list of 'unfiled' contacts.
+*/
+EXPORT_C CContactIdArray* CContactDatabase::UnfiledContactsL()
+ {
+ MLplCollection& collection = FactoryL()->GetCollectorL();
+ return collection.CollectionL(MLplCollection::EUnfiled);
+ }
+
+
+/**
+Opens the default contact database asynchronously.
+
+The Contacts server is asked to prepare the database to be opened. This may include
+cleaning up incomplete writes from when the device was last switched off, or updating the
+database format.
+
+If an error is encountered starting the asynchronous open the return value is NULL and the
+error is returned in the TRequestStatus parameter.
+
+Errors from the asynchronous open include:
+KErrNotFound The database file was not found or it did not have the correct UIDs.
+KErrLocked The file is in use by another client.
+Other system wide error codes.
+
+If the return value is not NULL the ownership of the CContactOpenOperation object is passed
+to the client. This may be deleted before the asynchronous open completes.
+
+When the client supplied TRequestStatus is completed with KErrNone the TakeDatabase() method
+of CContactOpenOperation is called to pass ownership of the open database to the client.
+
+@publishedAll
+@released
+@capability ReadUserData
+
+@param aStatus
+ On return, the request status for the asynchronous phase request.
+ The Open() action can fail with one of the system wide error codes. In this case, the
+ CContactDatabase object cannot access the database and must be deleted.
+@param aAccess
+ This argument should be ignored by developers.
+
+@return NULL if there is an error starting the asynhchronous open, otherwise a pointer to an
+ active object that manages the open operation.
+
+@see CContactOpenOperation
+*/
+EXPORT_C CContactOpenOperation* CContactDatabase::Open(TRequestStatus& aStatus, TThreadAccess /*aAccess*/)
+ {
+ aStatus = KRequestPending;
+ CContactOpenOperation* openOperation = NULL;
+
+ TRAPD(newError, openOperation = CContactOpenOperation::NewL(aStatus));
+ // failed? return the error in the TRequestStatus
+ if (newError != KErrNone)
+ {
+ TRequestStatus* ptrStatus = &aStatus;
+ User::RequestComplete(ptrStatus, newError);
+ }
+ return openOperation;
+ }
+
+
+/**
+Opens a named contact database asynchronously.
+
+The Contacts server is asked to prepare the database to be opened. This may include
+cleaning up incomplete writes from when the device was last switched off, or updating the
+database format.
+
+In v8.1, contact databases can be located in any directory on any writeable drive, and the
+format of the filename must include an absolute directory path such as
+c:\\system\\data\\contacts.cdb.
+
+From v9.0 onwards, contact databases can only be located in the correct data caged
+subdirectory. The filenames must have no path, for example c:contacts.cdb.
+The maximum length for the drive, filename and extension is 190 characters.
+
+If an empty path is entered, it will be treated as a request to open the default contact
+database.
+
+If an error is encountered starting the asynchronous open the return value is NULL and the
+error is returned in the TRequestStatus parameter.
+
+Errors from the asynchronous open include:
+KErrNotFound The database file was not found or it did not have the correct UIDs.
+KErrLocked The file is in use by another client.
+KErrBadName The filename is invalid; for example it includes wildcard characters
+or the drive is missing.
+Other system wide error codes.
+
+If the return value is not NULL the ownership of the CContactOpenOperation object is passed
+to the client. This may be deleted before the asynchronous open completes.
+
+When the client supplied TRequestStatus is completed with KErrNone the TakeDatabase() method
+of CContactOpenOperation is called to pass ownership of the open database to the client.
+
+@publishedAll
+@released
+@capability ReadUserData
+
+@param aFileName
+ The filename of the database to open.
+@param aStatus
+ On return, the request status for the asynchronous phase request.
+ The Open() action can fail with one of the system wide error codes. In this case the
+ CContactDatabase object cannot access the database and must be deleted.
+@param aAccess
+ This argument should be ignored by developers.
+
+@return NULL if there is an error starting the asynhchronous open, otherwise a pointer to an
+ active object that manages the open operation.
+
+@see CContactOpenOperation
+*/
+EXPORT_C CContactOpenOperation* CContactDatabase::Open(const TDesC& aFileName, TRequestStatus& aStatus, TThreadAccess /*aAccess*/)
+ {
+ TRequestStatus* ptrStatus = &aStatus;
+ CContactOpenOperation* openOperation = NULL;
+
+ TRAPD(newError, openOperation = CContactOpenOperation::NewL(aFileName, aStatus));
+ // failed? return the error in the TRequestStatus
+ if (newError != KErrNone)
+ {
+ User::RequestComplete(ptrStatus, newError);
+ }
+
+ return openOperation;
+ }
+
+
+/**
+A static method to list the contact databases on all drives.
+
+In v8.1, this function finds contact databases located anywhere on the drives,
+and the format of the returned filenames is c:\\system\\data\\contacts.cdb.
+
+From v9.0 onwards, this function finds contact databases only in the correct
+data caged subdirectory. The returned filenames have no path, for example
+c:contacts.cdb. The maximum length for the drive, filename and extension is 190
+characters.
+
+In either case, the filenames returned are in the correct format for Open(),
+OpenL(), CreateL(), ReplaceL() and DeleteDatabaseL().
+
+@publishedAll
+@released
+@capability ReadUserData
+
+@return An array containing zero or more contact database names.
+
+@leave KErrNoMemory Out of memory.
+*/
+EXPORT_C CDesCArray* CContactDatabase::ListDatabasesL()
+ {
+ CContactDatabase* db = NewLC();
+ CDesCArray* list = db->iCntSvr->ListDatabasesL();
+ CleanupStack::PopAndDestroy(db);
+ return list;
+ }
+
+
+/**
+A static method to list the contact databases on a specified drive.
+
+In v8.1, this function finds contact databases located anywhere on the drive,
+and the format of the returned filenames is c:\\system\\data\\contacts.cdb.
+
+From v9.0 onwards, this function finds contact databases only in the correct
+data caged subdirectory. The returned filenames have no path, for example
+c:contacts.cdb. The maximum length for the drive, filename and extension is 190
+characters.
+
+In either case, the filenames returned are in the correct format for Open(),
+OpenL(), CreateL(), ReplaceL() and DeleteDatabaseL().
+
+@publishedAll
+@released
+@capability ReadUserData
+
+@param aDriveUnit
+ The drive unit to search for contact databases.
+
+@return An array containing zero or more contact database names.
+
+@leave KErrNoMemory Out of memory.
+*/
+EXPORT_C CDesCArray* CContactDatabase::ListDatabasesL(TDriveUnit aDriveUnit)
+ {
+ CContactDatabase* db = NewLC();
+ CDesCArray* list = db->iCntSvr->ListDatabasesL(&aDriveUnit);
+ CleanupStack::PopAndDestroy(db);
+ return list;
+ }
+
+
+/**
+A static method to delete a named contact database.
+
+If the file is found, it is tested for the correct UIDs.
+
+In v8.1, contact databases can be located in any directory on any writeable drive,
+and the format of the filename must include an absolute directory path such as
+c:\\system\\data\\contacts.cdb.
+
+From v9.0 onwards, contact databases can only be located in the correct data caged
+subdirectory. The filenames must have no path, for example c:contacts.cdb.
+The maximum length for the drive, filename and extension is 190 characters.
+
+@publishedAll
+@released
+@capability WriteUserData
+
+@param aFileName
+ The contact database file to delete.
+
+@leave KErrBadName The filename is invalid; for example it contains
+wildcard characters or the drive is missing.
+@leave KErrInUse Another client has the database open.
+@leave KErrNotFound The database file was not found or it did not have the correct UIDs.
+@leave KErrArgument if the given descriptor contains more than the maximum length
+ of 190 characters.
+
+@see CContactDatabase::DeleteDefaultFileL()
+*/
+EXPORT_C void CContactDatabase::DeleteDatabaseL(const TDesC& aFileName)
+ {
+ CContactDatabase* db = NewLC();
+ User::LeaveIfError(db->iCntSvr->DeleteDatabase(aFileName));
+ CleanupStack::PopAndDestroy(db);
+ }
+
+
+/**
+A static method to determine if the default contact database exists.
+
+It searches the drive set by SetDatabaseDriveL(), or if no drive has been
+set, it searches drive c:.
+
+If the file is found, it is tested for the correct UIDs.
+
+@publishedAll
+@released
+@capability None
+
+@return ETrue if the file is found, EFalse otherwise.
+@leave KErrNotReady There is no media present in the drive.
+@leave KErrNotFound The database file was not found or it did not have the correct UIDs.
+@leave KErrCorrupt The file is not a valid database
+
+@see CContactDatabase::ContactDatabaseExistsL()
+*/
+EXPORT_C TBool CContactDatabase::DefaultContactDatabaseExistsL()
+ {
+ CContactDatabase* db = NewLC();
+ TBool theFlag = db->iCntSvr->DatabaseExistsL();
+ CleanupStack::PopAndDestroy(db);
+ return theFlag;
+ }
+
+
+/**
+A method to determine if a named contact database exists.
+
+If the file is found, it is tested for the correct UIDs.
+
+In v8.1, contact databases can be located in any directory on any writeable drive,
+and the format of the filename must include an absolute directory path such as
+c:\\system\\data\\contacts.cdb.
+
+From v9.0 onwards, contact databases can only be located in the correct data caged
+subdirectory. The filenames must have no path, for example c:contacts.cdb.
+The maximum length for the drive, filename and extension is 190 characters.
+
+@publishedAll
+@released
+@capability None
+
+@param aFileName
+ The contact database to search for.
+
+@return ETrue if the file is found, EFalse otherwise.
+
+@leave KErrNotReady There is no media present in the drive.
+@leave KErrBadName The filename is invalid; for example it contains
+wildcard characters or the drive is missing.
+@leave KErrNotFound The database file was not found or it did not have the correct UIDs.
+@leave KErrCorrupt The file is not a valid database
+@leave KErrArgument if the given descriptor contains more than the maximum length
+ of 190 characters.
+
+@see CContactDatabase::DefaultContactDatabaseExistsL()
+@see CContactDatabase::ListDatabasesL()
+*/
+EXPORT_C TBool CContactDatabase::ContactDatabaseExistsL(const TDesC& aFileName)
+ {
+ // Leave if the filename format is bad
+ TParse parseName;
+ User::LeaveIfError(parseName.SetNoWild(aFileName,NULL,NULL));
+ CContactDatabase* db = NewLC();
+ TBool dbExists = db->iCntSvr->DatabaseExistsL(aFileName);
+ CleanupStack::PopAndDestroy(db);
+
+ return dbExists;
+ }
+
+
+/**
+Searches the database for a text string. The function searches the fields
+contained in the field definition. The caller takes ownership of the returned
+object. There is a limit of 255 characters on the search string length, due to
+the implementation of the DBMS API, which also has a search string length
+restriction of 255 chars. If the search string passed in is over 255 characters
+this method will leave with KErrArgument.
+
+@param aText The text to search for.
+@param aFieldDef Specifies the fields to search.
+
+@return Array of contact IDs identifying the contact items which contain the
+specified text.
+*/
+EXPORT_C CContactIdArray* CContactDatabase::FindLC(const TDesC& aText,const CContactItemFieldDef* aFieldDef)
+ {
+ CContactIdArray* idArray = iCntSvr->FindL(aText,aFieldDef);
+ CleanupStack::PushL(idArray);
+ return idArray;
+ }
+
+
+/**
+Searches the database asynchronously for a text string. The function searches
+the fields contained in the field definition asynchronously using the MIdleFindObserver
+and CIdleFinder classes. The caller takes ownership of the returned object.
+
+@param aText The text to search for.
+@param aFieldDef Specifies the fields to search.
+@param aObserver Implements the callback function IdleFindCallback(). NULL
+if no observer is needed.
+
+@return A CIdle-derived object which provides information about the progress
+of the operation, and which can be used to retrieve an array of contact IDs.
+*/
+// !!! assert that the field definition doesn't contain any fields not included in the view?
+// !!! should change to set the column found also
+EXPORT_C CIdleFinder* CContactDatabase::FindAsyncL(const TDesC& aText,const CContactItemFieldDef *aFieldDef, MIdleFindObserver *aObserver)
+ {
+ return(CIdleFinder::NewL(*this,aText,aFieldDef,aObserver));
+ }
+
+
+/**
+Enables the user to search the database for a string containing
+text that is stored in one or more fields.
+
+The string is specified as an array of words.
+
+For example, a user might want to search for the string "John Smith".
+To the user the string is a single item, but the text which makes up
+the string is stored in two separate fields in the database.
+
+The caller of this function needs to provide an array of words to find
+(aFindWords), and a function to break down the text in the contact item
+into a list of words (aWordParserCallback).
+
+The array of words to find would typically not contain punctuation. For
+example if the user searches for 'Smith, John' this would be passed to
+this function as an array of two words: 'Smith' and 'John', with the
+separator being discarded.
+
+For a match to succeed, all words in the aFindWords array must match
+words in the array generated from the contact item by the aWordParserCallback
+function. To match, the word generated from the contact item must begin with
+the search word, i.e. a search for "Sm" would find any word beginning in "Sm".
+If a word is specified twice in the aFindWords array, then it must exist in
+two separate places in the contact item.
+
+The function only searches the fields contained in the currently set text
+definition.
+
+The caller takes ownership of the returned object.
+
+@param aFindWords An array of words to find.
+@param aWordParserCallback A function supplied by the caller to break the text
+in the contact down into a list of words.
+
+@return Array of contact IDs.
+*/
+EXPORT_C CContactIdArray* CContactDatabase::FindInTextDefLC(const MDesCArray& aFindWords, const TCallBack &aWordParserCallback)
+ {
+ return(FindInTextDefLC(aFindWords,iTextDef,aWordParserCallback));
+ }
+
+
+/**
+Enables the user to search the database for a string containing
+text that is stored in one or more fields.
+
+The string is specified as an array of words.
+
+For example, a user might want to search for the string "John Smith".
+To the user the string is a single item, but the text which makes up
+the string is stored in two separate fields in the database.
+
+The caller of this function needs to provide an array of words to find
+(aFindWords), and a function to break down the text in the contact item
+into a list of words (aWordParserCallback).
+
+The array of words to find would typically not contain punctuation. For
+example if the user searches for 'Smith, John' this would be passed to
+this function as an array of two words: 'Smith' and 'John', with the
+separator being discarded.
+
+For a match to succeed, all words in the aFindWords array must match
+words in the array generated from the contact item by the aWordParserCallback
+function. To match, the word generated from the contact item must begin with
+the search word, i.e. a search for "Sm" would find any word beginning in "Sm".
+If a word is specified twice in the aFindWords array, then it must exist in
+two separate places in the contact item.
+
+The function only searches the fields contained in the text definition aTextDef.
+
+The caller takes ownership of the returned object.
+
+@param aFindWords An array of words to find.
+@param aTextDef The text definition.
+@param aWordParserCallback A function supplied by the caller to break the text
+in the contact down into a list of words.
+
+@return Array of contact IDs.
+*/
+EXPORT_C CContactIdArray* CContactDatabase::FindInTextDefLC(const MDesCArray& aFindWords,CContactTextDef* aTextDef, const TCallBack &aWordParserCallback)
+ {
+ CIdleFinder* idleFinder=FindInTextDefAsyncL(aFindWords,aTextDef,NULL,aWordParserCallback);
+ CleanupStack::PushL(idleFinder);
+ while(idleFinder->doFindL()) {};
+ User::LeaveIfError(idleFinder->Error());
+ CContactIdArray *ids=idleFinder->TakeContactIds();
+ CleanupStack::PopAndDestroy(); // idleFinder
+ CleanupStack::PushL(ids);
+ return(ids);
+ }
+
+
+/**
+Asynchronously searches the database for an array of words.
+
+This function works in the same way as its corresponding variant in FindInTextDefLC(),
+except that it operates asynchronously using the MIdleFindObserver and CIdleFinder
+classes. The caller takes ownership of the returned object.
+
+@param aFindWords An array of words to find.
+@param aObserver Implements the callback function IdleFindCallback(). May be NULL if
+no observer is needed.
+@param aWordParserCallback A function to break the text in the contact down into a
+list of words.
+
+@return A CIdle-derived object which provides information about the progress of the
+operation, and which can be used to retrieve an array of contact IDs.
+*/
+EXPORT_C CIdleFinder* CContactDatabase::FindInTextDefAsyncL(const MDesCArray& aFindWords, MIdleFindObserver *aObserver, const TCallBack &aWordParserCallback)
+ {
+ return(FindInTextDefAsyncL(aFindWords,iTextDef,aObserver,aWordParserCallback));
+ }
+
+
+/**
+Asynchronously searches the database for an array of words.
+
+This function works in the same way as its corresponding variant in FindInTextDefLC(),
+except that it operates asynchronously using the MIdleFindObserver and CIdleFinder
+classes. The caller takes ownership of the returned object.
+
+@param aFindWords An array of words to find.
+@param aTextDef The text definition.
+@param aObserver Implements the callback function IdleFindCallback(). May be NULL if
+no observer is needed.
+@param aWordParserCallback A function to break the text in the contact down into a
+list of words.
+
+@return A CIdle-derived object which provides information about the progress of the
+operation, and which can be used to retrieve an array of contact IDs.
+*/
+EXPORT_C CIdleFinder* CContactDatabase::FindInTextDefAsyncL(const MDesCArray& aFindWords,const CContactTextDef* aTextDef, MIdleFindObserver *aObserver, const TCallBack &aWordParserCallback)
+ {
+ return(CIdleFinder::NewL(*this,&aFindWords,aTextDef,aObserver,aWordParserCallback));
+ }
+
+
+/**
+This function is not currently supported.
+@param aFormat This parameter should be ignored.
+@deprecated
+*/
+EXPORT_C void CContactDatabase::SetDateFormatTextL(const TDesC& /*aFormat*/)
+ {//Does nothing, Parameter should be ignored
+ }
+
+
+/**
+Returns an array of contact item IDs for all the contact items which may contain
+the specified telephone number in a telephone, fax or SMS type field.
+
+The comparison method used is not exact. The number is compared starting from
+the right side of the number and the method returns an array of candidate
+matches. Punctuation (eg. spaces) and other alphabetic characters are
+ignored when comparing.
+
+Additionally, if the contacts model phone parser (CNTPHONE.DLL) is available,
+then any DTMF digits are also excluded from the comparision.
+
+Notes:
+Due to the way numbers are stored in the database, it is recommended that at
+least 7 match digits are specified even when matching a number containing fewer
+digits. Failure to follow this guideline may (depending on the database contents)
+mean that the function will not return the expected Contacts Id set.
+
+@released
+@capability ReadUserData
+
+@param aNumber Phone number string. If the length of phone number string is greater than
+KCntMaxTextFieldLength then only the first KCntMaxTextFieldLength characters are used
+in the match.
+@param aMatchLengthFromRight Number of digits from the right of the phone number to use
+Up to 15 digits can be specified, and it is recommended that at least 7 match digits are
+specified.
+
+@return CContactIdArray of candidate matches
+*/
+EXPORT_C CContactIdArray* CContactDatabase::MatchPhoneNumberL(const TDesC& aNumber, const TInt aMatchLengthFromRight)
+ {
+ return iCntSvr->MatchPhoneNumberL(aNumber, aMatchLengthFromRight);
+ }
+
+
+TInt CContactDatabase::ContactPosL(TContactItemId aContactId) //for cntiter
+ {
+ return SortedItemsL()->Find(aContactId);
+ }
+
+
+TInt CContactDatabase::DoGotoL(TContactItemId /*aContactId*/)
+ {
+ return KErrNone;
+ }
+
+
+EXPORT_C void CContactDatabase::AddObserverL(MContactDbObserver& aChangeNotifier)
+ {
+ iCntSvr->AddObserverL(aChangeNotifier);
+ }
+
+
+EXPORT_C void CContactDatabase::RemoveObserver(const MContactDbObserver& aChangeNotifier)
+ {
+ iCntSvr->RemoveObserver(aChangeNotifier);
+ }
+
+EXPORT_C void CContactDatabase::AddObserverV2L(MContactDbObserverV2& aChangeNotifier)
+ {
+ iCntSvr->AddObserverV2L(aChangeNotifier);
+ }
+
+
+EXPORT_C void CContactDatabase::RemoveObserverV2(const MContactDbObserverV2& aChangeNotifier)
+ {
+ iCntSvr->RemoveObserverV2(aChangeNotifier);
+ }
+
+void CContactDatabase::CancelNotifyRequestL()
+ {
+ }
+
+
+TBool CContactDatabase::IsICCSynchronisedL()
+ {
+ return EFalse;
+ }
+
+
+MLplPersistenceLayerFactory* CContactDatabase::FactoryL()
+ {
+ if(iProxyFactory == NULL)
+ {
+ iProxyFactory = CProxyFactory::NewL(*this);
+ }
+ return iProxyFactory;
+ }
+
+
+void CContactDatabase::FetchGroupAndTemplateListsL()
+ {
+ delete iCardTemplateIds;
+ // Set the iCardTemplateIds to null in order to avoid a corruption
+ // should the FetchTemplateListIdsL leave.
+ iCardTemplateIds = NULL;
+ iCardTemplateIds = iCntSvr->FetchTemplateListIdsL();
+
+ delete iGroupIds;
+ iGroupIds = NULL; // See previous comment
+ iGroupIds = iCntSvr->FetchGroupListIdsL();
+ }
+
+void CContactDatabase::LoadSyncPluginL()
+ {
+ if (iContactSynchroniser == NULL)
+ {
+ //Instantiate a CContactSynchroniser object which loads the plugin.
+ //This is required to avoid a deadlock in the contacts server code.
+ iContactSynchroniser = CContactSynchroniser::NewL();
+ }
+ }
+
+/**
+@capability ReadUserData
+*/
+CContactOpenOperation* CContactOpenOperation::NewL(TRequestStatus& aPtrStatus)
+ {
+ CContactOpenOperation* self = new (ELeave) CContactOpenOperation(aPtrStatus);
+
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+@capability ReadUserData
+*/
+CContactOpenOperation* CContactOpenOperation::NewL(const TDesC& aFileName, TRequestStatus& aPtrStatus)
+ {
+ CContactOpenOperation* self = new (ELeave) CContactOpenOperation(aPtrStatus);
+
+ CleanupStack::PushL(self);
+ self->ConstructL(aFileName);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+CContactOpenOperation::CContactOpenOperation(TRequestStatus& aClientStatus) :
+CActive(EPriorityIdle), iClientStatus(&aClientStatus)
+ {}
+
+/**
+@capability ReadUserData
+@leave KErrArgument if the given descriptor contains more than the maximum length
+ of 190 characters.
+*/
+void CContactOpenOperation::ConstructL(const TDesC& aFileName)
+ {
+ iContactDatabase = CContactDatabase::NewLC();
+ CleanupStack::Pop(iContactDatabase);
+ iContactDatabase->iCntSvr->OpenDatabaseAsyncL(*iClientStatus, aFileName);
+ }
+
+
+/**
+For BC only, CActive is not used here.
+*/
+void CContactOpenOperation::RunL()
+ {
+ }
+
+
+/**
+For BC only, CActive is not used here.
+*/
+TInt CContactOpenOperation::RunError(TInt)
+ {
+ return KErrNone;
+ }
+
+
+/**
+For BC only, CActive is not used here.
+*/
+void CContactOpenOperation::DoCancel()
+ {
+ }
+
+
+/**
+Takes ownership of the contact database.
+
+Ownership of the contact database is passed to the client.
+Subsequent calls return NULL.
+
+@return A pointer to the CContactDatabase on the first call after
+ the asynchronous open has succeeded. Otherwise NULL.
+
+@see CContactDatabase::Open()
+*/
+EXPORT_C CContactDatabase* CContactOpenOperation::TakeDatabase()
+ {
+ // async open must have succeeded in server AND RunL must have completed
+ CContactDatabase* contactDatabase = iContactDatabase;
+ // prevent deletion of the database.
+ iContactDatabase = NULL;
+ return contactDatabase;
+ }
+
+
+/**
+Deletes the active object.
+
+If the asynchronous open is still in progress it is cancelled.
+
+If the TakeDatabase() API has not been called and the database
+has been opened it is closed.
+
+@capability None
+*/
+EXPORT_C CContactOpenOperation::~CContactOpenOperation()
+ {
+ if (iContactDatabase)
+ {
+ iContactDatabase->iCntSvr->CancelAsyncOpen();
+ delete iContactDatabase;
+ iContactDatabase = NULL;
+ }
+ }
+
+
+CDataBaseChangeObserver* CDataBaseChangeObserver::NewL(MContactDbPrivObserver& aPrivateObserver)
+ {
+ CDataBaseChangeObserver* temp = new (ELeave) CDataBaseChangeObserver(aPrivateObserver);
+ return temp;
+ }
+
+
+CDataBaseChangeObserver::CDataBaseChangeObserver(MContactDbPrivObserver& aPrivateObserver) : iPrivateObserver(aPrivateObserver)
+ {}
+
+
+void CDataBaseChangeObserver::HandleDatabaseEventL(TContactDbObserverEvent aEvent)
+ {
+ iPrivateObserver.HandleDatabaseEventL(aEvent);
+ }
+
+
+CDataBaseChangeObserver::~CDataBaseChangeObserver()
+ {}
+
+
+void CContactDatabase::HandleDiskSpaceEvent(TInt)
+/** Default behaviour for handling a low disk event - This function is unimplemented. */
+ {}//Do nothing.
+
+
+void CContactDatabase::RespondToEventL(const TContactDbObserverEventType aEventType, const TContactItemId aContactId)
+ {
+ switch(aEventType)
+ {
+ case EContactDbObserverEventContactChanged:
+ case EContactDbObserverEventGroupChanged:
+ HandleDbObserverEventGroupOrContactChangedL(aContactId);
+ break;
+
+ case EContactDbObserverEventContactAdded:
+ case EContactDbObserverEventGroupAdded:
+ HandleDbObserverEventGroupOrContactAddedL(aEventType, aContactId);
+ break;
+
+ case EContactDbObserverEventSpeedDialsChanged:
+ break;
+
+ case EContactDbObserverEventOwnCardDeleted:
+ case EContactDbObserverEventContactDeleted:
+ RemoveFromSortArray(aContactId);
+ break;
+
+ case EContactDbObserverEventGroupDeleted:
+ HandleDbObserverEventGroupDeletedL(aContactId);
+ break;
+
+ case EContactDbObserverEventTemplateAdded:
+ {
+ if (!iCardTemplateIds)
+ {
+ //if database was opened async, iCardTemplate is null.
+ //keep same behaviour like CContactDatabase::AddToTemplateListL
+ iCardTemplateIds = CContactIdArray::NewL();
+ }
+ iCardTemplateIds->AddL(aContactId);
+ }
+ break;
+
+ case EContactDbObserverEventTemplateChanged:
+ {
+ iTemplateCache->RemoveTemplate(aContactId);
+ }
+ break;
+
+ case EContactDbObserverEventTemplateDeleted:
+ {
+ iTemplateCache->RemoveTemplate(aContactId);
+ RemoveFromTemplateList(aContactId);
+ }
+ break;
+
+ case EContactDbObserverEventOwnCardChanged:
+ break;
+
+ case EContactDbObserverEventBackupBeginning:
+ case EContactDbObserverEventRestoreBeginning:
+ case EContactDbObserverEventBackupRestoreCompleted:
+ case EContactDbObserverEventRestoreBadDatabase:
+ // NB this handler decides on the event to send to observers
+ // HandleBackupOrRestoreEvent(aEvent);
+ return;
+
+ case EContactDbObserverEventTablesOpened:
+ iTablesOpen = ETrue;
+ break;
+
+ case EContactDbObserverEventTablesClosed:
+ iTablesOpen = EFalse;
+ break;
+
+ case EContactDbObserverEventUnknownChanges:
+ {
+ FetchGroupAndTemplateListsL();
+ // Reset the template cache
+ delete iTemplateCache;
+ iTemplateCache = NULL;
+ iTemplateCache = CCntTemplateCache::NewL(*iCntSvr);
+
+ TInt err=KErrGeneral;
+ if (iTablesOpen)
+ {
+ CArrayFix<TSortPref>* sortOrder = const_cast<CArrayFix<TSortPref>*>(iCntSvr->GetSortPreferenceL());
+ CleanupStack::PushL(sortOrder);
+ TRAP(err,ReSortL(sortOrder));
+ CleanupStack::PopAndDestroy(sortOrder);
+ }
+ CheckSortError(err);
+ }
+ break;
+ default:;
+ }
+ }
+
+
+/**
+Handle the Database event
+@internalTechnology
+@param aEvent Database change event
+*/
+EXPORT_C void CContactDatabase::HandleDatabaseEventL(const TContactDbObserverEvent& aEvent)
+ {
+ //Just respond to events created by other sessions
+ if (ConnectionId()!=aEvent.iConnectionId)
+ {
+ RespondToEventL(aEvent.iType, aEvent.iContactId);
+ }
+ }
+
+
+void CContactDatabase::RemoveFromSortArray(TContactItemId aContactId)
+ {
+ if (iSortedItems)
+ {
+ const TInt pos=iSortedItems->Find(aContactId);
+ if (pos!=KErrNotFound)
+ iSortedItems->Remove(pos);
+ }
+ }
+
+
+void CContactDatabase::RemoveFromGroupIds(const TContactItemId aContactId)
+ {
+ if (iGroupIds)
+ {
+ TInt pos = iGroupIds->Find(aContactId);
+ if ( pos != KErrNotFound )
+ {
+ iGroupIds->Remove( pos );
+ }
+ }
+ }
+
+
+void CContactDatabase::HandleDbObserverEventGroupDeletedL(const TContactItemId aContactId)
+ {
+ RemoveFromGroupIds(aContactId);
+ RespondToEventL(EContactDbObserverEventContactDeleted, aContactId);
+ }
+
+
+TBool CContactDatabase::AddContactToSortListL(TContactItemId aReqId, TContactItemId& aActualId,CBase* aItems, TUid& aFieldType, TBool aHasSortOrder)
+ {
+ TUid contactType;
+ TBool deleted;
+
+ if(!FactoryL()->GetCollectorL().SeekContactL(aReqId,aActualId,contactType,deleted))
+ {
+ return EFalse;
+ }
+
+ if(deleted || contactType != KUidContactCard)
+ {
+ return ETrue;
+ }
+ if (!aHasSortOrder)
+ {
+ ((CContactIdArray*)aItems)->AddL(aActualId);
+ }
+ else
+ {
+ CContactDatabase::TTextFieldMinimal textFieldMin;
+ if (aFieldType == KUidContactFieldDefinedText)
+ {
+ ReadContactTextDefL(aActualId,textFieldMin,iTextDef);
+ }
+ else
+ {
+ FactoryL()->GetViewIteratorManagerL().TextFieldL(aActualId,aFieldType,textFieldMin);
+ }
+ ((CSortArray*) aItems)->AppendL(textFieldMin,aActualId);
+ }
+ return ETrue;
+ }
+
+
+TInt CContactDatabase::NextExistingL(TInt aIndex)
+ {
+ TInt ret=KErrNotFound;
+ const CContactIdArray* sortedItems=SortedItemsL();
+ const TInt count=sortedItems->Count();
+ TContactItemId contactId=KNullContactId;
+ while ((ret==KErrNotFound) && (aIndex<count-1))
+ {
+ contactId=(*sortedItems)[++aIndex];
+ ret=DoGotoL(contactId);
+ }
+ if (ret==KErrNotFound)
+ return ret;
+ return aIndex;
+ }
+
+
+TInt CContactDatabase::PreviousExistingL(TInt aIndex)
+ {
+ TInt ret=KErrNotFound;
+ TContactItemId contactId=KNullContactId;
+ const CContactIdArray* sortedItems=SortedItemsL();
+ while (ret==KErrNotFound && aIndex>=1)
+ {
+ contactId=(*sortedItems)[--aIndex];
+ ret=DoGotoL(contactId);
+ }
+ if (ret==KErrNotFound)
+ return ret;
+ return aIndex+1;
+ }
+
+
+TInt CContactDatabase::NewSortIndexL(const CContactItem& aContact, TInt aMin, TInt aMax)
+ {
+ __ASSERT_DEBUG(&aContact!=NULL,Panic(ECntPanicNullPointer));
+ FOREVER
+ {
+ if (aMin==aMax)
+ return(aMin);
+ TInt index=(aMax-aMin)/2+aMin;
+ User::LeaveIfError(DoGotoL((*iSortedItems)[index]));
+ TInt compare=CompareSortFieldsL(aContact);
+ if (compare<=0)
+ {
+ if (aMin==index)
+ aMin++;
+ else
+ aMin=index;
+ }
+ else if (compare>0)
+ aMax=index;
+ }
+ }
+
+
+TBool CContactDatabase::CheckSortError(TInt aError)
+ {
+ if (aError!=KErrNone)
+ {
+ delete iSortedItems;
+ iSortedItems=NULL;
+ return(ETrue);
+ }
+ return(EFalse);
+ }
+
+
+void CContactDatabase::MoveInSortArray(const CContactItem& aContact)
+ {
+ TRAPD(err,MoveInSortArrayL(aContact));
+ CheckSortError(err);
+ }
+
+
+void CContactDatabase::InsertInSortArray(const CContactItem& aContact)
+ {
+ TRAPD(err,InsertInSortArrayL(aContact));
+ CheckSortError(err);
+ }
+
+
+void CContactDatabase::InsertInSortArrayL(const CContactItem& aContact)
+ {
+ __ASSERT_DEBUG(&aContact!=NULL,Panic(ECntPanicNullPointer));
+ if (CheckType(aContact.Type()) && iSortedItems)
+ {
+ const TContactItemId id=aContact.Id();
+ if (iSortedItems->Find(id)==KErrNotFound)
+ {
+ const TInt index=NewSortIndexL(aContact,0,iSortedItems->Count());
+ if (index<iSortedItems->Count())
+ iSortedItems->InsertL(index,id);
+ else
+ iSortedItems->AddL(id);
+ }
+ }
+ }
+
+
+void CContactDatabase::MoveInSortArrayL(const CContactItem& aContact)
+ {
+ __ASSERT_DEBUG(&aContact!=NULL,Panic(ECntPanicNullPointer));
+ if (iSortedItems && CheckType(aContact.Type()))
+ {
+ const TInt pos=iSortedItems->Find(aContact.Id());
+ TInt compare=0;
+ if (pos!=0 && PreviousExistingL(pos)!=KErrNotFound)
+ compare=CompareSortFieldsL(aContact);
+ TInt index;
+ TInt start=0;
+ TInt end=pos;
+ if (compare<=0)
+ {
+ if (NextExistingL(pos)!=KErrNotFound)
+ compare=CompareSortFieldsL(aContact);
+ if (compare>=0)
+ return;
+ start=pos;
+ end=iSortedItems->Count();
+ }
+ index=NewSortIndexL(aContact,start,end);
+ iSortedItems->MoveL(pos,index>pos?index-1:index);
+ }
+ }
+
+
+TInt CContactDatabase::CompareSortFieldsL(const CContactItem& aContact)
+ {
+ TInt compare=0;
+ TInt index=0;
+ CArrayFix<TSortPref>* sortOrder = iCntSvr->GetSortPreferenceL();
+ CleanupStack::PushL(sortOrder);
+ const TInt sortDefs=sortOrder->Count();
+ while (compare==0 && index<sortDefs)
+ {
+ TUid fieldType=(*sortOrder)[index++].iFieldType;
+ TTextFieldMinimal textFieldMin;
+ TTextFieldMinimal textFieldMin2;
+ if (fieldType==KUidContactFieldDefinedText)
+ {
+ // Reads from database.
+ ReadContactTextDefL(aContact.Id(),textFieldMin);
+ // Does not read from database.
+ ReadContactTextDefL(aContact,textFieldMin2);
+ }
+ else
+ {
+ MLplViewIteratorManager& manager = FactoryL()->GetViewIteratorManagerL();
+ manager.TextFieldL(aContact.Id(),fieldType,textFieldMin);
+ aContact.CardFields().NonZeroFieldText(fieldType,textFieldMin2);
+ }
+ compare=textFieldMin.CompareC(textFieldMin2,3,&iCollateMethod);
+ }
+ if (index>0)
+ --index;
+
+ TInt retVal = ((sortDefs==0) || ((*sortOrder)[index].iOrder==CContactDatabase::TSortPref::EAsc)? compare : -compare);
+ CleanupStack::PopAndDestroy(); //sortOrder
+ return retVal;
+ }
+
+
+/**
+Looks at the sort order and identifes what tables are required.
+*/
+void CContactDatabase::ConstructTableUsageFlagsFromSortOrderL(TInt& aFlags)
+ {
+ CContactTextDef* textDef=CContactTextDef::NewLC();
+ CArrayFix<TSortPref>* sortOrder = iCntSvr->GetSortPreferenceL();
+ CleanupStack::PushL(sortOrder);
+ TInt sortOrderCount=sortOrder->Count();
+ TInt columns=0;
+ aFlags=0;
+ for (TInt sortIndex=0;sortIndex<sortOrderCount;sortIndex++)
+ textDef->AppendL(TContactTextDefItem((*sortOrder)[sortIndex].iFieldType));
+ MLplCollection& collection = FactoryL()->GetCollectorL();
+ collection.ConstructBitwiseFlagsFromTextDef(aFlags,columns,textDef);
+ CleanupStack::PopAndDestroy(sortOrder);
+ CleanupStack::PopAndDestroy(textDef);
+ }
+
+
+/**
+Update sorted items list using contact card/group change event.
+
+@internalTechnology
+@since 7.0
+
+@param aEvent Database change event
+*/
+void CContactDatabase::HandleDbObserverEventGroupOrContactChangedL(const TContactItemId aContactId)
+ {
+ if (iSortedItems)
+ {
+ CArrayFix<TSortPref>* sortOrder = iCntSvr->GetSortPreferenceL();
+ CleanupStack::PushL(sortOrder);
+ if(sortOrder!=NULL && sortOrder->Count() > 0)
+ {
+ if (iTablesOpen)
+ {
+ CContactItem* contact = NULL;
+ TRAPD(error, contact = ReadContactL(aContactId));
+ if (CheckSortError(error)==EFalse && contact != NULL)
+ {
+ MoveInSortArray(*contact);
+ delete contact;
+ }
+ }
+ else
+ {
+ CheckSortError(KErrGeneral);
+ }
+ }
+ CleanupStack::PopAndDestroy(sortOrder);
+ }
+ }
+
+
+/**
+Add new contact card/group to sorted items list using add event.
+
+@internalTechnology
+@since 7.0
+
+@param aEvent Database change event
+*/
+void CContactDatabase::HandleDbObserverEventGroupOrContactAddedL(const TContactDbObserverEventType aEventType, const TContactItemId aContactId)
+ {
+ if (aEventType == EContactDbObserverEventGroupAdded)
+ {
+ if(iGroupIds == NULL)
+ {
+ //if database was opened async, iGroups is null, so we have to fetch the group ids first
+ iGroupIds = iCntSvr->FetchGroupListIdsL();
+ if(iGroupIds->Find(aContactId) == KErrNotFound)
+ {
+ iGroupIds->AddL(aContactId);
+ }
+ }
+ else
+ {
+ iGroupIds->AddL(aContactId);
+ }
+ }
+
+ if (iSortedItems)
+ {
+ if (iTablesOpen)
+ {
+ CContactItem* contact = NULL;
+ TInt error = KErrGeneral;
+ CArrayFix<TSortPref>* sortOrder = iCntSvr->GetSortPreferenceL();
+ CleanupStack::PushL(sortOrder);
+ if(sortOrder!= NULL && sortOrder->Count() > 0)
+ //There is a sort order, so the contact must be read
+ //to find out where to insert it into the sorted list
+ {
+ TRAP(error, contact = ReadContactL(aContactId));
+ CheckSortError(error);
+ if (error == KErrNone && contact != NULL)
+ {
+ InsertInSortArray(*contact);
+ delete contact;
+ }
+ }
+ else
+ {
+ // No sort order is defined only the contact's type is needed.
+ TContactItemId actualId;
+ TUid contactType = KNullUid;
+ TBool deleted = EFalse;
+ TBool found = EFalse;
+
+ MLplCollection& collection = FactoryL()->GetCollectorL();
+ TRAP(error, found = collection.SeekContactL(aContactId,actualId,contactType,deleted));
+
+ if (found && CheckSortError(error)==EFalse)
+ {
+ if (CheckType(contactType))
+ {
+ iSortedItems->AddL(aContactId);
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(sortOrder);
+ }
+ else // iTablesOpen == EFalse
+ {
+ CheckSortError(KErrGeneral);
+ }
+ }
+ }
+
+
+/**
+@internalTechnology
+*/
+void CContactDatabase::StartAsyncActivityL()
+ {
+ // starting: Recover, Async Find, Compress
+ ++iAsyncActivityCount;
+
+ // At least one async activity in progress, tell server.
+ if (iAsyncActivityCount == 1)
+ {
+ iCntSvr->SetAsyncActivityL(ETrue);
+ }
+ }
+
+
+/**
+@internalTechnology
+*/
+void CContactDatabase::EndAsyncActivityL()
+ {
+ // ending: Recover, Async Find, Compress
+ --iAsyncActivityCount;
+
+ // All async activities finished, tell server this so that it can process
+ // any pending database close.
+ if (iAsyncActivityCount == 0)
+ {
+ iCntSvr->SetAsyncActivityL(EFalse);
+ }
+ }
+
+
+/**
+Determine if the database is ready. Ready in this context means that the
+database is open and readable/writable (i.e. the state machine is in
+CStateWritable).
+
+@internalTechnology
+@capability None
+
+@return ETrue if the database is ready, EFalse if the database is not ready.
+*/
+TBool CContactDatabase::DatabaseReadyL() const
+ {
+ return iCntSvr->DatabaseReadyL();
+ }
+
+
+CCntIdleSorter::CCntIdleSorter(CContactDatabase &aContactDatabase)
+: iDb(aContactDatabase), iState(EReadContacts)
+ {
+ }
+
+
+CCntIdleSorter::~CCntIdleSorter()
+ {
+ if (iSortStarted)
+ {
+ // async Sort blocks Backup or Restore closing the database handles
+ TRAP_IGNORE(iDb.EndAsyncActivityL());
+ iSortStarted = EFalse;
+ }
+
+ if (iIdle)
+ iIdle->Cancel();
+ delete iIdle;
+ delete iSortOrder;
+ delete iSortedList;
+ delete iFinalItems;
+ }
+
+
+void CCntIdleSorter::ConstructL()
+ {
+ iIdle = CIdle::NewL(CActive::EPriorityIdle);
+ iSortedList = new(ELeave) CSortArray();
+ iFinalItems = CContactIdArray::NewL();
+
+ // Must call this to ensure the system template is loaded
+// Not required in client for cntmodel
+// iDb.SystemTemplateL();
+ }
+
+
+CCntIdleSorter* CCntIdleSorter::NewL(CContactDatabase &aContactDatabase)
+ {
+ CCntIdleSorter* self= new(ELeave) CCntIdleSorter(aContactDatabase);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+/**
+Prepare and begin the sort.
+*/
+void CCntIdleSorter::StartSortingL(CArrayFix<CContactDatabase::TSortPref>* aSortOrder, TRequestStatus& aStatus)
+ {
+ // Take ownership of sort order
+ iSortOrder = aSortOrder;
+
+ // Save the TRequestStatus so we can signal the client
+ iStatus = &aStatus;
+
+ // Set up how many records we will have to read
+ TotalCount() = iDb.CountL();
+
+ // async Sort uses database tables, so Backup or Restore handling must wait for the async activity to finish
+ iDb.StartAsyncActivityL();
+ iSortStarted = ETrue;
+
+ // Indicate that the sort is in progress. This will result in the client's
+ // RunL (if it's using an AO framework) to be called when the sort is completed
+ // or cancelled.
+ *iStatus = KRequestPending;
+
+ // Start the idle sorter.
+ iIdle->Start(TCallBack(CCntIdleSorter::SortCallBack, this));
+ }
+
+
+/**
+Sort with observer.
+*/
+void CCntIdleSorter::StartSortingL(CArrayFix<CContactDatabase::TSortPref>* aSortOrder, TRequestStatus& aStatus, MContactSortObserver& aObserver)
+ {
+ iObserver = &aObserver;
+ HasObserver() = ETrue;
+ StartSortingL(aSortOrder, aStatus);
+ }
+
+
+/**
+Initialise values to defaults.
+*/
+void CCntIdleSorter::ResetL()
+ {
+// iDb.iItemTable->iTable.BeginningL();
+ iState = EReadContacts;
+ iIdle->Cancel();
+
+ delete iSortOrder;
+ iSortOrder = NULL;
+
+ delete iSortedList;
+ iSortedList = NULL;
+ iSortedList = new(ELeave) CSortArray();
+
+ if (iSortStarted)
+ {
+ // async Sort blocks Backup or Restore closing the database handles
+ iDb.EndAsyncActivityL();
+ iSortStarted = EFalse;
+ }
+
+ delete iFinalItems;
+ iFinalItems = NULL;
+ iFinalItems = CContactIdArray::NewL();
+
+ iObserver = NULL;
+ iStatus = NULL;
+ HasObserver() = EFalse;
+ TotalCount() = 0;
+ ReadSoFar() = 0;
+ iCurrentId = 0;
+ }
+
+
+/**
+Callback function for idle object.
+*/
+TInt CCntIdleSorter::SortCallBack(TAny* aThis)
+ {
+ return static_cast<CCntIdleSorter*>(aThis)->PeformSortStep();
+ }
+
+
+/**
+Read a single contact.
+*/
+TBool CCntIdleSorter::ReadContactsL(TInt aNumber)
+ {
+ // Do we have to sort using specified order criteria?
+ TBool moreToDo = ETrue;
+ TBool haveSortOrder = (iSortOrder->Count() > 0);
+ TUid fieldType = (haveSortOrder) ? iSortOrder->At(0).iFieldType : KNullUid;
+ CBase* array = (haveSortOrder) ? (CBase*) iSortedList : (CBase*)iFinalItems;
+
+ // Only retrieve aNumber contacts from the contact store before yeilding
+ for (TInt i = 0; i < aNumber; i++)
+ {
+ ++ReadSoFar();
+ TContactItemId actualId(0);
+ moreToDo = iDb.AddContactToSortListL(iCurrentId,actualId,array, fieldType, haveSortOrder) && moreToDo;
+ iCurrentId = actualId+1;
+ if(!moreToDo)
+ break;
+ }
+
+ // Report progress to observer (if there is one)
+ ReportProgressL();
+
+ return moreToDo;
+ }
+
+
+/**
+This function is called once the reading from the database is complete.
+It replaces the contact database's sorted list (takes ownership of iFinalItems).
+*/
+void CCntIdleSorter::SortListAndSaveL()
+ {
+ iSortedList->SortL(iSortOrder->At(0).iOrder);
+ iDb.SortDuplicatesL(*iSortOrder, *iSortedList, 1);
+ const TInt count = iSortedList->Count();
+ for (TInt i=0; i<count; i++)
+ iFinalItems->AddL(iSortedList->Id(i));
+
+ // Safe to do this now...
+ delete iDb.iSortedItems;
+ iDb.iSortedItems = iFinalItems;
+ iFinalItems = NULL; // just so we don't delete it
+
+ if (iSortStarted)
+ {
+ // async Sort blocks Backup or Restore closing the database handles
+ iDb.EndAsyncActivityL();
+ iSortStarted = EFalse;
+ }
+
+ // Set the sort order in the server.
+ iDb.iCntSvr->SetSortPreferenceL(*iSortOrder);
+ }
+
+
+/**
+Called as a result of a cancellation request by the CContactDatabase class.
+*/
+void CCntIdleSorter::Cancel()
+ {
+ iIdle->Cancel();
+ CompleteRequest(KErrCancel);
+ TRAP_IGNORE(ResetL());
+ }
+
+
+/**
+Complete the client's request status with the specified error value (KErrNone by default).
+*/
+void CCntIdleSorter::CompleteRequest(TInt aError)
+ {
+ if (iStatus)
+ User::RequestComplete(iStatus, aError);
+ }
+
+
+/**
+if we have an observer, then we report progress as the sort is performed (in reality
+we actually only report progress during the read stage, not the sort itself).
+*/
+void CCntIdleSorter::ReportProgressL()
+ {
+ if (iObserver && HasObserver())
+ iObserver->HandleSortEventL(Max(TotalCount(), ReadSoFar()), TotalCount());
+ }
+
+
+/**
+Idle object callback which performs appropriate action based on internal state machine.
+*/
+TInt CCntIdleSorter::PeformSortStep()
+ {
+ TInt err = KErrNone;
+ TBool moreToDo = EFalse;
+
+ // Based on the current state machine value we perform either a read or a sort
+ switch (iState)
+ {
+ case EReadContacts:
+ // Read all contacts & when complete move to next state
+ TRAP(err, moreToDo = ReadContactsL())
+ if (err)
+ {
+ // There was an error sorting
+ CompleteRequest(err);
+ moreToDo = EFalse;
+ }
+ else if (!moreToDo)
+ {
+ // Indicate that the reading is complete
+ iState = ESortContacts;
+
+ // Set this back to ETrue because we now have to do the sort...
+ moreToDo = ETrue;
+ }
+
+ break;
+
+ case ESortContacts:
+ // Contact reading finished, now perform the sort
+ TRAP(err, SortListAndSaveL());
+ CompleteRequest(err);
+ moreToDo = EFalse;
+ break;
+ }
+
+ // Return a boolean indicating whether we want the idle to call this dispatch
+ // function again in future.
+ return moreToDo;
+ }
+
+
+/**
+Allocates and constructs a new contact database change notifier.
+
+@param aDatabase The contact database to observe.
+@param aObserver The observer for aDatabase. Its HandleDatabaseEventL() function
+is called whenever a change occurs to the database.
+
+@return Pointer to the newly created contact database change notifier.
+*/
+EXPORT_C CContactChangeNotifier* CContactChangeNotifier::NewL(CContactDatabase& aDatabase, MContactDbObserver* aObserver)
+ {
+ CContactChangeNotifier *self=new(ELeave) CContactChangeNotifier(aDatabase, aObserver);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return(self);
+ }
+
+
+CContactChangeNotifier::CContactChangeNotifier(CContactDatabase& aDatabase, MContactDbObserver *aObserver) :
+ iDatabase(aDatabase), iObserver(aObserver)
+ {}
+
+
+/**
+Removes the observer from the contact database.
+*/
+EXPORT_C CContactChangeNotifier::~CContactChangeNotifier()
+ {
+ if (iObserver)
+ {
+ iDatabase.RemoveObserver(*iObserver);
+ }
+ }
+
+
+void CContactChangeNotifier::ConstructL()
+ {
+ if (iObserver)
+ {
+ iDatabase.AddObserverL(*iObserver);
+ }
+ }
+
+
+/**
+Deletes a contact item.
+See doDeleteContactL() for details
+*/
+void CContactDatabase::DeleteContactSendEventActionL(TContactItemId aContactId, TCntSendEventAction aActionType)
+ {
+ iCntSvr->DeleteContactL(aContactId, aActionType);
+ //Now we check if the contact belonged to the sort array, if so
+ //remove it from iSortedItems
+ RemoveFromSortArray(aContactId);
+ //Now we check if the contact belonged to the template list, if so
+ //remove it from iCardTemplateIds
+ RemoveFromTemplateList(aContactId);
+ //Now we check if the contact belonged to the Group Id list, if so
+ //remove it from iGroupIds
+ RemoveFromGroupIds(aContactId);
+ }
+