159 } else if (detail.definitionName() == QContactNote::DefinitionName) { |
165 } else if (detail.definitionName() == QContactNote::DefinitionName) { |
160 encodeNote(property, detail); |
166 encodeNote(property, detail); |
161 } else if (detail.definitionName() == QContactOrganization::DefinitionName) { |
167 } else if (detail.definitionName() == QContactOrganization::DefinitionName) { |
162 encodeOrganization(document, detail); |
168 encodeOrganization(document, detail); |
163 addProperty = false; |
169 addProperty = false; |
|
170 } else if (detail.definitionName() == QContactRingtone::DefinitionName) { |
|
171 addProperty = encodeRingtone(property, detail); |
|
172 } else if (detail.definitionName() == QContactThumbnail::DefinitionName) { |
|
173 addProperty = encodeThumbnail(property, detail); |
|
174 if (!addProperty) |
|
175 unknown = true; |
164 } else if (detail.definitionName() == QContactAvatar::DefinitionName){ |
176 } else if (detail.definitionName() == QContactAvatar::DefinitionName){ |
165 addProperty = encodeAvatar(property, detail); |
177 addProperty = encodeAvatar(property, detail); |
166 if (!addProperty) |
178 if (!addProperty) |
167 unknown = true; |
179 unknown = true; |
168 } else if (detail.definitionName() == QContactAnniversary::DefinitionName) { |
180 } else if (detail.definitionName() == QContactAnniversary::DefinitionName) { |
169 encodeAnniversary(property, detail); |
181 encodeAnniversary(property, detail); |
170 } else if (detail.definitionName() == QContactNickname::DefinitionName) { |
182 } else if (detail.definitionName() == QContactNickname::DefinitionName) { |
171 encodeNickname(document, detail); |
183 encodeNickname(document, detail); |
|
184 addProperty = false; |
|
185 } else if (detail.definitionName() == QContactTag::DefinitionName) { |
|
186 encodeTag(document, detail); |
172 addProperty = false; |
187 addProperty = false; |
173 } else if (detail.definitionName() == QContactGender::DefinitionName) { |
188 } else if (detail.definitionName() == QContactGender::DefinitionName) { |
174 encodeGender(property, detail); |
189 encodeGender(property, detail); |
175 } else if (detail.definitionName() == QContactOnlineAccount::DefinitionName) { |
190 } else if (detail.definitionName() == QContactOnlineAccount::DefinitionName) { |
176 addProperty = encodeOnlineAccount(property, detail); |
191 addProperty = encodeOnlineAccount(property, detail); |
185 } else { |
200 } else { |
186 addProperty = false; |
201 addProperty = false; |
187 unknown = true; |
202 unknown = true; |
188 } |
203 } |
189 |
204 |
190 if (addProperty) |
205 if (addProperty) { |
191 document.addProperty(property); |
206 document.addProperty(property); |
|
207 } |
192 |
208 |
193 if (mDetailHandler) |
209 if (mDetailHandler) |
194 mDetailHandler->postProcessDetail(contact, detail, !unknown, &document); |
210 mDetailHandler->postProcessDetail(contact, detail, !unknown, &document); |
195 } |
211 } |
|
212 |
|
213 // Search through the document for FN or N properties. This will find it even if it was added |
|
214 // by a detail handler. |
|
215 if (!documentContainsName(document)) { |
|
216 *error = QVersitContactExporter::NoNameError; |
|
217 return false; |
|
218 } |
|
219 return true; |
|
220 } |
|
221 |
|
222 /*! |
|
223 * Returns true if and only if \a document has a "FN" or "N" property. |
|
224 */ |
|
225 bool QVersitContactExporterPrivate::documentContainsName(const QVersitDocument &document) |
|
226 { |
|
227 foreach (const QVersitProperty& property, document.properties()) { |
|
228 const QString& name = property.name(); |
|
229 if (name == QLatin1String("FN") || name == QLatin1String("N")) |
|
230 return true; |
|
231 } |
|
232 return false; |
196 } |
233 } |
197 |
234 |
198 /*! |
235 /*! |
199 * Encode Contact Name Field Information into the Versit Document |
236 * Encode Contact Name Field Information into the Versit Document |
200 */ |
237 */ |
201 void QVersitContactExporterPrivate::encodeName( |
238 void QVersitContactExporterPrivate::encodeName( |
202 QVersitProperty& property, |
239 QVersitProperty& property, |
203 const QContactDetail& detail) |
240 const QContactDetail& detail) |
204 { |
241 { |
205 QContactName contactName = static_cast<QContactName>(detail); |
242 QContactName contactName = static_cast<QContactName>(detail); |
206 property.setValue(QString::fromAscii("%1;%2;%3;%4;%5").arg( |
243 property.setValue(QStringList() |
207 escape(contactName.lastName()), |
244 << contactName.lastName() |
208 escape(contactName.firstName()), |
245 << contactName.firstName() |
209 escape(contactName.middleName()), |
246 << contactName.middleName() |
210 escape(contactName.prefix()), |
247 << contactName.prefix() |
211 escape(contactName.suffix()))); |
248 << contactName.suffix()); |
|
249 property.setValueType(QVersitProperty::CompoundType); |
212 } |
250 } |
213 |
251 |
214 /*! |
252 /*! |
215 * Encode Phone Number Field Information into the Versit Document |
253 * Encode Phone Number Field Information into the Versit Document |
216 */ |
254 */ |
242 QVersitProperty& property, |
280 QVersitProperty& property, |
243 const QContactDetail& detail) |
281 const QContactDetail& detail) |
244 { |
282 { |
245 QContactAddress address = static_cast<QContactAddress>(detail); |
283 QContactAddress address = static_cast<QContactAddress>(detail); |
246 encodeParameters(property, address.contexts(), address.subTypes()); |
284 encodeParameters(property, address.contexts(), address.subTypes()); |
247 // Leave out the extended address field: |
285 property.setValue(QStringList() |
248 property.setValue(QString::fromAscii("%1;;%2;%3;%4;%5;%6").arg( |
286 << address.postOfficeBox() |
249 escape(address.postOfficeBox()), |
287 << QString() // Leave out the extended address field |
250 escape(address.street()), |
288 << address.street() |
251 escape(address.locality()), |
289 << address.locality() |
252 escape(address.region()), |
290 << address.region() |
253 escape(address.postcode()), |
291 << address.postcode() |
254 escape(address.country()))); |
292 << address.country()); |
|
293 property.setValueType(QVersitProperty::CompoundType); |
255 } |
294 } |
256 |
295 |
257 /*! |
296 /*! |
258 * Encode URL Field Information into the Versit Document |
297 * Encode URL Field Information into the Versit Document |
259 */ |
298 */ |
332 void QVersitContactExporterPrivate::encodeNote( |
371 void QVersitContactExporterPrivate::encodeNote( |
333 QVersitProperty& property, |
372 QVersitProperty& property, |
334 const QContactDetail& detail) |
373 const QContactDetail& detail) |
335 { |
374 { |
336 QContactNote contactNote = static_cast<QContactNote>(detail); |
375 QContactNote contactNote = static_cast<QContactNote>(detail); |
337 setEscapedValue(property,contactNote.note()); |
376 property.setValue(contactNote.note()); |
338 } |
377 } |
339 |
378 |
340 /*! |
379 /*! |
341 * Encode Geo Prpoperties Field Information into the Versit Document |
380 * Encode Geo Prpoperties Field Information into the Versit Document |
342 */ |
381 */ |
343 void QVersitContactExporterPrivate::encodeGeoLocation( |
382 void QVersitContactExporterPrivate::encodeGeoLocation( |
344 QVersitProperty& property, |
383 QVersitProperty& property, |
345 const QContactDetail& detail) |
384 const QContactDetail& detail) |
346 { |
385 { |
347 QContactGeoLocation geoLocation = static_cast<QContactGeoLocation>(detail); |
386 QContactGeoLocation geoLocation = static_cast<QContactGeoLocation>(detail); |
348 QString value = |
387 property.setValue(QStringList() << QString::number(geoLocation.longitude()) |
349 QString::number(geoLocation.longitude()) + QLatin1Char(',') + |
388 << QString::number(geoLocation.latitude())); |
350 QString::number(geoLocation.latitude()); |
389 property.setValueType(QVersitProperty::CompoundType); |
351 property.setValue(value); |
|
352 } |
390 } |
353 |
391 |
354 /*! |
392 /*! |
355 * Encode organization properties to the versit document |
393 * Encode organization properties to the versit document |
356 */ |
394 */ |
360 { |
398 { |
361 QContactOrganization organization = static_cast<QContactOrganization>(detail); |
399 QContactOrganization organization = static_cast<QContactOrganization>(detail); |
362 if (organization.title().length() > 0) { |
400 if (organization.title().length() > 0) { |
363 QVersitProperty property; |
401 QVersitProperty property; |
364 property.setName(QLatin1String("TITLE")); |
402 property.setName(QLatin1String("TITLE")); |
365 setEscapedValue(property,organization.title()); |
403 property.setValue(organization.title()); |
366 document.addProperty(property); |
404 document.addProperty(property); |
367 } |
405 } |
368 if (organization.name().length() > 0 || organization.department().size() > 0) { |
406 if (organization.name().length() > 0 || organization.department().size() > 0) { |
369 QVersitProperty property; |
407 QVersitProperty property; |
370 property.setName(QLatin1String("ORG")); |
408 property.setName(QLatin1String("ORG")); |
371 QString value = escape(organization.name()); |
409 QStringList values(organization.name()); |
372 QStringList departments(organization.department()); |
410 values.append(organization.department()); |
373 if (departments.count() == 0) |
411 property.setValue(values); |
374 value += QLatin1Char(';'); |
412 property.setValueType(QVersitProperty::CompoundType); |
375 foreach (QString department, departments) { |
|
376 value += QLatin1Char(';'); |
|
377 value += escape(department); |
|
378 } |
|
379 property.setValue(value); |
|
380 document.addProperty(property); |
413 document.addProperty(property); |
381 } |
414 } |
382 if (organization.logo().length() > 0) { |
415 if (organization.logoUrl().isValid()) { |
383 QVersitProperty property; |
416 QVersitProperty property; |
384 if (encodeContentFromFile(organization.logo(), property)) { |
417 // XXX TODO: FIXME! |
|
418 if (encodeContentFromFile(organization.logoUrl().toString(), property)) { |
385 property.setName(QLatin1String("LOGO")); |
419 property.setName(QLatin1String("LOGO")); |
386 document.addProperty(property); |
420 document.addProperty(property); |
387 } |
421 } |
388 } |
422 } |
389 if (organization.assistantName().length() > 0) { |
423 if (organization.assistantName().length() > 0) { |
390 QVersitProperty property; |
424 QVersitProperty property; |
391 property.setName(QLatin1String("X-ASSISTANT")); |
425 property.setName(QLatin1String("X-ASSISTANT")); |
392 setEscapedValue(property,organization.assistantName()); |
426 property.setValue(organization.assistantName()); |
393 document.addProperty(property); |
427 document.addProperty(property); |
394 } |
428 } |
395 |
429 |
396 if (organization.role().length() > 0) { |
430 if (organization.role().length() > 0) { |
397 QVersitProperty property; |
431 QVersitProperty property; |
398 property.setName(QLatin1String("ROLE")); |
432 property.setName(QLatin1String("ROLE")); |
399 setEscapedValue(property,organization.role()); |
433 property.setValue(organization.role()); |
400 document.addProperty(property); |
434 document.addProperty(property); |
401 } |
435 } |
402 } |
436 } |
403 |
437 |
404 /*! |
438 bool QVersitContactExporterPrivate::encodeRingtone(QVersitProperty &property, const QContactDetail &detail) |
405 * Encode avatar content into the Versit Document |
439 { |
|
440 QContactRingtone ringtone = static_cast<QContactRingtone>(detail); |
|
441 Q_ASSERT(property.name() == QLatin1String("SOUND")); |
|
442 return encodeContentFromFile(ringtone.audioRingtoneUrl().toLocalFile(), property); |
|
443 } |
|
444 |
|
445 /*! |
|
446 * Encode thumbnail content into the Versit Document |
|
447 */ |
|
448 bool QVersitContactExporterPrivate::encodeThumbnail( |
|
449 QVersitProperty& property, |
|
450 const QContactDetail& detail) |
|
451 { |
|
452 QContactThumbnail contactThumbnail = static_cast<QContactThumbnail>(detail); |
|
453 property.setName(QLatin1String("PHOTO")); |
|
454 QImage image = contactThumbnail.thumbnail(); |
|
455 if (image.isNull()) |
|
456 return false; |
|
457 QByteArray imageData; |
|
458 QBuffer buffer(&imageData); |
|
459 buffer.open(QIODevice::WriteOnly); |
|
460 // Always store a pixmap as a PNG. |
|
461 if (!image.save(&buffer, "PNG")) { |
|
462 return false; |
|
463 } |
|
464 property.setValue(imageData); |
|
465 property.insertParameter(QLatin1String("TYPE"), QLatin1String("PNG")); |
|
466 return true; |
|
467 } |
|
468 |
|
469 /*! |
|
470 * Encode avatar URIs into the Versit Document |
406 */ |
471 */ |
407 bool QVersitContactExporterPrivate::encodeAvatar( |
472 bool QVersitContactExporterPrivate::encodeAvatar( |
408 QVersitProperty& property, |
473 QVersitProperty& property, |
409 const QContactDetail& detail) |
474 const QContactDetail& detail) |
410 { |
475 { |
|
476 property.setName(QLatin1String("PHOTO")); |
411 QContactAvatar contactAvatar = static_cast<QContactAvatar>(detail); |
477 QContactAvatar contactAvatar = static_cast<QContactAvatar>(detail); |
412 bool encoded = false; |
478 QUrl imageUrl(contactAvatar.imageUrl()); |
413 QString propertyName; |
479 // XXX: fix up this mess: checking the scheme here and in encodeContentFromFile, |
414 if (contactAvatar.subType() == QContactAvatar::SubTypeImage) { |
480 // organisation logo and ringtone are QStrings but avatar is a QUrl |
415 propertyName = QLatin1String("PHOTO"); |
481 if (!imageUrl.scheme().isEmpty() && !imageUrl.host().isEmpty()) { |
416 } else if (contactAvatar.subType() == QContactAvatar::SubTypeAudioRingtone) { |
482 property.insertParameter(QLatin1String("VALUE"), QLatin1String("URL")); |
417 propertyName = QLatin1String("SOUND"); |
483 property.setValue(imageUrl.toString()); |
|
484 return true; |
418 } else { |
485 } else { |
419 // NOP |
486 return encodeContentFromFile(contactAvatar.imageUrl().toString(), property); |
420 } |
487 } |
421 if (propertyName.length() > 0) { |
|
422 encoded = encodeContentFromFile(contactAvatar.avatar(), property); |
|
423 if (!encoded) |
|
424 encoded = encodeContentFromPixmap(contactAvatar.pixmap(), property); |
|
425 if (encoded) |
|
426 property.setName(propertyName); |
|
427 } |
|
428 return encoded; |
|
429 } |
488 } |
430 |
489 |
431 /*! |
490 /*! |
432 * Encode gender property information into Versit Document |
491 * Encode gender property information into Versit Document |
433 */ |
492 */ |
434 void QVersitContactExporterPrivate::encodeGender( |
493 void QVersitContactExporterPrivate::encodeGender( |
435 QVersitProperty& property,const |
494 QVersitProperty& property,const |
436 QContactDetail& detail) |
495 QContactDetail& detail) |
437 { |
496 { |
438 QContactGender gender = static_cast<QContactGender>(detail); |
497 QContactGender gender = static_cast<QContactGender>(detail); |
439 setEscapedValue(property,gender.gender()); |
498 property.setValue(gender.gender()); |
440 } |
499 } |
441 |
500 |
442 /*! |
501 /*! |
443 * Encodes nickname property information into the Versit Document |
502 * Encodes nickname property information into the Versit Document |
444 */ |
503 */ |
446 QVersitDocument& document, |
505 QVersitDocument& document, |
447 const QContactDetail& detail) |
506 const QContactDetail& detail) |
448 { |
507 { |
449 QContactNickname nicknameDetail = static_cast<QContactNickname>(detail); |
508 QContactNickname nicknameDetail = static_cast<QContactNickname>(detail); |
450 QVersitProperty property; |
509 QVersitProperty property; |
451 property.setName(QLatin1String("X-NICKNAME")); |
|
452 bool found = false; |
510 bool found = false; |
453 foreach (QVersitProperty currentProperty, document.properties()) { |
511 // XXX TODO: ensure it works for both X-NICKNAME and NICKNAME |
|
512 foreach (const QVersitProperty& currentProperty, document.properties()) { |
454 if (currentProperty.name() == QLatin1String("X-NICKNAME")) { |
513 if (currentProperty.name() == QLatin1String("X-NICKNAME")) { |
455 property = currentProperty; |
514 property = currentProperty; |
456 found = true; |
515 found = true; |
457 break; |
516 break; |
458 } |
517 } |
459 } |
518 } |
460 QString value(property.value()); |
519 QStringList value(property.variantValue().toStringList()); |
461 if (found) |
520 if (!found) |
462 value += QLatin1Char(','); |
521 property.setName(QLatin1String("X-NICKNAME")); |
463 QString nickname = escape(nicknameDetail.nickname()); |
522 value.append(nicknameDetail.nickname()); |
464 value.append(nickname); |
|
465 property.setValue(value); |
523 property.setValue(value); |
|
524 property.setValueType(QVersitProperty::ListType); |
466 // Replace the current property |
525 // Replace the current property |
467 document.removeProperties(QLatin1String("X-NICKNAME")); |
526 document.removeProperties(QLatin1String("X-NICKNAME")); |
|
527 document.addProperty(property); |
|
528 } |
|
529 |
|
530 /*! |
|
531 * Encodes a contact tag into the Versit Document |
|
532 */ |
|
533 void QVersitContactExporterPrivate::encodeTag( |
|
534 QVersitDocument& document, |
|
535 const QContactDetail& detail) |
|
536 { |
|
537 QContactTag tagDetail = static_cast<QContactTag>(detail); |
|
538 QVersitProperty property; |
|
539 bool found = false; |
|
540 foreach (const QVersitProperty& currentProperty, document.properties()) { |
|
541 if (currentProperty.name() == QLatin1String("CATEGORIES")) { |
|
542 property = currentProperty; |
|
543 found = true; |
|
544 break; |
|
545 } |
|
546 } |
|
547 QStringList value(property.variantValue().toStringList()); |
|
548 if (!found) |
|
549 property.setName(QLatin1String("CATEGORIES")); |
|
550 value.append(tagDetail.tag()); |
|
551 property.setValue(value); |
|
552 property.setValueType(QVersitProperty::ListType); |
|
553 // Replace the current property |
|
554 document.removeProperties(QLatin1String("CATEGORIES")); |
468 document.addProperty(property); |
555 document.addProperty(property); |
469 } |
556 } |
470 |
557 |
471 /*! |
558 /*! |
472 * Encode anniversary information into Versit Document |
559 * Encode anniversary information into Versit Document |
633 // The file doesn't exist. Don't encode the path to a local file. |
720 // The file doesn't exist. Don't encode the path to a local file. |
634 } |
721 } |
635 property.setValue(value); |
722 property.setValue(value); |
636 return encodeContent; |
723 return encodeContent; |
637 } |
724 } |
638 |
|
639 /*! |
|
640 * Encode embedded content from the given \a pixmap into \a property. |
|
641 */ |
|
642 bool QVersitContactExporterPrivate::encodeContentFromPixmap(const QPixmap& pixmap, |
|
643 QVersitProperty& property) |
|
644 { |
|
645 if (pixmap.isNull()) |
|
646 return false; |
|
647 QByteArray imageData; |
|
648 QBuffer buffer(&imageData); |
|
649 buffer.open(QIODevice::WriteOnly); |
|
650 // Always store a pixmap as a PNG. |
|
651 if (!pixmap.save(&buffer, "PNG")) { |
|
652 return false; |
|
653 } |
|
654 property.setValue(imageData); |
|
655 property.insertParameter(QLatin1String("TYPE"), QLatin1String("PNG")); |
|
656 return true; |
|
657 } |
|
658 |
|
659 /*! |
|
660 * Escapes \a value if necessary and sets it to \a property |
|
661 */ |
|
662 void QVersitContactExporterPrivate::setEscapedValue( |
|
663 QVersitProperty& property, |
|
664 const QString& value) |
|
665 { |
|
666 QString escapedValue(escape(value)); |
|
667 property.setValue(escapedValue); |
|
668 } |
|
669 |
|
670 /*! |
|
671 * Escapes \a value if necessary. |
|
672 * For vCard there is no concept of escaping the property values. |
|
673 * Starting from 3.0 the property values having certain special |
|
674 * characters should be escaped. |
|
675 */ |
|
676 QString QVersitContactExporterPrivate::escape(const QString& value) |
|
677 { |
|
678 QString escaped(value); |
|
679 if (mVersitType != QVersitDocument::VCard21Type) { |
|
680 VersitUtils::backSlashEscape(escaped); |
|
681 } |
|
682 return escaped; |
|
683 } |
|