qtcontactsmobility/src/versit/qversitcontactexporter_p.cpp
changeset 25 76a2435edfd4
parent 24 0ba2181d7c28
child 27 de1630741fbe
--- a/qtcontactsmobility/src/versit/qversitcontactexporter_p.cpp	Fri Mar 19 09:27:18 2010 +0200
+++ b/qtcontactsmobility/src/versit/qversitcontactexporter_p.cpp	Fri Apr 16 14:53:18 2010 +0300
@@ -39,8 +39,9 @@
 **
 ****************************************************************************/
 
+#include "qversitcontactexporter.h"
 #include "qversitcontactexporter_p.h"
-#include "qversitdefs.h"
+#include "qversitdefs_p.h"
 #include "versitutils_p.h"
 #include "qmobilityglobal.h"
 
@@ -65,52 +66,44 @@
 #include <qcontactfamily.h>
 #include <qcontactdisplaylabel.h>
 
-#include <QFile>
 #include <QUrl>
 #include <QBuffer>
-#include <QImageWriter>
 
-QTM_BEGIN_NAMESPACE
+QTM_USE_NAMESPACE
 
 /*!
  * Constructor.
  */
 QVersitContactExporterPrivate::QVersitContactExporterPrivate() :
-    mVersitType(QVersitDocument::VCard21)
+    mDetailHandler(NULL),
+    mDefaultResourceHandler(new QVersitDefaultResourceHandler),
+    mVersitType(QVersitDocument::InvalidType)
 {
+    mResourceHandler = mDefaultResourceHandler;
+
     // Detail mappings
     int versitPropertyCount =
-        sizeof(versitContactDetailMappings)/sizeof(versitContactDetailMapping);
+        sizeof(versitContactDetailMappings)/sizeof(VersitContactDetailMapping);
     for (int i=0; i < versitPropertyCount; i++) {
-        QString contactDetailName =
-            QString::fromAscii(versitContactDetailMappings[i].contactDetailDefinitionName);
-        QString versitPropertyName =
-            QString::fromAscii(versitContactDetailMappings[i].versitPropertyName);
-        mPropertyMappings.insert(contactDetailName,versitPropertyName);
+        mPropertyMappings.insert(
+                QLatin1String(versitContactDetailMappings[i].contactDetailDefinitionName),
+                QLatin1String(versitContactDetailMappings[i].versitPropertyName));
     }
 
     // Contexts mappings
-    int contextCount = sizeof(versitContextMappings)/sizeof(versitMapping);
+    int contextCount = sizeof(versitContextMappings)/sizeof(VersitMapping);
     for (int i=0; i < contextCount; i++) {
         mParameterMappings.insert(
-            QString::fromAscii(versitContextMappings[i].contactString),
-            QString::fromAscii(versitContextMappings[i].versitString));
+                QLatin1String(versitContextMappings[i].contactString),
+                QLatin1String(versitContextMappings[i].versitString));
     }
 
     // Subtypes mappings
-    int subTypeCount = sizeof(versitSubTypeMappings)/sizeof(versitMapping);
+    int subTypeCount = sizeof(versitSubTypeMappings)/sizeof(VersitMapping);
     for (int i=0; i < subTypeCount; i++) {
         mParameterMappings.insert(
-            QString::fromAscii(versitSubTypeMappings[i].contactString),
-            QString::fromAscii(versitSubTypeMappings[i].versitString));
-    }
-
-    // File extension mappings
-    int fileExtensionCount = sizeof(versitFileExtensionMappings)/sizeof(versitMapping);
-    for (int i=0; i < fileExtensionCount; i++) {
-        mParameterMappings.insert(
-            QString::fromAscii(versitFileExtensionMappings[i].contactString),
-            QString::fromAscii(versitFileExtensionMappings[i].versitString));
+                QLatin1String(versitSubTypeMappings[i].contactString),
+                QLatin1String(versitSubTypeMappings[i].versitString));
     }
 }
 
@@ -119,6 +112,7 @@
  */
 QVersitContactExporterPrivate::~QVersitContactExporterPrivate()
 {
+    delete mDefaultResourceHandler;
 }
 
 
