src/versit/qversitcontactexporter_p.cpp
changeset 0 876b1a06bc25
child 5 603d3f8b6302
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qversitcontactexporter.h"
       
    43 #include "qversitcontactexporter_p.h"
       
    44 #include "qversitdefs_p.h"
       
    45 #include "versitutils_p.h"
       
    46 #include "qmobilityglobal.h"
       
    47 
       
    48 #include <qcontact.h>
       
    49 #include <qcontactdetail.h>
       
    50 #include <qcontactname.h>
       
    51 #include <qcontactemailaddress.h>
       
    52 #include <qcontactphonenumber.h>
       
    53 #include <qcontactaddress.h>
       
    54 #include <qcontacturl.h>
       
    55 #include <qcontactguid.h>
       
    56 #include <qcontactorganization.h>
       
    57 #include <qcontacttimestamp.h>
       
    58 #include <qcontactbirthday.h>
       
    59 #include <qcontactnote.h>
       
    60 #include <qcontactgeolocation.h>
       
    61 #include <qcontactavatar.h>
       
    62 #include <qcontactgender.h>
       
    63 #include <qcontactnickname.h>
       
    64 #include <qcontactanniversary.h>
       
    65 #include <qcontactonlineaccount.h>
       
    66 #include <qcontactfamily.h>
       
    67 #include <qcontactdisplaylabel.h>
       
    68 #include <qcontactthumbnail.h>
       
    69 
       
    70 #include <QUrl>
       
    71 #include <QBuffer>
       
    72 
       
    73 QTM_USE_NAMESPACE
       
    74 
       
    75 /*!
       
    76  * Constructor.
       
    77  */
       
    78 QVersitContactExporterPrivate::QVersitContactExporterPrivate() :
       
    79     mDetailHandler(NULL),
       
    80     mDetailHandler2(NULL),
       
    81     mDetailHandlerVersion(0),
       
    82     mDefaultResourceHandler(new QVersitDefaultResourceHandler),
       
    83     mResourceHandler(mDefaultResourceHandler),
       
    84     mVersitType(QVersitDocument::InvalidType)
       
    85 {
       
    86     // Detail mappings
       
    87     int versitPropertyCount =
       
    88         sizeof(versitContactDetailMappings)/sizeof(VersitContactDetailMapping);
       
    89     for (int i=0; i < versitPropertyCount; i++) {
       
    90         mPropertyMappings.insert(
       
    91                 QLatin1String(versitContactDetailMappings[i].contactDetailDefinitionName),
       
    92                 QLatin1String(versitContactDetailMappings[i].versitPropertyName));
       
    93     }
       
    94 
       
    95     // Contexts mappings
       
    96     int contextCount = sizeof(versitContextMappings)/sizeof(VersitMapping);
       
    97     for (int i=0; i < contextCount; i++) {
       
    98         mParameterMappings.insert(
       
    99                 QLatin1String(versitContextMappings[i].contactString),
       
   100                 QLatin1String(versitContextMappings[i].versitString));
       
   101     }
       
   102 
       
   103     // Subtypes mappings
       
   104     int subTypeCount = sizeof(versitSubTypeMappings)/sizeof(VersitMapping);
       
   105     for (int i=0; i < subTypeCount; i++) {
       
   106         mParameterMappings.insert(
       
   107                 QLatin1String(versitSubTypeMappings[i].contactString),
       
   108                 QLatin1String(versitSubTypeMappings[i].versitString));
       
   109     }
       
   110 }
       
   111 
       
   112 /*!
       
   113  * Destructor.
       
   114  */
       
   115 QVersitContactExporterPrivate::~QVersitContactExporterPrivate()
       
   116 {
       
   117     delete mDefaultResourceHandler;
       
   118 }
       
   119 
       
   120 
       
   121 /*!
       
   122  * Export QT Contact into Versit Document.
       
   123  */
       
   124 bool QVersitContactExporterPrivate::exportContact(
       
   125     const QContact& contact,
       
   126     QVersitDocument& document,
       
   127     QVersitContactExporter::Error* error)
       
   128 {
       
   129     mVersitType = document.type();
       
   130     QList<QContactDetail> allDetails = contact.details();
       
   131     if (allDetails.isEmpty()) {
       
   132         *error = QVersitContactExporter::EmptyContactError;
       
   133         return false;
       
   134     }
       
   135     for (int i = 0; i < allDetails.size(); i++) {
       
   136         QContactDetail detail = allDetails.at(i);
       
   137 
       
   138         // If the custom detail handler handles it, we don't have to.
       
   139         if (mDetailHandler
       
   140             && mDetailHandler->preProcessDetail(contact, detail, &document))
       
   141             continue;
       
   142 
       
   143         QList<QVersitProperty> removedProperties;
       
   144         QList<QVersitProperty> generatedProperties;
       
   145         QSet<QString> processedFields;
       
   146 
       
   147         if (detail.definitionName() == QContactName::DefinitionName) {
       
   148             encodeName(detail, document, &removedProperties, &generatedProperties, &processedFields);
       
   149         } else if (detail.definitionName() == QContactPhoneNumber::DefinitionName) {
       
   150             encodePhoneNumber(detail, &generatedProperties, &processedFields);
       
   151         } else if (detail.definitionName() == QContactEmailAddress::DefinitionName) {
       
   152             encodeEmail(detail, &generatedProperties, &processedFields);
       
   153         } else if (detail.definitionName() == QContactAddress::DefinitionName) {
       
   154             encodeAddress(detail, &generatedProperties, &processedFields);
       
   155         } else if (detail.definitionName() == QContactGuid::DefinitionName) {
       
   156             encodeUid(detail, &generatedProperties, &processedFields);
       
   157         } else if (detail.definitionName() == QContactUrl::DefinitionName) {
       
   158             encodeUrl(detail, &generatedProperties, &processedFields);
       
   159         } else if (detail.definitionName() == QContactTimestamp::DefinitionName) {
       
   160             encodeRev(detail, &generatedProperties, &processedFields);
       
   161         } else if (detail.definitionName() == QContactBirthday::DefinitionName) {
       
   162             encodeBirthDay(detail, &generatedProperties, &processedFields);
       
   163         } else if (detail.definitionName() == QContactGeoLocation::DefinitionName) {
       
   164             encodeGeoLocation(detail, &generatedProperties, &processedFields);
       
   165         } else if (detail.definitionName() == QContactNote::DefinitionName) {
       
   166             encodeNote(detail, &generatedProperties, &processedFields);
       
   167         } else if (detail.definitionName() == QContactOrganization::DefinitionName) {
       
   168             encodeOrganization(detail, &generatedProperties, &processedFields);
       
   169         } else if (detail.definitionName() == QContactRingtone::DefinitionName) {
       
   170             encodeRingtone(detail, &generatedProperties, &processedFields);
       
   171         } else if (detail.definitionName() == QContactThumbnail::DefinitionName) {
       
   172             encodeThumbnail(detail, &generatedProperties, &processedFields);
       
   173         } else if (detail.definitionName() == QContactAvatar::DefinitionName){
       
   174             encodeAvatar(detail, &generatedProperties, &processedFields);
       
   175         } else if (detail.definitionName() == QContactAnniversary::DefinitionName) {
       
   176             encodeAnniversary(detail, &generatedProperties, &processedFields);
       
   177         } else if (detail.definitionName() == QContactNickname::DefinitionName) {
       
   178             encodeNickname(detail, document, &removedProperties, &generatedProperties, &processedFields);
       
   179         } else if (detail.definitionName() == QContactTag::DefinitionName) {
       
   180             encodeTag(detail, document, &removedProperties, &generatedProperties, &processedFields);
       
   181         } else if (detail.definitionName() == QContactGender::DefinitionName) {
       
   182             encodeGender(detail, &generatedProperties, &processedFields);
       
   183         } else if (detail.definitionName() == QContactOnlineAccount::DefinitionName) {
       
   184             encodeOnlineAccount(detail, &generatedProperties, &processedFields);
       
   185         } else if (detail.definitionName() == QContactFamily::DefinitionName) {
       
   186             encodeFamily(detail, &generatedProperties, &processedFields);
       
   187         } else if (detail.definitionName() == QContactDisplayLabel::DefinitionName) {
       
   188             encodeDisplayLabel(detail, document, &removedProperties, &generatedProperties, &processedFields);
       
   189         }
       
   190 
       
   191         if (mDetailHandler2 && mDetailHandlerVersion > 1) {
       
   192             mDetailHandler2->detailProcessed(contact, detail, processedFields, document,
       
   193                                              &removedProperties, &generatedProperties);
       
   194         }
       
   195 
       
   196         foreach(const QVersitProperty& property, removedProperties) {
       
   197             document.removeProperty(property);
       
   198         }
       
   199         foreach(const QVersitProperty& property, generatedProperties) {
       
   200             document.addProperty(property);
       
   201         }
       
   202 
       
   203         if (mDetailHandler && mDetailHandlerVersion == 1) {
       
   204             mDetailHandler->postProcessDetail(contact, detail, !processedFields.isEmpty(), &document);
       
   205         }
       
   206     }
       
   207 
       
   208     if (mDetailHandler2 && mDetailHandlerVersion > 1) {
       
   209         mDetailHandler2->contactProcessed(contact, &document);
       
   210     }
       
   211 
       
   212     // Search through the document for FN or N properties.  This will find it even if it was added
       
   213     // by a detail handler.
       
   214     if (!documentContainsName(document)) {
       
   215         *error = QVersitContactExporter::NoNameError;
       
   216         return false;
       
   217     }
       
   218     return true;
       
   219 }
       
   220 
       
   221 /*!
       
   222  * Returns true if and only if \a document has a "FN" or "N" property.
       
   223  */
       
   224 bool QVersitContactExporterPrivate::documentContainsName(const QVersitDocument &document)
       
   225 {
       
   226     foreach (const QVersitProperty& property, document.properties()) {
       
   227         const QString& name = property.name();
       
   228         if (name == QLatin1String("FN") || name == QLatin1String("N"))
       
   229             return true;
       
   230     }
       
   231     return false;
       
   232 }
       
   233 
       
   234 /*!
       
   235  * Encode Contact Name Field Information into the Versit Document
       
   236  */
       
   237 void QVersitContactExporterPrivate::encodeName(
       
   238     const QContactDetail& detail,
       
   239     const QVersitDocument& document,
       
   240     QList<QVersitProperty>* removedProperties,
       
   241     QList<QVersitProperty>* generatedProperties,
       
   242     QSet<QString>* processedFields)
       
   243 {
       
   244     QContactName contactName = static_cast<QContactName>(detail);
       
   245     if (!contactName.lastName().isEmpty()
       
   246         || !contactName.firstName().isEmpty()
       
   247         || !contactName.middleName().isEmpty()
       
   248         || !contactName.prefix().isEmpty()
       
   249         || !contactName.suffix().isEmpty()) {
       
   250         QVersitProperty property;
       
   251         property.setName(mPropertyMappings.value(detail.definitionName()));
       
   252         property.setValue(QStringList()
       
   253                           << contactName.lastName()
       
   254                           << contactName.firstName()
       
   255                           << contactName.middleName()
       
   256                           << contactName.prefix()
       
   257                           << contactName.suffix());
       
   258         property.setValueType(QVersitProperty::CompoundType);
       
   259         *generatedProperties << property;
       
   260     }
       
   261 
       
   262     // Generate an FN field if none is already there
       
   263     // Don't override previously exported FN properties (eg. exported by a DisplayLabel detail)
       
   264     QVersitProperty fnProperty = takeProperty(document, QLatin1String("FN"), removedProperties);
       
   265     if (fnProperty.value().isEmpty()) {
       
   266         fnProperty.setName(QLatin1String("FN"));
       
   267         if (!contactName.customLabel().isEmpty()) {
       
   268             fnProperty.setValue(contactName.customLabel());
       
   269         } else if (!contactName.firstName().isEmpty()) {
       
   270             if (!contactName.lastName().isEmpty()) {
       
   271                 fnProperty.setValue(QString::fromAscii("%1 %2").arg(contactName.firstName(),
       
   272                                                                     contactName.lastName()));
       
   273             } else {
       
   274                 fnProperty.setValue(contactName.firstName());
       
   275             }
       
   276         } else if (!contactName.lastName().isEmpty()) {
       
   277             fnProperty.setValue(contactName.lastName());
       
   278         }
       
   279     }
       
   280 
       
   281     *generatedProperties << fnProperty;
       
   282     *processedFields << QContactName::FieldLastName
       
   283                      << QContactName::FieldFirstName
       
   284                      << QContactName::FieldMiddleName
       
   285                      << QContactName::FieldPrefix
       
   286                      << QContactName::FieldSuffix
       
   287                      << QContactName::FieldCustomLabel;
       
   288 }
       
   289 
       
   290 /*!
       
   291  * Encode Phone Number Field Information into the Versit Document
       
   292  */
       
   293 void QVersitContactExporterPrivate::encodePhoneNumber(
       
   294     const QContactDetail& detail,
       
   295     QList<QVersitProperty>* generatedProperties,
       
   296     QSet<QString>* processedFields)
       
   297 {
       
   298     QContactPhoneNumber phoneNumber = static_cast<QContactPhoneNumber>(detail);
       
   299     QStringList subTypes = phoneNumber.subTypes();
       
   300     QVersitProperty property;
       
   301     if (subTypes.contains(QContactPhoneNumber::SubTypeAssistant))
       
   302         property.setName(QLatin1String("X-ASSISTANT-TEL"));
       
   303     else
       
   304         property.setName(QLatin1String("TEL"));
       
   305     encodeParameters(property, phoneNumber.contexts(), subTypes);
       
   306     property.setValue(phoneNumber.number());
       
   307     *generatedProperties << property;
       
   308     *processedFields << QContactPhoneNumber::FieldContext
       
   309                       << QContactPhoneNumber::FieldSubTypes
       
   310                       << QContactPhoneNumber::FieldNumber;
       
   311 }
       
   312 
       
   313 /*!
       
   314  * Encode Email Field Information into the Versit Document
       
   315  */
       
   316 void QVersitContactExporterPrivate::encodeEmail(
       
   317     const QContactDetail& detail,
       
   318     QList<QVersitProperty>* generatedProperties,
       
   319     QSet<QString>* processedFields)
       
   320 {
       
   321     QContactEmailAddress emailAddress = static_cast<QContactEmailAddress>(detail);
       
   322     QVersitProperty property;
       
   323     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   324     encodeParameters(property, emailAddress.contexts());
       
   325     property.setValue(emailAddress.emailAddress());
       
   326     *generatedProperties << property;
       
   327     *processedFields << QContactEmailAddress::FieldContext
       
   328                       << QContactEmailAddress::FieldEmailAddress;
       
   329 }
       
   330 
       
   331 /*!
       
   332  * Encode Address Field Information into the Versit Document
       
   333  */
       
   334 void QVersitContactExporterPrivate::encodeAddress(
       
   335     const QContactDetail& detail,
       
   336     QList<QVersitProperty>* generatedProperties,
       
   337     QSet<QString>* processedFields)
       
   338 {
       
   339     QContactAddress address = static_cast<QContactAddress>(detail);
       
   340     QVersitProperty property;
       
   341     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   342     encodeParameters(property, address.contexts(), address.subTypes());
       
   343     property.setValue(QStringList()
       
   344                       << address.postOfficeBox()
       
   345                       << QString() // Leave out the extended address field
       
   346                       << address.street()
       
   347                       << address.locality()
       
   348                       << address.region()
       
   349                       << address.postcode()
       
   350                       << address.country());
       
   351     property.setValueType(QVersitProperty::CompoundType);
       
   352     *generatedProperties << property;
       
   353     *processedFields << QContactAddress::FieldContext
       
   354                       << QContactAddress::FieldSubTypes
       
   355                       << QContactAddress::FieldPostOfficeBox
       
   356                       << QContactAddress::FieldStreet
       
   357                       << QContactAddress::FieldLocality
       
   358                       << QContactAddress::FieldRegion
       
   359                       << QContactAddress::FieldPostcode
       
   360                       << QContactAddress::FieldCountry;
       
   361 }
       
   362 
       
   363 /*!
       
   364  * Encode URL Field Information into the Versit Document
       
   365  */
       
   366 void QVersitContactExporterPrivate::encodeUrl(
       
   367     const QContactDetail& detail,
       
   368     QList<QVersitProperty>* generatedProperties,
       
   369     QSet<QString>* processedFields)
       
   370 {
       
   371     QContactUrl contactUrl = static_cast<QContactUrl>(detail);
       
   372     QVersitProperty property;
       
   373     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   374     encodeParameters(property, contactUrl.contexts());
       
   375     // The vCard specifications do not define any TYPEs for URL property.
       
   376     // No need to try to convert the subtypes to TYPEs.
       
   377     property.setValue(contactUrl.url());
       
   378     *generatedProperties << property;
       
   379     *processedFields << QContactUrl::FieldContext
       
   380                       << QContactUrl::FieldUrl;
       
   381 }
       
   382 
       
   383 /*!
       
   384  * Encode Uid Field Information into the Versit Document
       
   385  */
       
   386 void QVersitContactExporterPrivate::encodeUid(
       
   387     const QContactDetail& detail,
       
   388     QList<QVersitProperty>* generatedProperties,
       
   389     QSet<QString>* processedFields)
       
   390 {
       
   391     QContactGuid uid = static_cast<QContactGuid>(detail);
       
   392     QVersitProperty property;
       
   393     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   394     property.setValue(uid.guid());
       
   395     *generatedProperties << property;
       
   396     *processedFields << QContactGuid::FieldGuid;
       
   397 }
       
   398 
       
   399 /*!
       
   400  * Encode REV Field Information into the Versit Document
       
   401  */
       
   402 void QVersitContactExporterPrivate::encodeRev(
       
   403     const QContactDetail& detail,
       
   404     QList<QVersitProperty>* generatedProperties,
       
   405     QSet<QString>* processedFields)
       
   406 {
       
   407     QContactTimestamp  rev = static_cast<QContactTimestamp>(detail);
       
   408     QString value;
       
   409     QVersitProperty property;
       
   410     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   411 
       
   412     if ( rev.lastModified().toString(Qt::ISODate).size() ) {
       
   413         if ( rev.lastModified().timeSpec() == Qt::UTC ) {
       
   414             value = rev.lastModified().toString(Qt::ISODate) + QLatin1Char('Z');
       
   415         }
       
   416         else {
       
   417             value = rev.lastModified().toString(Qt::ISODate);
       
   418         }
       
   419         property.setValue(value);
       
   420         *generatedProperties << property;
       
   421         *processedFields << QContactTimestamp::FieldModificationTimestamp;
       
   422     } else if ( rev.created().toString(Qt::ISODate).size()) {
       
   423         if ( rev.created().timeSpec() == Qt::UTC ) {
       
   424             value = rev.created().toString(Qt::ISODate) + QLatin1Char('Z');
       
   425         }
       
   426         else {
       
   427             value = rev.created().toString(Qt::ISODate);
       
   428         }
       
   429         property.setValue(value);
       
   430         *generatedProperties << property;
       
   431         *processedFields << QContactTimestamp::FieldCreationTimestamp;
       
   432     }
       
   433 }
       
   434 
       
   435 /*!
       
   436  * Encode BirthDay Field Information into the Versit Document
       
   437  */
       
   438 void QVersitContactExporterPrivate::encodeBirthDay(
       
   439     const QContactDetail& detail,
       
   440     QList<QVersitProperty>* generatedProperties,
       
   441     QSet<QString>* processedFields)
       
   442 {
       
   443     QContactBirthday bday = static_cast<QContactBirthday>(detail);
       
   444     QVersitProperty property;
       
   445     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   446     QString value = bday.date().toString(Qt::ISODate);
       
   447     property.setValue(value);
       
   448     *generatedProperties << property;
       
   449     *processedFields << QContactBirthday::FieldBirthday;
       
   450 }
       
   451 
       
   452 /*!
       
   453  * Encode Comment i.e. Note Field Information into the Versit Document
       
   454  */
       
   455 void QVersitContactExporterPrivate::encodeNote(
       
   456     const QContactDetail& detail,
       
   457     QList<QVersitProperty>* generatedProperties,
       
   458     QSet<QString>* processedFields)
       
   459 {
       
   460     QContactNote contactNote = static_cast<QContactNote>(detail);
       
   461     QVersitProperty property;
       
   462     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   463     property.setValue(contactNote.note());
       
   464     *generatedProperties << property;
       
   465     *processedFields << QContactNote::FieldNote;
       
   466 }
       
   467 
       
   468 /*!
       
   469  * Encode Geo Prpoperties Field Information into the Versit Document
       
   470  */
       
   471 void QVersitContactExporterPrivate::encodeGeoLocation(
       
   472     const QContactDetail& detail,
       
   473     QList<QVersitProperty>* generatedProperties,
       
   474     QSet<QString>* processedFields)
       
   475 {
       
   476     QContactGeoLocation geoLocation = static_cast<QContactGeoLocation>(detail);
       
   477     QVersitProperty property;
       
   478     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   479     property.setValue(QStringList() << QString::number(geoLocation.longitude())
       
   480                       << QString::number(geoLocation.latitude()));
       
   481     property.setValueType(QVersitProperty::CompoundType);
       
   482     *generatedProperties << property;
       
   483     *processedFields << QContactGeoLocation::FieldLongitude
       
   484                       << QContactGeoLocation::FieldLatitude;
       
   485 }
       
   486 
       
   487 /*!
       
   488  * Encode organization properties to the versit document
       
   489  */
       
   490 void QVersitContactExporterPrivate::encodeOrganization(
       
   491     const QContactDetail& detail,
       
   492     QList<QVersitProperty>* generatedProperties,
       
   493     QSet<QString>* processedFields)
       
   494 {
       
   495     QContactOrganization organization = static_cast<QContactOrganization>(detail);
       
   496     if (organization.title().length() > 0) {
       
   497         QVersitProperty property;
       
   498         property.setName(QLatin1String("TITLE"));
       
   499         property.setValue(organization.title());
       
   500         *generatedProperties << property;
       
   501         *processedFields << QContactOrganization::FieldTitle;
       
   502     }
       
   503     if (organization.name().length() > 0 || organization.department().size() > 0) {
       
   504         QVersitProperty property;
       
   505         property.setName(QLatin1String("ORG"));
       
   506         QStringList values(organization.name());
       
   507         values.append(organization.department());
       
   508         property.setValue(values);
       
   509         property.setValueType(QVersitProperty::CompoundType);
       
   510         *generatedProperties << property;
       
   511         *processedFields << QContactOrganization::FieldName
       
   512                           << QContactOrganization::FieldDepartment;
       
   513     }
       
   514     if (organization.logoUrl().isValid()) {
       
   515         QVersitProperty property;
       
   516         if (encodeContentFromFile(organization.logoUrl().toString(), property)) {
       
   517             property.setName(QLatin1String("LOGO"));
       
   518             *generatedProperties << property;
       
   519             *processedFields << QContactOrganization::FieldLogoUrl;
       
   520         }
       
   521     }
       
   522     if (organization.assistantName().length() > 0) {
       
   523         QVersitProperty property;
       
   524         property.setName(QLatin1String("X-ASSISTANT"));
       
   525         property.setValue(organization.assistantName());
       
   526         *generatedProperties << property;
       
   527         *processedFields << QContactOrganization::FieldAssistantName;
       
   528     }
       
   529 
       
   530     if (organization.role().length() > 0) {
       
   531         QVersitProperty property;
       
   532         property.setName(QLatin1String("ROLE"));
       
   533         property.setValue(organization.role());
       
   534         *generatedProperties << property;
       
   535         *processedFields << QContactOrganization::FieldRole;
       
   536     }
       
   537 }
       
   538 
       
   539 void QVersitContactExporterPrivate::encodeRingtone(
       
   540     const QContactDetail &detail,
       
   541     QList<QVersitProperty>* generatedProperties,
       
   542     QSet<QString>* processedFields)
       
   543 {
       
   544     QContactRingtone ringtone = static_cast<QContactRingtone>(detail);
       
   545     QVersitProperty property;
       
   546     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   547     if (encodeContentFromFile(ringtone.audioRingtoneUrl().toLocalFile(), property)) {
       
   548         *generatedProperties << property;
       
   549         *processedFields << QContactRingtone::FieldAudioRingtoneUrl;
       
   550     }
       
   551 }
       
   552 
       
   553 /*!
       
   554  * Encode thumbnail content into the Versit Document
       
   555  */
       
   556 void QVersitContactExporterPrivate::encodeThumbnail(
       
   557     const QContactDetail &detail,
       
   558     QList<QVersitProperty>* generatedProperties,
       
   559     QSet<QString>* processedFields)
       
   560 {
       
   561     QContactThumbnail contactThumbnail = static_cast<QContactThumbnail>(detail);
       
   562     QVersitProperty property;
       
   563     property.setName(QLatin1String("PHOTO"));
       
   564     QImage image = contactThumbnail.thumbnail();
       
   565     if (image.isNull())
       
   566         return;
       
   567     QByteArray imageData;
       
   568     QBuffer buffer(&imageData);
       
   569     buffer.open(QIODevice::WriteOnly);
       
   570     // Always store a pixmap as a PNG.
       
   571     if (!image.save(&buffer, "PNG"))
       
   572         return;
       
   573     property.setValue(imageData);
       
   574     property.insertParameter(QLatin1String("TYPE"), QLatin1String("PNG"));
       
   575     *generatedProperties << property;
       
   576     *processedFields << QContactThumbnail::FieldThumbnail;
       
   577 }
       
   578 
       
   579 /*!
       
   580  * Encode avatar URIs into the Versit Document
       
   581  */
       
   582 void QVersitContactExporterPrivate::encodeAvatar(
       
   583     const QContactDetail &detail,
       
   584     QList<QVersitProperty>* generatedProperties,
       
   585     QSet<QString>* processedFields)
       
   586 {
       
   587     QVersitProperty property;
       
   588     property.setName(QLatin1String("PHOTO"));
       
   589     QContactAvatar contactAvatar = static_cast<QContactAvatar>(detail);
       
   590     QUrl imageUrl(contactAvatar.imageUrl());
       
   591     // XXX: fix up this mess: checking the scheme here and in encodeContentFromFile,
       
   592     // organisation logo and ringtone are QStrings but avatar is a QUrl
       
   593     if (!imageUrl.scheme().isEmpty() && !imageUrl.host().isEmpty()) {
       
   594         property.insertParameter(QLatin1String("VALUE"), QLatin1String("URL"));
       
   595         property.setValue(imageUrl.toString());
       
   596         *generatedProperties << property;
       
   597         *processedFields << QContactAvatar::FieldImageUrl;
       
   598     } else {
       
   599         if (encodeContentFromFile(contactAvatar.imageUrl().toString(), property)) {
       
   600             *generatedProperties << property;
       
   601             *processedFields << QContactAvatar::FieldImageUrl;
       
   602         }
       
   603     }
       
   604 }
       
   605 
       
   606 /*!
       
   607  * Encode gender property information into Versit Document
       
   608  */
       
   609 void QVersitContactExporterPrivate::encodeGender(
       
   610     const QContactDetail &detail,
       
   611     QList<QVersitProperty>* generatedProperties,
       
   612     QSet<QString>* processedFields)
       
   613 {
       
   614     QContactGender gender = static_cast<QContactGender>(detail);
       
   615     QVersitProperty property;
       
   616     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   617     property.setValue(gender.gender());
       
   618     *generatedProperties << property;
       
   619     *processedFields << QContactGender::FieldGender;
       
   620 }
       
   621 
       
   622 /*!
       
   623  * Encodes nickname property information into the Versit Document
       
   624  */
       
   625 void QVersitContactExporterPrivate::encodeNickname(
       
   626     const QContactDetail &detail,
       
   627     const QVersitDocument& document,
       
   628     QList<QVersitProperty>* removedProperties,
       
   629     QList<QVersitProperty>* generatedProperties,
       
   630     QSet<QString>* processedFields)
       
   631 {
       
   632     QContactNickname nicknameDetail = static_cast<QContactNickname>(detail);
       
   633     QVersitProperty property = takeProperty(document, QLatin1String("X-NICKNAME"), removedProperties);
       
   634     property.setName(QLatin1String("X-NICKNAME"));
       
   635     QStringList value(property.variantValue().toStringList());
       
   636     value.append(nicknameDetail.nickname());
       
   637     property.setValue(value);
       
   638     property.setValueType(QVersitProperty::ListType);
       
   639     *generatedProperties << property;
       
   640     *processedFields << QContactNickname::FieldNickname;
       
   641 }
       
   642 
       
   643 /*!
       
   644  * Encodes a contact tag into the Versit Document
       
   645  */
       
   646 void QVersitContactExporterPrivate::encodeTag(
       
   647     const QContactDetail &detail,
       
   648     const QVersitDocument& document,
       
   649     QList<QVersitProperty>* removedProperties,
       
   650     QList<QVersitProperty>* generatedProperties,
       
   651     QSet<QString>* processedFields)
       
   652 {
       
   653     QContactTag tagDetail = static_cast<QContactTag>(detail);
       
   654     QVersitProperty property = takeProperty(document, QLatin1String("CATEGORIES"), removedProperties);
       
   655     property.setName(QLatin1String("CATEGORIES"));
       
   656     QStringList value(property.variantValue().toStringList());
       
   657     value.append(tagDetail.tag());
       
   658     property.setValue(value);
       
   659     property.setValueType(QVersitProperty::ListType);
       
   660     *generatedProperties << property;
       
   661     *processedFields << QContactTag::FieldTag;
       
   662 }
       
   663 
       
   664 /*!
       
   665  * Encode anniversary information into Versit Document
       
   666  */
       
   667 void QVersitContactExporterPrivate::encodeAnniversary(
       
   668     const QContactDetail &detail,
       
   669     QList<QVersitProperty>* generatedProperties,
       
   670     QSet<QString>* processedFields)
       
   671 {
       
   672     QContactAnniversary anniversary = static_cast<QContactAnniversary>(detail);
       
   673     QVersitProperty property;
       
   674     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   675     property.setValue(anniversary.originalDate().toString(Qt::ISODate));
       
   676     *generatedProperties << property;
       
   677     *processedFields << QContactAnniversary::FieldOriginalDate;
       
   678 }
       
   679 
       
   680 /*!
       
   681  * Encode online account information into the Versit Document
       
   682  */
       
   683 void QVersitContactExporterPrivate::encodeOnlineAccount(
       
   684     const QContactDetail &detail,
       
   685     QList<QVersitProperty>* generatedProperties,
       
   686     QSet<QString>* processedFields)
       
   687 {
       
   688     QContactOnlineAccount onlineAccount = static_cast<QContactOnlineAccount>(detail);
       
   689     QStringList subTypes = onlineAccount.subTypes();
       
   690 
       
   691     if (subTypes.contains(QContactOnlineAccount::SubTypeSip) ||
       
   692         subTypes.contains(QContactOnlineAccount::SubTypeSipVoip) ||
       
   693         subTypes.contains(QContactOnlineAccount::SubTypeVideoShare) ||
       
   694         subTypes.contains(QContactOnlineAccount::SubTypeImpp)) {
       
   695         QVersitProperty property;
       
   696         encodeParameters(property, onlineAccount.contexts(), subTypes);
       
   697         QString name(QLatin1String("X-SIP"));
       
   698         if (subTypes.contains(QContactOnlineAccount::SubTypeImpp))
       
   699             name = QLatin1String("X-IMPP");
       
   700         property.setName(name);
       
   701         property.setValue(onlineAccount.accountUri());
       
   702         *generatedProperties << property;
       
   703         *processedFields << QContactOnlineAccount::FieldSubTypes
       
   704                           << QContactOnlineAccount::FieldAccountUri;
       
   705     }
       
   706 }
       
   707 
       
   708 /*!
       
   709  * Encode family versit property if its supported in Versit Document
       
   710  */
       
   711 void QVersitContactExporterPrivate::encodeFamily(
       
   712     const QContactDetail &detail,
       
   713     QList<QVersitProperty>* generatedProperties,
       
   714     QSet<QString>* processedFields)
       
   715 {
       
   716     QContactFamily family = static_cast<QContactFamily>(detail);
       
   717 
       
   718     if (family.spouse().size()) {
       
   719         QVersitProperty property;
       
   720         property.setName(QLatin1String("X-SPOUSE"));
       
   721         property.setValue(family.spouse());
       
   722         *generatedProperties << property;
       
   723         *processedFields << QContactFamily::FieldSpouse;
       
   724     }
       
   725 
       
   726     if (family.children().size()) {
       
   727         QVersitProperty property;
       
   728         property.setName(QLatin1String("X-CHILDREN"));
       
   729         property.setValue(family.children());
       
   730         property.setValueType(QVersitProperty::ListType);
       
   731         *generatedProperties << property;
       
   732         *processedFields << QContactFamily::FieldChildren;
       
   733     }
       
   734 }
       
   735 
       
   736 
       
   737 /*!
       
   738  * Encode family versit property if its supported in Versit Document
       
   739  */
       
   740 void QVersitContactExporterPrivate::encodeDisplayLabel(
       
   741     const QContactDetail &detail,
       
   742     const QVersitDocument& document,
       
   743     QList<QVersitProperty>* removedProperties,
       
   744     QList<QVersitProperty>* generatedProperties,
       
   745     QSet<QString>* processedFields)
       
   746 {
       
   747     // Override any previous FN property
       
   748     QVersitProperty property = takeProperty(document, QLatin1String("FN"), removedProperties);
       
   749     property.setName(mPropertyMappings.value(detail.definitionName()));
       
   750     QContactDisplayLabel displayLabel = static_cast<QContactDisplayLabel>(detail);
       
   751     if (!displayLabel.label().isEmpty()) {
       
   752         property.setValue(displayLabel.label());
       
   753         *generatedProperties << property;
       
   754         *processedFields << QContactDisplayLabel::FieldLabel;
       
   755     }
       
   756 }
       
   757 
       
   758 /*!
       
   759  * Finds a property in the \a document with the given \a propertyName, removes it and returns it.
       
   760  */
       
   761 QVersitProperty QVersitContactExporterPrivate::takeProperty(const QVersitDocument& document,
       
   762                                                             const QString& propertyName,
       
   763                                                             QList<QVersitProperty>* toBeRemoved) {
       
   764     foreach (const QVersitProperty& currentProperty, document.properties()) {
       
   765         if (currentProperty.name() == propertyName) {
       
   766             *toBeRemoved << currentProperty;
       
   767             return currentProperty;
       
   768         }
       
   769     }
       
   770     return QVersitProperty();
       
   771 }
       
   772 
       
   773 /*!
       
   774  * Check if \a resourceIdentifier represents a valid remote resource
       
   775  */
       
   776 bool QVersitContactExporterPrivate::isValidRemoteUrl(
       
   777     const QString& resourceIdentifier)
       
   778 {
       
   779     QUrl remoteResource(resourceIdentifier);
       
   780     if ((!remoteResource.scheme().isEmpty() &&
       
   781          !remoteResource.host().isEmpty()) ||
       
   782         resourceIdentifier.contains(QLatin1String("www."), Qt::CaseInsensitive))
       
   783         return true;
       
   784     return false;
       
   785 }
       
   786 
       
   787 /*!
       
   788  * Encode parameters to \a property
       
   789  */
       
   790 void QVersitContactExporterPrivate::encodeParameters(
       
   791     QVersitProperty& property,
       
   792     const QStringList& contexts,
       
   793     const QStringList& subTypes)
       
   794 {
       
   795     QStringList parameterList(contexts); // Contexts should be encoded first
       
   796     parameterList << subTypes;
       
   797     while (!parameterList.isEmpty()) {
       
   798         QString value = parameterList.takeLast();
       
   799         QString mappedValue = mParameterMappings.value(value);
       
   800         if (mappedValue.length() > 0) {
       
   801             // QVersitProperty::addParameter inserts into beginning.
       
   802             // This is why the last value is taken from the list
       
   803             property.insertParameter(QLatin1String("TYPE"),mappedValue);
       
   804         }
       
   805     }
       
   806 }
       
   807 
       
   808 /*!
       
   809  * Encode embedded content from the given \a resourcePath into \a property.
       
   810  */
       
   811 bool QVersitContactExporterPrivate::encodeContentFromFile(const QString& resourcePath,
       
   812                                                           QVersitProperty& property)
       
   813 {
       
   814     bool encodeContent = false;
       
   815     QVariant value;
       
   816     QByteArray imageData;
       
   817     QString mimeType;
       
   818     if (isValidRemoteUrl( resourcePath )) {
       
   819         encodeContent = true;
       
   820         value.setValue(resourcePath);
       
   821         property.insertParameter(QLatin1String("VALUE"), QLatin1String("URL"));
       
   822     } else if (mResourceHandler
       
   823                && mResourceHandler->loadResource(resourcePath, &imageData, &mimeType)) {
       
   824         value.setValue(imageData);
       
   825         if (!mimeType.isEmpty()) {
       
   826             // If mimeType is (eg.) "image/jpeg", set type parameter to "JPEG"
       
   827             int slashIndex = mimeType.indexOf(QLatin1Char('/'));
       
   828             if (slashIndex >= 0)
       
   829                 property.insertParameter(QLatin1String("TYPE"),
       
   830                                          mimeType.remove(0, slashIndex+1).toUpper());
       
   831         }
       
   832         encodeContent = true;
       
   833     } else {
       
   834         // The file doesn't exist. Don't encode the path to a local file.
       
   835     }
       
   836     property.setValue(value);
       
   837     return encodeContent;
       
   838 }