/** * Set the phone number field of the contact with id aId to contain the number aNumber * @param aDb Contact database * @param aId Contact item id * @param aNumber A telephone number */ void SetPhoneNumberField(CContactDatabase& aDb,TContactItemId aId,const TDesC& aNumber) { syncChecker->ResetMethodCallCountsL(); CContactItem* item = aDb.OpenContactLX(aId); CleanupStack::PushL(item); if (item->Type() == KUidContactICCEntry) { test(syncChecker->ValidateMethodCallCountL() == 2); } else { test(syncChecker->ValidateMethodCallCountL() == 0); } CContactItemFieldSet& fieldset = item->CardFields(); TInt pos = fieldset.Find(KUidContactFieldPhoneNumber); test(pos!=KErrNotFound); CContactItemField& field = fieldset[pos]; CContactTextField* textfield = field.TextStorage(); textfield->SetTextL(aNumber); syncChecker->ResetMethodCallCountsL(); aDb.CommitContactL(*item); if (item->Type() == KUidContactICCEntry) { test(syncChecker->ValidateMethodCallCountL() == 2); } else { test(syncChecker->ValidateMethodCallCountL() == 0); } CleanupStack::PopAndDestroy(2); // item, lock record }
/** Merging pure (minimal) contact with the template should be out of scope of the Persistence Layer. The only reason to have this functions in the test interface is that CContactItem::RestoreTemplateFieldsL() is not exported. */ void CLplTester::MergeContactWithTemplateL(CContactItem& aContact, const CContactItem& aTempl, const CContactItemViewDef& aView) const { if (aContact.TemplateRefId()!=KNullContactId && aContact.Type() != KUidContactCardTemplate) { aContact.RestoreTemplateFieldsL(iProps.SystemTemplateL().CardFields(), aTempl.CardFields(), aView); } }
/** Deletes all the communication addresses for a particular contact item. Should be used when deleting a contact item from the database altogether. @param aItem The contact item whose communcation addresses are to be deleted. */ void CPplCommAddrTable::DeleteL(const CContactItem& aItem, TBool& aLowDiskErrorOccurred) { const TUid KType = aItem.Type(); if (KType != KUidContactCard && KType != KUidContactOwnCard && KType != KUidContactICCEntry && KType != KUidContactGroup) { return; } RSqlStatement stmnt; CleanupClosePushL(stmnt); stmnt.PrepareL(iDatabase, iAllForItemDeleteStmnt->SqlStringL() ); const TInt KContactIdParamIndex(KFirstIndex); // first and only parameter in query User::LeaveIfError(stmnt.BindInt(KContactIdParamIndex, aItem.Id() ) ); TInt err = stmnt.Exec(); CleanupStack::PopAndDestroy(&stmnt); if (err == KErrDiskFull) { aLowDiskErrorOccurred = ETrue; } else { User::LeaveIfError(err); } }
TBool CPackagerCntComparator::DoCompareCContactItemType(const CContactItem& anItem1, const CContactItem& anItem2) const /** Compares two CContactItem items' types. @param anItem1 The first CContactItem type to be compared. @param anItem2 The second CContactItem type to be compared. @return ETrue if the two items are equal, EFalse otherwise. */ { TUid cntItem1Uid = anItem1.Type(); if(!DoCompareTUid(cntItem1Uid, anItem2.Type())) { return EFalse; } TBool result = ETrue; switch(cntItem1Uid.iUid) { // GroupsJoined() and ItemsContained() // do not hand over ownership, see cntitem.cpp. case KUidContactCardValue: result = Compare(*(static_cast<CContactCard&>((const_cast<CContactItem&>(anItem1))).GroupsJoined()), *(static_cast<CContactCard&>((const_cast<CContactItem&>(anItem2))).GroupsJoined())); break; case KUidContactGroupValue: result = (Compare(*(static_cast<CContactGroup&>((const_cast<CContactItem&>(anItem1))).GroupsJoined()), *(static_cast<CContactGroup&>((const_cast<CContactItem&>(anItem2))).GroupsJoined())) & Compare(*(static_cast<CContactGroup&>((const_cast<CContactItem&>(anItem1))).ItemsContained()), *(static_cast<CContactGroup&>((const_cast<CContactItem&>(anItem1))).ItemsContained()))); break; case KUidContactOwnCardValue: result = Compare(*(static_cast<CContactOwnCard&>((const_cast<CContactItem&>(anItem1))).GroupsJoined()), *(static_cast<CContactOwnCard&>((const_cast<CContactItem&>(anItem2))).GroupsJoined())); break; case KUidContactICCEntryValue: result = Compare(*(static_cast<CContactICCEntry&>((const_cast<CContactItem&>(anItem1))).GroupsJoined()), *(static_cast<CContactICCEntry&>((const_cast<CContactItem&>(anItem2))).GroupsJoined())); break; default: break; } return result; }
/** Updates informations related to passed contact item within group table @param aItem Reference to contact item. */ void CPplGroupsTable::UpdateL(const CContactItem& aItem) { // Only write to the table if it's a group. If we add the relationship from both sides // (i.e. once for the group and once for the item) we will have duplicate records. if (aItem.Type() == KUidContactGroup) { WriteGroupMembersL(aItem); } }
/** * Verify that the template was correctly added * @param aTemplate CContactCardTemplate template item */ void CheckTemplateL(CContactItem& aTemplate) { test(aTemplate.Type() == KUidContactCardTemplate); test(aTemplate.TemplateRefId() == KNullContactId); test(static_cast<CContactCardTemplate&>(aTemplate).GetTemplateLabelL() == KTemplateName); CContactItemFieldSet& fieldset = aTemplate.CardFields(); TInt pos = fieldset.Find(KUidContactFieldTemplateLabel); test(pos!=KErrNotFound); TInt count = fieldset.Count(); test(count==5); //label, name, number, ICC slot, phonebook }
void TestDatabaseIterationL(CContactDatabase& aDb) { test.Next(_L("Test database iteration")); aDb.SetDbViewContactType(KUidContactICCEntry); TContactIter iterator(aDb); TContactItemId id = iterator.FirstL(); while (id!=KNullContactId) { CContactItem* item = aDb.ReadContactLC(id); test(item->Type() == KUidContactICCEntry); CleanupStack::PopAndDestroy(item); id = iterator.NextL(); } }
/* * Private implementation for fetching the members of a group. */ QSet<QContactLocalId> CntSymbianDatabase::groupMembersL(QContactLocalId groupId) { QSet<QContactLocalId> groupMembers; CContactItem *contactItem = m_contactDatabase->ReadContactLC(TContactItemId(groupId)); Q_ASSERT(contactItem && contactItem->Type() == KUidContactGroup); CContactGroup *group = static_cast<CContactGroup*>(contactItem); const CContactIdArray *idArray = group->ItemsContained(); //loop through all the contacts and add them to the list for (int i(0); i < idArray->Count(); i++) { groupMembers.insert((*idArray)[i]); } CleanupStack::PopAndDestroy(contactItem); return groupMembers; }
/** ReadL has a dual functionality. If passed parameter is a group, will be filled to contacts bellonging to that group. Otherwirse, the contact item will be filed with all groups to which it belongs @param aItem Reference to contact item. */ void CPplGroupsTable::ReadL(CContactItem& aItem) { const TContactItemId KItemId(aItem.Id() ); const TUid KType(aItem.Type() ); if (KType == KUidContactGroup) { CContactGroup& group = static_cast<CContactGroup&>(aItem); group.ResetItems(); group.SetItems(GetListForItemL(KItemId, ETrue)); } if (KType == KUidContactCard || KType == KUidContactOwnCard || KType == KUidContactICCEntry || KType == KUidContactGroup) { CContactItemPlusGroup& item = static_cast<CContactItemPlusGroup&>(aItem); item.ResetGroups(); item.SetGroups(GetListForItemL(KItemId, EFalse)); } }
/** Updates communication addresses in the database. If there are the same number of items to be updated as are already in the database, the existing records are overwritten using the update statement. However, if there is a different number of addresses to be updated, records in the database (if there are any) are deleted (using DeleteL() ) and the new data is inserted (using CreateInDbL() ). @param aItem A contact item whose communication addresses are to be updated in the contacts database. */ void CPplCommAddrTable::UpdateL(const CContactItem& aItem) { // Check that the contact item is a card, own card or ICC entry. const TUid type(aItem.Type() ); if (type != KUidContactCard && type != KUidContactOwnCard && type != KUidContactICCEntry && type != KUidContactGroup) { return; } const TContactItemId KItemId(aItem.Id() ); // create lists for comm_addrs and go through contact item to populate them with any new ones we find RArray<TMatch> newPhones; RArray<TPtrC> newEmails; RArray<TPtrC> newSips; CleanupClosePushL(newPhones); CleanupClosePushL(newEmails); CleanupClosePushL(newSips); CPplCommAddrTable::TCommAddrExtraInfoType extraInfoType = ENonMobileNumber; for (TInt fieldNum = aItem.CardFields().Count() - 1; fieldNum >= 0; --fieldNum) { CContactItemField& currField = aItem.CardFields()[fieldNum]; const CContentType& contType = currField.ContentType(); TBool isPhone(contType.ContainsFieldType(KUidContactFieldPhoneNumber) || contType.ContainsFieldType(KUidContactFieldFax) || contType.ContainsFieldType(KUidContactFieldSms) ); TBool isEmail(contType.ContainsFieldType(KUidContactFieldEMail) ); TBool isSip(contType.ContainsFieldType(KUidContactFieldSIPID) ); // check it's a field we want and that it's not empty // store a new address if we haven't already seen it -- no point storing the same one twice. if ((isPhone || isEmail || isSip) && currField.StorageType() == KStorageTypeText && currField.TextStorage()->IsFull() ) { // get phone numbers if (isPhone) { TMatch phoneNumber; phoneNumber = CreatePaddedPhoneDigitsL(currField.TextStorage()->Text(), KLowerSevenDigits, KMaxPhoneMatchLength - KLowerSevenDigits); if (newPhones.Find(phoneNumber, TIdentityRelation<TMatch>(&TMatch::Equals) ) == KErrNotFound) { newPhones.AppendL(phoneNumber); } if(contType.ContainsFieldType(KUidContactFieldVCardMapCELL)) { extraInfoType = EMobileNumber; } } // get email addresses else if (isEmail && newEmails.Find(currField.TextStorage()->Text() ) == KErrNotFound) { newEmails.AppendL(currField.TextStorage()->Text() ); } // get SIP addresses else if (newSips.Find(currField.TextStorage()->Text() ) == KErrNotFound) { newSips.AppendL(currField.TextStorage()->Text() ); } } } // if there are no comm addresses in the contact item, delete any from the database if (!(newPhones.Count() + newEmails.Count() + newSips.Count() ) ) { TBool lowDiskErr(EFalse); DeleteL(aItem, lowDiskErr); CleanupStack::PopAndDestroy(3, &newPhones); // and newSips, newEmails if (lowDiskErr) { User::Leave(KErrDiskFull); } return; } // create from the database a list of comm_addr_ids that can be recycled as their // comm_addrs are in the database but not in the new version of the contact item RArray<TInt> freeCommAddrIds; CleanupClosePushL(freeCommAddrIds); // weed out addresses from the list that are already in the db but haven't changed // and populate the freeCommAddrIds list RemoveNonUpdatedAddrsL(newPhones, newEmails, newSips, freeCommAddrIds, KItemId, extraInfoType); // do the actual updating on an address-by-address basis DoUpdateCommAddrsL(newPhones, newEmails, newSips, freeCommAddrIds, KItemId,extraInfoType); CleanupStack::PopAndDestroy(4, &newPhones); // and freeCommAddrIds, newSips, newEmails }
/** Insert new communication addresses into the comm_addr table. @param aItem A contact item whose communication addresses are to be added to the contacts database. */ void CPplCommAddrTable::CreateInDbL(CContactItem& aItem) { // Check that the contact item is a card, own card or ICC entry. const TUid KType = aItem.Type(); if (KType != KUidContactCard && KType != KUidContactOwnCard && KType != KUidContactICCEntry && KType != KUidContactGroup) { return; } // create lists for comm_addrs to keep track of what we have already seen so as to avoid duplicates RArray<TMatch> newPhones; RArray<TPtrC> newEmails; RArray<TPtrC> newSips; CleanupClosePushL(newPhones); CleanupClosePushL(newEmails); CleanupClosePushL(newSips); for (TInt fieldNum = aItem.CardFields().Count() - 1; fieldNum >= 0; --fieldNum) { CContactItemField& currField = aItem.CardFields()[fieldNum]; const CContentType& contType = currField.ContentType(); TBool isPhone(contType.ContainsFieldType(KUidContactFieldPhoneNumber) || contType.ContainsFieldType(KUidContactFieldFax) || contType.ContainsFieldType(KUidContactFieldSms) ); TBool isEmail(contType.ContainsFieldType(KUidContactFieldEMail) ); TBool isSip(contType.ContainsFieldType(KUidContactFieldSIPID) ); // check it's a field we want and that it's not empty // insert a new address only if we haven't already seen it -- no point storing the same one twice. if ((isPhone || isEmail || isSip) && currField.StorageType() == KStorageTypeText && currField.TextStorage()->IsFull() ) { const TContactItemId KItemId(aItem.Id()); // get phone numbers if (isPhone) { TMatch phoneNumber; phoneNumber = CreatePaddedPhoneDigitsL(currField.TextStorage()->Text(), KLowerSevenDigits, KMaxPhoneMatchLength - KLowerSevenDigits); if (newPhones.Find(phoneNumber, TIdentityRelation<TMatch>(&TMatch::Equals) ) == KErrNotFound) { if(contType.ContainsFieldType(KUidContactFieldVCardMapCELL)) { DoPhoneNumWriteOpL(phoneNumber, EInsert, KItemId,EPhoneNumber,EMobileNumber); } else { DoPhoneNumWriteOpL(phoneNumber, EInsert, KItemId); } newPhones.AppendL(phoneNumber); } } // get email addresses else if (isEmail && newEmails.Find(currField.TextStorage()->Text() ) == KErrNotFound) { DoNonPhoneWriteOpL(currField.TextStorage()->Text(), EInsert, KItemId, EEmailAddress); newEmails.AppendL(currField.TextStorage()->Text() ); } // get SIP addresses else if (newSips.Find(currField.TextStorage()->Text() ) == KErrNotFound) { DoNonPhoneWriteOpL(currField.TextStorage()->Text(), EInsert, KItemId, ESipAddress); newSips.AppendL(currField.TextStorage()->Text() ); } } } CleanupStack::PopAndDestroy(3, &newPhones); // and newSips, newEmails }
EXPORT_C void PrintContactL(const TDesC& aFilename, const CContactItem& aContact) { TBuf8<255> buf; TBuf16<100> buf16; RFs fs; User::LeaveIfError(fs.Connect()); CleanupClosePushL(fs); fs.MkDirAll(aFilename); RFile outFile; User::LeaveIfError(outFile.Replace(fs, aFilename, EFileWrite | EFileStreamText)); CleanupClosePushL(outFile); const CMyContact& myContact = reinterpret_cast<const CMyContact&>(aContact); buf.Format(_L8("<table><tr><td>Attributes:</td><td>0x%08x</td></tr>\r\n"), myContact.iAttributes); outFile.Write(buf); buf.Format(_L8("<tr><td>Contact ID:</td><td>%d (%x)</td></tr>\r\n"), myContact.iId, myContact.iId); outFile.Write(buf); buf.Format(_L8("<tr><td>Template Ref ID:</td><td> %d (%x)</td></tr>\r\n"), myContact.iTemplateRefId, myContact.iTemplateRefId); outFile.Write(buf); /* outFile.Write(_L8("<tr><td>Last Modified:</td><td>")); myContact.iLastModified.FormatL(buf16,KDateTimeFormat); buf.Copy(buf16); outFile.Write(buf); outFile.Write(_L8("</td></tr>\r\n")); outFile.Write(_L8("<tr><td>Creation Date:</td><td>")); myContact.iCreationDate.FormatL(buf16,KDateTimeFormat); buf.Copy(buf16); outFile.Write(buf); outFile.Write(_L8("</td></tr>\r\n"));*/ buf.Format(_L8("<tr><td>Access count:</td><td> %d</td></tr>\r\n"), myContact.iTemplateRefId, myContact.iAccessCount); outFile.Write(buf); if (aContact.Type() == KUidContactCard || aContact.Type() == KUidContactGroup || aContact.Type() == KUidContactOwnCard) { const CMyContactPlusGroup& myContactPlusGroup = reinterpret_cast<const CMyContactPlusGroup&>(aContact); PrintIdArrayL(outFile, myContactPlusGroup.iGroups, _L8("Belongs to"), buf); if (aContact.Type() == KUidContactGroup) { const CMyContactGroup& myContactGrp = reinterpret_cast<const CMyContactGroup&>(aContact); PrintIdArrayL(outFile, myContactGrp.iItems, _L8("Contains"), buf); } } outFile.Write(_L8("</table><br/>\r\n")); PrintFieldsTableL(outFile, aContact.CardFields(), buf); CleanupStack::PopAndDestroy(&outFile); CleanupStack::PopAndDestroy(&fs); }
/** Persist the items belonging to curent group into group table @param aGroup referece to a contact group */ void CPplGroupsTable::WriteGroupMembersL(const CContactItem& aGroup) { if (aGroup.Type() != KUidContactGroup) { return; } const TContactItemId KGroupId(aGroup.Id() ); // make sure we clear out any previous, out-of-date data TBool lowDiskErr(EFalse); DeleteItemL(KGroupId, lowDiskErr); if (lowDiskErr) { User::Leave(KErrDiskFull); } // build the RSqlStatement RSqlStatement stmnt; CleanupClosePushL(stmnt); stmnt.PrepareL(iDatabase, iInsertStmnt->SqlStringL() ); const TInt KGroupIdIndex(KFirstIndex); // first parameter in query... const TInt KMemberIdIndex(KGroupIdIndex + 1); // ...and the second parameter // copy and sort the member id array so we can see if there are duplicates const CContactIdArray* contactIdArray = static_cast<const CContactGroup&>(aGroup).ItemsContained(); //does not take the ownership const TInt arrayCount = contactIdArray->Count(); CArrayFixFlat<TContactItemId>* sortedList = new(ELeave) CArrayFixFlat<TContactItemId>(KArrayGranularity); CleanupStack::PushL(sortedList); for(TInt loop = 0;loop < arrayCount; ++loop) { sortedList->AppendL((*contactIdArray)[loop]); } TKeyArrayFix key(0,ECmpTInt); sortedList->Sort(key); // insert the group-member relationships const TInt KCountStmntParamIndex(KFirstIndex); // first and only parameter in query const TInt listLen(sortedList->Count() ); TInt lastId(0); for (TInt i = 0; i < listLen; ++i) { TInt itemId((*sortedList)[i]); //check if a contact item with itemId id really exists in contact database RSqlStatement countStmnt; CleanupClosePushL(countStmnt); countStmnt.PrepareL(iDatabase, iCountContactsStmnt->SqlStringL() ); User::LeaveIfError(countStmnt.BindInt(KCountStmntParamIndex, itemId) ); TInt count = 0; TInt err = KErrNone; if((err = countStmnt.Next() ) == KSqlAtRow) { count = countStmnt.ColumnInt(iCountContactsStmnt->ParameterIndex(KSqlCount) ); } else { User::LeaveIfError(err); } if(count == 0) { User::Leave(KErrNotFound); } CleanupStack::PopAndDestroy(&countStmnt); // only insert this if we haven't already seen it if (itemId != lastId || i == 0) { User::LeaveIfError(stmnt.BindInt(KGroupIdIndex, KGroupId) ); User::LeaveIfError(stmnt.BindInt(KMemberIdIndex, itemId) ); User::LeaveIfError(stmnt.Exec() ); User::LeaveIfError(stmnt.Reset() ); } lastId = itemId; } CleanupStack::PopAndDestroy(2, &stmnt); // and sortedList }
/** Add the given contact item to the database. Forward the call to CPplTableBase based classes representing the tables in the contact database. @param aItem The contact item to be added to the database. @param aSessionId The ID of the session that issued the request. Used to prevent Phonebook Synchroniser deadlock. @return Contact item ID of the contact added to the database. */ TContactItemId CPplContactItemManager::CreateL(CContactItem& aItem, TUint aSessionId) { TBool controlTransaction = !(iTransactionManager.IsTransactionActive()); TBool compressedGuid=EFalse; // If needed generate a gui for the current contact item if (aItem.Guid() == TPtrC(KNullDesC)) { iPreferencePersistor->SetGuidL(aItem, compressedGuid); } if (compressedGuid) { aItem.SetHasCompressedGuid(compressedGuid); } if (aItem.Type() == KUidContactICCEntry) { const TInt ret = iContactProperties.ContactSynchroniserL(aSessionId).ValidateWriteContact(static_cast<CContactICCEntry&>(aItem)); User::LeaveIfError(ret); } if(controlTransaction) { StartTransactionL(aSessionId); } iContactTable->CreateInDbL(aItem); iGroupTable->CreateInDbL(aItem); iCommAddrTable->CreateInDbL(aItem); TContactItemId groupId = iIccContactStore.CreateInDbL(aItem, aSessionId); if(groupId != KNullContactId) { //Every ICC entry is added to a special group, created by the Phonebook //Synchroniser server during the initial synchronisation with the Contacts Model. CContactItemViewDef* itemDef = CContactItemViewDef::NewLC(CContactItemViewDef::EIncludeFields,CContactItemViewDef::EMaskHiddenFields); itemDef->AddL(KUidContactFieldMatchAll); // Add ICC entry to the group. CContactGroup* grp = static_cast<CContactGroup*>(ReadLC(groupId, *itemDef, EPlAllInfo, aSessionId)); grp->AddContactL(aItem.Id()); UpdateL(*grp, aSessionId); CleanupStack::PopAndDestroy(2, itemDef); // grp } if(controlTransaction) { CommitTransactionL(); } // Assuming success if no leaves at this point, so update // the metadata search store for this entry //CCntMetadataOperation* op = CCntMetadataOperation::NewLC(iColSession); //TRAP_IGNORE(op->SaveContactLD(aItem)); //CleanupStack::Pop(op); // Do not destroy - called LD function return aItem.Id(); }