--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/pim/cntadapter/src.s60/cpimcontactitemadapter.cpp Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,1467 @@
+/*
+* 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 conversion between PIM API Contact Items and Contacts
+ * Model Contact Cards
+ *
+*/
+
+
+// CLASS HEADER
+#include "cpimcontactitemadapter.h"
+
+// INTERNAL INCLUDES
+#include "cpimcontactcategorymanager.h"
+#include "pimpanics.h"
+#include "mpimcontactitem.h"
+#include "mpimitemdata.h"
+#include "cpimimagescaler.h"
+#include "cpimcontactfieldinfo.h"
+#include "logger.h"
+
+// EXTERNAL INCLUDES
+#include <cntitem.h> // CContactCard etc.
+#include <cntfldst.h> // CContactTextField etc.
+#include <tz.h>
+#include <tzconverter.h>
+
+
+
+// UNNAMED LOCAL NAMESPACE
+namespace
+{
+// Phonebook maps Syncronisation field values with specified
+// hard-coded string values. At the time implementing, the header
+// was not exported so it is necessary to define own constants
+// with same values
+_LIT(KPIMContactClassPrivate, "private");
+_LIT(KPIMContactClassPublic, "public");
+_LIT(KPIMContactClassConfidential, "none");
+}
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CPIMContactItemAdapter* CPIMContactItemAdapter::NewL(
+ CPIMContactCategoryManager& aCategoryManager)
+{
+ JELOG2(EPim);
+ CPIMContactItemAdapter* self =
+ new(ELeave) CPIMContactItemAdapter(aCategoryManager);
+
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+
+ return self;
+}
+
+// destructor
+CPIMContactItemAdapter::~CPIMContactItemAdapter()
+{
+ JELOG2(EPim);
+ delete iImageScaler;
+ delete iFieldInfo;
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::CardL
+// Converts from a PIM item data to a Contacts Model contact card.
+// Returns: A contact card with the same information as given in
+// the parameter item. The ownership of the card is
+// transferred to the caller.
+// -----------------------------------------------------------------------------
+//
+CContactCard* CPIMContactItemAdapter::CardL(const MPIMContactItem& aItem)
+{
+ JELOG2(EPim);
+ CContactCard* card = CContactCard::NewLC();
+ const MPIMItemData& item = aItem.ItemData();
+ __ASSERT_DEBUG((aItem.ContactItemIdL() == 0), User::Panic(
+ KPIMPanicCategory, EPIMPanicInvalidItemID));
+ CArrayFix<TPIMField>* fields = item.FieldsLC();
+
+ TInt fieldCount = fields->Count();
+ for (TInt i = 0; i < fieldCount; i++)
+ {
+ ConvertFieldL(aItem, *card,
+ static_cast<TPIMContactField>(fields->At(i)));
+ }
+
+ // Set default values if not present in PIM item
+ if (item.CountValues(EPIMContactClass) == 0)
+ {
+ CContentType* type = CContentType::NewL(KUidContactFieldClass,
+ KUidContactFieldVCardMapClass);
+ CleanupStack::PushL(type);
+
+ // Add value to the contact field
+ CContactItemField* field = CContactItemField::NewLC(KStorageTypeText,
+ *type);
+ field->SetUserFlags(EContactCategoryNone);
+ CContactTextField* textField = field->TextStorage();
+ textField->SetTextL(KPIMContactClassPrivate());
+ card->AddFieldL(*field);
+
+ CleanupStack::Pop(field);
+ CleanupStack::PopAndDestroy(type);
+ }
+
+ CleanupStack::PopAndDestroy(fields);
+ CleanupStack::Pop(card);
+ return card;
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::FillItemL
+// Converts from a Contacts Model contact card to the PIM representation.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::FillItemL(MPIMContactItem& aItem, // Item data container to fill with the data
+ const CContactCard& aCard) // Contact Card to convert
+{
+ JELOG2(EPim);
+ // convert fields
+ CContactItemFieldSet& fieldSet = aCard.CardFields();
+ TInt fieldCount = fieldSet.Count();
+ for (TInt i = 0; i < fieldCount; i++)
+ {
+ ConvertFieldL(fieldSet[i], aItem);
+ }
+ // convert categories
+ MPIMItemData& item = aItem.ItemData();
+ CContactIdArray* groupArray = aCard.GroupsJoinedLC();
+ TInt groupCount = groupArray->Count();
+ for (TInt i = 0; i < groupCount; i++)
+ {
+ HBufC* label = iCategoryManager.GroupLabelL((*groupArray)[i]);
+ CleanupStack::PushL(label);
+ // Add item to this category if it doesn't belong to it already
+ if (item.FindCategory(*label) == KErrNotFound)
+ {
+ item.AddNewCategoryL(*label);
+ }
+ CleanupStack::PopAndDestroy(label);
+ }
+ CleanupStack::PopAndDestroy(groupArray);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::UpdateCardL
+// Updates the data in the Contacts Model contact card to match
+// the data in the PIM item data container.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::UpdateCardL(const MPIMContactItem& aItem, // Item from which the data is read
+ CContactCard& aCard) // The card which is updated
+{
+ JELOG2(EPim);
+ CleanCard(aCard);
+ const MPIMItemData& itemData = aItem.ItemData();
+ // Get fields
+ CArrayFix<TPIMField>* fields = itemData.FieldsLC();
+ TInt fieldCount = fields->Count();
+ for (TInt i = 0; i < fieldCount; i++)
+ {
+ ConvertFieldL(aItem, aCard, (TPIMContactField)(fields->At(i)));
+ }
+ CleanupStack::PopAndDestroy(); // fields
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::UpdateCategoriesL
+// Updates the category information in the database.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::UpdateCategoriesL(const MPIMContactItem& aItem, // Item containing the new categories
+ const CContactCard& aCard) // Item to update
+{
+ JELOG2(EPim);
+ const CDesCArray& pimCategories = aItem.ItemData().Categories();
+ const TInt pimCategoryCount = pimCategories.Count();
+ TBool* newCategoryTable = new(ELeave) TBool[pimCategoryCount];
+ CleanupArrayDeletePushL(newCategoryTable);
+ TInt i = 0;
+ for (i = 0; i < pimCategoryCount; i++)
+ {
+ newCategoryTable[i] = ETrue;
+ }
+
+ CContactIdArray* cardCategories = aCard.GroupsJoinedLC();
+ TContactItemId id = aItem.ContactItemIdL();
+
+ // first remove extra groups
+ const TInt cardCategoryCount = cardCategories->Count();
+ for (i = 0; i < cardCategoryCount; i++)
+ {
+ TContactItemId groupId = (*cardCategories)[i];
+ HBufC* groupLabel = iCategoryManager.GroupLabelL(groupId);
+ TInt pos;
+ TInt found = pimCategories.Find(*groupLabel, pos, ECmpNormal);
+ delete groupLabel;
+ if (found != 0)
+ {
+ // removed group
+ iCategoryManager.RemoveFromGroupL(id, groupId);
+ }
+ else
+ {
+ // old group
+ newCategoryTable[pos] = EFalse;
+ }
+ }
+ // then add new categories
+ for (i = 0; i < pimCategoryCount; i++)
+ {
+ if (newCategoryTable[i])
+ {
+ TPtrC category = pimCategories[i];
+ iCategoryManager.AddToGroupL(id, category);
+ }
+ }
+ CleanupStack::PopAndDestroy(2); // cardCategories, newCategoryTable
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ContactsModelFieldType
+// Other items were commented in the header
+// -----------------------------------------------------------------------------
+//
+CArrayFix<TInt>* CPIMContactItemAdapter::ContactsModelFieldTypeL(
+ TPIMContactField aContactField) const
+{
+ JELOG2(EPim);
+ return iFieldInfo->MatchPIMFieldL(aContactField);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::CPIMContactItemAdapter
+// C++ constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CPIMContactItemAdapter::CPIMContactItemAdapter(
+ CPIMContactCategoryManager& aCategoryManager) :
+ iCategoryManager(aCategoryManager)
+{
+ JELOG2(EPim);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+inline void CPIMContactItemAdapter::ConstructL()
+{
+ JELOG2(EPim);
+ iFieldInfo = CPIMContactFieldInfo::NewL();
+ iImageScaler = CPIMImageScaler::NewL();
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::CleanCardL
+// Deletes all the supported fields from the contact card.
+// Those fields which are not supported are left as is.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::CleanCard(CContactCard& aCard)
+{
+ JELOG2(EPim);
+ // convert fields
+ CContactItemFieldSet& fieldSet = aCard.CardFields();
+ TInt fieldCount = fieldSet.Count();
+ for (TInt i = 0; i < fieldCount; i++)
+ {
+ if (IsSupportedField(fieldSet[i]))
+ {
+ // as the field is removed, the array shrinks
+ aCard.RemoveField(i--);
+ fieldCount--;
+ }
+ }
+}
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::IsSupportedFieldL
+// Checks if we support this particular contact field.
+// Returns: ETrue if the field is supported
+// EFalse otherwise
+// -----------------------------------------------------------------------------
+//
+TBool CPIMContactItemAdapter::IsSupportedField(CContactItemField& aField)
+{
+ JELOG2(EPim);
+ const CContentType& type = aField.ContentType();
+ if (type.FieldTypeCount() == 0)
+ {
+ // we don't support unknown types
+ return EFalse;
+ }
+
+ TFieldType fieldTypeUid = type.FieldType(0);
+ TInt fieldType = fieldTypeUid.iUid;
+ switch (fieldType)
+ {
+ case KUidContactFieldAddressValue:
+ {
+ // Label addresses are also stored in the database using
+ // KUidContactFieldAddressValue, but we don't support them
+ if (type.ContainsFieldType(KUidContactFieldVCardMapADR))
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+ case KUidContactFieldPictureValue:
+ {
+ // Thumbnails are supported while pictures are not
+ if (type.ContainsFieldType(KUidContactFieldVCardMapPHOTO))
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+ case KUidContactFieldSIPIDValue:
+ case KUidContactFieldFamilyNameValue:
+ case KUidContactFieldGivenNameValue:
+ case KUidContactFieldSecondNameValue:
+ case KUidContactFieldFamilyNamePronunciationValue:
+ case KUidContactFieldGivenNamePronunciationValue:
+ case KUidContactFieldAdditionalNameValue:
+ case KUidContactFieldPrefixNameValue:
+ case KUidContactFieldSuffixNameValue:
+ case KUidContactFieldPhoneNumberValue:
+ case KUidContactFieldFaxValue:
+ case KUidContactFieldEMailValue:
+ case KUidContactFieldUrlValue:
+ case KUidContactFieldPostOfficeValue:
+ case KUidContactFieldExtendedAddressValue:
+ case KUidContactFieldPostCodeValue:
+ case KUidContactFieldLocalityValue:
+ case KUidContactFieldRegionValue:
+ case KUidContactFieldCountryValue:
+ case KUidContactFieldCompanyNameValue:
+ case KUidContactFieldNoteValue:
+ case KUidContactFieldBirthdayValue:
+ case KUidContactFieldJobTitleValue:
+ case KUidContactFieldDTMFValue:
+ case KUidContactFieldIMAddressValue:
+ case KUidContactFieldDepartmentNameValue:
+ case KUidContactFieldAssistantValue:
+ case KUidContactFieldChildrenValue:
+ case KUidContactFieldSpouseValue:
+ case KUidContactFieldAnniversaryValue:
+ case KUidContactFieldClassValue:
+ {
+ return ETrue;
+ }
+ default:
+ {
+ return EFalse;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertFieldL
+// Converts a field from a PIM Item to a Contact Card.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertFieldL(const MPIMContactItem& aItem, // item to read the field from
+ CContactCard& aCard, // card to write the field to
+ TPIMContactField aField) // field to convert
+{
+ JELOG2(EPim);
+ const MPIMItemData& itemData = aItem.ItemData();
+
+ // These are indexes in PIM Item address values
+ TInt plainAddressIndex = KErrNotFound;
+ TInt homeAddressIndex = KErrNotFound;
+ TInt workAddressIndex = KErrNotFound;
+ if (aField == EPIMContactAddr)
+ {
+ AddressAttributesL(itemData, plainAddressIndex, homeAddressIndex,
+ workAddressIndex);
+ ConvertAddressFieldL(itemData, aCard, aField, plainAddressIndex,
+ KPIMAttrNone);
+ ConvertAddressFieldL(itemData, aCard, aField, homeAddressIndex,
+ EPIMContactAttrHome);
+ ConvertAddressFieldL(itemData, aCard, aField, workAddressIndex,
+ EPIMContactAttrWork);
+ return;
+ }
+
+ TInt valueCount = itemData.CountValues(aField);
+ for (TInt i = 0; i < valueCount; i++)
+ {
+ switch (aField)
+ {
+ case EPIMContactUid:
+ case EPIMContactRevision:
+ {
+ // uid and revision fields are totally ignored
+ break;
+ }
+ case EPIMContactBirthday:
+ case EPIMContactExtAnniversary:
+ {
+ ConvertDateFieldL(itemData, aCard, aField, i);
+ break;
+ }
+ case EPIMContactEmail:
+ case EPIMContactNickname:
+ case EPIMContactNote:
+ case EPIMContactOrg:
+ case EPIMContactTel:
+ case EPIMContactTitle:
+ case EPIMContactUrl:
+ case EPIMContactExtSip:
+ case EPIMContactExtDtmf:
+ case EPIMContactExtWvUserId:
+ case EPIMContactExtDepartment:
+ case EPIMContactExtAssistantName:
+ case EPIMContactExtChildren:
+ case EPIMContactExtSpouse:
+ case EPIMContactExtVoip:
+ case EPIMContactExtPTT:
+ case EPIMContactExtSWIS:
+ {
+ ConvertStringFieldL(itemData, aCard, aField, i);
+ break;
+ }
+ case EPIMContactName:
+ {
+ ConvertNameFieldL(itemData, aCard, aField, i);
+ break;
+ }
+ case EPIMContactPhoto:
+ {
+ ConvertPhotoFieldL(itemData, aCard, aField, i);
+ break;
+ }
+ case EPIMContactClass:
+ {
+ ConvertClassFieldL(itemData, aCard, aField, i);
+ break;
+ }
+ case EPIMContactFormattedName:
+ case EPIMContactFormattedAddr:
+ case EPIMContactPhotoUrl:
+ case EPIMContactPublicKey:
+ case EPIMContactPublicKeyString:
+ default:
+ {
+ __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
+ EPIMPanicUnsupportedField));
+ return;
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertFieldL
+// Converts a field from a Contact Card to a PIM Item.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertFieldL(const CContactItemField& aField, // field to read data from
+ MPIMContactItem& aItem) // field to write the data to
+{
+ JELOG2(EPim);
+ TStorageType type = aField.StorageType();
+ switch (type)
+ {
+ case KStorageTypeText:
+ {
+ ConvertTextFieldL(aField, aItem);
+ break;
+ }
+ case KStorageTypeStore:
+ {
+ ConvertStoreFieldL(aField, aItem);
+ break;
+ }
+ case KStorageTypeContactItemId:
+ {
+ break;
+ }
+ case KStorageTypeDateTime:
+ {
+ ConvertDateFieldL(aField, aItem);
+ break;
+ }
+ default:
+ {
+ __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
+ EPIMPanicUnsupportedField));
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertTextFieldL
+// Converts a text field from a Contact Card to a PIM Item.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertTextFieldL(const CContactItemField& aField, // field to read data from
+ MPIMContactItem& aItem) // field to write the data to
+{
+ JELOG2(EPim);
+ MPIMItemData& itemData = aItem.ItemData();
+ CContactTextField* textField = aField.TextStorage();
+ const CContentType& type = aField.ContentType();
+
+ // Check that can we handle this field
+ if (!(textField->IsFull()) || (type.FieldTypeCount() == 0))
+ {
+ return;
+ }
+
+ TPtrC text = textField->Text();
+ TFieldType fieldTypeUid = type.FieldType(0);
+ TPIMAttribute attributes = KPIMAttrNone;
+
+ TPIMField field = iFieldInfo->MatchContactField(fieldTypeUid.iUid);
+ // Check which field we must handle
+ switch (field)
+ {
+ case EPIMContactName:
+ {
+ TPIMContactNameElement
+ nameElement =
+ static_cast<TPIMContactNameElement>(iFieldInfo->MatchContactArrayElement(
+ fieldTypeUid.iUid));
+ AddNameFieldToItemL(text, aItem, nameElement, aField.Label());
+ break;
+ }
+ case EPIMContactAddr:
+ {
+ TPIMContactAddrElement
+ addrElement =
+ static_cast<TPIMContactAddrElement>(iFieldInfo->MatchContactArrayElement(
+ fieldTypeUid.iUid));
+ attributes = iFieldInfo->FieldAttributes(aField.ContentType());
+
+ // Label addresses are also stored in the database using
+ // KUidContactFieldAddressValue, but we don't support them
+ if (fieldTypeUid.iUid == KUidContactFieldAddressValue)
+ {
+ if (type.ContainsFieldType(KUidContactFieldVCardMapADR))
+ {
+ AddAddressFieldToItemL(text, aItem, EPIMContactAddrStreet,
+ attributes, aField.Label());
+ }
+ }
+ else
+ {
+ AddAddressFieldToItemL(text, aItem, addrElement, attributes,
+ aField.Label());
+ }
+ break;
+ }
+ case EPIMContactClass:
+ {
+ AddClassFieldToItemL(itemData, text, aField.Label());
+ break;
+ }
+ case EPIMContactExtSip:
+ case EPIMContactExtVoip:
+ case EPIMContactExtPTT:
+ case EPIMContactExtSWIS:
+ {
+ // SIPID value can hold PoC (Push-To-Talk) Share view, SIP
+ // and VOIP (Voice Over IP) fields inside it.
+ // Apply internal attributes
+ CArrayFix<TUid>* attrs = new(ELeave) CArrayFixFlat<TUid> (3);
+ CleanupStack::PushL(attrs);
+ iFieldInfo->GetFieldInternalAttributesL(type, *attrs);
+ // VOIP (Internet telephone) field
+ if (type.ContainsFieldType(KUidContactFieldVCardMapVOIP))
+ {
+ attributes = iFieldInfo->FieldAttributes(type);
+ field = EPIMContactExtVoip;
+ }
+ else if (type.ContainsFieldType(KUidContactFieldVCardMapPOC))
+ {
+ field = EPIMContactExtPTT;
+ }
+ else if (type.ContainsFieldType(KUidContactFieldVCardMapSWIS))
+ {
+ field = EPIMContactExtSWIS;
+ }
+ else
+ {
+ field = EPIMContactExtSip;
+ }
+ // Add field, attributes, internal attributes and label to the item
+ // Note that internal attributes are popped from the cleanup stack
+ // inside the following function and there is no need to pop after it
+ AddStringFieldWithLabelL(itemData, field, attributes, attrs, text,
+ aField.Label());
+ break;
+ }
+ case EPIMContactEmail:
+ case EPIMContactNickname:
+ case EPIMContactNote:
+ case EPIMContactOrg:
+ case EPIMContactTel:
+ case EPIMContactTitle:
+ case EPIMContactUrl:
+ case EPIMContactExtDtmf:
+ case EPIMContactExtWvUserId:
+ case EPIMContactExtDepartment:
+ case EPIMContactExtAssistantName:
+ case EPIMContactExtChildren:
+ case EPIMContactExtSpouse:
+ {
+ // Get internal attributes from the content type
+ CArrayFix<TUid>* attrs = new(ELeave) CArrayFixFlat<TUid> (3);
+ CleanupStack::PushL(attrs);
+ iFieldInfo->GetFieldInternalAttributesL(type, *attrs);
+ // Add attributes. FAX is special so it must be handled separately
+ attributes = iFieldInfo->FieldAttributes(aField.ContentType());
+ if (fieldTypeUid.iUid == KUidContactFieldFaxValue)
+ {
+ attributes |= EPIMContactAttrFax;
+ }
+ // Add field, attributes, internal attributes and label to the item
+ // Note that internal attributes are popped from the cleanup stack
+ // inside the following function and there is no need to pop after it
+ AddStringFieldWithLabelL(itemData, field, attributes, attrs, text,
+ aField.Label());
+ break;
+ }
+ default:
+ {
+ // The field is not supported so we don't know what to do with it
+ // and it is ignored. NOTE that contacts are opened first before
+ // writing those to the contact database to ensure that unsupported
+ // fields will still be included the to item and no data will be lost
+ break;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::AddStringFieldWithLabelL
+// Adds a string field to the item, and optionally sets the fields label.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::AddStringFieldWithLabelL(MPIMItemData& aItem,
+ TPIMField aField, TPIMAttribute aAttributes,
+ CArrayFix<TUid>* aInternalAttributes, const TPtrC aValue,
+ const TPtrC aLabel)
+{
+ JELOG2(EPim);
+ TInt valueCount = aItem.CountValues(aField);
+ TPIMFieldData fieldData(aField, aAttributes, aValue.AllocLC());
+
+ // Add data to the item
+ aItem.AddValueL(fieldData);
+ CleanupStack::Pop(); // aValue.AlloclC()
+ // Apply internal attributes
+ aItem.SetInternalAttributesL(aField, valueCount, aInternalAttributes);
+ // aItem now owns aInternalAttributes
+ CleanupStack::Pop(aInternalAttributes);
+
+ // Set preferred index if it is set to this field value index
+ // Only one value index of this field can have preferred index set
+ // so we have to remove all existing preferred indexes. This has to
+ // be done to SMS attribute also. There cannot be more than one
+ // preferred SMS number in the S60 Phonebook
+ if (aAttributes & EPIMContactAttrPreferred || aAttributes
+ & EPIMContactAttrSms)
+ {
+ // Clear "preferred index" attribute from all other values
+ // except this one (previously added one)
+ for (TInt i = 0; i < valueCount; i++)
+ {
+ TPIMAttribute attributes = aItem.AttributesL(aField, i);
+ // Clear attributes from preferred index
+ if (aAttributes & EPIMContactAttrPreferred)
+ {
+ attributes &= ~EPIMContactAttrPreferred;
+ }
+ if (aAttributes & EPIMContactAttrSms)
+ {
+ attributes &= ~EPIMContactAttrSms;
+ }
+ aItem.SetAttributesL(aField, i, attributes);
+ }
+ }
+
+ // Add label if necessary
+ if (aLabel.Length() > 0)
+ {
+ aItem.SetLabelL(aField, valueCount, 0, aLabel);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertDateFieldL
+// Converts a date field from a Contact Card to a PIM Item.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertDateFieldL(const CContactItemField& aField, // field to read data from
+ MPIMContactItem& aItem) // field to write the data to
+{
+ JELOG2(EPim);
+ MPIMItemData& itemData = aItem.ItemData();
+ CContactDateField* dateField = aField.DateTimeStorage();
+ if (!(dateField->IsFull()))
+ {
+ // if date is not set, we don't read it
+ return;
+ }
+ TTime time = dateField->Time();
+ const CContentType& type = aField.ContentType();
+
+ TPIMField field(0);
+ // Check the field type
+ if (type.ContainsFieldType(KUidContactFieldBirthday))
+ {
+ field = EPIMContactBirthday;
+ }
+ else if (type.ContainsFieldType(KUidContactFieldAnniversary))
+ {
+ field = EPIMContactExtAnniversary;
+ }
+
+ // Anniversary and Birthday are only dates so we are not interested
+ // in which is the time in these fields. This is because Phonebook
+ // doesn't take into account what time is used within these fields
+ // Time conversion between UTC and local time is not needed here
+ // because Phonebook handles only dates and PIM API times are in UTC
+ // format causing this date to be set to the start of the UTC date time
+ // and the date is shown correctly when midlet accesses it on the Java-side
+ TDateTime temp(time.DateTime());
+ temp.SetHour(0);
+ temp.SetSecond(0);
+ temp.SetMinute(0);
+ temp.SetMicroSecond(0);
+
+ // Count values and add new data
+ TInt valueCount = itemData.CountValues(field);
+ TPIMFieldData fieldData(field, KPIMAttrNone, TPIMDate(temp));
+ itemData.AddValueL(fieldData);
+
+ // Set label
+ if (aField.Label().Length() > 0)
+ {
+ itemData.SetLabelL(field, valueCount, 0, aField.Label());
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertStoreFieldL
+// Converts a store field from a Contact Card to a PIM Item.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertStoreFieldL(
+ const CContactItemField& aField, // field to read data from
+ MPIMContactItem& aItem) // field to write the data to
+{
+ JELOG2(EPim);
+ CContactStoreField* storeField = aField.StoreStorage();
+ if (!(storeField->IsFull()))
+ {
+ return;
+ }
+ const CContentType& type = aField.ContentType();
+ if (type.ContainsFieldType(KUidContactFieldPicture))
+ {
+ // We don't care about other store fields
+ MPIMItemData& itemData = aItem.ItemData();
+ HBufC8* data = storeField->Thing();
+ if (data)
+ {
+ TInt dataLength = data->Length();
+ CPIMByteArray* byteArray = new(ELeave) CPIMByteArray(dataLength);
+ CleanupStack::PushL(byteArray);
+ byteArray->AppendL(data->Ptr(), dataLength);
+ TPIMFieldData fieldData(EPIMContactPhoto, KPIMAttrNone, byteArray);
+ itemData.AddValueL(fieldData);
+ CleanupStack::Pop(); // byteArray
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::AddNameFieldToItemL
+// Adds a name field to a PIM Item
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::AddNameFieldToItemL(TPtrC aText, // text to add
+ MPIMContactItem& aItem, // item to add to
+ TPIMContactNameElement aElement, // element to add
+ TPtrC aLabel) // label of the field
+{
+ JELOG2(EPim);
+ MPIMItemData& itemData = aItem.ItemData();
+ // 7 for array granularity
+ CDesCArrayFlat* nameArray = new(ELeave) CDesC16ArrayFlat(7);
+ CleanupStack::PushL(nameArray);
+ // do we already have a name field in the item
+ TInt nameCount = itemData.CountValues(EPIMContactName);
+ if (nameCount > 0)
+ {
+ const TPIMFieldData fieldData = itemData.ValueL(EPIMContactName, 0);
+ const CDesCArray& oldNameArray = fieldData.StringArrayValue();
+ TInt elementCount = oldNameArray.Count();
+
+ for (TInt i = 0; i < elementCount; i++)
+ {
+ TPtrC16 oldName = oldNameArray[i];
+ nameArray->AppendL(oldName);
+ }
+ // don't trust that item data has correct amount of elements
+ for (TInt i = elementCount; i < EPIMContactNameNumElements; i++)
+ {
+ nameArray->AppendL(KPIMNullArrayElement());
+ }
+ // Add new element
+ nameArray->Delete(aElement);
+ nameArray->InsertL(aElement, aText);
+ TPIMFieldData newFieldData(EPIMContactName, KPIMAttrNone, nameArray);
+ itemData.SetValueL(newFieldData);
+ }
+ else
+ {
+ for (TInt i = 0; i < EPIMContactNameNumElements; i++)
+ {
+ nameArray->AppendL(KPIMNullArrayElement());
+ }
+ // Add new element
+ nameArray->Delete(aElement);
+ nameArray->InsertL(aElement, aText);
+ TPIMFieldData newFieldData(EPIMContactName, KPIMAttrNone, nameArray);
+ itemData.AddValueL(newFieldData);
+ }
+ // Name array is now owned by the item
+ CleanupStack::Pop(nameArray);
+ // Add label if it exists
+ if (aLabel.Length() > 0)
+ {
+ itemData.SetLabelL(EPIMContactName, 0, aElement, aLabel);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::AddAddressFieldToItemL
+// Adds an address field to a PIM Item
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::AddAddressFieldToItemL(TPtrC aText, // text to add
+ MPIMContactItem& aItem, // item to add to
+ TPIMContactAddrElement aElement, // element to add
+ TPIMAttribute aAttributes, // attributes of the address
+ TPtrC aLabel) // label
+{
+ JELOG2(EPim);
+ MPIMItemData& itemData = aItem.ItemData();
+ // 7 for array granularity
+ CDesCArrayFlat* addrArray = new(ELeave) CDesC16ArrayFlat(7);
+ CleanupStack::PushL(addrArray);
+ // do we already have an address field in the item with the same attributes
+ TInt addrCount = itemData.CountValues(EPIMContactAddr);
+ TBool notFound = ETrue;
+ TInt index = -1;
+ for (TInt i = 0; (notFound) && (i < addrCount); i++)
+ {
+ if (itemData.AttributesL(EPIMContactAddr, i) == aAttributes)
+ {
+ const TPIMFieldData fieldData = itemData.ValueL(EPIMContactAddr, i);
+ const CDesCArray& oldAddrArray = fieldData.StringArrayValue();
+ TInt elementCount = oldAddrArray.Count();
+ for (TInt j = 0; j < elementCount; j++)
+ {
+ TPtrC oldAddr = oldAddrArray[j];
+ addrArray->AppendL(oldAddr);
+ }
+ for (TInt j = elementCount; j < EPIMContactAddrNumElements; j++)
+ {
+ addrArray->AppendL(KPIMNullArrayElement());
+ }
+ notFound = EFalse;
+ addrArray->Delete(aElement);
+ addrArray->InsertL(aElement, aText);
+ TPIMFieldData newFieldData(EPIMContactAddr, aAttributes, addrArray);
+ newFieldData.SetIndex(i);
+ itemData.SetValueL(newFieldData);
+ index = i;
+ }
+ }
+ if (notFound)
+ {
+ for (TInt i = 0; i < EPIMContactAddrNumElements; i++)
+ {
+ addrArray->AppendL(KPIMNullArrayElement);
+ }
+ addrArray->Delete(aElement);
+ addrArray->InsertL(aElement, aText);
+ TPIMFieldData fieldData(EPIMContactAddr, aAttributes, addrArray);
+ itemData.AddValueL(fieldData);
+ }
+ // Array is now owned by the item
+ CleanupStack::Pop(addrArray);
+
+ // Add label if it exists
+ if (aLabel.Length() > 0)
+ {
+ // If the index is -1, it indicates that we are
+ // adding new string array at the end of the others
+ // so the index should be same as addrCount
+ index = (index == -1) ? addrCount : index;
+ itemData.SetLabelL(EPIMContactAddr, index, aElement, aLabel);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertAddressFieldL
+// Converts an address field from a PIM Item to a Contact Card.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertAddressFieldL(const MPIMItemData& aItem, // item to convert from
+ CContactCard& aCard, // card to write to
+ TPIMContactField aField, // field to convert
+ TInt aIndex, // index to the field
+ TPIMAttribute aAttributes) // attributes of the field
+{
+ JELOG2(EPim);
+ if (aIndex == KErrNotFound)
+ {
+ return;
+ }
+ const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
+ const CDesCArray& addrArray = fieldData.StringArrayValue();
+ EContactFieldCategory category = EContactCategoryNone;
+ if (aAttributes == EPIMContactAttrHome)
+ {
+ category = EContactCategoryHome;
+ }
+ if (aAttributes == EPIMContactAttrWork)
+ {
+ category = EContactCategoryWork;
+ }
+
+ TInt addrCount = addrArray.Count();
+ for (TInt i = 0; i < addrCount; i++)
+ {
+ if (addrArray[i].Compare(KPIMNullArrayElement()) == 0)
+ {
+ // we don't add null elements
+ continue;
+ }
+
+ EnsureValidAddrElemLengthL(TPIMContactAddrElement(i), addrArray[i]);
+
+ CContentType* type = iFieldInfo->AddressContentTypeL(
+ static_cast<TPIMContactAddrElement>(i), category);
+ CleanupStack::PushL(type);
+
+ CContactItemField* field = CContactItemField::NewLC(KStorageTypeText,
+ *type);
+
+ // Add label to the field
+ TPIMContactAddrElement element = TPIMContactAddrElement(i);
+ const TPtrC label = aItem.LabelL(aField, aIndex, element);
+ if (label.Compare(KPIMNullArrayElement) != 0)
+ {
+ field->SetLabelL(label);
+ }
+ field->SetUserFlags(category);
+ // we don't store any label, Contacts Model should use default template
+ CContactTextField* textField = field->TextStorage();
+ textField->SetTextL(addrArray[i]);
+ // Card takes the ownership of the field
+ aCard.AddFieldL(*field);
+ CleanupStack::Pop(field);
+ CleanupStack::PopAndDestroy(type);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertNameFieldL
+// Converts an address field from a PIM Item to a Contact Card.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertNameFieldL(const MPIMItemData& aItem, // item to convert from
+ CContactCard& aCard, // card to write to
+ TPIMContactField aField, // field to convert
+ TInt aIndex) // index to the field
+{
+ JELOG2(EPim);
+ const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
+ const CDesCArray& nameArray = fieldData.StringArrayValue();
+ EContactFieldCategory category = EContactCategoryHome;
+
+ TInt nameCount = nameArray.Count();
+ for (TInt i = 0; i < nameCount; i++)
+ {
+ if (nameArray[i].Compare(KPIMNullArrayElement()) == 0)
+ {
+ // we don't add null elements
+ continue;
+ }
+
+ EnsureValidNameElemLengthL(TPIMContactNameElement(i), nameArray[i]);
+
+ CContentType* type = iFieldInfo->NameContentTypeL(
+ static_cast<TPIMContactNameElement>(i));
+ CleanupStack::PushL(type);
+
+ CContactItemField* field = CContactItemField::NewLC(KStorageTypeText,
+ *type);
+
+ // Add label to the field. aIndex should be 0 in this case because
+ // there are only one string array in the name field
+ TPIMContactNameElement element = TPIMContactNameElement(i);
+ const TPtrC label = aItem.LabelL(aField, aIndex, element);
+ if (label.Compare(KPIMNullArrayElement) != 0)
+ {
+ field->SetLabelL(label);
+ }
+ field->SetUserFlags(category);
+ // we don't store any label, Contacts Model should use default template
+ CContactTextField* textField = field->TextStorage();
+ textField->SetTextL(nameArray[i]);
+ // Card takes ownership of the field
+ aCard.AddFieldL(*field);
+ CleanupStack::Pop(field);
+ CleanupStack::PopAndDestroy(type);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertDateFieldL
+// Converts a date field from a PIM Item to a Contact Card.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertDateFieldL(const MPIMItemData& aItem, // item to convert from
+ CContactCard& aCard, // card to write to
+ TPIMContactField aField, // field to convert
+ TInt aIndex) // index to the field
+{
+ JELOG2(EPim);
+ const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
+ const TPIMDate& date = fieldData.DateValue();
+ CContentType* type = NULL;
+
+ switch (aField)
+ {
+ case EPIMContactBirthday:
+ {
+ type = CContentType::NewL(KUidContactFieldBirthday,
+ KUidContactFieldVCardMapBDAY);
+ CleanupStack::PushL(type);
+ break;
+ }
+ case EPIMContactExtAnniversary:
+ {
+ type = CContentType::NewL(KUidContactFieldAnniversary,
+ KUidContactFieldVCardMapAnniversary);
+ CleanupStack::PushL(type);
+ break;
+ }
+ default:
+ {
+ User::Panic(KPIMPanicCategory, EPIMPanicUnsupportedDateField);
+ break;
+ }
+ }
+ CContactItemField* field = CContactItemField::NewLC(KStorageTypeDateTime,
+ *type);
+ // set label if set in pim item
+ const TPtrC label = aItem.LabelL(aField, aIndex, 0);
+ if (label.Compare(KPIMNullArrayElement) != 0)
+ {
+ field->SetLabelL(label);
+ }
+
+ field->SetUserFlags(EContactCategoryOther);
+ CContactDateField* dateField = field->DateTimeStorage();
+
+ // PIM API stores dates as UTC time. Phonebook instead expects that dates
+ // are stored as in local time format in the Contacts Model database
+ RTz tzServer;
+ User::LeaveIfError(tzServer.Connect());
+ CleanupClosePushL(tzServer);
+
+ // Create timezone converter
+ CTzConverter* converter = CTzConverter::NewL(tzServer);
+ CleanupStack::PushL(converter);
+
+ TTime localTime(date);
+ User::LeaveIfError(converter->ConvertToLocalTime(localTime));
+ CleanupStack::PopAndDestroy(2); // converter, tzServer
+
+ // Anniversary and Birthday are only dates so we are not interested
+ // in which is the time in these fields. This is because Phonebook
+ // doesn't take into account what time is used within these fields
+ TDateTime temp(localTime.DateTime());
+ temp.SetHour(0);
+ temp.SetMinute(0);
+ temp.SetSecond(0);
+ temp.SetMicroSecond(0);
+
+ dateField->SetTime(TTime(temp));
+ // Card takes ownership of the field
+ aCard.AddFieldL(*field);
+ CleanupStack::Pop(field);
+ CleanupStack::PopAndDestroy(type);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertStringFieldL
+// Converts a string field from a PIM Item to a Contact Card.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertStringFieldL(const MPIMItemData& aItem, // item to convert from
+ CContactCard& aCard, // card to write to
+ TPIMContactField aField, // field to convert
+ TInt aIndex) // index to the field
+{
+ JELOG2(EPim);
+ const CArrayFix<TUid>& attrs = aItem.InternalAttributesL(aField, aIndex);
+ const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
+ const TDesC& string = fieldData.StringValue();
+ TPIMAttribute attributes = fieldData.Attributes();
+ EContactFieldCategory category = EContactCategoryNone;
+
+ EnsureValidStringValueLengthL(aField, string);
+
+ if ((attributes & EPIMContactAttrHome) != 0)
+ {
+ category = EContactCategoryHome;
+ }
+ if ((attributes & EPIMContactAttrWork) != 0)
+ {
+ category = EContactCategoryWork;
+ }
+ CContentType* type = iFieldInfo->StringFieldContentTypeL(aField,
+ attributes, category);
+ CleanupStack::PushL(type);
+ // Apply internal attributes if any
+ TInt interalAttrCount = attrs.Count();
+ for (TInt i = 0; i < interalAttrCount; i++)
+ {
+ TFieldType fieldType = attrs.At(i);
+ // Check to avoid duplicate field types in the content type
+ // this may be possible when unrecognized fields are added to
+ // internal attribute list (e.g incorrectly generated ContentType)
+ if (!type->ContainsFieldType(fieldType))
+ {
+ type->AddFieldTypeL(fieldType);
+ }
+ }
+ // Create new contact item field which is a text storage
+ CContactItemField* field =
+ CContactItemField::NewLC(KStorageTypeText, *type);
+ // set label if set in pim item
+ const TPtrC label = aItem.LabelL(aField, aIndex, 0);
+ if (label.Compare(KPIMNullArrayElement) != 0)
+ {
+ field->SetLabelL(label);
+ }
+
+ field->SetUserFlags(category);
+ CContactTextField* textField = field->TextStorage();
+ textField->SetTextL(string);
+ // Card takes ownership of the field
+ aCard.AddFieldL(*field);
+ CleanupStack::Pop(field);
+ CleanupStack::PopAndDestroy(type);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertPhotoFieldL
+// Converts a photo field from a PIM Item to a Contact Card.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertPhotoFieldL(const MPIMItemData& aItem, // item to convert from
+ CContactCard& aCard, // card to write to
+ TPIMContactField aField, // field to convert
+ TInt aIndex) // index to the field
+{
+ JELOG2(EPim);
+ const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
+ const CPIMByteArray& byteArray = fieldData.BinaryValue();
+ EContactFieldCategory category = EContactCategoryNone;
+ CContentType* type = CContentType::NewL(KUidContactFieldPicture,
+ KUidContactFieldVCardMapPHOTO);
+ CleanupStack::PushL(type);
+
+ CContactItemField* field = CContactItemField::NewLC(KStorageTypeStore,
+ *type);
+ field->SetUserFlags(category);
+
+ const TUint8& byteRef = byteArray.At(0);
+ const TUint8* bytePtr = &byteRef;
+ TPtrC8 data(bytePtr, byteArray.Count());
+
+ HBufC8* thumbNail = iImageScaler->ScaleL(data);
+ CleanupStack::PushL(thumbNail);
+
+ CContactStoreField* storeField = field->StoreStorage();
+ storeField->SetThingL(*thumbNail);
+ CleanupStack::PopAndDestroy(); // thumbNail
+ // Card takes ownership of the field
+ aCard.AddFieldL(*field);
+ CleanupStack::Pop(field);
+ CleanupStack::PopAndDestroy(type);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertClassFieldL
+// Converts a CLASS field from a PIM Item to a Contact Card.
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::ConvertClassFieldL(const MPIMItemData& aItemData,
+ CContactCard& aCard, TPIMContactField aField, TInt aIndex)
+{
+ JELOG2(EPim);
+ TPtrC classValueDes(KPIMContactClassPrivate());
+ const TPIMFieldData fieldData = aItemData.ValueL(aField, aIndex);
+ const TInt classValue = fieldData.IntegerValue();
+ CContentType* type = CContentType::NewL(KUidContactFieldClass,
+ KUidContactFieldVCardMapClass);
+ CleanupStack::PushL(type);
+
+ switch (classValue)
+ {
+ case EPIMContactClassPrivate:
+ {
+ classValueDes.Set(KPIMContactClassPrivate());
+ break;
+ }
+ case EPIMContactClassPublic:
+ {
+ classValueDes.Set(KPIMContactClassPublic());
+ break;
+ }
+ case EPIMContactClassConfidential:
+ {
+ classValueDes.Set(KPIMContactClassConfidential());
+ break;
+ }
+ default:
+ {
+ __ASSERT_DEBUG(EFalse, User::Invariant());
+ break; // For a happy compiler
+ }
+ }
+ // Add value to the contact field
+ CContactItemField* field =
+ CContactItemField::NewLC(KStorageTypeText, *type);
+ field->SetUserFlags(EContactCategoryNone);
+
+ // Set label if any
+ const TPtrC label = aItemData.LabelL(aField, aIndex, 0);
+ if (label.Compare(KPIMNullArrayElement) != 0)
+ {
+ field->SetLabelL(label);
+ }
+
+ CContactTextField* textField = field->TextStorage();
+ textField->SetTextL(classValueDes);
+ // Card takes ownership of the field
+ aCard.AddFieldL(*field);
+ CleanupStack::Pop(field);
+ CleanupStack::PopAndDestroy(type);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::ConvertClassFieldL
+// Converts a CLASS field from a Contact Card to PIM item
+// -----------------------------------------------------------------------------
+//
+void CPIMContactItemAdapter::AddClassFieldToItemL(MPIMItemData& aItemData,
+ TPtrC& aClassDesValue, TPtrC aLabel)
+{
+ JELOG2(EPim);
+ // Syncronisation is private for default
+ TPIMContactClassValue classValue = EPIMContactClassPrivate;
+ TInt valueCount = aItemData.CountValues(EPIMContactClass);
+
+ if (aClassDesValue.Compare(KPIMContactClassPublic()) == 0)
+ {
+ classValue = EPIMContactClassPublic;
+ }
+ else if (aClassDesValue.Compare(KPIMContactClassPrivate()) == 0)
+ {
+ classValue = EPIMContactClassPrivate;
+ }
+ else if (aClassDesValue.Compare(KPIMContactClassConfidential()) == 0)
+ {
+ classValue = EPIMContactClassConfidential;
+ }
+ TPIMFieldData fieldData(EPIMContactClass, EPIMFieldInt, KPIMAttrNone,
+ classValue);
+ aItemData.AddValueL(fieldData);
+ // Label if any
+ if (aLabel.Length() > 0)
+ {
+ aItemData.SetLabelL(EPIMContactClass, valueCount, 0, aLabel);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::AddressAttributesL
+// Checks the optimal attributes for the addresses
+// -----------------------------------------------------------------------------
+void CPIMContactItemAdapter::AddressAttributesL(const MPIMItemData& aItem,
+ TInt& aPlainAddressIndex, TInt& aHomeAddressIndex, TInt& aWorkAddressIndex)
+{
+ JELOG2(EPim);
+ aPlainAddressIndex = KErrNotFound;
+ aHomeAddressIndex = KErrNotFound;
+ aWorkAddressIndex = KErrNotFound;
+ TInt addressCount = aItem.CountValues(EPIMContactAddr);
+
+ // first pass - find zero and single attribute values if exist
+ TInt i = 0;
+ for (; i < addressCount; i++)
+ {
+ if (aItem.AttributesL(EPIMContactAddr, i) == KPIMAttrNone)
+ {
+ aPlainAddressIndex = i;
+ }
+ else if (aItem.AttributesL(EPIMContactAddr, i) == EPIMContactAttrHome)
+ {
+ aHomeAddressIndex = i;
+ }
+ else if (aItem.AttributesL(EPIMContactAddr, i) == EPIMContactAttrWork)
+ {
+ aWorkAddressIndex = i;
+ }
+ }
+
+ // second pass - fill in the rest
+ for (i = 0; i < addressCount; i++)
+ {
+ if ((aPlainAddressIndex != i) && (aHomeAddressIndex != i)
+ && (aWorkAddressIndex != i))
+ {
+ // this index has not been used yet
+ if (KErrNotFound == aWorkAddressIndex)
+ {
+ aWorkAddressIndex = i;
+ }
+ else if (KErrNotFound == aHomeAddressIndex)
+ {
+ aHomeAddressIndex = i;
+ }
+ else if (KErrNotFound == aPlainAddressIndex)
+ {
+ aPlainAddressIndex = i;
+ }
+ else
+ {
+ // all indexes are filled
+ break; // out of the for loop
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::EnsureValidStringValueLengthL
+// -----------------------------------------------------------------------------
+void CPIMContactItemAdapter::EnsureValidStringValueLengthL(
+ TPIMContactField aField, const TDesC& aValue)
+{
+ JELOG2(EPim);
+ const TInt* maxLengthArr = NULL;
+ TInt offset = 0;
+ TInt arrLen = 0;
+
+ if (aField >= KContactExtStringMaxLengthOffset)
+ {
+ maxLengthArr = KContactExtStringMaxLengths;
+ offset = KContactExtStringMaxLengthOffset;
+ arrLen = KContactExtStringMaxLengthsLen;
+ }
+ else
+ {
+ maxLengthArr = KContactStringMaxLengths;
+ offset = KContactStringMaxLengthsOffset;
+ arrLen = KContactStringMaxLengthsLen;
+ }
+
+ TInt index = aField - offset;
+
+ __ASSERT_ALWAYS((index >= 0), User::Invariant());
+ __ASSERT_ALWAYS((index < arrLen), User::Invariant());
+
+ TInt maxLen = maxLengthArr[index];
+ if ((maxLen > 0) && (aValue.Length() > maxLen))
+ {
+ User::Leave(KErrTooBig);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::EnsureValidAddrElemLengthL
+// -----------------------------------------------------------------------------
+void CPIMContactItemAdapter::EnsureValidAddrElemLengthL(
+ TPIMContactAddrElement aElemIndex, const TDesC& aElemValue)
+{
+ JELOG2(EPim);
+ __ASSERT_DEBUG((aElemIndex >= 0), User::Invariant());
+
+ __ASSERT_DEBUG((aElemIndex < EPIMContactAddrNumElements), User::Invariant());
+
+ __ASSERT_DEBUG(
+ (KContactAddrElemMaxLengths[aElemIndex] != KErrNotSupported),
+ User::Invariant());
+
+ if ((KContactAddrElemMaxLengths[aElemIndex] != KErrNotSupported)
+ && (aElemValue.Length() > KContactAddrElemMaxLengths[aElemIndex]))
+ {
+ User::Leave(KErrTooBig);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMContactItemAdapter::EnsureValidNameElemLengthL
+// -----------------------------------------------------------------------------
+void CPIMContactItemAdapter::EnsureValidNameElemLengthL(
+ TPIMContactNameElement aElemIndex, const TDesC& aElemValue)
+{
+ JELOG2(EPim);
+ __ASSERT_DEBUG((aElemIndex >= 0), User::Invariant());
+
+ __ASSERT_DEBUG((aElemIndex < EPIMContactNameNumElements), User::Invariant());
+
+ __ASSERT_DEBUG(
+ (KContactNameElemMaxLengths[aElemIndex] != KErrNotSupported),
+ User::Invariant());
+
+ if ((KContactNameElemMaxLengths[aElemIndex] != KErrNotSupported)
+ && (aElemValue.Length() > KContactNameElemMaxLengths[aElemIndex]))
+ {
+ User::Leave(KErrTooBig);
+ }
+}
+
+// End of File