diff -r f5050f1da672 -r 04becd199f91 javaextensions/pim/cntadapter/src.s60/cpimcontactlistadapter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaextensions/pim/cntadapter/src.s60/cpimcontactlistadapter.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,827 @@ +/* +* Copyright (c) 2008 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: Handles PIM contact list <-> Contacts Model conversions + * +*/ + + +// CLASS HEADER +#include "cpimcontactlistadapter.h" + +// INTERNAL INCLUDES +#include "cpimcontactcategorymanager.h" +#include "cpimcontactitemadapter.h" +#include "mpimcontactitem.h" +#include "mpimitemdata.h" +#include "logger.h" + +// EXTERNAL INCLUDES +#include +#include +#include // CContactGroup +#include // CCntFilter + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CPIMContactListAdapter* CPIMContactListAdapter::NewL( + java::util::FunctionServer* aFuncServer) +{ + JELOG2(EPim); + CPIMContactListAdapter* self = + new(ELeave) CPIMContactListAdapter(aFuncServer); + + CallMethodL(self, &CPIMContactListAdapter::ConstructL, self->iFuncServer); + + return self; +} + +// Destructor +CPIMContactListAdapter::~CPIMContactListAdapter() +{ + JELOG2(EPim); + Close(); +} +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::HandleDatabaseEventL +// Tests the contact database observer event type and handles it. The ID of +// a contact affected by the change event, if relevant, can be retrieved +// via TContactDbObserverEvent::iContactId. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::HandleDatabaseEventL( + TContactDbObserverEvent aEvent) // information about the change event +{ + JELOG2(EPim); + switch (aEvent.iType) + { + case EContactDbObserverEventGroupAdded: + { + ExternalGroupChangeL(aEvent.iContactId, EPIMExternalChangeNew); + break; + } + case EContactDbObserverEventGroupChanged: + { + ExternalGroupChangeL(aEvent.iContactId, EPIMExternalChangeModified); + break; + } + case EContactDbObserverEventGroupDeleted: + { + ExternalGroupChangeL(aEvent.iContactId, EPIMExternalChangeRemoved); + break; + } + case EContactDbObserverEventContactAdded: + { + ExternalItemChangeL(aEvent.iContactId, EPIMExternalChangeNew); + break; + } + case EContactDbObserverEventContactChanged: + { + ExternalItemChangeL(aEvent.iContactId, EPIMExternalChangeModified); + break; + } + case EContactDbObserverEventContactDeleted: + { + ExternalItemChangeL(aEvent.iContactId, EPIMExternalChangeRemoved); + break; + } + default: + { + // we don't care about other changes + return; + } + } +} + + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::GetCategoriesL +// Provides all categories currently existing in the native database. +// Returns: Array of categories +// ----------------------------------------------------------------------------- +// +const CDesCArray& CPIMContactListAdapter::GetCategoriesL() +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iCategoryManager, User::Leave(KErrNotReady)); + return iCategoryManager->CallGetCategoriesL(); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::AddCategoryL +// Adds a new category to the native database. +// If the category already exists, nothing is done and the method returns +// successfully. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::AddCategoryL(const TDesC& aNewCategory) +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iCategoryManager, User::Leave(KErrNotReady)); + CallMethodL(iCategoryManager, &CPIMContactCategoryManager::AddCategoryL, + aNewCategory, iFuncServer); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::DeleteCategoryL +// Deletes an existing category. +// If there is no such category, nothing is done and the method returns +// successfully. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::DeleteCategoryL(const TDesC& aCategory) +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iCategoryManager, User::Leave(KErrNotReady)); + CallMethodL(iCategoryManager, &CPIMContactCategoryManager::DeleteCategoryL, + aCategory, iFuncServer); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::RenameCategoryL +// Renames an existing category. +// Entries in the old category are moved to the new category. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::RenameCategoryL(const TDesC& aOldCategory, // The old category name + const TDesC& aNewCategory) // The new category name +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iCategoryManager, User::Leave(KErrNotReady)); + CallMethodL(iCategoryManager, &CPIMContactCategoryManager::RenameCategoryL, + aOldCategory, aNewCategory, iFuncServer); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::IsCategoriesExternallyModified +// Checks whether there have been external changes to the categories in +// the native database after last call to +// GetExternalCategoryModifications or list adapter creation. +// Returns: ETrue: If there are any external changes +// EFalse: Otherwise +// ----------------------------------------------------------------------------- +// +TBool CPIMContactListAdapter::IsCategoriesExternallyModified() +{ + JELOG2(EPim); + if (iCategoryChanges) + { + return ETrue; + } + return EFalse; +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::GetExternalCategoryModificationsL +// Provides the external changes to the categories in the native database. +// Returns: An array of category state change objects. The ownership +// of the array is transferred to the caller. Note that the +// array elements contain heap-allocated data. +// ----------------------------------------------------------------------------- +// +RPointerArray* +CPIMContactListAdapter::GetExternalCategoryModificationsL() +{ + JELOG2(EPim); + CallMethodL(this, &CPIMContactListAdapter::IsDatabaseReadyL, iFuncServer); + RPointerArray* retval = iCategoryChanges; + iCategoryChanges = NULL; + return retval; +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::IsItemsExternallyModified +// Checks whether there have been external changes to the items in +// the native database after last call to +// GetExternalItemModifications or list adapter creation. +// Returns: EExternalChangesMinor: If there are any external changes +// EExternalChangesNone: Otherwise +// ----------------------------------------------------------------------------- +// +MPIMListAdapter::TExternalItemChangeClass CPIMContactListAdapter::IsItemsExternallyModified() +{ + JELOG2(EPim); + if ((iItemChanges || iFirstItemChanges)) + { + return MPIMListAdapter::EExternalChangesMinor; + } + return MPIMListAdapter::EExternalChangesNone; +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::GetExternalItemModificationsL +// Provides the external changes to the items in the native database. +// Returns: An array of item state change objects. The ownership +// of the array is transferred to the caller. Note that the +// array elements contain heap-allocated data. +// ----------------------------------------------------------------------------- +// +RPointerArray* +CPIMContactListAdapter::GetExternalItemModificationsL() +{ + JELOG2(EPim); + CallMethodL(this, &CPIMContactListAdapter::IsDatabaseReadyL, iFuncServer); + + // the first time, + // we check for all cards + if (iFirstItemChanges) + { + //FilterAllContactsL(); + CallMethodL(this, &CPIMContactListAdapter::FilterAllContactsL, + iFuncServer); + iFirstItemChanges = EFalse; + } + + RPointerArray* retval = iItemChanges; + iItemChanges = NULL; + return retval; +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::Close +// Used to inform the list adapter that the list has been closed. +// The list adapter may then release all resources it has reserved. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::Close() +{ + JELOG2(EPim); + CallMethod(this, &CPIMContactListAdapter::DoClose, iFuncServer); +} + +void CPIMContactListAdapter::DoClose() +{ + JELOG2(EPim); + if (iCategoryChanges) + { + iCategoryChanges->ResetAndDestroy(); + delete iCategoryChanges; + iCategoryChanges = NULL; + } + if (iItemChanges) + { + iItemChanges->ResetAndDestroy(); + delete iItemChanges; + iItemChanges = NULL; + } + delete iNotifier; + iNotifier = NULL; + delete iItemAdapter; + iItemAdapter = NULL; + delete iCategoryManager; + iCategoryManager = NULL; + delete iDatabase; + iDatabase = NULL; + delete iMinimalFieldsViewDef; + iMinimalFieldsViewDef = NULL; +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::GetPimListAdapter +// Provides access to the MPIMListAdapter representation of this +// MPIMContactListAdapter object. +// ----------------------------------------------------------------------------- +// +MPIMListAdapter* CPIMContactListAdapter::GetPimListAdapter() +{ + JELOG2(EPim); + return this; +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::CreateContactItemL +// Creates a new contact item (entry) in the native database. +// The adapter creates a new native database entry, sets its data +// according to the data in aContactItem, adds it to the database +// and sets the Item ID of aContactItem. aContactItem must +// contain valid data and have Item ID KPIMNullItemID. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::CreateContactItemL(MPIMContactItem& aContactItem) // The contact item to add +{ + JELOG2(EPim); + CallMethodL(this, &CPIMContactListAdapter::DoCreateContactItemL, + aContactItem, iFuncServer); + ReadContactItemL(aContactItem); +} + +void CPIMContactListAdapter::DoCreateContactItemL(MPIMContactItem& aContactItem) // The contact item to add +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iItemAdapter || iDatabase, User::Leave(KErrNotReady)); + CContactCard* card = iItemAdapter->CardL(aContactItem); + CleanupStack::PushL(card); + // Leaves with KErrDiskFull if there is not enough disk + // space to create a new contact item + TContactItemId id = iDatabase->AddNewContactL(*card); + // Set new item id. If this leaves it means that + // SetContactItemIdL leaved with KErrOutNoMemory + TRAPD(err, aContactItem.SetContactItemIdL(id)); + if (KErrNone != err) + { + TBuf8 entryId; + entryId.Num(static_cast(id)); + DoRemoveContactItemL(entryId); + User::Leave(err); + } + iItemAdapter->UpdateCategoriesL(aContactItem, *card); + CleanupStack::PopAndDestroy(card); + // update possible changes (e.g. dropped attributes) to the item + aContactItem.PrepareForLoadL(); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::ReadContactItemL +// Reads an existing contact item from the native database. +// The adapter maps the Item ID in aContactItem to a native database +// entry identifier, reads the entry and sets the data of +// aContactItem according to the data in the native entry. This operation +// is very performance sensitive, so it must be used with cause and only +// when the full contact item is needed +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::ReadContactItemL(MPIMContactItem& aContactItem) // The contact item to be read +{ + JELOG2(EPim); + CallMethodL(this, &CPIMContactListAdapter::DoCallReadContactItemL, + aContactItem, iFuncServer); +} + +void CPIMContactListAdapter::DoCallReadContactItemL( + MPIMContactItem& aContactItem) // The contact item to be read +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iItemAdapter || iDatabase, User::Leave(KErrNotReady)); + const TContactItemId id = aContactItem.ContactItemIdL(); + __ASSERT_ALWAYS(id != 0, User::Leave(KErrArgument)); + // If the contact item contains data we don't want to overwrite it + // so we create a mask item view definition if needed. Otherwise + // we just read full contact item from the database + CContactItemViewDef* itemViewDef = CContactItemViewDef::NewLC( + CContactItemViewDef::EMaskFields, + CContactItemViewDef::EIncludeHiddenFields); + CArrayFix* fields = aContactItem.ItemData().FieldsLC(); + TInt count = fields->Count(); + + // Mask fields and do not include. Note that if there is no fields in the + // item the view should provide all possible fields from the database + for (TInt i = 0; i < count; i++) + { + TPIMContactField field = static_cast(fields->At(i)); + // Get Contacts Model fields mapped to PIM fields + CArrayFix* fieldArray = iItemAdapter->ContactsModelFieldTypeL( + field); + CleanupStack::PushL(fieldArray); + // Add retrieved fields to the item view definition + TInt fieldCount = fieldArray->Count(); + for (TInt j = 0; j < fieldCount; j++) + { + const TUid fieldUid = + { fieldArray->At(j) }; + // Do not add the field to the view if it already contains + // this type of a field (e.g the field is a name array element) + if (itemViewDef->Find(fieldUid) == KErrNotFound) + { + itemViewDef->AddL(fieldUid); + } + } + CleanupStack::PopAndDestroy(fieldArray); + } + DoReadContactItemL(aContactItem, *itemViewDef); + CleanupStack::PopAndDestroy(2, itemViewDef); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::ReadMinimalContactItemL +// This version reads a minimal contact item from the native database by using +// contact database view definition. The view definition is initialized in +// the constructor of this class and needs to be up to date with currently +// required contact fields when the item is read for the first time. This +// function was introduced due to improve poor performance of the PIM API +// ContactList +// ----------------------------------------------------------------------------- + +void CPIMContactListAdapter::ReadMinimalContactItemL( + MPIMContactItem& aContactItem) +{ + JELOG2(EPim); + CallMethodL(this, &CPIMContactListAdapter::DoCallReadMinimalContactItemL, + aContactItem, iFuncServer); +} + +void CPIMContactListAdapter::DoCallReadMinimalContactItemL( + MPIMContactItem& aContactItem) +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iItemAdapter || iDatabase, User::Leave(KErrNotReady)); + TContactItemId id = aContactItem.ContactItemIdL(); + __ASSERT_ALWAYS(id != 0, User::Leave(KErrArgument)); + + // Reset item for reading + aContactItem.PrepareForLoadL(); + + // Use contact database filtering. Currently only all name elements + // are retrieved from the database to improve performance of the list + DoReadContactItemL(aContactItem, *iMinimalFieldsViewDef); + +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::ReadMinimalContactItemL +// This version reads a minimal contact item from the native database by using +// contact database view definition. The view definition is initialized in +// the constructor of this class and it can be modified to fetch specified fields +// by the matching item given as an argument to this function +// ----------------------------------------------------------------------------- + +void CPIMContactListAdapter::ReadMinimalContactItemL( + MPIMContactItem& aContactItem, const MPIMContactItem& aMatchingContactItem) +{ + JELOG2(EPim); + // Get fields from the matching item and add those to the view definition + CArrayFix* fields = aMatchingContactItem.ItemData().FieldsLC(); + TInt count = fields->Count(); + for (TInt i = 0; i < count; i++) + { + TPIMContactField field = static_cast(fields->At(i)); + // Get Contacts Model fields mapped to PIM fields + CArrayFix* fieldArray = iItemAdapter->ContactsModelFieldTypeL( + field); + CleanupStack::PushL(fieldArray); + // Add retrieved fields to the item view definition + TInt fieldCount = fieldArray->Count(); + for (TInt j = 0; j < fieldCount; j++) + { + const TUid fieldUid = + { fieldArray->At(j) }; + // Do not add the field to the view if it already contains + // this type of a field (e.g the field is a name array element) + if (iMinimalFieldsViewDef->Find(fieldUid) == KErrNotFound) + { + iMinimalFieldsViewDef->AddL(fieldUid); + } + } + CleanupStack::PopAndDestroy(fieldArray); + } + CleanupStack::PopAndDestroy(fields); + // Read contact item using minimal field definition + ReadMinimalContactItemL(aContactItem); + // Reset the view definition to its previous state + InitializeMinimalViewDefinitionL(); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::ReadContactFieldL +// Reads one field from the contact database +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::ReadContactFieldL(MPIMContactItem& aContactItem, + TPIMContactField aContactField) +{ + JELOG2(EPim); + CallMethodL(this, &CPIMContactListAdapter::DoReadContactFieldL, + aContactItem, aContactField, iFuncServer); +} + +void CPIMContactListAdapter::DoReadContactFieldL(MPIMContactItem& aContactItem, + TPIMContactField aContactField) +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iItemAdapter || iDatabase, User::Leave(KErrNotReady)); + TContactItemId id = aContactItem.ContactItemIdL(); + __ASSERT_ALWAYS(id != 0, User::Leave(KErrArgument)); + + // Create new view definition + CContactItemViewDef* itemViewDef = CContactItemViewDef::NewLC( + CContactItemViewDef::EIncludeFields, + CContactItemViewDef::EIncludeHiddenFields); + CArrayFix* fieldArray = iItemAdapter->ContactsModelFieldTypeL( + aContactField); + CleanupStack::PushL(fieldArray); + // Add retrieved fields to the item view definition + TInt fieldCount = fieldArray->Count(); + for (TInt i = 0; i < fieldCount; i++) + { + const TUid fieldUid = + { fieldArray->At(i) }; + itemViewDef->AddL(fieldUid); + } + // The view cannot be empty so check the field count in debug builds + __ASSERT_DEBUG(itemViewDef->Count() > 0, User::Panic(KPIMPanicCategory, + EPIMPanicInvalidState)); + CleanupStack::PopAndDestroy(fieldArray); + DoReadContactItemL(aContactItem, *itemViewDef); + CleanupStack::PopAndDestroy(itemViewDef); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::WriteContactItemL +// Writes an existing contact item to the native database. +// The adapter maps the Item ID in aContactItem to a native database +// entry identifier, reads the entry and sets the data of the entry +// according to the data in aContactItem. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::WriteContactItemL(MPIMContactItem& aContactItem) // The contact item to write +{ + JELOG2(EPim); + CallMethodL(this, &CPIMContactListAdapter::DoWriteContactItemL, + aContactItem, iFuncServer); + ReadContactItemL(aContactItem); +} + +void CPIMContactListAdapter::DoWriteContactItemL(MPIMContactItem& aContactItem) // The contact item to write +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iItemAdapter || iDatabase, User::Leave(KErrNotReady)); + TContactItemId id = aContactItem.ContactItemIdL(); + __ASSERT_ALWAYS(id != 0, User::Leave(KErrArgument)); + + // OpenContactLX leaves the lock item in the cleanup stack + CContactCard* contactItem = + static_cast(iDatabase->OpenContactLX(id)); + CleanupStack::PushL(contactItem); + iItemAdapter->UpdateCardL(aContactItem, *contactItem); + iDatabase->CommitContactL(*contactItem); + // Note: Even though the above line closed the contact, we can still + // keep the lock item in the cleanup stack as closing a contact + // twice is harmless + iItemAdapter->UpdateCategoriesL(aContactItem, *contactItem); + CleanupStack::PopAndDestroy(contactItem); + CleanupStack::Pop(); // contactItem lock item + // update possible changes (e.g. dropped attributes) to the item + aContactItem.PrepareForLoadL(); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::ReadContactItemL +// Removes an existing contact from the native database. +// The adapter maps aItemID to a native database entry and removes it. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::RemoveContactItemL(TPIMItemID aItemID) +{ + JELOG2(EPim); + CallMethodL(this, &CPIMContactListAdapter::DoRemoveContactItemL, aItemID, + iFuncServer); +} + +void CPIMContactListAdapter::DoRemoveContactItemL(TPIMItemID aItemID) +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iDatabase, User::Leave(KErrNotReady)); + // Convert string id to integer id + TUint id; + TLex8 lex(aItemID); + TInt status = lex.Val(id); + User::LeaveIfError(status); + // Delete contact from the contact database + iDatabase->DeleteContactL(id); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::CPIMContactListAdapter +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CPIMContactListAdapter::CPIMContactListAdapter( + java::util::FunctionServer* aFuncServer) +{ + JELOG2(EPim); + iFirstItemChanges = ETrue; + iFuncServer = aFuncServer; +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::ConstructL() +{ + JELOG2(EPim); + // Create default contact database if it does not exist. This may happen + // if the current Phonebook engine is not running or started during + // device boot. Usually, the database should be available but this is precaution + if (!CContactDatabase::DefaultContactDatabaseExistsL()) + { + iDatabase + = CContactDatabase::CreateL(/*CContactDatabase::EMultiThread*/); + } + else + { + iDatabase = CContactDatabase::OpenL(/*CContactDatabase::EMultiThread*/); + } + + // Create other contact adapter resources and initialize item view + iCategoryManager + = CPIMContactCategoryManager::NewL(*iDatabase, iFuncServer); + iNotifier = CContactChangeNotifier::NewL(*iDatabase, this); + iItemAdapter = CPIMContactItemAdapter::NewL(*iCategoryManager); + // Initialize minimal fields view definition + iMinimalFieldsViewDef = CContactItemViewDef::NewL( + CContactItemViewDef::EIncludeFields, + CContactItemViewDef::EIncludeHiddenFields); + InitializeMinimalViewDefinitionL(); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::ExternalGroupChangeL +// Adds an entry to external category change list. +// Also causes the category cache to be flushed. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::ExternalGroupChangeL(TContactItemId aId, // Id of the changed category + TPIMExternalChangeType aType) // type of the change +{ + JELOG2(EPim); + iCategoryManager->FlushCache(); + + // This should never happen + __ASSERT_ALWAYS(iCategoryManager, User::Leave(KErrNotReady)); + + if (!iCategoryChanges) + { + iCategoryChanges + = new(ELeave) RPointerArray (1); + } + CPIMCategoryStateChange* change = NULL; + switch (aType) + { + case EPIMExternalChangeModified: + { + HBufC* newCategoryName = iCategoryManager->GroupLabelL(aId); + CleanupStack::PushL(newCategoryName); + HBufC* oldCategoryName = iCategoryManager->LabelFromCacheL(aId); + CleanupStack::PushL(oldCategoryName); + change + = new(ELeave) CPIMCategoryStateChange(oldCategoryName, aType, newCategoryName); + CleanupStack::Pop(2); // newCategoryName and oldCategoryName are + // now owned by change + break; + } + case EPIMExternalChangeNew: + { + HBufC* newCategoryName = iCategoryManager->GroupLabelL(aId); + CleanupStack::PushL(newCategoryName); + change = new(ELeave) CPIMCategoryStateChange(newCategoryName, aType); + CleanupStack::Pop(); // newCategoryName is now owned by change + break; + } + case EPIMExternalChangeRemoved: + { + HBufC* oldCategoryName = iCategoryManager->LabelFromCacheL(aId); + CleanupStack::PushL(oldCategoryName); + change = new(ELeave) CPIMCategoryStateChange(oldCategoryName, aType); + CleanupStack::Pop(); // newCategoryName is now owned by change + break; + } + default: + { + User::Leave(KErrArgument); + } + } + + CleanupStack::PushL(change); + User::LeaveIfError(iCategoryChanges->Append(change)); + CleanupStack::Pop(change); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::ExternalItemChangeL +// Adds an entry to external item change list. +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::ExternalItemChangeL(TContactItemId aId, // Id of the changed category + TPIMExternalChangeType aType) // type of the change +{ + JELOG2(EPim); + if (!iItemChanges) + { + iItemChanges = new(ELeave) RPointerArray (10); + } + HBufC8* changeId = HBufC8::NewLC(KPIMItemIdDesSize); + TPtr8 entryId = changeId->Des(); + entryId.Num(static_cast(aId)); + CPIMItemStateChange* change = + new(ELeave) CPIMItemStateChange(changeId, aType); + // The ownership of changeId is transferred to the item state change object + CleanupStack::Pop(changeId); + + CleanupStack::PushL(change); + iItemChanges->AppendL(change); + CleanupStack::Pop(change); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::FilterAllContacts +// Filters all contact items from the database to the changes list +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::FilterAllContactsL() +{ + JELOG2(EPim); + CCntFilter* filter = CCntFilter::NewLC(); + filter->SetIncludeNewContacts(EFalse); + if (!iItemChanges) + { + iItemChanges = new(ELeave) RPointerArray (10); + } + filter->SetContactFilterTypeALL(EFalse); + filter->SetContactFilterTypeCard(ETrue); + iDatabase->FilterDatabaseL(*filter); + CContactIdArray* idArray = filter->iIds; + TInt idCount = idArray->Count(); + TInt i = 0; + for (i = 0; i < idCount; i++) + { + TContactItemId id = (*idArray)[i]; + TBool wasInList = EFalse; + TInt changeCount = iItemChanges->Count(); + for (TInt j = 0; j < changeCount; j++) + { + TBuf8 entryId; + entryId.Num(static_cast(id)); + if ((*iItemChanges)[j]->ItemID().Compare(entryId) == 0) + { + wasInList = ETrue; + } + } + if (!wasInList) + { + ExternalItemChangeL(id, EPIMExternalChangeNew); + } + } + CleanupStack::PopAndDestroy(); // filter +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::InitializeMinimalViewDefinitionL +// Initializes minimal view definition +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::InitializeMinimalViewDefinitionL() +{ + JELOG2(EPim); + __ASSERT_DEBUG(iMinimalFieldsViewDef, User::Panic(KPIMPanicCategory, + EPIMPanicInvalidState)); + // Reset view definition + iMinimalFieldsViewDef->Reset(); + // Add fields which are to retrieved from the native database + // when minimal item is to be created or read + iMinimalFieldsViewDef->AddL(KUidContactFieldAdditionalName); + iMinimalFieldsViewDef->AddL(KUidContactFieldGivenName); + iMinimalFieldsViewDef->AddL(KUidContactFieldFamilyName); + iMinimalFieldsViewDef->AddL(KUidContactFieldGivenNamePronunciation); + iMinimalFieldsViewDef->AddL(KUidContactFieldFamilyNamePronunciation); + iMinimalFieldsViewDef->AddL(KUidContactFieldPrefixName); + iMinimalFieldsViewDef->AddL(KUidContactFieldSuffixName); +} + +// ----------------------------------------------------------------------------- +// CPIMContactListAdapter::DoReadContactItemL +// Reads contact from the contacts database using item view definition +// ----------------------------------------------------------------------------- +// +void CPIMContactListAdapter::DoReadContactItemL(MPIMContactItem& aContactItem, + const CContactItemViewDef& aContactItemViewDef) +{ + JELOG2(EPim); + const TContactItemId id = aContactItem.ContactItemIdL(); + __ASSERT_DEBUG(id != 0, User::Panic(KPIMPanicCategory, + EPIMPanicInvalidItemID)); + // Read contact item using the item view definition + CContactCard* contactItem = + static_cast(iDatabase->ReadContactLC(id, + aContactItemViewDef)); + // Set date and fill the PIM item + TTime lastModified = contactItem->LastModified(); + aContactItem.SetLastModifiedL(lastModified); + iItemAdapter->FillItemL(aContactItem, *contactItem); + CleanupStack::PopAndDestroy(contactItem); +} + +void CPIMContactListAdapter::IsDatabaseReadyL() +{ + JELOG2(EPim); + __ASSERT_ALWAYS(iDatabase, User::Leave(KErrNotReady)); +} + +// End of file