@@ -126,17 +120,23 @@
  * Export QT Contact into Versit Document.
  */
 void QVersitContactExporterPrivate::exportContact(
-    QVersitDocument& versitDocument,
-    const QContact& contact)
+    const QContact& contact,
+    QVersitDocument& document)
 {
-    mUnknownContactDetails.clear();
-    mVersitType = versitDocument.versitType();
+    mVersitType = document.type();
     QList<QContactDetail> allDetails = contact.details();
     for (int i = 0; i < allDetails.size(); i++) {
         QContactDetail detail = allDetails.at(i);
+
+        // If the custom detail handler handles it, we don't have to.
+        if (mDetailHandler
+            && mDetailHandler->preProcessDetail(contact, detail, &document))
+            continue;
+
         QVersitProperty property;
         property.setName(mPropertyMappings.value(detail.definitionName()));
         bool addProperty = true;
+        bool unknown = false;
 
         if (detail.definitionName() == QContactName::DefinitionName) {
             encodeName(property, detail);
@@ -159,36 +159,39 @@
         } else if (detail.definitionName() == QContactNote::DefinitionName) {
             encodeNote(property, detail);
         } else if (detail.definitionName() == QContactOrganization::DefinitionName) {
-            encodeOrganization(versitDocument, detail);
+            encodeOrganization(document, detail);
             addProperty = false;
         } else if (detail.definitionName() == QContactAvatar::DefinitionName){
             addProperty = encodeAvatar(property, detail);
             if (!addProperty)
-                mUnknownContactDetails.append(detail);
+                unknown = true;
         } else if (detail.definitionName() == QContactAnniversary::DefinitionName) {
             encodeAnniversary(property, detail);
         } else if (detail.definitionName() == QContactNickname::DefinitionName) {
-            encodeNickname(versitDocument, detail);
+            encodeNickname(document, detail);
             addProperty = false;
         } else if (detail.definitionName() == QContactGender::DefinitionName) {
             encodeGender(property, detail);
         } else if (detail.definitionName() == QContactOnlineAccount::DefinitionName) {
             addProperty = encodeOnlineAccount(property, detail);
             if (!addProperty)
-                mUnknownContactDetails.append(detail);
+                unknown = true;
         } else if (detail.definitionName() == QContactFamily::DefinitionName) {
-            addProperty = encodeFamily(versitDocument, detail);
+            addProperty = encodeFamily(document, detail);
         } else if (detail.definitionName() == QContactDisplayLabel::DefinitionName) {
             addProperty = encodeDisplayLabel(property, detail, contact);
             if (!addProperty)
-                mUnknownContactDetails.append(detail);
+                unknown = true;
         } else {
             addProperty = false;
-            mUnknownContactDetails.append(detail);
+            unknown = true;
         }
 
         if (addProperty)
-            versitDocument.addProperty(property);
+            document.addProperty(property);
+
+        if (mDetailHandler)
+            mDetailHandler->postProcessDetail(contact, detail, !unknown, &document);
     }
 }
 
