87
QVariantMap ContactMatcher::contactInfo(const QString &accountId, const QString &identifier)
88
* \brief Returns the contact information for the given \param identifier, taking into account
89
* the addressable fields of the given \param accountId.
90
* If \param synchronous is specified, a blocking synchronous request will be made to the contact
91
* manager to return the specified data.
93
* Note that synchronous requests should only be placed after \ref TelepathyHelper is ready.
95
QVariantMap ContactMatcher::contactInfo(const QString &accountId, const QString &identifier, bool synchronous)
89
97
InternalContactMap &internalMap = mContactMap[accountId];
93
101
return internalMap[identifier];
96
// now if there was no string match, try phone number matching if the account supports phone numbers
97
if (addressableFields(accountId).contains("tel")) {
98
Q_FOREACH(const QString &key, internalMap.keys()) {
99
if (PhoneUtils::comparePhoneNumbers(key, identifier)) {
100
return internalMap[key];
105
105
// and if there was no match, asynchronously request the info, and return an empty map for now
106
106
if (TelepathyHelper::instance()->ready()) {
107
requestContactInfo(accountId, identifier);
107
map = requestContactInfo(accountId, identifier, synchronous);
108
} else if (!synchronous) {
109
109
RequestInfo info{accountId, identifier};
110
110
mPendingRequests.append(info);
113
112
map[History::FieldIdentifier] = identifier;
113
map[History::FieldAccountId] = accountId;
114
114
mContactMap[accountId][identifier] = map;
118
QVariantList ContactMatcher::contactInfo(const QString &accountId, const QStringList &identifiers)
118
QVariantList ContactMatcher::contactInfo(const QString &accountId, const QStringList &identifiers, bool synchronous)
120
120
QVariantList contacts;
121
121
Q_FOREACH(const QString &identifier, identifiers) {
122
contacts << contactInfo(accountId, identifier);
122
contacts << contactInfo(accountId, identifier, synchronous);
127
void ContactMatcher::watchIdentifier(const QString &accountId, const QString &identifier, const QVariantMap ¤tInfo)
129
// only add the identifier to the map of watched identifiers
130
QVariantMap map = currentInfo;
131
map[History::FieldIdentifier] = identifier;
132
mContactMap[accountId][identifier] = map;
127
135
void ContactMatcher::onContactsAdded(QList<QContactId> ids)
129
137
QList<QContact> contacts = mManager->contacts(ids);
140
148
for (; it2 != end2; ++it2) {
141
149
QString identifier = it2.key();
142
150
// skip entries that already have a match
143
if (it2.value().contains(History::FieldContactId)) {
151
if (hasMatch(it2.value())) {
147
155
// now for each entry not populated, check if it matches one of the newly added contacts
148
156
Q_FOREACH(const QContact &contact, contacts) {
149
if (matchAndUpdate(accountId, identifier, contact)) {
157
QVariantMap map = matchAndUpdate(accountId, identifier, contact);
174
183
QString identifier = it2.key();
176
185
Q_FOREACH(const QContact &contact, contacts) {
177
bool previousMatch = (contactInfo[History::FieldContactId].toString() == contact.id().toString());
178
if (matchAndUpdate(accountId, identifier, contact)) {
186
bool previousMatch = (contactInfo.contains(History::FieldContactId) &&
187
contactInfo[History::FieldContactId].toString() == contact.id().toString());
188
QVariantMap map = matchAndUpdate(accountId, identifier, contact);
180
191
} else if (previousMatch) {
181
192
// if there was a previous match but it does not match anymore, try to match the phone number
207
218
QStringList identifiersToMatch;
209
220
for (; it2 != end2; ++it2) {
221
QVariantMap &info = it2.value();
210
222
// skip entries that didn't have a match
211
if (!it2.value().contains(History::FieldContactId)) {
223
if (!hasMatch(info)) {
215
227
Q_FOREACH(const QContactId &id, ids) {
216
if (id.toString() == it2.value()[History::FieldContactId].toString()) {
228
if (id.toString() == info[History::FieldContactId].toString()) {
217
229
identifiersToMatch << it2.key();
245
257
QVariantMap info;
246
258
info[History::FieldIdentifier] = identifier;
247
259
Q_EMIT contactInfoChanged(accountId, identifier, info);
260
requestContactInfo(accountId, identifier);
280
void ContactMatcher::requestContactInfo(const QString &accountId, const QString &identifier)
294
* \brief Requests contact info, and if the preference is for a synchronous request returns the contact information in a
295
* QVariantMap. For asynchronous requests, an empty QVariantMap is returned.
297
QVariantMap ContactMatcher::requestContactInfo(const QString &accountId, const QString &identifier, bool synchronous)
282
299
QStringList addressableVCardFields = addressableFields(accountId);
283
300
if (addressableVCardFields.isEmpty()) {
284
301
// FIXME: add support for generic accounts
302
return QVariantMap();
288
305
bool phoneCompare = addressableVCardFields.contains("tel");
290
// check if there is a request already going on for the given contact
291
Q_FOREACH(const RequestInfo &info, mRequests.values()) {
292
if (info.accountId != accountId) {
293
// skip to the next item
297
if (info.identifier == identifier ||
298
phoneCompare && PhoneUtils::comparePhoneNumbers(info.identifier, identifier)) {
299
// if so, just wait for it to finish
304
QContactFetchRequest *request = new QContactFetchRequest(this);
305
307
QContactFetchHint hint;
306
308
hint.setMaxCountHint(1);
307
309
// FIXME: maybe we need to fetch the full contact?
309
311
<< QContactDetail::TypePhoneNumber
310
312
<< QContactDetail::TypeAvatar
311
313
<< QContactDetail::TypeExtendedDetail);
312
request->setFetchHint(hint);
314
315
QContactUnionFilter topLevelFilter;
315
316
Q_FOREACH(const QString &field, addressableVCardFields) {
339
request->setFilter(topLevelFilter);
340
request->setManager(mManager);
342
SIGNAL(stateChanged(QContactAbstractRequest::State)),
343
SLOT(onRequestStateChanged(QContactAbstractRequest::State)));
346
info.accountId = accountId;
347
info.identifier = identifier;
348
mRequests[request] = info;
341
QList<QContact> contacts = mManager->contacts(topLevelFilter, QList<QContactSortOrder>(), hint);
342
if (contacts.isEmpty()) {
343
return QVariantMap();
345
// for synchronous requests, return the results right away.
346
return matchAndUpdate(accountId, identifier, contacts.first());
348
// check if there is a request already going on for the given contact
349
Q_FOREACH(const RequestInfo &info, mRequests.values()) {
350
if (info.accountId != accountId) {
351
// skip to the next item
355
if (info.identifier == identifier) {
356
// if so, just wait for it to finish
357
return QVariantMap();
361
QContactFetchRequest *request = new QContactFetchRequest(this);
362
request->setFetchHint(hint);
363
request->setFilter(topLevelFilter);
364
request->setManager(mManager);
366
SIGNAL(stateChanged(QContactAbstractRequest::State)),
367
SLOT(onRequestStateChanged(QContactAbstractRequest::State)));
370
info.accountId = accountId;
371
info.identifier = identifier;
372
mRequests[request] = info;
375
return QVariantMap();
352
378
QVariantList ContactMatcher::toVariantList(const QList<int> &list)
358
384
return variantList;
361
bool ContactMatcher::matchAndUpdate(const QString &accountId, const QString &identifier, const QContact &contact)
388
* \brief Matches contact data against the given identifier. If the match succeeds, return the updated data in a
389
* QVariantMap, returns an empty map otherwise.
391
QVariantMap ContactMatcher::matchAndUpdate(const QString &accountId, const QString &identifier, const QContact &contact)
393
QVariantMap contactInfo;
394
contactInfo[History::FieldIdentifier] = identifier;
395
contactInfo[History::FieldAccountId] = accountId;
363
397
if (contact.isEmpty()) {
367
401
QStringList fields = addressableFields(accountId);
368
QVariantMap contactInfo;
369
402
bool match = false;
404
int fieldsCount = fields.count();
371
405
Q_FOREACH(const QString &field, fields) {
372
406
if (field == "tel") {
373
Q_FOREACH(const QContactPhoneNumber number, contact.details(QContactDetail::TypePhoneNumber)) {
407
QList<QContactDetail> details = contact.details(QContactDetail::TypePhoneNumber);
408
Q_FOREACH(const QContactPhoneNumber number, details) {
374
409
if (PhoneUtils::comparePhoneNumbers(number.number(), identifier)) {
375
410
QVariantMap detailProperties;
376
411
detailProperties["phoneSubTypes"] = toVariantList(number.subTypes());
400
contactInfo[History::FieldIdentifier] = identifier;
401
435
contactInfo[History::FieldContactId] = contact.id().toString();
402
436
contactInfo[History::FieldAlias] = QContactDisplayLabel(contact.detail(QContactDetail::TypeDisplayLabel)).label();
403
437
contactInfo[History::FieldAvatar] = QContactAvatar(contact.detail(QContactDetail::TypeAvatar)).imageUrl().toString();