javaextensions/pim/cntadapter/src.s60/cpimcontactitemadapter.cpp
branchRCL_3
changeset 14 04becd199f91
child 25 ae942d28ec0e
equal deleted inserted replaced
13:f5050f1da672 14:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Handles conversion between PIM API Contact Items and Contacts
       
    15  *                Model Contact Cards
       
    16  *
       
    17 */
       
    18 
       
    19 
       
    20 // CLASS HEADER
       
    21 #include "cpimcontactitemadapter.h"
       
    22 
       
    23 // INTERNAL INCLUDES
       
    24 #include "cpimcontactcategorymanager.h"
       
    25 #include "pimpanics.h"
       
    26 #include "mpimcontactitem.h"
       
    27 #include "mpimitemdata.h"
       
    28 #include "cpimimagescaler.h"
       
    29 #include "cpimcontactfieldinfo.h"
       
    30 #include "logger.h"
       
    31 
       
    32 // EXTERNAL INCLUDES
       
    33 #include <cntitem.h> // CContactCard etc.
       
    34 #include <cntfldst.h> // CContactTextField etc.
       
    35 #include <tz.h>
       
    36 #include <tzconverter.h>
       
    37 
       
    38 
       
    39 
       
    40 // UNNAMED LOCAL NAMESPACE
       
    41 namespace
       
    42 {
       
    43 // Phonebook maps Syncronisation field values with specified
       
    44 // hard-coded string values. At the time implementing, the header
       
    45 // was not exported so it is necessary to define own constants
       
    46 // with same values
       
    47 _LIT(KPIMContactClassPrivate, "private");
       
    48 _LIT(KPIMContactClassPublic, "public");
       
    49 _LIT(KPIMContactClassConfidential, "none");
       
    50 }
       
    51 
       
    52 // ============================ MEMBER FUNCTIONS ===============================
       
    53 
       
    54 // -----------------------------------------------------------------------------
       
    55 // CPIMContactItemAdapter::NewL
       
    56 // Two-phased constructor.
       
    57 // -----------------------------------------------------------------------------
       
    58 //
       
    59 CPIMContactItemAdapter* CPIMContactItemAdapter::NewL(
       
    60     CPIMContactCategoryManager& aCategoryManager)
       
    61 {
       
    62     JELOG2(EPim);
       
    63     CPIMContactItemAdapter* self =
       
    64         new(ELeave) CPIMContactItemAdapter(aCategoryManager);
       
    65 
       
    66     CleanupStack::PushL(self);
       
    67     self->ConstructL();
       
    68     CleanupStack::Pop(self);
       
    69 
       
    70     return self;
       
    71 }
       
    72 
       
    73 // destructor
       
    74 CPIMContactItemAdapter::~CPIMContactItemAdapter()
       
    75 {
       
    76     JELOG2(EPim);
       
    77     delete iImageScaler;
       
    78     delete iFieldInfo;
       
    79 }
       
    80 
       
    81 // -----------------------------------------------------------------------------
       
    82 // CPIMContactItemAdapter::CardL
       
    83 // Converts from a PIM item data to a Contacts Model contact card.
       
    84 // Returns: A contact card with the same information as given in
       
    85 //          the parameter item. The ownership of the card is
       
    86 //          transferred to the caller.
       
    87 // -----------------------------------------------------------------------------
       
    88 //
       
    89 CContactCard* CPIMContactItemAdapter::CardL(const MPIMContactItem& aItem)
       
    90 {
       
    91     JELOG2(EPim);
       
    92     CContactCard* card = CContactCard::NewLC();
       
    93     const MPIMItemData& item = aItem.ItemData();
       
    94     __ASSERT_DEBUG((aItem.ContactItemIdL() == 0), User::Panic(
       
    95                        KPIMPanicCategory, EPIMPanicInvalidItemID));
       
    96     CArrayFix<TPIMField>* fields = item.FieldsLC();
       
    97 
       
    98     TInt fieldCount = fields->Count();
       
    99     for (TInt i = 0; i < fieldCount; i++)
       
   100     {
       
   101         ConvertFieldL(aItem, *card,
       
   102                       static_cast<TPIMContactField>(fields->At(i)));
       
   103     }
       
   104 
       
   105     // Set default values if not present in PIM item
       
   106     if (item.CountValues(EPIMContactClass) == 0)
       
   107     {
       
   108         CContentType* type = CContentType::NewL(KUidContactFieldClass,
       
   109                                                 KUidContactFieldVCardMapClass);
       
   110         CleanupStack::PushL(type);
       
   111 
       
   112         // Add value to the contact field
       
   113         CContactItemField* field = CContactItemField::NewLC(KStorageTypeText,
       
   114                                    *type);
       
   115         field->SetUserFlags(EContactCategoryNone);
       
   116         CContactTextField* textField = field->TextStorage();
       
   117         textField->SetTextL(KPIMContactClassPrivate());
       
   118         card->AddFieldL(*field);
       
   119 
       
   120         CleanupStack::Pop(field);
       
   121         CleanupStack::PopAndDestroy(type);
       
   122     }
       
   123 
       
   124     CleanupStack::PopAndDestroy(fields);
       
   125     CleanupStack::Pop(card);
       
   126     return card;
       
   127 }
       
   128 
       
   129 // -----------------------------------------------------------------------------
       
   130 // CPIMContactItemAdapter::FillItemL
       
   131 // Converts from a Contacts Model contact card to the PIM representation.
       
   132 // -----------------------------------------------------------------------------
       
   133 //
       
   134 void CPIMContactItemAdapter::FillItemL(MPIMContactItem& aItem, // Item data container to fill with the data
       
   135                                        const CContactCard& aCard) // Contact Card to convert
       
   136 {
       
   137     JELOG2(EPim);
       
   138     // convert fields
       
   139     CContactItemFieldSet& fieldSet = aCard.CardFields();
       
   140     TInt fieldCount = fieldSet.Count();
       
   141     for (TInt i = 0; i < fieldCount; i++)
       
   142     {
       
   143         ConvertFieldL(fieldSet[i], aItem);
       
   144     }
       
   145     // convert categories
       
   146     MPIMItemData& item = aItem.ItemData();
       
   147     CContactIdArray* groupArray = aCard.GroupsJoinedLC();
       
   148     TInt groupCount = groupArray->Count();
       
   149     for (TInt i = 0; i < groupCount; i++)
       
   150     {
       
   151         HBufC* label = iCategoryManager.GroupLabelL((*groupArray)[i]);
       
   152         CleanupStack::PushL(label);
       
   153         // Add item to this category if it doesn't belong to it already
       
   154         if (item.FindCategory(*label) == KErrNotFound)
       
   155         {
       
   156             item.AddNewCategoryL(*label);
       
   157         }
       
   158         CleanupStack::PopAndDestroy(label);
       
   159     }
       
   160     CleanupStack::PopAndDestroy(groupArray);
       
   161 }
       
   162 
       
   163 // -----------------------------------------------------------------------------
       
   164 // CPIMContactItemAdapter::UpdateCardL
       
   165 // Updates the data in the Contacts Model contact card to match
       
   166 // the data in the PIM item data container.
       
   167 // -----------------------------------------------------------------------------
       
   168 //
       
   169 void CPIMContactItemAdapter::UpdateCardL(const MPIMContactItem& aItem, // Item from which the data is read
       
   170         CContactCard& aCard) // The card which is updated
       
   171 {
       
   172     JELOG2(EPim);
       
   173     CleanCard(aCard);
       
   174     const MPIMItemData& itemData = aItem.ItemData();
       
   175     // Get fields
       
   176     CArrayFix<TPIMField>* fields = itemData.FieldsLC();
       
   177     TInt fieldCount = fields->Count();
       
   178     for (TInt i = 0; i < fieldCount; i++)
       
   179     {
       
   180         ConvertFieldL(aItem, aCard, (TPIMContactField)(fields->At(i)));
       
   181     }
       
   182     CleanupStack::PopAndDestroy(); // fields
       
   183 }
       
   184 
       
   185 // -----------------------------------------------------------------------------
       
   186 // CPIMContactItemAdapter::UpdateCategoriesL
       
   187 // Updates the category information in the database.
       
   188 // -----------------------------------------------------------------------------
       
   189 //
       
   190 void CPIMContactItemAdapter::UpdateCategoriesL(const MPIMContactItem& aItem, // Item containing the new categories
       
   191         const CContactCard& aCard) // Item to update
       
   192 {
       
   193     JELOG2(EPim);
       
   194     const CDesCArray& pimCategories = aItem.ItemData().Categories();
       
   195     const TInt pimCategoryCount = pimCategories.Count();
       
   196     TBool* newCategoryTable = new(ELeave) TBool[pimCategoryCount];
       
   197     CleanupArrayDeletePushL(newCategoryTable);
       
   198     TInt i = 0;
       
   199     for (i = 0; i < pimCategoryCount; i++)
       
   200     {
       
   201         newCategoryTable[i] = ETrue;
       
   202     }
       
   203 
       
   204     CContactIdArray* cardCategories = aCard.GroupsJoinedLC();
       
   205     TContactItemId id = aItem.ContactItemIdL();
       
   206 
       
   207     // first remove extra groups
       
   208     const TInt cardCategoryCount = cardCategories->Count();
       
   209     for (i = 0; i < cardCategoryCount; i++)
       
   210     {
       
   211         TContactItemId groupId = (*cardCategories)[i];
       
   212         HBufC* groupLabel = iCategoryManager.GroupLabelL(groupId);
       
   213         TInt pos;
       
   214         TInt found = pimCategories.Find(*groupLabel, pos, ECmpNormal);
       
   215         delete groupLabel;
       
   216         if (found != 0)
       
   217         {
       
   218             // removed group
       
   219             iCategoryManager.RemoveFromGroupL(id, groupId);
       
   220         }
       
   221         else
       
   222         {
       
   223             // old group
       
   224             newCategoryTable[pos] = EFalse;
       
   225         }
       
   226     }
       
   227     // then add new categories
       
   228     for (i = 0; i < pimCategoryCount; i++)
       
   229     {
       
   230         if (newCategoryTable[i])
       
   231         {
       
   232             TPtrC category = pimCategories[i];
       
   233             iCategoryManager.AddToGroupL(id, category);
       
   234         }
       
   235     }
       
   236     CleanupStack::PopAndDestroy(2); // cardCategories, newCategoryTable
       
   237 }
       
   238 
       
   239 // -----------------------------------------------------------------------------
       
   240 // CPIMContactItemAdapter::ContactsModelFieldType
       
   241 // Other items were commented in the header
       
   242 // -----------------------------------------------------------------------------
       
   243 //
       
   244 CArrayFix<TInt>* CPIMContactItemAdapter::ContactsModelFieldTypeL(
       
   245     TPIMContactField aContactField) const
       
   246 {
       
   247     JELOG2(EPim);
       
   248     return iFieldInfo->MatchPIMFieldL(aContactField);
       
   249 }
       
   250 
       
   251 // -----------------------------------------------------------------------------
       
   252 // CPIMContactItemAdapter::CPIMContactItemAdapter
       
   253 // C++ constructor can NOT contain any code, that
       
   254 // might leave.
       
   255 // -----------------------------------------------------------------------------
       
   256 //
       
   257 CPIMContactItemAdapter::CPIMContactItemAdapter(
       
   258     CPIMContactCategoryManager& aCategoryManager) :
       
   259         iCategoryManager(aCategoryManager)
       
   260 {
       
   261     JELOG2(EPim);
       
   262 }
       
   263 
       
   264 // -----------------------------------------------------------------------------
       
   265 // CPIMContactItemAdapter::ConstructL
       
   266 // Symbian 2nd phase constructor can leave.
       
   267 // -----------------------------------------------------------------------------
       
   268 //
       
   269 inline void CPIMContactItemAdapter::ConstructL()
       
   270 {
       
   271     JELOG2(EPim);
       
   272     iFieldInfo = CPIMContactFieldInfo::NewL();
       
   273     iImageScaler = CPIMImageScaler::NewL();
       
   274 }
       
   275 
       
   276 // -----------------------------------------------------------------------------
       
   277 // CPIMContactItemAdapter::CleanCardL
       
   278 // Deletes all the supported fields from the contact card.
       
   279 // Those fields which are not supported are left as is.
       
   280 // -----------------------------------------------------------------------------
       
   281 //
       
   282 void CPIMContactItemAdapter::CleanCard(CContactCard& aCard)
       
   283 {
       
   284     JELOG2(EPim);
       
   285     // convert fields
       
   286     CContactItemFieldSet& fieldSet = aCard.CardFields();
       
   287     TInt fieldCount = fieldSet.Count();
       
   288     for (TInt i = 0; i < fieldCount; i++)
       
   289     {
       
   290         if (IsSupportedField(fieldSet[i]))
       
   291         {
       
   292             // as the field is removed, the array shrinks
       
   293             aCard.RemoveField(i--);
       
   294             fieldCount--;
       
   295         }
       
   296     }
       
   297 }
       
   298 // -----------------------------------------------------------------------------
       
   299 // CPIMContactItemAdapter::IsSupportedFieldL
       
   300 // Checks if we support this particular contact field.
       
   301 // Returns:     ETrue if the field is supported
       
   302 //              EFalse otherwise
       
   303 // -----------------------------------------------------------------------------
       
   304 //
       
   305 TBool CPIMContactItemAdapter::IsSupportedField(CContactItemField& aField)
       
   306 {
       
   307     JELOG2(EPim);
       
   308     const CContentType& type = aField.ContentType();
       
   309     if (type.FieldTypeCount() == 0)
       
   310     {
       
   311         // we don't support unknown types
       
   312         return EFalse;
       
   313     }
       
   314 
       
   315     TFieldType fieldTypeUid = type.FieldType(0);
       
   316     TInt fieldType = fieldTypeUid.iUid;
       
   317     switch (fieldType)
       
   318     {
       
   319     case KUidContactFieldAddressValue:
       
   320     {
       
   321         // Label addresses are also stored in the database using
       
   322         // KUidContactFieldAddressValue, but we don't support them
       
   323         if (type.ContainsFieldType(KUidContactFieldVCardMapADR))
       
   324         {
       
   325             return ETrue;
       
   326         }
       
   327         else
       
   328         {
       
   329             return EFalse;
       
   330         }
       
   331     }
       
   332     case KUidContactFieldPictureValue:
       
   333     {
       
   334         // Thumbnails are supported while pictures are not
       
   335         if (type.ContainsFieldType(KUidContactFieldVCardMapPHOTO))
       
   336         {
       
   337             return ETrue;
       
   338         }
       
   339         else
       
   340         {
       
   341             return EFalse;
       
   342         }
       
   343     }
       
   344     case KUidContactFieldSIPIDValue:
       
   345     case KUidContactFieldFamilyNameValue:
       
   346     case KUidContactFieldGivenNameValue:
       
   347     case KUidContactFieldSecondNameValue:
       
   348     case KUidContactFieldFamilyNamePronunciationValue:
       
   349     case KUidContactFieldGivenNamePronunciationValue:
       
   350     case KUidContactFieldAdditionalNameValue:
       
   351     case KUidContactFieldPrefixNameValue:
       
   352     case KUidContactFieldSuffixNameValue:
       
   353     case KUidContactFieldPhoneNumberValue:
       
   354     case KUidContactFieldFaxValue:
       
   355     case KUidContactFieldEMailValue:
       
   356     case KUidContactFieldUrlValue:
       
   357     case KUidContactFieldPostOfficeValue:
       
   358     case KUidContactFieldExtendedAddressValue:
       
   359     case KUidContactFieldPostCodeValue:
       
   360     case KUidContactFieldLocalityValue:
       
   361     case KUidContactFieldRegionValue:
       
   362     case KUidContactFieldCountryValue:
       
   363     case KUidContactFieldCompanyNameValue:
       
   364     case KUidContactFieldNoteValue:
       
   365     case KUidContactFieldBirthdayValue:
       
   366     case KUidContactFieldJobTitleValue:
       
   367     case KUidContactFieldDTMFValue:
       
   368     case KUidContactFieldIMAddressValue:
       
   369     case KUidContactFieldDepartmentNameValue:
       
   370     case KUidContactFieldAssistantValue:
       
   371     case KUidContactFieldChildrenValue:
       
   372     case KUidContactFieldSpouseValue:
       
   373     case KUidContactFieldAnniversaryValue:
       
   374     case KUidContactFieldClassValue:
       
   375     {
       
   376         return ETrue;
       
   377     }
       
   378     default:
       
   379     {
       
   380         return EFalse;
       
   381     }
       
   382     }
       
   383 }
       
   384 
       
   385 // -----------------------------------------------------------------------------
       
   386 // CPIMContactItemAdapter::ConvertFieldL
       
   387 // Converts a field from a PIM Item to a Contact Card.
       
   388 // -----------------------------------------------------------------------------
       
   389 //
       
   390 void CPIMContactItemAdapter::ConvertFieldL(const MPIMContactItem& aItem, // item to read the field from
       
   391         CContactCard& aCard, // card to write the field to
       
   392         TPIMContactField aField) // field to convert
       
   393 {
       
   394     JELOG2(EPim);
       
   395     const MPIMItemData& itemData = aItem.ItemData();
       
   396 
       
   397     // These are indexes in PIM Item address values
       
   398     TInt plainAddressIndex = KErrNotFound;
       
   399     TInt homeAddressIndex = KErrNotFound;
       
   400     TInt workAddressIndex = KErrNotFound;
       
   401     if (aField == EPIMContactAddr)
       
   402     {
       
   403         AddressAttributesL(itemData, plainAddressIndex, homeAddressIndex,
       
   404                            workAddressIndex);
       
   405         ConvertAddressFieldL(itemData, aCard, aField, plainAddressIndex,
       
   406                              KPIMAttrNone);
       
   407         ConvertAddressFieldL(itemData, aCard, aField, homeAddressIndex,
       
   408                              EPIMContactAttrHome);
       
   409         ConvertAddressFieldL(itemData, aCard, aField, workAddressIndex,
       
   410                              EPIMContactAttrWork);
       
   411         return;
       
   412     }
       
   413 
       
   414     TInt valueCount = itemData.CountValues(aField);
       
   415     for (TInt i = 0; i < valueCount; i++)
       
   416     {
       
   417         switch (aField)
       
   418         {
       
   419         case EPIMContactUid:
       
   420         case EPIMContactRevision:
       
   421         {
       
   422             // uid and revision fields are totally ignored
       
   423             break;
       
   424         }
       
   425         case EPIMContactBirthday:
       
   426         case EPIMContactExtAnniversary:
       
   427         {
       
   428             ConvertDateFieldL(itemData, aCard, aField, i);
       
   429             break;
       
   430         }
       
   431         case EPIMContactEmail:
       
   432         case EPIMContactNickname:
       
   433         case EPIMContactNote:
       
   434         case EPIMContactOrg:
       
   435         case EPIMContactTel:
       
   436         case EPIMContactTitle:
       
   437         case EPIMContactUrl:
       
   438         case EPIMContactExtSip:
       
   439         case EPIMContactExtDtmf:
       
   440         case EPIMContactExtWvUserId:
       
   441         case EPIMContactExtDepartment:
       
   442         case EPIMContactExtAssistantName:
       
   443         case EPIMContactExtChildren:
       
   444         case EPIMContactExtSpouse:
       
   445         case EPIMContactExtVoip:
       
   446         case EPIMContactExtPTT:
       
   447         case EPIMContactExtSWIS:
       
   448         {
       
   449             ConvertStringFieldL(itemData, aCard, aField, i);
       
   450             break;
       
   451         }
       
   452         case EPIMContactName:
       
   453         {
       
   454             ConvertNameFieldL(itemData, aCard, aField, i);
       
   455             break;
       
   456         }
       
   457         case EPIMContactPhoto:
       
   458         {
       
   459             ConvertPhotoFieldL(itemData, aCard, aField, i);
       
   460             break;
       
   461         }
       
   462         case EPIMContactClass:
       
   463         {
       
   464             ConvertClassFieldL(itemData, aCard, aField, i);
       
   465             break;
       
   466         }
       
   467         case EPIMContactFormattedName:
       
   468         case EPIMContactFormattedAddr:
       
   469         case EPIMContactPhotoUrl:
       
   470         case EPIMContactPublicKey:
       
   471         case EPIMContactPublicKeyString:
       
   472         default:
       
   473         {
       
   474             __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
       
   475                                                EPIMPanicUnsupportedField));
       
   476             return;
       
   477         }
       
   478         }
       
   479     }
       
   480 }
       
   481 
       
   482 // -----------------------------------------------------------------------------
       
   483 // CPIMContactItemAdapter::ConvertFieldL
       
   484 // Converts a field from a Contact Card to a PIM Item.
       
   485 // -----------------------------------------------------------------------------
       
   486 //
       
   487 void CPIMContactItemAdapter::ConvertFieldL(const CContactItemField& aField, // field to read data from
       
   488         MPIMContactItem& aItem) // field to write the data to
       
   489 {
       
   490     JELOG2(EPim);
       
   491     TStorageType type = aField.StorageType();
       
   492     switch (type)
       
   493     {
       
   494     case KStorageTypeText:
       
   495     {
       
   496         ConvertTextFieldL(aField, aItem);
       
   497         break;
       
   498     }
       
   499     case KStorageTypeStore:
       
   500     {
       
   501         ConvertStoreFieldL(aField, aItem);
       
   502         break;
       
   503     }
       
   504     case KStorageTypeContactItemId:
       
   505     {
       
   506         break;
       
   507     }
       
   508     case KStorageTypeDateTime:
       
   509     {
       
   510         ConvertDateFieldL(aField, aItem);
       
   511         break;
       
   512     }
       
   513     default:
       
   514     {
       
   515         __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
       
   516                                            EPIMPanicUnsupportedField));
       
   517     }
       
   518     }
       
   519 }
       
   520 
       
   521 // -----------------------------------------------------------------------------
       
   522 // CPIMContactItemAdapter::ConvertTextFieldL
       
   523 // Converts a text field from a Contact Card to a PIM Item.
       
   524 // -----------------------------------------------------------------------------
       
   525 //
       
   526 void CPIMContactItemAdapter::ConvertTextFieldL(const CContactItemField& aField, // field to read data from
       
   527         MPIMContactItem& aItem) // field to write the data to
       
   528 {
       
   529     JELOG2(EPim);
       
   530     MPIMItemData& itemData = aItem.ItemData();
       
   531     CContactTextField* textField = aField.TextStorage();
       
   532     const CContentType& type = aField.ContentType();
       
   533 
       
   534     // Check that can we handle this field
       
   535     if (!(textField->IsFull()) || (type.FieldTypeCount() == 0))
       
   536     {
       
   537         return;
       
   538     }
       
   539 
       
   540     TPtrC text = textField->Text();
       
   541     TFieldType fieldTypeUid = type.FieldType(0);
       
   542     TPIMAttribute attributes = KPIMAttrNone;
       
   543 
       
   544     TPIMField field = iFieldInfo->MatchContactField(fieldTypeUid.iUid);
       
   545     // Check which field we must handle
       
   546     switch (field)
       
   547     {
       
   548     case EPIMContactName:
       
   549     {
       
   550         TPIMContactNameElement
       
   551         nameElement =
       
   552             static_cast<TPIMContactNameElement>(iFieldInfo->MatchContactArrayElement(
       
   553                                                     fieldTypeUid.iUid));
       
   554         AddNameFieldToItemL(text, aItem, nameElement, aField.Label());
       
   555         break;
       
   556     }
       
   557     case EPIMContactAddr:
       
   558     {
       
   559         TPIMContactAddrElement
       
   560         addrElement =
       
   561             static_cast<TPIMContactAddrElement>(iFieldInfo->MatchContactArrayElement(
       
   562                                                     fieldTypeUid.iUid));
       
   563         attributes = iFieldInfo->FieldAttributes(aField.ContentType());
       
   564 
       
   565         // Label addresses are also stored in the database using
       
   566         // KUidContactFieldAddressValue, but we don't support them
       
   567         if (fieldTypeUid.iUid == KUidContactFieldAddressValue)
       
   568         {
       
   569             if (type.ContainsFieldType(KUidContactFieldVCardMapADR))
       
   570             {
       
   571                 AddAddressFieldToItemL(text, aItem, EPIMContactAddrStreet,
       
   572                                        attributes, aField.Label());
       
   573             }
       
   574         }
       
   575         else
       
   576         {
       
   577             AddAddressFieldToItemL(text, aItem, addrElement, attributes,
       
   578                                    aField.Label());
       
   579         }
       
   580         break;
       
   581     }
       
   582     case EPIMContactClass:
       
   583     {
       
   584         AddClassFieldToItemL(itemData, text, aField.Label());
       
   585         break;
       
   586     }
       
   587     case EPIMContactExtSip:
       
   588     case EPIMContactExtVoip:
       
   589     case EPIMContactExtPTT:
       
   590     case EPIMContactExtSWIS:
       
   591     {
       
   592         // SIPID value can hold PoC (Push-To-Talk) Share view, SIP
       
   593         // and VOIP (Voice Over IP) fields inside it.
       
   594         // Apply internal attributes
       
   595         CArrayFix<TUid>* attrs = new(ELeave) CArrayFixFlat<TUid> (3);
       
   596         CleanupStack::PushL(attrs);
       
   597         iFieldInfo->GetFieldInternalAttributesL(type, *attrs);
       
   598         // VOIP (Internet telephone) field
       
   599         if (type.ContainsFieldType(KUidContactFieldVCardMapVOIP))
       
   600         {
       
   601             attributes = iFieldInfo->FieldAttributes(type);
       
   602             field = EPIMContactExtVoip;
       
   603         }
       
   604         else if (type.ContainsFieldType(KUidContactFieldVCardMapPOC))
       
   605         {
       
   606             field = EPIMContactExtPTT;
       
   607         }
       
   608         else if (type.ContainsFieldType(KUidContactFieldVCardMapSWIS))
       
   609         {
       
   610             field = EPIMContactExtSWIS;
       
   611         }
       
   612         else
       
   613         {
       
   614             field = EPIMContactExtSip;
       
   615         }
       
   616         // Add field, attributes, internal attributes and label to the item
       
   617         // Note that internal attributes are popped from the cleanup stack
       
   618         // inside the following function and there is no need to pop after it
       
   619         AddStringFieldWithLabelL(itemData, field, attributes, attrs, text,
       
   620                                  aField.Label());
       
   621         break;
       
   622     }
       
   623     case EPIMContactEmail:
       
   624     case EPIMContactNickname:
       
   625     case EPIMContactNote:
       
   626     case EPIMContactOrg:
       
   627     case EPIMContactTel:
       
   628     case EPIMContactTitle:
       
   629     case EPIMContactUrl:
       
   630     case EPIMContactExtDtmf:
       
   631     case EPIMContactExtWvUserId:
       
   632     case EPIMContactExtDepartment:
       
   633     case EPIMContactExtAssistantName:
       
   634     case EPIMContactExtChildren:
       
   635     case EPIMContactExtSpouse:
       
   636     {
       
   637         // Get internal attributes from the content type
       
   638         CArrayFix<TUid>* attrs = new(ELeave) CArrayFixFlat<TUid> (3);
       
   639         CleanupStack::PushL(attrs);
       
   640         iFieldInfo->GetFieldInternalAttributesL(type, *attrs);
       
   641         // Add attributes. FAX is special so it must be handled separately
       
   642         attributes = iFieldInfo->FieldAttributes(aField.ContentType());
       
   643         if (fieldTypeUid.iUid == KUidContactFieldFaxValue)
       
   644         {
       
   645             attributes |= EPIMContactAttrFax;
       
   646         }
       
   647         // Add field, attributes, internal attributes and label to the item
       
   648         // Note that internal attributes are popped from the cleanup stack
       
   649         // inside the following function and there is no need to pop after it
       
   650         AddStringFieldWithLabelL(itemData, field, attributes, attrs, text,
       
   651                                  aField.Label());
       
   652         break;
       
   653     }
       
   654     default:
       
   655     {
       
   656         // The field is not supported so we don't know what to do with it
       
   657         // and it is ignored. NOTE that contacts are opened first before
       
   658         // writing those to the contact database to ensure that unsupported
       
   659         // fields will still be included the to item and no data will be lost
       
   660         break;
       
   661     }
       
   662     }
       
   663 }
       
   664 
       
   665 // -----------------------------------------------------------------------------
       
   666 // CPIMContactItemAdapter::AddStringFieldWithLabelL
       
   667 // Adds a string field to the item, and optionally sets the fields label.
       
   668 // -----------------------------------------------------------------------------
       
   669 //
       
   670 void CPIMContactItemAdapter::AddStringFieldWithLabelL(MPIMItemData& aItem,
       
   671         TPIMField aField, TPIMAttribute aAttributes,
       
   672         CArrayFix<TUid>* aInternalAttributes, const TPtrC aValue,
       
   673         const TPtrC aLabel)
       
   674 {
       
   675     JELOG2(EPim);
       
   676     TInt valueCount = aItem.CountValues(aField);
       
   677     TPIMFieldData fieldData(aField, aAttributes, aValue.AllocLC());
       
   678 
       
   679     // Add data to the item
       
   680     aItem.AddValueL(fieldData);
       
   681     CleanupStack::Pop(); // aValue.AlloclC()
       
   682     // Apply internal attributes
       
   683     aItem.SetInternalAttributesL(aField, valueCount, aInternalAttributes);
       
   684     // aItem now owns aInternalAttributes
       
   685     CleanupStack::Pop(aInternalAttributes);
       
   686 
       
   687     // Set preferred index if it is set to this field value index
       
   688     // Only one value index of this field can have preferred index set
       
   689     // so we have to remove all existing preferred indexes. This has to
       
   690     // be done to SMS attribute also. There cannot be more than one
       
   691     // preferred SMS number in the S60 Phonebook
       
   692     if (aAttributes & EPIMContactAttrPreferred || aAttributes
       
   693             & EPIMContactAttrSms)
       
   694     {
       
   695         // Clear "preferred index" attribute from all other values
       
   696         // except this one (previously added one)
       
   697         for (TInt i = 0; i < valueCount; i++)
       
   698         {
       
   699             TPIMAttribute attributes = aItem.AttributesL(aField, i);
       
   700             // Clear attributes from preferred index
       
   701             if (aAttributes & EPIMContactAttrPreferred)
       
   702             {
       
   703                 attributes &= ~EPIMContactAttrPreferred;
       
   704             }
       
   705             if (aAttributes & EPIMContactAttrSms)
       
   706             {
       
   707                 attributes &= ~EPIMContactAttrSms;
       
   708             }
       
   709             aItem.SetAttributesL(aField, i, attributes);
       
   710         }
       
   711     }
       
   712 
       
   713     // Add label if necessary
       
   714     if (aLabel.Length() > 0)
       
   715     {
       
   716         aItem.SetLabelL(aField, valueCount, 0, aLabel);
       
   717     }
       
   718 }
       
   719 
       
   720 // -----------------------------------------------------------------------------
       
   721 // CPIMContactItemAdapter::ConvertDateFieldL
       
   722 // Converts a date field from a Contact Card to a PIM Item.
       
   723 // -----------------------------------------------------------------------------
       
   724 //
       
   725 void CPIMContactItemAdapter::ConvertDateFieldL(const CContactItemField& aField, // field to read data from
       
   726         MPIMContactItem& aItem) // field to write the data to
       
   727 {
       
   728     JELOG2(EPim);
       
   729     MPIMItemData& itemData = aItem.ItemData();
       
   730     CContactDateField* dateField = aField.DateTimeStorage();
       
   731     if (!(dateField->IsFull()))
       
   732     {
       
   733         // if date is not set, we don't read it
       
   734         return;
       
   735     }
       
   736     TTime time = dateField->Time();
       
   737     const CContentType& type = aField.ContentType();
       
   738 
       
   739     TPIMField field(0);
       
   740     // Check the field type
       
   741     if (type.ContainsFieldType(KUidContactFieldBirthday))
       
   742     {
       
   743         field = EPIMContactBirthday;
       
   744     }
       
   745     else if (type.ContainsFieldType(KUidContactFieldAnniversary))
       
   746     {
       
   747         field = EPIMContactExtAnniversary;
       
   748     }
       
   749 
       
   750     // Anniversary and Birthday are only dates so we are not interested
       
   751     // in which is the time in these fields. This is because Phonebook
       
   752     // doesn't take into account what time is used within these fields
       
   753     // Time conversion between UTC and local time is not needed here
       
   754     // because Phonebook handles only dates and PIM API times are in UTC
       
   755     // format causing this date to be set to the start of the UTC date time
       
   756     // and the date is shown correctly when midlet accesses it on the Java-side
       
   757     TDateTime temp(time.DateTime());
       
   758     temp.SetHour(0);
       
   759     temp.SetSecond(0);
       
   760     temp.SetMinute(0);
       
   761     temp.SetMicroSecond(0);
       
   762 
       
   763     // Count values and add new data
       
   764     TInt valueCount = itemData.CountValues(field);
       
   765     TPIMFieldData fieldData(field, KPIMAttrNone, TPIMDate(temp));
       
   766     itemData.AddValueL(fieldData);
       
   767 
       
   768     // Set label
       
   769     if (aField.Label().Length() > 0)
       
   770     {
       
   771         itemData.SetLabelL(field, valueCount, 0, aField.Label());
       
   772     }
       
   773 }
       
   774 
       
   775 // -----------------------------------------------------------------------------
       
   776 // CPIMContactItemAdapter::ConvertStoreFieldL
       
   777 // Converts a store field from a Contact Card to a PIM Item.
       
   778 // -----------------------------------------------------------------------------
       
   779 //
       
   780 void CPIMContactItemAdapter::ConvertStoreFieldL(
       
   781     const CContactItemField& aField, // field to read data from
       
   782     MPIMContactItem& aItem) // field to write the data to
       
   783 {
       
   784     JELOG2(EPim);
       
   785     CContactStoreField* storeField = aField.StoreStorage();
       
   786     if (!(storeField->IsFull()))
       
   787     {
       
   788         return;
       
   789     }
       
   790     const CContentType& type = aField.ContentType();
       
   791     if (type.ContainsFieldType(KUidContactFieldPicture))
       
   792     {
       
   793         // We don't care about other store fields
       
   794         MPIMItemData& itemData = aItem.ItemData();
       
   795         HBufC8* data = storeField->Thing();
       
   796         if (data)
       
   797         {
       
   798             TInt dataLength = data->Length();
       
   799             CPIMByteArray* byteArray = new(ELeave) CPIMByteArray(dataLength);
       
   800             CleanupStack::PushL(byteArray);
       
   801             byteArray->AppendL(data->Ptr(), dataLength);
       
   802             TPIMFieldData fieldData(EPIMContactPhoto, KPIMAttrNone, byteArray);
       
   803             itemData.AddValueL(fieldData);
       
   804             CleanupStack::Pop(); // byteArray
       
   805         }
       
   806     }
       
   807 }
       
   808 
       
   809 // -----------------------------------------------------------------------------
       
   810 // CPIMContactItemAdapter::AddNameFieldToItemL
       
   811 // Adds a name field to a PIM Item
       
   812 // -----------------------------------------------------------------------------
       
   813 //
       
   814 void CPIMContactItemAdapter::AddNameFieldToItemL(TPtrC aText, // text to add
       
   815         MPIMContactItem& aItem, // item to add to
       
   816         TPIMContactNameElement aElement, // element to add
       
   817         TPtrC aLabel) // label of the field
       
   818 {
       
   819     JELOG2(EPim);
       
   820     MPIMItemData& itemData = aItem.ItemData();
       
   821     // 7 for array granularity
       
   822     CDesCArrayFlat* nameArray = new(ELeave) CDesC16ArrayFlat(7);
       
   823     CleanupStack::PushL(nameArray);
       
   824     // do we already have a name field in the item
       
   825     TInt nameCount = itemData.CountValues(EPIMContactName);
       
   826     if (nameCount > 0)
       
   827     {
       
   828         const TPIMFieldData fieldData = itemData.ValueL(EPIMContactName, 0);
       
   829         const CDesCArray& oldNameArray = fieldData.StringArrayValue();
       
   830         TInt elementCount = oldNameArray.Count();
       
   831 
       
   832         for (TInt i = 0; i < elementCount; i++)
       
   833         {
       
   834             TPtrC16 oldName = oldNameArray[i];
       
   835             nameArray->AppendL(oldName);
       
   836         }
       
   837         // don't trust that item data has correct amount of elements
       
   838         for (TInt i = elementCount; i < EPIMContactNameNumElements; i++)
       
   839         {
       
   840             nameArray->AppendL(KPIMNullArrayElement());
       
   841         }
       
   842         // Add new element
       
   843         nameArray->Delete(aElement);
       
   844         nameArray->InsertL(aElement, aText);
       
   845         TPIMFieldData newFieldData(EPIMContactName, KPIMAttrNone, nameArray);
       
   846         itemData.SetValueL(newFieldData);
       
   847     }
       
   848     else
       
   849     {
       
   850         for (TInt i = 0; i < EPIMContactNameNumElements; i++)
       
   851         {
       
   852             nameArray->AppendL(KPIMNullArrayElement());
       
   853         }
       
   854         // Add new element
       
   855         nameArray->Delete(aElement);
       
   856         nameArray->InsertL(aElement, aText);
       
   857         TPIMFieldData newFieldData(EPIMContactName, KPIMAttrNone, nameArray);
       
   858         itemData.AddValueL(newFieldData);
       
   859     }
       
   860     // Name array is now owned by the item
       
   861     CleanupStack::Pop(nameArray);
       
   862     // Add label if it exists
       
   863     if (aLabel.Length() > 0)
       
   864     {
       
   865         itemData.SetLabelL(EPIMContactName, 0, aElement, aLabel);
       
   866     }
       
   867 }
       
   868 
       
   869 // -----------------------------------------------------------------------------
       
   870 // CPIMContactItemAdapter::AddAddressFieldToItemL
       
   871 // Adds an address field to a PIM Item
       
   872 // -----------------------------------------------------------------------------
       
   873 //
       
   874 void CPIMContactItemAdapter::AddAddressFieldToItemL(TPtrC aText, // text to add
       
   875         MPIMContactItem& aItem, // item to add to
       
   876         TPIMContactAddrElement aElement, // element to add
       
   877         TPIMAttribute aAttributes, // attributes of the address
       
   878         TPtrC aLabel) // label
       
   879 {
       
   880     JELOG2(EPim);
       
   881     MPIMItemData& itemData = aItem.ItemData();
       
   882     // 7 for array granularity
       
   883     CDesCArrayFlat* addrArray = new(ELeave) CDesC16ArrayFlat(7);
       
   884     CleanupStack::PushL(addrArray);
       
   885     // do we already have an address field in the item with the same attributes
       
   886     TInt addrCount = itemData.CountValues(EPIMContactAddr);
       
   887     TBool notFound = ETrue;
       
   888     TInt index = -1;
       
   889     for (TInt i = 0; (notFound) && (i < addrCount); i++)
       
   890     {
       
   891         if (itemData.AttributesL(EPIMContactAddr, i) == aAttributes)
       
   892         {
       
   893             const TPIMFieldData fieldData = itemData.ValueL(EPIMContactAddr, i);
       
   894             const CDesCArray& oldAddrArray = fieldData.StringArrayValue();
       
   895             TInt elementCount = oldAddrArray.Count();
       
   896             for (TInt j = 0; j < elementCount; j++)
       
   897             {
       
   898                 TPtrC oldAddr = oldAddrArray[j];
       
   899                 addrArray->AppendL(oldAddr);
       
   900             }
       
   901             for (TInt j = elementCount; j < EPIMContactAddrNumElements; j++)
       
   902             {
       
   903                 addrArray->AppendL(KPIMNullArrayElement());
       
   904             }
       
   905             notFound = EFalse;
       
   906             addrArray->Delete(aElement);
       
   907             addrArray->InsertL(aElement, aText);
       
   908             TPIMFieldData newFieldData(EPIMContactAddr, aAttributes, addrArray);
       
   909             newFieldData.SetIndex(i);
       
   910             itemData.SetValueL(newFieldData);
       
   911             index = i;
       
   912         }
       
   913     }
       
   914     if (notFound)
       
   915     {
       
   916         for (TInt i = 0; i < EPIMContactAddrNumElements; i++)
       
   917         {
       
   918             addrArray->AppendL(KPIMNullArrayElement);
       
   919         }
       
   920         addrArray->Delete(aElement);
       
   921         addrArray->InsertL(aElement, aText);
       
   922         TPIMFieldData fieldData(EPIMContactAddr, aAttributes, addrArray);
       
   923         itemData.AddValueL(fieldData);
       
   924     }
       
   925     // Array is now owned by the item
       
   926     CleanupStack::Pop(addrArray);
       
   927 
       
   928     // Add label if it exists
       
   929     if (aLabel.Length() > 0)
       
   930     {
       
   931         // If the index is -1, it indicates that we are
       
   932         // adding new string array at the end of the others
       
   933         // so the index should be same as addrCount
       
   934         index = (index == -1) ? addrCount : index;
       
   935         itemData.SetLabelL(EPIMContactAddr, index, aElement, aLabel);
       
   936     }
       
   937 }
       
   938 
       
   939 // -----------------------------------------------------------------------------
       
   940 // CPIMContactItemAdapter::ConvertAddressFieldL
       
   941 // Converts an address field from a PIM Item to a Contact Card.
       
   942 // -----------------------------------------------------------------------------
       
   943 //
       
   944 void CPIMContactItemAdapter::ConvertAddressFieldL(const MPIMItemData& aItem, // item to convert from
       
   945         CContactCard& aCard, // card to write to
       
   946         TPIMContactField aField, // field to convert
       
   947         TInt aIndex, // index to the field
       
   948         TPIMAttribute aAttributes) // attributes of the field
       
   949 {
       
   950     JELOG2(EPim);
       
   951     if (aIndex == KErrNotFound)
       
   952     {
       
   953         return;
       
   954     }
       
   955     const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
       
   956     const CDesCArray& addrArray = fieldData.StringArrayValue();
       
   957     EContactFieldCategory category = EContactCategoryNone;
       
   958     if (aAttributes == EPIMContactAttrHome)
       
   959     {
       
   960         category = EContactCategoryHome;
       
   961     }
       
   962     if (aAttributes == EPIMContactAttrWork)
       
   963     {
       
   964         category = EContactCategoryWork;
       
   965     }
       
   966 
       
   967     TInt addrCount = addrArray.Count();
       
   968     for (TInt i = 0; i < addrCount; i++)
       
   969     {
       
   970         if (addrArray[i].Compare(KPIMNullArrayElement()) == 0)
       
   971         {
       
   972             // we don't add null elements
       
   973             continue;
       
   974         }
       
   975 
       
   976         EnsureValidAddrElemLengthL(TPIMContactAddrElement(i), addrArray[i]);
       
   977 
       
   978         CContentType* type = iFieldInfo->AddressContentTypeL(
       
   979                                  static_cast<TPIMContactAddrElement>(i), category);
       
   980         CleanupStack::PushL(type);
       
   981 
       
   982         CContactItemField* field = CContactItemField::NewLC(KStorageTypeText,
       
   983                                    *type);
       
   984 
       
   985         // Add label to the field
       
   986         TPIMContactAddrElement element = TPIMContactAddrElement(i);
       
   987         const TPtrC label = aItem.LabelL(aField, aIndex, element);
       
   988         if (label.Compare(KPIMNullArrayElement) != 0)
       
   989         {
       
   990             field->SetLabelL(label);
       
   991         }
       
   992         field->SetUserFlags(category);
       
   993         // we don't store any label, Contacts Model should use default template
       
   994         CContactTextField* textField = field->TextStorage();
       
   995         textField->SetTextL(addrArray[i]);
       
   996         // Card takes the ownership of the field
       
   997         aCard.AddFieldL(*field);
       
   998         CleanupStack::Pop(field);
       
   999         CleanupStack::PopAndDestroy(type);
       
  1000     }
       
  1001 }
       
  1002 
       
  1003 // -----------------------------------------------------------------------------
       
  1004 // CPIMContactItemAdapter::ConvertNameFieldL
       
  1005 // Converts an address field from a PIM Item to a Contact Card.
       
  1006 // -----------------------------------------------------------------------------
       
  1007 //
       
  1008 void CPIMContactItemAdapter::ConvertNameFieldL(const MPIMItemData& aItem, // item to convert from
       
  1009         CContactCard& aCard, // card to write to
       
  1010         TPIMContactField aField, // field to convert
       
  1011         TInt aIndex) // index to the field
       
  1012 {
       
  1013     JELOG2(EPim);
       
  1014     const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
       
  1015     const CDesCArray& nameArray = fieldData.StringArrayValue();
       
  1016     EContactFieldCategory category = EContactCategoryHome;
       
  1017 
       
  1018     TInt nameCount = nameArray.Count();
       
  1019     for (TInt i = 0; i < nameCount; i++)
       
  1020     {
       
  1021         if (nameArray[i].Compare(KPIMNullArrayElement()) == 0)
       
  1022         {
       
  1023             // we don't add null elements
       
  1024             continue;
       
  1025         }
       
  1026 
       
  1027         EnsureValidNameElemLengthL(TPIMContactNameElement(i), nameArray[i]);
       
  1028 
       
  1029         CContentType* type = iFieldInfo->NameContentTypeL(
       
  1030                                  static_cast<TPIMContactNameElement>(i));
       
  1031         CleanupStack::PushL(type);
       
  1032 
       
  1033         CContactItemField* field = CContactItemField::NewLC(KStorageTypeText,
       
  1034                                    *type);
       
  1035 
       
  1036         // Add label to the field. aIndex should be 0 in this case because
       
  1037         // there are only one string array in the name field
       
  1038         TPIMContactNameElement element = TPIMContactNameElement(i);
       
  1039         const TPtrC label = aItem.LabelL(aField, aIndex, element);
       
  1040         if (label.Compare(KPIMNullArrayElement) != 0)
       
  1041         {
       
  1042             field->SetLabelL(label);
       
  1043         }
       
  1044         field->SetUserFlags(category);
       
  1045         // we don't store any label, Contacts Model should use default template
       
  1046         CContactTextField* textField = field->TextStorage();
       
  1047         textField->SetTextL(nameArray[i]);
       
  1048         // Card takes ownership of the field
       
  1049         aCard.AddFieldL(*field);
       
  1050         CleanupStack::Pop(field);
       
  1051         CleanupStack::PopAndDestroy(type);
       
  1052     }
       
  1053 }
       
  1054 
       
  1055 // -----------------------------------------------------------------------------
       
  1056 // CPIMContactItemAdapter::ConvertDateFieldL
       
  1057 // Converts a date field from a PIM Item to a Contact Card.
       
  1058 // -----------------------------------------------------------------------------
       
  1059 //
       
  1060 void CPIMContactItemAdapter::ConvertDateFieldL(const MPIMItemData& aItem, // item to convert from
       
  1061         CContactCard& aCard, // card to write to
       
  1062         TPIMContactField aField, // field to convert
       
  1063         TInt aIndex) // index to the field
       
  1064 {
       
  1065     JELOG2(EPim);
       
  1066     const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
       
  1067     const TPIMDate& date = fieldData.DateValue();
       
  1068     CContentType* type = NULL;
       
  1069 
       
  1070     switch (aField)
       
  1071     {
       
  1072     case EPIMContactBirthday:
       
  1073     {
       
  1074         type = CContentType::NewL(KUidContactFieldBirthday,
       
  1075                                   KUidContactFieldVCardMapBDAY);
       
  1076         CleanupStack::PushL(type);
       
  1077         break;
       
  1078     }
       
  1079     case EPIMContactExtAnniversary:
       
  1080     {
       
  1081         type = CContentType::NewL(KUidContactFieldAnniversary,
       
  1082                                   KUidContactFieldVCardMapAnniversary);
       
  1083         CleanupStack::PushL(type);
       
  1084         break;
       
  1085     }
       
  1086     default:
       
  1087     {
       
  1088         User::Panic(KPIMPanicCategory, EPIMPanicUnsupportedDateField);
       
  1089         break;
       
  1090     }
       
  1091     }
       
  1092     CContactItemField* field = CContactItemField::NewLC(KStorageTypeDateTime,
       
  1093                                *type);
       
  1094     // set label if set in pim item
       
  1095     const TPtrC label = aItem.LabelL(aField, aIndex, 0);
       
  1096     if (label.Compare(KPIMNullArrayElement) != 0)
       
  1097     {
       
  1098         field->SetLabelL(label);
       
  1099     }
       
  1100 
       
  1101     field->SetUserFlags(EContactCategoryOther);
       
  1102     CContactDateField* dateField = field->DateTimeStorage();
       
  1103 
       
  1104     // PIM API stores dates as UTC time. Phonebook instead expects that dates
       
  1105     // are stored as in local time format in the Contacts Model database
       
  1106     RTz tzServer;
       
  1107     User::LeaveIfError(tzServer.Connect());
       
  1108     CleanupClosePushL(tzServer);
       
  1109 
       
  1110     // Create timezone converter
       
  1111     CTzConverter* converter = CTzConverter::NewL(tzServer);
       
  1112     CleanupStack::PushL(converter);
       
  1113 
       
  1114     TTime localTime(date);
       
  1115     User::LeaveIfError(converter->ConvertToLocalTime(localTime));
       
  1116     CleanupStack::PopAndDestroy(2); // converter, tzServer
       
  1117 
       
  1118     // Anniversary and Birthday are only dates so we are not interested
       
  1119     // in which is the time in these fields. This is because Phonebook
       
  1120     // doesn't take into account what time is used within these fields
       
  1121     TDateTime temp(localTime.DateTime());
       
  1122     temp.SetHour(0);
       
  1123     temp.SetMinute(0);
       
  1124     temp.SetSecond(0);
       
  1125     temp.SetMicroSecond(0);
       
  1126 
       
  1127     dateField->SetTime(TTime(temp));
       
  1128     // Card takes ownership of the field
       
  1129     aCard.AddFieldL(*field);
       
  1130     CleanupStack::Pop(field);
       
  1131     CleanupStack::PopAndDestroy(type);
       
  1132 }
       
  1133 
       
  1134 // -----------------------------------------------------------------------------
       
  1135 // CPIMContactItemAdapter::ConvertStringFieldL
       
  1136 // Converts a string field from a PIM Item to a Contact Card.
       
  1137 // -----------------------------------------------------------------------------
       
  1138 //
       
  1139 void CPIMContactItemAdapter::ConvertStringFieldL(const MPIMItemData& aItem, // item to convert from
       
  1140         CContactCard& aCard, // card to write to
       
  1141         TPIMContactField aField, // field to convert
       
  1142         TInt aIndex) // index to the field
       
  1143 {
       
  1144     JELOG2(EPim);
       
  1145     const CArrayFix<TUid>& attrs = aItem.InternalAttributesL(aField, aIndex);
       
  1146     const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
       
  1147     const TDesC& string = fieldData.StringValue();
       
  1148     TPIMAttribute attributes = fieldData.Attributes();
       
  1149     EContactFieldCategory category = EContactCategoryNone;
       
  1150 
       
  1151     EnsureValidStringValueLengthL(aField, string);
       
  1152 
       
  1153     if ((attributes & EPIMContactAttrHome) != 0)
       
  1154     {
       
  1155         category = EContactCategoryHome;
       
  1156     }
       
  1157     if ((attributes & EPIMContactAttrWork) != 0)
       
  1158     {
       
  1159         category = EContactCategoryWork;
       
  1160     }
       
  1161     CContentType* type = iFieldInfo->StringFieldContentTypeL(aField,
       
  1162                          attributes, category);
       
  1163     CleanupStack::PushL(type);
       
  1164     // Apply internal attributes if any
       
  1165     TInt interalAttrCount = attrs.Count();
       
  1166     for (TInt i = 0; i < interalAttrCount; i++)
       
  1167     {
       
  1168         TFieldType fieldType = attrs.At(i);
       
  1169         // Check to avoid duplicate field types in the content type
       
  1170         // this may be possible when unrecognized fields are added to
       
  1171         // internal attribute list (e.g incorrectly generated ContentType)
       
  1172         if (!type->ContainsFieldType(fieldType))
       
  1173         {
       
  1174             type->AddFieldTypeL(fieldType);
       
  1175         }
       
  1176     }
       
  1177     // Create new contact item field which is a text storage
       
  1178     CContactItemField* field =
       
  1179         CContactItemField::NewLC(KStorageTypeText, *type);
       
  1180     // set label if set in pim item
       
  1181     const TPtrC label = aItem.LabelL(aField, aIndex, 0);
       
  1182     if (label.Compare(KPIMNullArrayElement) != 0)
       
  1183     {
       
  1184         field->SetLabelL(label);
       
  1185     }
       
  1186 
       
  1187     field->SetUserFlags(category);
       
  1188     CContactTextField* textField = field->TextStorage();
       
  1189     textField->SetTextL(string);
       
  1190     // Card takes ownership of the field
       
  1191     aCard.AddFieldL(*field);
       
  1192     CleanupStack::Pop(field);
       
  1193     CleanupStack::PopAndDestroy(type);
       
  1194 }
       
  1195 
       
  1196 // -----------------------------------------------------------------------------
       
  1197 // CPIMContactItemAdapter::ConvertPhotoFieldL
       
  1198 // Converts a photo field from a PIM Item to a Contact Card.
       
  1199 // -----------------------------------------------------------------------------
       
  1200 //
       
  1201 void CPIMContactItemAdapter::ConvertPhotoFieldL(const MPIMItemData& aItem, // item to convert from
       
  1202         CContactCard& aCard, // card to write to
       
  1203         TPIMContactField aField, // field to convert
       
  1204         TInt aIndex) // index to the field
       
  1205 {
       
  1206     JELOG2(EPim);
       
  1207     const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
       
  1208     const CPIMByteArray& byteArray = fieldData.BinaryValue();
       
  1209     EContactFieldCategory category = EContactCategoryNone;
       
  1210     CContentType* type = CContentType::NewL(KUidContactFieldPicture,
       
  1211                                             KUidContactFieldVCardMapPHOTO);
       
  1212     CleanupStack::PushL(type);
       
  1213 
       
  1214     CContactItemField* field = CContactItemField::NewLC(KStorageTypeStore,
       
  1215                                *type);
       
  1216     field->SetUserFlags(category);
       
  1217 
       
  1218     const TUint8& byteRef = byteArray.At(0);
       
  1219     const TUint8* bytePtr = &byteRef;
       
  1220     TPtrC8 data(bytePtr, byteArray.Count());
       
  1221 
       
  1222     HBufC8* thumbNail = iImageScaler->ScaleL(data);
       
  1223     CleanupStack::PushL(thumbNail);
       
  1224 
       
  1225     CContactStoreField* storeField = field->StoreStorage();
       
  1226     storeField->SetThingL(*thumbNail);
       
  1227     CleanupStack::PopAndDestroy(); // thumbNail
       
  1228     // Card takes ownership of the field
       
  1229     aCard.AddFieldL(*field);
       
  1230     CleanupStack::Pop(field);
       
  1231     CleanupStack::PopAndDestroy(type);
       
  1232 }
       
  1233 
       
  1234 // -----------------------------------------------------------------------------
       
  1235 // CPIMContactItemAdapter::ConvertClassFieldL
       
  1236 // Converts a CLASS field from a PIM Item to a Contact Card.
       
  1237 // -----------------------------------------------------------------------------
       
  1238 //
       
  1239 void CPIMContactItemAdapter::ConvertClassFieldL(const MPIMItemData& aItemData,
       
  1240         CContactCard& aCard, TPIMContactField aField, TInt aIndex)
       
  1241 {
       
  1242     JELOG2(EPim);
       
  1243     TPtrC classValueDes(KPIMContactClassPrivate());
       
  1244     const TPIMFieldData fieldData = aItemData.ValueL(aField, aIndex);
       
  1245     const TInt classValue = fieldData.IntegerValue();
       
  1246     CContentType* type = CContentType::NewL(KUidContactFieldClass,
       
  1247                                             KUidContactFieldVCardMapClass);
       
  1248     CleanupStack::PushL(type);
       
  1249 
       
  1250     switch (classValue)
       
  1251     {
       
  1252     case EPIMContactClassPrivate:
       
  1253     {
       
  1254         classValueDes.Set(KPIMContactClassPrivate());
       
  1255         break;
       
  1256     }
       
  1257     case EPIMContactClassPublic:
       
  1258     {
       
  1259         classValueDes.Set(KPIMContactClassPublic());
       
  1260         break;
       
  1261     }
       
  1262     case EPIMContactClassConfidential:
       
  1263     {
       
  1264         classValueDes.Set(KPIMContactClassConfidential());
       
  1265         break;
       
  1266     }
       
  1267     default:
       
  1268     {
       
  1269         __ASSERT_DEBUG(EFalse, User::Invariant());
       
  1270         break; // For a happy compiler
       
  1271     }
       
  1272     }
       
  1273     // Add value to the contact field
       
  1274     CContactItemField* field =
       
  1275         CContactItemField::NewLC(KStorageTypeText, *type);
       
  1276     field->SetUserFlags(EContactCategoryNone);
       
  1277 
       
  1278     // Set label if any
       
  1279     const TPtrC label = aItemData.LabelL(aField, aIndex, 0);
       
  1280     if (label.Compare(KPIMNullArrayElement) != 0)
       
  1281     {
       
  1282         field->SetLabelL(label);
       
  1283     }
       
  1284 
       
  1285     CContactTextField* textField = field->TextStorage();
       
  1286     textField->SetTextL(classValueDes);
       
  1287     // Card takes ownership of the field
       
  1288     aCard.AddFieldL(*field);
       
  1289     CleanupStack::Pop(field);
       
  1290     CleanupStack::PopAndDestroy(type);
       
  1291 }
       
  1292 
       
  1293 // -----------------------------------------------------------------------------
       
  1294 // CPIMContactItemAdapter::ConvertClassFieldL
       
  1295 // Converts a CLASS field from a Contact Card to PIM item
       
  1296 // -----------------------------------------------------------------------------
       
  1297 //
       
  1298 void CPIMContactItemAdapter::AddClassFieldToItemL(MPIMItemData& aItemData,
       
  1299         TPtrC& aClassDesValue, TPtrC aLabel)
       
  1300 {
       
  1301     JELOG2(EPim);
       
  1302     // Syncronisation is private for default
       
  1303     TPIMContactClassValue classValue = EPIMContactClassPrivate;
       
  1304     TInt valueCount = aItemData.CountValues(EPIMContactClass);
       
  1305 
       
  1306     if (aClassDesValue.Compare(KPIMContactClassPublic()) == 0)
       
  1307     {
       
  1308         classValue = EPIMContactClassPublic;
       
  1309     }
       
  1310     else if (aClassDesValue.Compare(KPIMContactClassPrivate()) == 0)
       
  1311     {
       
  1312         classValue = EPIMContactClassPrivate;
       
  1313     }
       
  1314     else if (aClassDesValue.Compare(KPIMContactClassConfidential()) == 0)
       
  1315     {
       
  1316         classValue = EPIMContactClassConfidential;
       
  1317     }
       
  1318     TPIMFieldData fieldData(EPIMContactClass, EPIMFieldInt, KPIMAttrNone,
       
  1319                             classValue);
       
  1320     aItemData.AddValueL(fieldData);
       
  1321     // Label if any
       
  1322     if (aLabel.Length() > 0)
       
  1323     {
       
  1324         aItemData.SetLabelL(EPIMContactClass, valueCount, 0, aLabel);
       
  1325     }
       
  1326 }
       
  1327 
       
  1328 // -----------------------------------------------------------------------------
       
  1329 // CPIMContactItemAdapter::AddressAttributesL
       
  1330 // Checks the optimal attributes for the addresses
       
  1331 // -----------------------------------------------------------------------------
       
  1332 void CPIMContactItemAdapter::AddressAttributesL(const MPIMItemData& aItem,
       
  1333         TInt& aPlainAddressIndex, TInt& aHomeAddressIndex, TInt& aWorkAddressIndex)
       
  1334 {
       
  1335     JELOG2(EPim);
       
  1336     aPlainAddressIndex = KErrNotFound;
       
  1337     aHomeAddressIndex = KErrNotFound;
       
  1338     aWorkAddressIndex = KErrNotFound;
       
  1339     TInt addressCount = aItem.CountValues(EPIMContactAddr);
       
  1340 
       
  1341     // first pass - find zero and single attribute values if exist
       
  1342     TInt i = 0;
       
  1343     for (; i < addressCount; i++)
       
  1344     {
       
  1345         if (aItem.AttributesL(EPIMContactAddr, i) == KPIMAttrNone)
       
  1346         {
       
  1347             aPlainAddressIndex = i;
       
  1348         }
       
  1349         else if (aItem.AttributesL(EPIMContactAddr, i) == EPIMContactAttrHome)
       
  1350         {
       
  1351             aHomeAddressIndex = i;
       
  1352         }
       
  1353         else if (aItem.AttributesL(EPIMContactAddr, i) == EPIMContactAttrWork)
       
  1354         {
       
  1355             aWorkAddressIndex = i;
       
  1356         }
       
  1357     }
       
  1358 
       
  1359     // second pass - fill in the rest
       
  1360     for (i = 0; i < addressCount; i++)
       
  1361     {
       
  1362         if ((aPlainAddressIndex != i) && (aHomeAddressIndex != i)
       
  1363                 && (aWorkAddressIndex != i))
       
  1364         {
       
  1365             // this index has not been used yet
       
  1366             if (KErrNotFound == aWorkAddressIndex)
       
  1367             {
       
  1368                 aWorkAddressIndex = i;
       
  1369             }
       
  1370             else if (KErrNotFound == aHomeAddressIndex)
       
  1371             {
       
  1372                 aHomeAddressIndex = i;
       
  1373             }
       
  1374             else if (KErrNotFound == aPlainAddressIndex)
       
  1375             {
       
  1376                 aPlainAddressIndex = i;
       
  1377             }
       
  1378             else
       
  1379             {
       
  1380                 // all indexes are filled
       
  1381                 break; // out of the for loop
       
  1382             }
       
  1383         }
       
  1384     }
       
  1385 }
       
  1386 
       
  1387 // -----------------------------------------------------------------------------
       
  1388 // CPIMContactItemAdapter::EnsureValidStringValueLengthL
       
  1389 // -----------------------------------------------------------------------------
       
  1390 void CPIMContactItemAdapter::EnsureValidStringValueLengthL(
       
  1391     TPIMContactField aField, const TDesC& aValue)
       
  1392 {
       
  1393     JELOG2(EPim);
       
  1394     const TInt* maxLengthArr = NULL;
       
  1395     TInt offset = 0;
       
  1396     TInt arrLen = 0;
       
  1397 
       
  1398     if (aField >= KContactExtStringMaxLengthOffset)
       
  1399     {
       
  1400         maxLengthArr = KContactExtStringMaxLengths;
       
  1401         offset = KContactExtStringMaxLengthOffset;
       
  1402         arrLen = KContactExtStringMaxLengthsLen;
       
  1403     }
       
  1404     else
       
  1405     {
       
  1406         maxLengthArr = KContactStringMaxLengths;
       
  1407         offset = KContactStringMaxLengthsOffset;
       
  1408         arrLen = KContactStringMaxLengthsLen;
       
  1409     }
       
  1410 
       
  1411     TInt index = aField - offset;
       
  1412 
       
  1413     __ASSERT_ALWAYS((index >= 0), User::Invariant());
       
  1414     __ASSERT_ALWAYS((index < arrLen), User::Invariant());
       
  1415 
       
  1416     TInt maxLen = maxLengthArr[index];
       
  1417     if ((maxLen > 0) && (aValue.Length() > maxLen))
       
  1418     {
       
  1419         User::Leave(KErrTooBig);
       
  1420     }
       
  1421 }
       
  1422 
       
  1423 // -----------------------------------------------------------------------------
       
  1424 // CPIMContactItemAdapter::EnsureValidAddrElemLengthL
       
  1425 // -----------------------------------------------------------------------------
       
  1426 void CPIMContactItemAdapter::EnsureValidAddrElemLengthL(
       
  1427     TPIMContactAddrElement aElemIndex, const TDesC& aElemValue)
       
  1428 {
       
  1429     JELOG2(EPim);
       
  1430     __ASSERT_DEBUG((aElemIndex >= 0), User::Invariant());
       
  1431 
       
  1432     __ASSERT_DEBUG((aElemIndex < EPIMContactAddrNumElements), User::Invariant());
       
  1433 
       
  1434     __ASSERT_DEBUG(
       
  1435         (KContactAddrElemMaxLengths[aElemIndex] != KErrNotSupported),
       
  1436         User::Invariant());
       
  1437 
       
  1438     if ((KContactAddrElemMaxLengths[aElemIndex] != KErrNotSupported)
       
  1439             && (aElemValue.Length() > KContactAddrElemMaxLengths[aElemIndex]))
       
  1440     {
       
  1441         User::Leave(KErrTooBig);
       
  1442     }
       
  1443 }
       
  1444 
       
  1445 // -----------------------------------------------------------------------------
       
  1446 // CPIMContactItemAdapter::EnsureValidNameElemLengthL
       
  1447 // -----------------------------------------------------------------------------
       
  1448 void CPIMContactItemAdapter::EnsureValidNameElemLengthL(
       
  1449     TPIMContactNameElement aElemIndex, const TDesC& aElemValue)
       
  1450 {
       
  1451     JELOG2(EPim);
       
  1452     __ASSERT_DEBUG((aElemIndex >= 0), User::Invariant());
       
  1453 
       
  1454     __ASSERT_DEBUG((aElemIndex < EPIMContactNameNumElements), User::Invariant());
       
  1455 
       
  1456     __ASSERT_DEBUG(
       
  1457         (KContactNameElemMaxLengths[aElemIndex] != KErrNotSupported),
       
  1458         User::Invariant());
       
  1459 
       
  1460     if ((KContactNameElemMaxLengths[aElemIndex] != KErrNotSupported)
       
  1461             && (aElemValue.Length() > KContactNameElemMaxLengths[aElemIndex]))
       
  1462     {
       
  1463         User::Leave(KErrTooBig);
       
  1464     }
       
  1465 }
       
  1466 
       
  1467 // End of File