@@ -200,13 +203,12 @@
     const QContactDetail& detail)
 {   
     QContactName contactName = static_cast<QContactName>(detail);
-    QByteArray value =
-        escape(contactName.last().toAscii()) + ';' +
-        escape(contactName.first().toAscii()) + ';' +
-        escape(contactName.middle().toAscii()) + ';' +
-        escape(contactName.prefix().toAscii()) + ';' +
-        escape(contactName.suffix().toAscii());
-    property.setValue(value);
+    property.setValue(QString::fromAscii("%1;%2;%3;%4;%5").arg(
+            escape(contactName.lastName()),
+            escape(contactName.firstName()),
+            escape(contactName.middleName()),
+            escape(contactName.prefix()),
+            escape(contactName.suffix())));
 }
 
 /*!
@@ -242,15 +244,14 @@
 {
     QContactAddress address = static_cast<QContactAddress>(detail);
     encodeParameters(property, address.contexts(), address.subTypes());
-    QByteArray value =
-        escape(address.postOfficeBox().toAscii()) + ';' +
-        ';' + // Extended address
-        escape(address.street().toAscii()) + ';' +
-        escape(address.locality().toAscii()) + ';' +
-        escape(address.region().toAscii()) + ';' +
-        escape(address.postcode().toAscii()) + ';' +
-        escape(address.country().toAscii());
-    property.setValue(value);
+    // Leave out the extended address field:
+    property.setValue(QString::fromAscii("%1;;%2;%3;%4;%5;%6").arg(
+            escape(address.postOfficeBox()),
+            escape(address.street()),
+            escape(address.locality()),
+            escape(address.region()),
+            escape(address.postcode()),
+            escape(address.country())));
 }
 
 /*!
@@ -264,7 +265,7 @@
     encodeParameters(property, contactUrl.contexts());
     // The vCard specifications do not define any TYPEs for URL property.
     // No need to try to convert the subtypes to TYPEs.
-    property.setValue(contactUrl.url().toAscii());
+    property.setValue(contactUrl.url());
 }
 
 /*!
@@ -292,7 +293,7 @@
     if ( rev.lastModified().toString(Qt::ISODate).size() ) {
         encoded = true;
         if ( rev.lastModified().timeSpec() == Qt::UTC ) {
-            value = rev.lastModified().toString(Qt::ISODate) + QString::fromAscii("Z");
+            value = rev.lastModified().toString(Qt::ISODate) + QLatin1Char('Z');
         }
         else {
             value = rev.lastModified().toString(Qt::ISODate);
@@ -302,13 +303,13 @@
     else if ( rev.created().toString(Qt::ISODate).size()) {
         encoded = true;
         if ( rev.created().timeSpec() == Qt::UTC ) {
-            value = rev.created().toString(Qt::ISODate) + QString::fromAscii("Z");
+            value = rev.created().toString(Qt::ISODate) + QLatin1Char('Z');
         }
         else {
             value = rev.created().toString(Qt::ISODate);
         }
     }
-    property.setValue(value.toAscii());
+    property.setValue(value);
 
     return encoded;
 }
@@ -322,7 +323,7 @@
 {
     QContactBirthday bday = static_cast<QContactBirthday>(detail);
     QString value = bday.date().toString(Qt::ISODate);
-    property.setValue(value.toAscii());
+    property.setValue(value);
 }
 
 /*!
@@ -343,12 +344,10 @@
     QVersitProperty& property,
     const QContactDetail& detail)
 {
-    QContactGeolocation geoLocation = static_cast<QContactGeolocation>(detail);
-    QByteArray longitude;
-    QByteArray latitude;
-    QByteArray value =
-        longitude.setNum(geoLocation.longitude()) + ',' +
-        latitude.setNum(geoLocation.latitude());
+    QContactGeoLocation geoLocation = static_cast<QContactGeoLocation>(detail);
+    QString value =
+        QString::number(geoLocation.longitude()) + QLatin1Char(',') +
+        QString::number(geoLocation.latitude());
     property.setValue(value);
 }
 
@@ -362,41 +361,41 @@
     QContactOrganization organization = static_cast<QContactOrganization>(detail);
     if (organization.title().length() > 0) {
         QVersitProperty property;
-        property.setName(QString::fromAscii("TITLE"));
+        property.setName(QLatin1String("TITLE"));
         setEscapedValue(property,organization.title());
         document.addProperty(property);
     }
     if (organization.name().length() > 0 || organization.department().size() > 0) {
         QVersitProperty property;
-        property.setName(QString::fromAscii("ORG"));
-        QByteArray value = escape(organization.name().toAscii());
+        property.setName(QLatin1String("ORG"));
+        QString value = escape(organization.name());
         QStringList departments(organization.department());
         if (departments.count() == 0)
-            value += ";";
+            value += QLatin1Char(';');
         foreach (QString department, departments) {
-            value += ";";
-            value += escape(department.toAscii());
+            value += QLatin1Char(';');
+            value += escape(department);
         }
         property.setValue(value);
         document.addProperty(property);
     }
     if (organization.logo().length() > 0) {
         QVersitProperty property;
-        if (encodeEmbeddedContent(organization.logo(), property, true)) {
-            property.setName(QString::fromAscii("LOGO"));
+        if (encodeContentFromFile(organization.logo(), property)) {
+            property.setName(QLatin1String("LOGO"));
             document.addProperty(property);
         }
     }
     if (organization.assistantName().length() > 0) {
         QVersitProperty property;
-        property.setName(QString::fromAscii("X-ASSISTANT"));
+        property.setName(QLatin1String("X-ASSISTANT"));
         setEscapedValue(property,organization.assistantName());
         document.addProperty(property);
     }
 
     if (organization.role().length() > 0) {
         QVersitProperty property;
-        property.setName(QString::fromAscii("ROLE"));
+        property.setName(QLatin1String("ROLE"));
         setEscapedValue(property,organization.role());
         document.addProperty(property);
     }
@@ -410,19 +409,19 @@
     const QContactDetail& detail)
 {
     QContactAvatar contactAvatar = static_cast<QContactAvatar>(detail);
-    bool scalingAllowed = false;
     bool encoded = false;
     QString propertyName;
     if (contactAvatar.subType() == QContactAvatar::SubTypeImage) {
-        scalingAllowed = true;
-        propertyName = QString::fromAscii("PHOTO");
+        propertyName = QLatin1String("PHOTO");
     } else if (contactAvatar.subType() == QContactAvatar::SubTypeAudioRingtone) {
-        propertyName = QString::fromAscii("SOUND");
+        propertyName = QLatin1String("SOUND");
     } else {
         // NOP
     }
     if (propertyName.length() > 0) {
-        encoded = encodeEmbeddedContent(contactAvatar.avatar(), property, scalingAllowed);
+        encoded = encodeContentFromFile(contactAvatar.avatar(), property);
+        if (!encoded)
+            encoded = encodeContentFromPixmap(contactAvatar.pixmap(), property);
         if (encoded)
             property.setName(propertyName);
     }
@@ -449,23 +448,23 @@
 {
     QContactNickname nicknameDetail = static_cast<QContactNickname>(detail);
     QVersitProperty property;
-    property.setName(QString::fromAscii("X-NICKNAME"));
+    property.setName(QLatin1String("X-NICKNAME"));
     bool found = false;
-    for (int i=0; i < document.properties().count() && !found; i++) {
-        QVersitProperty currentProperty = document.properties()[i];
-        if (currentProperty.name() == QString::fromAscii("X-NICKNAME")) {
+    foreach (QVersitProperty currentProperty, document.properties()) {
+        if (currentProperty.name() == QLatin1String("X-NICKNAME")) {
             property = currentProperty;
             found = true;
+            break;
         }
     }
-    QByteArray value(property.value());
+    QString value(property.value());
     if (found)
-        value += ',';
-    QByteArray nickname = escape(nicknameDetail.nickname().toAscii());
+        value += QLatin1Char(',');
+    QString nickname = escape(nicknameDetail.nickname());
     value.append(nickname);
     property.setValue(value);
     // Replace the current property
-    document.removeProperties(QString::fromAscii("X-NICKNAME"));
+    document.removeProperties(QLatin1String("X-NICKNAME"));
     document.addProperty(property);
 }
 
@@ -477,7 +476,7 @@
     const QContactDetail& detail)
 {
     QContactAnniversary anniversary = static_cast<QContactAnniversary>(detail);
-    property.setValue(anniversary.originalDate().toString(Qt::ISODate).toAscii());
+    property.setValue(anniversary.originalDate().toString(Qt::ISODate));
 }
 
 /*!
@@ -497,9 +496,9 @@
         subTypes.contains(QContactOnlineAccount::SubTypeImpp)) {
         encoded = true;
         encodeParameters(property, onlineAccount.contexts(), subTypes);
-        QString name(QString::fromAscii("X-SIP"));
+        QString name(QLatin1String("X-SIP"));
         if (subTypes.contains(QContactOnlineAccount::SubTypeImpp))
-            name = QString::fromAscii("X-IMPP");
+            name = QLatin1String("X-IMPP");
         property.setName(name);
         setEscapedValue(property,onlineAccount.accountUri());
     }
@@ -517,15 +516,15 @@
 
     if (family.spouse().size()) {
         QVersitProperty property;
-        property.setName(QString::fromAscii("X-SPOUSE"));
+        property.setName(QLatin1String("X-SPOUSE"));
         setEscapedValue(property,family.spouse());
         document.addProperty(property);
     }
 
     if (family.children().size()) {
         QVersitProperty property;
-        property.setName(QString::fromAscii("X-CHILDREN"));
-        QString children = family.children().join(QString::fromAscii(","));
+        property.setName(QLatin1String("X-CHILDREN"));
+        QString children = family.children().join(QLatin1String(","));
         setEscapedValue(property,children);
         document.addProperty(property);
     }
@@ -554,15 +553,15 @@
                 break;
         }
         QContactName name = static_cast<QContactName>(contactDetail);
-        QByteArray value;
+        QString value;
         if (name.customLabel().length()) {
-            value = name.customLabel().toAscii();
+            value = name.customLabel();
         } else {
-            value = name.first().toAscii() + ' ' + name.last().toAscii();
+            value = name.firstName() + QLatin1Char(' ') + name.lastName();
         }
         if (name.customLabel().length() ||
-            name.first().length() ||
-            name.last().length()) {
+            name.firstName().length() ||
+            name.lastName().length()) {
             encoded = true;
             property.setValue(escape(value));
         }
@@ -579,7 +578,7 @@
     QUrl remoteResource(resourceIdentifier);
     if ((!remoteResource.scheme().isEmpty() &&
          !remoteResource.host().isEmpty()) ||
-         resourceIdentifier.contains(QString::fromAscii("www."),Qt::CaseInsensitive))
+        resourceIdentifier.contains(QLatin1String("www."), Qt::CaseInsensitive))
         return true;
     return false;
 }
@@ -600,54 +599,61 @@
         if (mappedValue.length() > 0) {
             // QVersitProperty::addParameter inserts into beginning.
             // This is why the last value is taken from the list
-            property.addParameter(QString::fromAscii("TYPE"),mappedValue);
+            property.insertParameter(QLatin1String("TYPE"),mappedValue);
         }
     }
 }
 
 /*!
- * Encode embedded content into the Versit Document
+ * Encode embedded content from the given \a resourcePath into \a property.
  */
