bool CntSimStorePrivate::read(int index, int numSlots, QContactManager::Error *error) { if (IsActive()) { *error = QContactManager::LockedError; return false; } // ON store requires different read approach. // fetch ON contacts synchronously since there are usually only couple of them if (m_storeInfo.m_storeName == KParameterValueSimStoreNameOn) { TRequestStatus status; QList<QContact> fetchedContacts; for (int i = index; i <= numSlots; i++) { RMobileONStore::TMobileONEntryV1 onEntry; onEntry.iIndex = i; RMobileONStore::TMobileONEntryV1Pckg onEntryPkg(onEntry); m_etelOnStore.Read(status, onEntryPkg); User::WaitForRequest(status); if (status.Int() == KErrNone) { QContact c; c.setType(QContactType::TypeContact); QContactName name; name.setCustomLabel(QString::fromUtf16(onEntry.iText.Ptr(), onEntry.iText.Length())); c.saveDetail(&name); QContactPhoneNumber number; number.setNumber(QString::fromUtf16(onEntry.iNumber.iTelNumber.Ptr(), onEntry.iNumber.iTelNumber.Length())); c.saveDetail(&number); QScopedPointer<QContactId> contactId(new QContactId()); contactId->setLocalId(i); contactId->setManagerUri(m_managerUri); c.setId(*contactId); fetchedContacts.append(c); } } emit m_simStore.readComplete(fetchedContacts, QContactManager::NoError); *error = QContactManager::NoError; return true; } // start reading m_buffer.Zero(); m_buffer.ReAlloc(KOneSimContactBufferSize*numSlots); m_etelStore.Read(iStatus, index, numSlots, m_buffer); SetActive(); m_state = ReadState; *error = QContactManager::NoError; return true; }
void SeasideCache::displayLabelOrderChanged() { #ifdef HAS_MLITE QVariant displayLabelOrder = m_displayLabelOrderConf.value(); if (displayLabelOrder.isValid() && displayLabelOrder.toInt() != m_displayLabelOrder) { m_displayLabelOrder = SeasideFilteredModel::DisplayLabelOrder(displayLabelOrder.toInt()); #ifdef SEASIDE_SPARQL_QUERIES m_contactIdRequest.setSortOnFirstName(true); #else QContactSortOrder firstNameOrder; firstNameOrder.setDetailDefinitionName( QContactName::DefinitionName, QContactName::FieldFirstName); firstNameOrder.setCaseSensitivity(Qt::CaseInsensitive); firstNameOrder.setDirection(Qt::AscendingOrder); firstNameOrder.setBlankPolicy(QContactSortOrder::BlanksFirst); QContactSortOrder secondNameOrder; secondNameOrder.setDetailDefinitionName( QContactName::DefinitionName, QContactName::FieldLastName); secondNameOrder.setCaseSensitivity(Qt::CaseInsensitive); secondNameOrder.setDirection(Qt::AscendingOrder); secondNameOrder.setBlankPolicy(QContactSortOrder::BlanksFirst); QList<QContactSortOrder> sorting = m_displayLabelOrder == SeasideFilteredModel::FirstNameFirst ? (QList<QContactSortOrder>() << firstNameOrder << secondNameOrder) : (QList<QContactSortOrder>() << secondNameOrder << firstNameOrder); m_fetchRequest.setSorting(sorting); m_contactIdRequest.setSorting(sorting); #endif typedef QHash<QContactLocalId, SeasideCacheItem>::iterator iterator; for (iterator it = m_people.begin(); it != m_people.begin(); ++it) { if (it->person) { it->person->recalculateDisplayLabel(SeasideProxyModel::DisplayLabelOrder(m_displayLabelOrder)); it->contact = it->person->contact(); } else { QContactName name = it->contact.detail<QContactName>(); name.setCustomLabel(SeasidePerson::generateDisplayLabel(it->contact)); it->contact.saveDetail(&name); } } for (int i = 0; i < SeasideFilteredModel::FilterTypesCount; ++i) { for (int j = 0; j < m_models[i].count(); ++j) m_models[i].at(j)->updateDisplayLabelOrder(); } m_refreshRequired = true; requestUpdate(); } #endif }
/*! Adds contacts in \a newContacts into \a manager, converting categories specified with tags into group membership relationships. Note that this implementation uses the synchronous API of QContactManager for clarity. It is recommended that the asynchronous API is used in practice. Relationships are added so that if a contact, A, has a tag "b", then a HasMember relationship is created between a group contact in the manager, B with display label "b", and contact A. If there does not exist a group contact with display label "b", one is created. */ void insertWithGroups(const QList<QContact>& newContacts, QContactManager* manager) { // Cache map from group names to QContactIds QMap<QString, QContactId> groupMap; foreach (QContact contact, newContacts) { if (!manager->saveContact(&contact)) continue; // In practice, better error handling may be required foreach (const QContactTag& tag, contact.details<QContactTag>()) { QString groupName = tag.tag(); QContactId groupId; if (groupMap.contains(groupName)) { // We've already seen a group with the right name groupId = groupMap.value(groupName); } else { QContactDetailFilter groupFilter; groupFilter.setDetailDefinitionName(QContactType::DefinitionName); groupFilter.setValue(QLatin1String(QContactType::TypeGroup)); groupFilter.setMatchFlags(QContactFilter::MatchExactly); // In practice, some detail other than the display label could be used QContactDetailFilter nameFilter = QContactDisplayLabel::match(groupName); QList<QContactLocalId> matchingGroups = manager->contactIds(groupFilter & nameFilter); if (!matchingGroups.isEmpty()) { // Found an existing group in the manager QContactId groupId; groupId.setManagerUri(manager->managerUri()); groupId.setLocalId(matchingGroups.first()); groupMap.insert(groupName, groupId); } else { // Make a new group QContact groupContact; QContactName name; name.setCustomLabel(groupName); // Beware that not all managers support custom label groupContact.saveDetail(&name); if (!manager->saveContact(&groupContact)) continue; // In practice, better error handling may be required groupId = groupContact.id(); groupMap.insert(groupName, groupId); } } // Add the relationship QContactRelationship rel; rel.setFirst(groupId); rel.setRelationshipType(QContactRelationship::HasMember); rel.setSecond(contact.id()); manager->saveRelationship(&rel); } } }
void SeasidePerson::recalculateDisplayLabel(SeasideProxyModel::DisplayLabelOrder order) { QString oldDisplayLabel = mDisplayLabel; QString newDisplayLabel = generateDisplayLabel(mContact, order); if (oldDisplayLabel != newDisplayLabel) { // Save the display label as the custom label. QContactName name = mContact.detail<QContactName>(); name.setCustomLabel(newDisplayLabel); mContact.saveDetail(&name); mDisplayLabel = newDisplayLabel; emit displayLabelChanged(); } }
void SeasideCache::contactsAvailable() { if (m_fetchFilter == SeasideFilteredModel::FilterFavorites || m_fetchFilter == SeasideFilteredModel::FilterOnline || m_fetchFilter == SeasideFilteredModel::FilterAll) { // Part of an initial query. appendContacts(m_fetchRequest.contacts()); } else { // An update. const QList<QContact> contacts = m_fetchRequest.contacts(); for (int i = m_resultsRead; i < contacts.count(); ++i) { QContact contact = contacts.at(i); SeasideCacheItem &item = m_people[contact.localId()]; QContactName oldName = item.contact.detail<QContactName>(); QContactName newName = contact.detail<QContactName>(); if (newName.customLabel().isEmpty()) { newName.setCustomLabel(oldName.customLabel()); contact.saveDetail(&newName); } const bool roleDataChanged = newName != oldName || contact.detail<QContactAvatar>().imageUrl() != item.contact.detail<QContactAvatar>().imageUrl(); item.contact = contact; item.hasCompleteContact = true; if (item.person) { item.person->setContact(contact); item.person->setComplete(true); } QList<QContactPhoneNumber> phoneNumbers = contact.details<QContactPhoneNumber>(); for (int j = 0; j < phoneNumbers.count(); ++j) { m_phoneNumberIds[phoneNumbers.at(j).number()] = contact.localId(); } if (roleDataChanged) { instance->updateContactData(contact.localId(), SeasideFilteredModel::FilterFavorites); instance->updateContactData(contact.localId(), SeasideFilteredModel::FilterOnline); instance->updateContactData(contact.localId(), SeasideFilteredModel::FilterAll); } } m_resultsRead = contacts.count(); } }
QContactDetail *CntTransformName::transformItemField(const CContactItemField& field, const QContact &contact) { QContactName *name = new QContactName(contact.detail<QContactName>()); CContactTextField* storage = field.TextStorage(); QString nameValue = QString::fromUtf16(storage->Text().Ptr(), storage->Text().Length()); for (int i = 0; i < field.ContentType().FieldTypeCount(); i++) { //Prefix if (field.ContentType().FieldType(i) == KUidContactFieldPrefixName) { name->setPrefix(nameValue); } //First name else if (field.ContentType().FieldType(i) == KUidContactFieldGivenName) { name->setFirstName(nameValue); } //Middle name else if (field.ContentType().FieldType(i) == KUidContactFieldAdditionalName) { name->setMiddleName(nameValue); } //Last name else if (field.ContentType().FieldType(i) == KUidContactFieldFamilyName) { name->setLastName(nameValue); } //Suffix else if (field.ContentType().FieldType(i) == KUidContactFieldSuffixName) { name->setSuffix(nameValue); } // custom label else if (field.ContentType().FieldType(i) == KUidContactFieldTemplateLabel) { name->setCustomLabel(nameValue); } } return name; }
/*! Parses SIM contacts in TLV format. * * \param rawData SIM contacts in TLV format. * \return List of contacts. */ QList<QContact> CntSimStorePrivate::decodeSimContactsL(TDes8& rawData) const { PbkPrintToLog(_L("CntSymbianSimEngine::decodeSimContactsL() - IN")); QList<QContact> fetchedContacts; QContact currentContact; TBuf16<KDataClientBuf> buffer; TPtrC16 bufPtr(buffer); TUint8 tagValue(0); CPhoneBookBuffer::TPhBkTagType dataType; bool isAdditionalNumber = false; CPhoneBookBuffer* pbBuffer = new(ELeave) CPhoneBookBuffer(); CleanupStack::PushL(pbBuffer); pbBuffer->Set(&rawData); pbBuffer->StartRead(); while (pbBuffer->GetTagAndType(tagValue, dataType) == KErrNone) { switch (tagValue) { case RMobilePhoneBookStore::ETagPBAdnIndex: { //save contact's id (SIM card index) and manager's name TUint16 index; if (pbBuffer->GetValue(index) == KErrNone) { QScopedPointer<QContactId> contactId(new QContactId()); contactId->setLocalId(index); contactId->setManagerUri(m_managerUri); currentContact.setId(*contactId); } isAdditionalNumber = false; break; } case RMobilePhoneBookStore::ETagPBTonNpi: { // Note, that TON info can be incorporated into the phone number by Etel // implementation (TSY). E.g. this is the case with Nokia TSY. // Here general case is implemented. // Check number type, we are only interested if it's international or not. // We assume here that ETagPBTonNpi always comes after ETagPBNumber, not before. TUint8 tonNpi; if (pbBuffer->GetValue(tonNpi) == KErrNone) { TUint8 intFlag = (tonNpi & KEtsiTonPosition) >> 4; if (intFlag == 1) { //international number format, append "+" to the last //saved number QList<QContactDetail> phoneNumbers = currentContact.details( QContactPhoneNumber::DefinitionName); if (phoneNumbers.count() > 0) { QContactPhoneNumber lastNumber = static_cast<QContactPhoneNumber>( phoneNumbers.at(phoneNumbers.count() - 1)); QString number = lastNumber.number(); number.insert(0, "+"); lastNumber.setNumber(number); if (m_storeInfo.m_readOnlyAccess) m_engine.setReadOnlyAccessConstraint(&lastNumber); currentContact.saveDetail(&lastNumber); } } } // We have rearched to the end of the number, // invalidate additional number flag. isAdditionalNumber = false; break; } case RMobilePhoneBookStore::ETagPBText: { if (pbBuffer->GetValue(bufPtr) == KErrNone) { if (isAdditionalNumber) { // For additional number bufPtr contains number alpha string, // this is ignored currently } else { // Contact name otherwise QContactName name; QString nameString = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length()); name.setCustomLabel(nameString); if (m_storeInfo.m_readOnlyAccess) m_engine.setReadOnlyAccessConstraint(&name); currentContact.saveDetail(&name); QContactManager::Error error(QContactManager::NoError); m_engine.setContactDisplayLabel(¤tContact, m_engine.synthesizedDisplayLabel(currentContact, &error)); } } break; } case RMobilePhoneBookStore::ETagPBSecondName: { if (pbBuffer->GetValue(bufPtr) == KErrNone) { QContactNickname nickName; QString name = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length()); nickName.setNickname(name); if (m_storeInfo.m_readOnlyAccess) m_engine.setReadOnlyAccessConstraint(&nickName); currentContact.saveDetail(&nickName); } break; } case RMobilePhoneBookStore::ETagPBNumber: { if (pbBuffer->GetValue(bufPtr) == KErrNone) { QContactPhoneNumber phoneNumber; QString number = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length()); phoneNumber.setNumber(number); if (m_storeInfo.m_readOnlyAccess) m_engine.setReadOnlyAccessConstraint(&phoneNumber); currentContact.saveDetail(&phoneNumber); } break; } case RMobilePhoneBookStore::ETagPBAnrStart: { // This tag should precede every additional number entry isAdditionalNumber = true; break; } case RMobilePhoneBookStore::ETagPBEmailAddress: { if (pbBuffer->GetValue(bufPtr) == KErrNone) { QContactEmailAddress email; QString emailAddress = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length()); email.setEmailAddress(emailAddress); if (m_storeInfo.m_readOnlyAccess) m_engine.setReadOnlyAccessConstraint(&email); currentContact.saveDetail(&email); } break; } case RMobilePhoneBookStore::ETagPBNewEntry: { // This signals the end of the entry and is a special case // which will be handled below. break; } default: { // An unsupported field type - just skip this value pbBuffer->SkipValue(dataType); break; } } //switch // save contact to the array of contact to be returned if the whole entry was extracted if ((tagValue == RMobilePhoneBookStore::ETagPBNewEntry && currentContact.localId() > 0) || (pbBuffer->RemainingReadLength() == 0 && currentContact.localId() > 0)) { fetchedContacts.append(currentContact); //clear current contact currentContact.clearDetails(); QScopedPointer<QContactId> contactId(new QContactId()); contactId->setLocalId(0); contactId->setManagerUri(QString()); currentContact.setId(*contactId); } } //while
void TestSymbianEngine::saveContact() { QContactManager::Error err; QList<QContactSortOrder> sortOrders; QContactId empty; QContactFilter defaultFilter = QContactFilter(); int init_count = m_engine->contactIds(defaultFilter, sortOrders, &err).count(); QVERIFY(err == QContactManager::NoError); // Save a "NULL" contact QVERIFY(!m_engine->saveContact(NULL, &err)); QVERIFY(err == QContactManager::BadArgumentError); int current_count = m_engine->contactIds(defaultFilter, sortOrders, &err).count(); QVERIFY(err == QContactManager::NoError); QVERIFY(init_count == current_count); // Save a contact that is not in database QContact invaId; QVERIFY(m_engine->saveContact(&invaId, &err)); // Add to db QVERIFY(err == QContactManager::NoError); QContactId cId = invaId.id(); m_engine->removeContact(invaId.localId(), &err); // Ensure not in db QVERIFY(err == QContactManager::NoError); invaId.setId(cId); QVERIFY(!m_engine->saveContact(&invaId, &err)); // Update non existent contact QVERIFY(err == QContactManager::DoesNotExistError); current_count = m_engine->contactIds(defaultFilter, sortOrders, &err).count(); QVERIFY(err == QContactManager::NoError); QVERIFY(init_count == current_count); QContact alice; alice.setType("Jargon"); // Save a "non contact(Jargon) type" contact QVERIFY(!m_engine->saveContact(&alice, &err)); QVERIFY(err == QContactManager::InvalidDetailError); QVERIFY(alice.id() == empty); QVERIFY(alice.localId() == 0); current_count = m_engine->contactIds(defaultFilter, sortOrders, &err).count(); QVERIFY(err == QContactManager::NoError); QVERIFY(init_count == current_count); // Save a valid contact alice.setType(QContactType::TypeContact); QVERIFY(m_engine->saveContact(&alice, &err)); QVERIFY(err == QContactManager::NoError); QVERIFY(alice.id() != empty); QVERIFY(alice.localId() != 0); QString uri = QString(QLatin1String(CNT_SYMBIAN_MANAGER_NAME)); QVERIFY(alice.id().managerUri().contains(uri, Qt::CaseInsensitive)); current_count = m_engine->contactIds(defaultFilter, sortOrders, &err).count(); QVERIFY(err == QContactManager::NoError); QVERIFY(init_count + 1 == current_count); // Save a valid contact QContact g; g.setType(QContactType::TypeGroup); QContactName en; en.setCustomLabel("ccc"); QVERIFY(g.saveDetail(&en)); QVERIFY(m_engine->saveContact(&g, &err)); QVERIFY(err == QContactManager::NoError); QVERIFY(g.id() != empty); QVERIFY(g.localId() != 0); QVERIFY(g.id().managerUri().contains(uri, Qt::CaseInsensitive)); }