// 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;
}
/**
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;
}
/**
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;
}
void CContactDatabase::AddObserverL(MContactDbObserver& aChangeNotifier)
{
iCntSvr->AddObserverL(aChangeNotifier);
}
void CContactDatabase::RemoveObserver(const MContactDbObserver& aChangeNotifier)
{
iCntSvr->RemoveObserver(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;
MLplCollection& collection = FactoryL()->GetCollectorL();
TRAP(error, collection.SeekContactL(aContactId,actualId,contactType,deleted));
if (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);
}