-bool QVersitContactExporterPrivate::encodeEmbeddedContent(
-    const QString& resourcePath,
-    QVersitProperty& property,
-    bool performScaling)
+bool QVersitContactExporterPrivate::encodeContentFromFile(const QString& resourcePath,
+                                                          QVersitProperty& property)
 {
     bool encodeContent = false;
-    QString resourceExt = resourcePath.section(QString::fromAscii("."), -1).toUpper();
-    QString resourceFormat = mParameterMappings.value(resourceExt);
-
-    if (!resourceFormat.length())
-        resourceFormat = resourceExt;
+    QVariant value;
+    QByteArray imageData;
+    QString mimeType;
+    if (isValidRemoteUrl( resourcePath )) {
+        encodeContent = true;
+        value.setValue(resourcePath);
+        property.insertParameter(QLatin1String("VALUE"), QLatin1String("URL"));
+    } else if (mResourceHandler
+               && mResourceHandler->loadResource(resourcePath, &imageData, &mimeType)) {
+        value.setValue(imageData);
+        if (!mimeType.isEmpty()) {
+            // If mimeType is (eg.) "image/jpeg", set type parameter to "JPEG"
+            int slashIndex = mimeType.indexOf(QLatin1Char('/'));
+            if (slashIndex >= 0)
+                property.insertParameter(QLatin1String("TYPE"),
+                                         mimeType.remove(0, slashIndex+1).toUpper());
+        }
+        encodeContent = true;
+    } else {
+        // The file doesn't exist. Don't encode the path to a local file.
+    }
+    property.setValue(value);
+    return encodeContent;
+}
 
