43 #include "qversitcontactimporter_p.h" |
43 #include "qversitcontactimporter_p.h" |
44 #include "qversitdocument.h" |
44 #include "qversitdocument.h" |
45 #include "qversitproperty.h" |
45 #include "qversitproperty.h" |
46 #include "qmobilityglobal.h" |
46 #include "qmobilityglobal.h" |
47 |
47 |
|
48 #include <qcontactmanagerengine.h> |
48 #include <qcontact.h> |
49 #include <qcontact.h> |
49 #include <qcontactdetail.h> |
50 #include <qcontactdetail.h> |
50 #include <qcontactname.h> |
51 #include <qcontactname.h> |
51 #include <qcontactphonenumber.h> |
52 #include <qcontactphonenumber.h> |
52 #include <qcontactaddress.h> |
53 #include <qcontactaddress.h> |
120 } |
123 } |
121 |
124 |
122 /*! |
125 /*! |
123 * Generates a QContact from \a versitDocument. |
126 * Generates a QContact from \a versitDocument. |
124 */ |
127 */ |
125 QContact QVersitContactImporterPrivate::importContact( |
128 bool QVersitContactImporterPrivate::importContact( |
126 const QVersitDocument& document, int contactIndex) |
129 const QVersitDocument& document, int contactIndex, QContact* contact, |
127 { |
130 QVersitContactImporter::Error* error) |
128 QContact contact; |
131 { |
|
132 if (document.type() != QVersitDocument::VCard21Type |
|
133 && document.type() != QVersitDocument::VCard30Type) { |
|
134 *error = QVersitContactImporter::InvalidDocumentError; |
|
135 return false; |
|
136 } |
129 const QList<QVersitProperty> properties = document.properties(); |
137 const QList<QVersitProperty> properties = document.properties(); |
|
138 if (properties.size() == 0) { |
|
139 *error = QVersitContactImporter::EmptyDocumentError; |
|
140 return false; |
|
141 } |
|
142 |
130 // First, do the properties with PREF set so they appear first in the contact details |
143 // First, do the properties with PREF set so they appear first in the contact details |
131 foreach (const QVersitProperty& property, properties) { |
144 foreach (const QVersitProperty& property, properties) { |
132 if (property.parameters().contains(QLatin1String("TYPE"), QLatin1String("PREF"))) |
145 if (property.parameters().contains(QLatin1String("TYPE"), QLatin1String("PREF"))) |
133 importProperty(document, property, contactIndex, &contact); |
146 importProperty(document, property, contactIndex, contact); |
134 } |
147 } |
135 // ... then, do the rest of the properties. |
148 // ... then, do the rest of the properties. |
136 foreach (const QVersitProperty& property, properties) { |
149 foreach (const QVersitProperty& property, properties) { |
137 if (!property.parameters().contains(QLatin1String("TYPE"), QLatin1String("PREF"))) |
150 if (!property.parameters().contains(QLatin1String("TYPE"), QLatin1String("PREF"))) |
138 importProperty(document, property, contactIndex, &contact); |
151 importProperty(document, property, contactIndex, contact); |
139 } |
152 } |
140 |
153 |
141 contact.setType(QContactType::TypeContact); |
154 contact->setType(QContactType::TypeContact); |
142 return contact; |
155 QContactManagerEngine::setContactDisplayLabel(contact, QVersitContactImporterPrivate::synthesizedDisplayLabel(*contact)); |
|
156 return true; |
143 } |
157 } |
144 |
158 |
145 void QVersitContactImporterPrivate::importProperty( |
159 void QVersitContactImporterPrivate::importProperty( |
146 const QVersitDocument& document, const QVersitProperty& property, int contactIndex, |
160 const QVersitDocument& document, const QVersitProperty& property, int contactIndex, |
147 QContact* contact) const |
161 QContact* contact) const |
164 success = createGeoLocation(property, contact); |
178 success = createGeoLocation(property, contact); |
165 } else if (detailDefinitionName == QContactOrganization::DefinitionName) { |
179 } else if (detailDefinitionName == QContactOrganization::DefinitionName) { |
166 success = createOrganization(property, contact); |
180 success = createOrganization(property, contact); |
167 } else if (detailDefinitionName == QContactNickname::DefinitionName) { |
181 } else if (detailDefinitionName == QContactNickname::DefinitionName) { |
168 success = createNicknames(property, contact); |
182 success = createNicknames(property, contact); |
169 } else if (detailDefinitionName == QContactAvatar::DefinitionName) { |
183 } else if (detailDefinitionName == QContactRingtone::DefinitionName) { |
170 success = createAvatar(property,detailDefinition.second, contact); |
184 success = createRingtone(property, contact); |
|
185 } else if (detailDefinitionName == QContactThumbnail::DefinitionName) { |
|
186 success = createThumbnail(property, contact); |
171 } else if (detailDefinitionName == QContactTimestamp::DefinitionName) { |
187 } else if (detailDefinitionName == QContactTimestamp::DefinitionName) { |
172 success = createTimeStamp(property, contact); |
188 success = createTimeStamp(property, contact); |
173 } else if (detailDefinitionName == QContactPhoneNumber::DefinitionName) { |
189 } else if (detailDefinitionName == QContactPhoneNumber::DefinitionName) { |
174 success = createPhone(property, contact); |
190 success = createPhone(property, contact); |
175 } else if (detailDefinitionName == QContactAnniversary::DefinitionName) { |
191 } else if (detailDefinitionName == QContactAnniversary::DefinitionName) { |
176 success = createAnniversary(property, contact); |
192 success = createAnniversary(property, contact); |
177 } else if (detailDefinitionName == QContactFamily::DefinitionName) { |
193 } else if (detailDefinitionName == QContactFamily::DefinitionName) { |
178 success = createFamily(property, contact); |
194 success = createFamily(property, contact); |
179 } else if (detailDefinitionName == QContactOnlineAccount::DefinitionName) { |
195 } else if (detailDefinitionName == QContactOnlineAccount::DefinitionName) { |
180 success = createOnlineAccount(property, contact); |
196 success = createOnlineAccount(property, contact); |
|
197 } else if (detailDefinitionName == QContactTag::DefinitionName) { |
|
198 success = createTags(property, contact); |
181 } else if (detailDefinitionName == QContactDisplayLabel::DefinitionName) { |
199 } else if (detailDefinitionName == QContactDisplayLabel::DefinitionName) { |
182 // This actually sets the QContactName's customLabel field (not QContactDisplayLabel) |
200 // This actually sets the QContactName's customLabel field (not QContactDisplayLabel) |
183 success = createLabel(property, contact); |
201 success = createCustomLabel(property, contact); |
184 } else { |
202 } else { |
185 // Look up mDetailMappings for a simple mapping from property to detail. |
203 // Look up mDetailMappings for a simple mapping from property to detail. |
186 success = createNameValueDetail(property, contact); |
204 success = createNameValueDetail(property, contact); |
187 } |
205 } |
188 |
206 |
197 { |
215 { |
198 QContactName name; |
216 QContactName name; |
199 QContactDetail detail = contact->detail(QContactName::DefinitionName); |
217 QContactDetail detail = contact->detail(QContactName::DefinitionName); |
200 if (!detail.isEmpty()) { |
218 if (!detail.isEmpty()) { |
201 // If multiple name properties exist, |
219 // If multiple name properties exist, |
202 // discard all except the first occurence |
220 // discard all except the first occurrence |
203 if (!detail.value(QContactName::FieldFirstName).isEmpty()) |
221 if (!detail.value(QContactName::FieldFirstName).isEmpty()) |
204 return false; |
222 return false; |
205 else |
223 else |
206 name = QContactName(static_cast<QContactName>(detail)); |
224 name = QContactName(static_cast<QContactName>(detail)); |
207 } |
225 } |
208 |
226 |
209 QStringList values = property.value().split(QLatin1Char(';')); |
227 QVariant variant = property.variantValue(); |
|
228 if (property.valueType() != QVersitProperty::CompoundType |
|
229 || variant.type() != QVariant::StringList) |
|
230 return false; |
|
231 QStringList values = variant.toStringList(); |
210 name.setLastName(takeFirst(values)); |
232 name.setLastName(takeFirst(values)); |
211 name.setFirstName(takeFirst(values)); |
233 name.setFirstName(takeFirst(values)); |
212 name.setMiddleName(takeFirst(values)); |
234 name.setMiddleName(takeFirst(values)); |
213 name.setPrefix(takeFirst(values)); |
235 name.setPrefix(takeFirst(values)); |
214 name.setSuffix(takeFirst(values)); |
236 name.setSuffix(takeFirst(values)); |
237 bool QVersitContactImporterPrivate::createAddress( |
259 bool QVersitContactImporterPrivate::createAddress( |
238 const QVersitProperty& property, QContact* contact) const |
260 const QVersitProperty& property, QContact* contact) const |
239 { |
261 { |
240 QContactAddress address; |
262 QContactAddress address; |
241 |
263 |
242 QStringList addressParts = property.value().split(QLatin1Char(';')); |
264 QVariant variant = property.variantValue(); |
|
265 if (property.valueType() != QVersitProperty::CompoundType |
|
266 || variant.type() != QVariant::StringList) |
|
267 return false; |
|
268 QStringList addressParts = variant.toStringList(); |
243 address.setPostOfficeBox(takeFirst(addressParts)); |
269 address.setPostOfficeBox(takeFirst(addressParts)); |
244 // There is no setter for the Extended Address in QContactAddress: |
270 // There is no setter for the Extended Address in QContactAddress: |
245 if (!addressParts.isEmpty()) |
271 if (!addressParts.isEmpty()) |
246 addressParts.removeFirst(); |
272 addressParts.removeFirst(); |
247 address.setStreet(takeFirst(addressParts)); |
273 address.setStreet(takeFirst(addressParts)); |
264 QContactOrganization organization; |
290 QContactOrganization organization; |
265 QPair<QString,QString> detailNameAndFieldName = |
291 QPair<QString,QString> detailNameAndFieldName = |
266 mDetailMappings.value(property.name()); |
292 mDetailMappings.value(property.name()); |
267 QString fieldName = detailNameAndFieldName.second; |
293 QString fieldName = detailNameAndFieldName.second; |
268 QList<QContactOrganization> organizations = contact->details<QContactOrganization>(); |
294 QList<QContactOrganization> organizations = contact->details<QContactOrganization>(); |
269 foreach(QContactOrganization current, organizations) { |
295 foreach(const QContactOrganization& current, organizations) { |
270 if (current.value(fieldName).length() == 0) { |
296 if (current.value(fieldName).length() == 0) { |
271 organization = current; |
297 organization = current; |
272 break; |
298 break; |
273 } |
299 } |
274 } |
300 } |
276 setOrganizationNames(organization, property); |
302 setOrganizationNames(organization, property); |
277 } else if (fieldName == QContactOrganization::FieldTitle) { |
303 } else if (fieldName == QContactOrganization::FieldTitle) { |
278 organization.setTitle(property.value()); |
304 organization.setTitle(property.value()); |
279 } else if (fieldName == QContactOrganization::FieldRole) { |
305 } else if (fieldName == QContactOrganization::FieldRole) { |
280 organization.setRole(property.value()); |
306 organization.setRole(property.value()); |
281 } else if (fieldName == QContactOrganization::FieldLogo) { |
307 } else if (fieldName == QContactOrganization::FieldLogoUrl) { |
282 setOrganizationLogo(organization, property); |
308 setOrganizationLogo(organization, property); |
283 } else if (fieldName == QContactOrganization::FieldAssistantName) { |
309 } else if (fieldName == QContactOrganization::FieldAssistantName) { |
284 organization.setAssistantName(property.value()); |
310 organization.setAssistantName(property.value()); |
285 } else { |
311 } else { |
286 return false; |
312 return false; |
294 * Set the organization name and department(s) from \a property. |
320 * Set the organization name and department(s) from \a property. |
295 */ |
321 */ |
296 void QVersitContactImporterPrivate::setOrganizationNames( |
322 void QVersitContactImporterPrivate::setOrganizationNames( |
297 QContactOrganization& organization, const QVersitProperty& property) const |
323 QContactOrganization& organization, const QVersitProperty& property) const |
298 { |
324 { |
299 QString value = property.value(); |
325 QVariant variant = property.variantValue(); |
300 int firstSemicolon = value.indexOf(QLatin1Char(';')); |
326 if (property.valueType() == QVersitProperty::CompoundType |
301 if (firstSemicolon >= 0) { |
327 && variant.type() == QVariant::StringList) { |
302 organization.setName(value.left(firstSemicolon)); |
328 QStringList values = variant.toStringList(); |
303 QString departmentsStr(value.mid(firstSemicolon+1)); |
329 organization.setName(takeFirst(values)); |
304 QStringList departments = |
330 organization.setDepartment(values); |
305 departmentsStr.split(QLatin1Char(';'), QString::SkipEmptyParts); |
|
306 organization.setDepartment(departments); |
|
307 } else { |
|
308 organization.setName(value); |
|
309 } |
331 } |
310 } |
332 } |
311 |
333 |
312 /*! |
334 /*! |
313 * Set the organization logo from \a property. |
335 * Set the organization logo from \a property. |
377 * Creates QContactNicknames from \a property and adds them to \a contact |
399 * Creates QContactNicknames from \a property and adds them to \a contact |
378 */ |
400 */ |
379 bool QVersitContactImporterPrivate::createNicknames( |
401 bool QVersitContactImporterPrivate::createNicknames( |
380 const QVersitProperty& property, QContact* contact) const |
402 const QVersitProperty& property, QContact* contact) const |
381 { |
403 { |
382 QStringList values = property.value().split(QLatin1Char(','), QString::SkipEmptyParts); |
404 QVariant variant = property.variantValue(); |
|
405 if (property.valueType() != QVersitProperty::ListType |
|
406 || variant.type() != QVariant::StringList) |
|
407 return false; |
|
408 QStringList values = variant.toStringList(); |
383 QStringList contexts = extractContexts(property); |
409 QStringList contexts = extractContexts(property); |
384 foreach(QString value, values) { |
410 foreach(const QString& value, values) { |
385 QContactNickname nickName; |
411 QContactNickname nickName; |
386 nickName.setNickname(value); |
412 nickName.setNickname(value); |
387 saveDetailWithContext(contact, &nickName, extractContexts(property)); |
413 saveDetailWithContext(contact, &nickName, contexts); |
|
414 } |
|
415 return true; |
|
416 } |
|
417 |
|
418 /*! |
|
419 * Creates QContactTags from \a property and adds them to \a contact |
|
420 */ |
|
421 bool QVersitContactImporterPrivate::createTags( |
|
422 const QVersitProperty& property, QContact* contact) const |
|
423 { |
|
424 QVariant variant = property.variantValue(); |
|
425 if (property.valueType() != QVersitProperty::ListType |
|
426 || variant.type() != QVariant::StringList) |
|
427 return false; |
|
428 QStringList values = variant.toStringList(); |
|
429 QStringList contexts = extractContexts(property); |
|
430 foreach(const QString& value, values) { |
|
431 QContactTag tag; |
|
432 tag.setTag(value); |
|
433 saveDetailWithContext(contact, &tag, contexts); |
388 } |
434 } |
389 return true; |
435 return true; |
390 } |
436 } |
391 |
437 |
392 /*! |
438 /*! |
414 |
460 |
415 saveDetailWithContext(contact, &onlineAccount, extractContexts(property)); |
461 saveDetailWithContext(contact, &onlineAccount, extractContexts(property)); |
416 return true; |
462 return true; |
417 } |
463 } |
418 |
464 |
419 /*! |
465 bool QVersitContactImporterPrivate::createRingtone(const QVersitProperty &property, |
420 * Creates a QContactAvatar from \a property |
466 QContact *contact) const |
421 */ |
|
422 bool QVersitContactImporterPrivate::createAvatar( |
|
423 const QVersitProperty& property, const QString& subType, QContact* contact) const |
|
424 { |
467 { |
425 QString location; |
468 QString location; |
426 QByteArray data; |
469 QByteArray data; |
427 if (!(saveDataFromProperty(property, &location, &data))) |
470 if (saveDataFromProperty(property, &location, &data) && !location.isEmpty()) { |
428 return false; |
471 QContactRingtone ringtone; |
429 |
472 ringtone.setAudioRingtoneUrl(location); |
430 QContactAvatar avatar; |
473 saveDetailWithContext(contact, &ringtone, extractContexts(property)); |
431 if (!location.isEmpty()) |
474 return true; |
432 avatar.setAvatar(location); |
475 } |
433 // Creating a pixmap in a non-GUI thread crashes on S60. |
476 return false; |
434 // XXX reenable this when the QtContacts stores QImages. |
477 } |
435 // if (subType == QContactAvatar::SubTypeImage && !data.isEmpty()) { |
478 |
436 // QPixmap pixmap; |
479 /*! |
437 // if (pixmap.loadFromData(data)) |
480 * Creates a QContactAvatar from \a property |
438 // avatar.setPixmap(pixmap); |
481 */ |
439 // } |
482 bool QVersitContactImporterPrivate::createThumbnail( |
440 avatar.setSubType(subType); |
483 const QVersitProperty& property, QContact* contact) const |
441 |
484 { |
442 saveDetailWithContext(contact, &avatar, extractContexts(property)); |
485 QString location; |
443 return true; |
486 QByteArray data; |
|
487 bool success = false; |
|
488 |
|
489 if (saveDataFromProperty(property, &location, &data) && !location.isEmpty()) { |
|
490 QContactAvatar avatar; |
|
491 avatar.setImageUrl(location); |
|
492 saveDetailWithContext(contact, &avatar, extractContexts(property)); |
|
493 success = true; |
|
494 } |
|
495 if (!data.isEmpty()) { |
|
496 QImage image; |
|
497 if (image.loadFromData(data)) { |
|
498 QContactThumbnail thumbnail = contact->detail<QContactThumbnail>(); |
|
499 // In the case of multiple thumbnails, pick the smallest one. |
|
500 if (thumbnail.isEmpty() || image.byteCount() < thumbnail.thumbnail().byteCount()) { |
|
501 thumbnail.setThumbnail(image); |
|
502 } |
|
503 saveDetailWithContext(contact, &thumbnail, extractContexts(property)); |
|
504 success = true; |
|
505 } |
|
506 } |
|
507 |
|
508 return success; |
444 } |
509 } |
445 |
510 |
446 /*! |
511 /*! |
447 * Creates a QContactGeoLocation from \a property |
512 * Creates a QContactGeoLocation from \a property |
448 */ |
513 */ |
449 bool QVersitContactImporterPrivate::createGeoLocation( |
514 bool QVersitContactImporterPrivate::createGeoLocation( |
450 const QVersitProperty& property, QContact* contact) const |
515 const QVersitProperty& property, QContact* contact) const |
451 { |
516 { |
452 QContactGeoLocation geo; |
517 QContactGeoLocation geo; |
453 QStringList values = property.value().split(QLatin1Char(',')); |
518 QVariant variant = property.variantValue(); |
|
519 if (property.valueType() != QVersitProperty::CompoundType |
|
520 || variant.type() != QVariant::StringList) |
|
521 return false; |
|
522 QStringList values = variant.toStringList(); |
454 geo.setLongitude(takeFirst(values).toDouble()); |
523 geo.setLongitude(takeFirst(values).toDouble()); |
455 geo.setLatitude(takeFirst(values).toDouble()); |
524 geo.setLatitude(takeFirst(values).toDouble()); |
456 |
525 |
457 saveDetailWithContext(contact, &geo, extractContexts(property)); |
526 saveDetailWithContext(contact, &geo, extractContexts(property)); |
458 return true; |
527 return true; |
467 QString val = property.value(); |
536 QString val = property.value(); |
468 QContactFamily family = contact->detail<QContactFamily>(); |
537 QContactFamily family = contact->detail<QContactFamily>(); |
469 if (property.name() == QLatin1String("X-SPOUSE")) { |
538 if (property.name() == QLatin1String("X-SPOUSE")) { |
470 family.setSpouse(val); |
539 family.setSpouse(val); |
471 } else if (property.name() == QLatin1String("X-CHILDREN")) { |
540 } else if (property.name() == QLatin1String("X-CHILDREN")) { |
472 family.setChildren(val.split(QLatin1String(","))); |
541 QVariant variant = property.variantValue(); |
|
542 if (property.valueType() != QVersitProperty::ListType |
|
543 || variant.type() != QVariant::StringList) |
|
544 return false; |
|
545 QStringList values = variant.toStringList(); |
|
546 family.setChildren(values); |
473 } |
547 } |
474 |
548 |
475 saveDetailWithContext(contact, &family, extractContexts(property)); |
549 saveDetailWithContext(contact, &family, extractContexts(property)); |
476 return true; |
550 return true; |
477 } |
551 } |
519 const QVersitProperty& property) const |
593 const QVersitProperty& property) const |
520 { |
594 { |
521 QStringList types = |
595 QStringList types = |
522 property.parameters().values(QLatin1String("TYPE")); |
596 property.parameters().values(QLatin1String("TYPE")); |
523 QStringList contexts; |
597 QStringList contexts; |
524 foreach (QString type, types) { |
598 foreach (const QString& type, types) { |
525 QString value = mContextMappings.value(type); |
599 QString value = mContextMappings.value(type); |
526 if (value.length() > 0) |
600 if (value.length() > 0) |
527 contexts.append(value); |
601 contexts.append(value); |
528 } |
602 } |
529 return contexts; |
603 return contexts; |
618 { |
692 { |
619 if (!contexts.isEmpty()) |
693 if (!contexts.isEmpty()) |
620 detail->setContexts(contexts); |
694 detail->setContexts(contexts); |
621 contact->saveDetail(detail); |
695 contact->saveDetail(detail); |
622 } |
696 } |
|
697 |
|
698 /*! Synthesize the display label from the name of the contact, or, failing that, the nickname of |
|
699 the contact, or failing that, the organisation of the contact. |
|
700 Returns the synthesized display label. |
|
701 */ |
|
702 QString QVersitContactImporterPrivate::synthesizedDisplayLabel(const QContact& contact) |
|
703 { |
|
704 /* XXX This is copied and modified from QContactManagerEngine. This should be made a public |
|
705 static function in QCME and called here */ |
|
706 QList<QContactName> allNames = contact.details<QContactName>(); |
|
707 |
|
708 const QLatin1String space(" "); |
|
709 |
|
710 // synthesize the display label from the name. |
|
711 foreach (const QContactName& name, allNames) { |
|
712 if (!name.customLabel().isEmpty()) { |
|
713 // default behaviour is to allow the user to define a custom display label. |
|
714 return name.customLabel(); |
|
715 } |
|
716 |
|
717 QString result; |
|
718 if (!name.value(QContactName::FieldPrefix).trimmed().isEmpty()) { |
|
719 result += name.value(QContactName::FieldPrefix); |
|
720 } |
|
721 if (!name.value(QContactName::FieldFirstName).trimmed().isEmpty()) { |
|
722 if (!result.isEmpty()) |
|
723 result += space; |
|
724 result += name.value(QContactName::FieldFirstName); |
|
725 } |
|
726 if (!name.value(QContactName::FieldMiddleName).trimmed().isEmpty()) { |
|
727 if (!result.isEmpty()) |
|
728 result += space; |
|
729 result += name.value(QContactName::FieldMiddleName); |
|
730 } |
|
731 if (!name.value(QContactName::FieldLastName).trimmed().isEmpty()) { |
|
732 if (!result.isEmpty()) |
|
733 result += space; |
|
734 result += name.value(QContactName::FieldLastName); |
|
735 } |
|
736 if (!name.value(QContactName::FieldSuffix).trimmed().isEmpty()) { |
|
737 if (!result.isEmpty()) |
|
738 result += space; |
|
739 result += name.value(QContactName::FieldSuffix); |
|
740 } |
|
741 if (!result.isEmpty()) |
|
742 return result; |
|
743 } |
|
744 |
|
745 QList<QContactNickname> allNicknames = contact.details<QContactNickname>(); |
|
746 foreach (const QContactNickname& nickname, allNicknames) { |
|
747 if (!nickname.nickname().isEmpty()) |
|
748 return nickname.nickname(); |
|
749 } |
|
750 |
|
751 /* Well, we had no non empty names. if we have orgs, fall back to those */ |
|
752 QList<QContactOrganization> allOrgs = contact.details<QContactOrganization>(); |
|
753 foreach (const QContactOrganization& org, allOrgs) { |
|
754 if (!org.name().isEmpty()) |
|
755 return org.name(); |
|
756 } |
|
757 |
|
758 return QString(); |
|
759 } |