-    if (resourceFormat.length() > 0) {
-        QByteArray value;
-        QFile resourceFile(resourcePath);
-        if ( resourceFile.open(QIODevice::ReadOnly)) {
-            encodeContent = true;
-            if (performScaling)
-                emit scale(resourcePath,value);
-            if (value.length() == 0)
-                value = resourceFile.readAll(); // Image not scaled
-            value = value.toBase64();
-            property.addParameter(
-                QString::fromAscii("ENCODING"),
-                QString::fromAscii("BASE64"));
-            property.addParameter(QString::fromAscii("TYPE"),resourceFormat);
-        }
-        else if (isValidRemoteUrl( resourcePath )) {
-            encodeContent = true;
-            value = resourcePath.toAscii();
-            property.addParameter(
-                QString::fromAscii("VALUE"),
-                QString::fromAscii("URL"));
-            property.addParameter(QString::fromAscii("TYPE"),resourceFormat);
-        } else {
-            // The file has been removed. Don't encode the path to a local file.
-        }
-        property.setValue(value);
+/*!
+ * Encode embedded content from the given \a pixmap into \a property.
+ */
+bool QVersitContactExporterPrivate::encodeContentFromPixmap(const QPixmap& pixmap,
+                                                            QVersitProperty& property)
+{
+    if (pixmap.isNull())
+        return false;
+    QByteArray imageData;
+    QBuffer buffer(&imageData);
+    buffer.open(QIODevice::WriteOnly);
+    // Always store a pixmap as a PNG.
+    if (!pixmap.save(&buffer, "PNG")) {
+        return false;
     }
-    return encodeContent;
+    property.setValue(imageData);
+    property.insertParameter(QLatin1String("TYPE"), QLatin1String("PNG"));
+    return true;
 }
 
 /*!
@@ -657,7 +663,7 @@
     QVersitProperty& property,
     const QString& value)
 {
-    QByteArray escapedValue(escape(value.toAscii()));
+    QString escapedValue(escape(value));
     property.setValue(escapedValue);
 }
 
@@ -667,15 +673,11 @@
  * Starting from 3.0 the property values having certain special
  * characters should be escaped.
  */
-QByteArray QVersitContactExporterPrivate::escape(const QByteArray& value)
+QString QVersitContactExporterPrivate::escape(const QString& value)
 {
-    QByteArray escaped(value);
-    if (mVersitType != QVersitDocument::VCard21) {
+    QString escaped(value);
+    if (mVersitType != QVersitDocument::VCard21Type) {
         VersitUtils::backSlashEscape(escaped);
     }
     return escaped;
 }
-
-#include "moc_qversitcontactexporter_p.cpp"
-
-QTM_END_NAMESPACE