~chris.gagnon/+junk/qtpim-coverage

« back to all changes in this revision

Viewing changes to src/versit/qversitcontactexporter_p.cpp

  • Committer: chris.gagnon
  • Date: 2013-12-10 23:09:37 UTC
  • Revision ID: chris.gagnon@canonical.com-20131210230937-2akf1ft1edcttk87
first post

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtVersit module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include <qversitcontactexporter.h>
 
43
#include "qversitcontactexporter_p.h"
 
44
#include "qversitcontactimporter_p.h"
 
45
#include "qversitcontactsdefs_p.h"
 
46
#include "qversitutils_p.h"
 
47
 
 
48
#include <qcontact.h>
 
49
#include <qcontactdetails.h>
 
50
#include "qversitcontacthandler.h"
 
51
#include "qversitcontactpluginloader_p.h"
 
52
 
 
53
#include <QUrl>
 
54
#include <QBuffer>
 
55
 
 
56
QT_BEGIN_NAMESPACE_VERSIT
 
57
 
 
58
/*!
 
59
 * Constructor.
 
60
 */
 
61
QVersitContactExporterPrivate::QVersitContactExporterPrivate(const QStringList& profiles) :
 
62
    mDetailHandler(NULL),
 
63
    mDetailHandler2(NULL),
 
64
    mDetailHandlerVersion(0),
 
65
    mDefaultResourceHandler(new QVersitDefaultResourceHandler),
 
66
    mResourceHandler(mDefaultResourceHandler)
 
67
{
 
68
    // Detail mappings
 
69
    int versitPropertyCount =
 
70
        sizeof(versitContactDetailMappings)/sizeof(VersitContactDetailMapping);
 
71
    // Put them in in reverse order so the entries at the top of the list take precedence
 
72
    for (int i = versitPropertyCount-1; i >= 0; i--) {
 
73
        mPropertyMappings.insert(
 
74
                versitContactDetailMappings[i].detailType,
 
75
                    QPair<int, QString>(
 
76
                        versitContactDetailMappings[i].detailField,
 
77
                        QLatin1String(versitContactDetailMappings[i].versitPropertyName)));
 
78
    }
 
79
 
 
80
    // Contexts mappings
 
81
    int contextCount = sizeof(versitContextMappings)/sizeof(VersitContextMapping);
 
82
    for (int i=0; i < contextCount; i++) {
 
83
        mContextMappings.insert(
 
84
                versitContextMappings[i].contactContext,
 
85
                QLatin1String(versitContextMappings[i].versitString));
 
86
    }
 
87
 
 
88
    // Subtypes mappings
 
89
    int subTypeCount = sizeof(versitSubTypeMappings)/sizeof(VersitSubTypeMapping);
 
90
    for (int i=0; i < subTypeCount; i++) {
 
91
        mSubTypeMappings.insert(
 
92
                    QPair<QContactDetail::DetailType, int>(
 
93
                        versitSubTypeMappings[i].detailType, versitSubTypeMappings[i].contactSubType),
 
94
                        QLatin1String(versitSubTypeMappings[i].versitString));
 
95
    }
 
96
    mPluginDetailHandlers = QVersitContactPluginLoader::instance()->createContactHandlers(profiles);
 
97
}
 
98
 
 
99
/*!
 
100
 * Destructor.
 
101
 */
 
102
QVersitContactExporterPrivate::~QVersitContactExporterPrivate()
 
103
{
 
104
    delete mDefaultResourceHandler;
 
105
    foreach (QVersitContactHandler* pluginHandler, mPluginDetailHandlers) {
 
106
        delete pluginHandler;
 
107
    }
 
108
}
 
109
 
 
110
 
 
111
/*!
 
112
 * Export QT Contact into Versit Document.
 
113
 */
 
114
void QVersitContactExporterPrivate::exportContact(
 
115
    const QContact& contact,
 
116
    QVersitDocument& document)
 
117
{
 
118
    QList<QContactDetail> allDetails = contact.details();
 
119
    foreach (const QContactDetail& detail, allDetails) {
 
120
        if (mDetailHandler
 
121
            && mDetailHandler->preProcessDetail(contact, detail, &document))
 
122
            continue;
 
123
 
 
124
        QList<QVersitProperty> removedProperties;
 
125
        QList<QVersitProperty> generatedProperties;
 
126
        QSet<int> processedFields;
 
127
 
 
128
        switch (detail.type()) {
 
129
        case QContactDetail::TypeAddress:
 
130
            encodeAddress(detail, &generatedProperties, &processedFields);
 
131
            break;
 
132
        case QContactDetail::TypeAnniversary:
 
133
            encodeAnniversary(detail, &generatedProperties, &processedFields);
 
134
            break;
 
135
        case QContactDetail::TypeAvatar:
 
136
            encodeAvatar(detail, &generatedProperties, &processedFields);
 
137
            break;
 
138
        case QContactDetail::TypeBirthday:
 
139
            encodeBirthDay(detail, &generatedProperties, &processedFields);
 
140
            break;
 
141
        case QContactDetail::TypeDisplayLabel:
 
142
            encodeDisplayLabel(detail, document, &removedProperties, &generatedProperties, &processedFields);
 
143
            break;
 
144
        case QContactDetail::TypeEmailAddress:
 
145
            encodeEmail(detail, &generatedProperties, &processedFields);
 
146
            break;
 
147
        case QContactDetail::TypeExtendedDetail:
 
148
            encodeExtendedDetail(detail, &generatedProperties, &processedFields);
 
149
            break;
 
150
        case QContactDetail::TypeFamily:
 
151
            encodeFamily(detail, &generatedProperties, &processedFields);
 
152
            break;
 
153
        case QContactDetail::TypeFavorite:
 
154
            encodeFavorite(detail, &generatedProperties, &processedFields);
 
155
            break;
 
156
        case QContactDetail::TypeGender:
 
157
            encodeGender(detail, &generatedProperties, &processedFields);
 
158
            break;
 
159
        case QContactDetail::TypeGeoLocation:
 
160
            encodeGeoLocation(detail, &generatedProperties, &processedFields);
 
161
            break;
 
162
        case QContactDetail::TypeGuid:
 
163
            encodeUid(detail, &generatedProperties, &processedFields);
 
164
            break;
 
165
        case QContactDetail::TypeName:
 
166
            encodeName(detail, document, &removedProperties, &generatedProperties, &processedFields);
 
167
            break;
 
168
        case QContactDetail::TypeNickname:
 
169
            encodeNickname(detail, document, &removedProperties, &generatedProperties, &processedFields);
 
170
            break;
 
171
        case QContactDetail::TypeNote:
 
172
            encodeNote(detail, &generatedProperties, &processedFields);
 
173
            break;
 
174
        case QContactDetail::TypeOnlineAccount:
 
175
            encodeOnlineAccount(detail, &generatedProperties, &processedFields);
 
176
            break;
 
177
        case QContactDetail::TypeOrganization:
 
178
            encodeOrganization(detail, &generatedProperties, &processedFields);
 
179
            break;
 
180
        case QContactDetail::TypePhoneNumber:
 
181
            encodePhoneNumber(detail, &generatedProperties, &processedFields);
 
182
            break;
 
183
        case QContactDetail::TypeRingtone:
 
184
            encodeRingtone(detail, &generatedProperties, &processedFields);
 
185
            break;
 
186
        case QContactDetail::TypeTag:
 
187
            encodeTag(detail, document, &removedProperties, &generatedProperties, &processedFields);
 
188
            break;
 
189
        case QContactDetail::TypeTimestamp:
 
190
            encodeRev(detail, &generatedProperties, &processedFields);
 
191
            break;
 
192
        case QContactDetail::TypeUrl:
 
193
            encodeUrl(detail, &generatedProperties, &processedFields);
 
194
            break;
 
195
        case QContactDetail::TypeVersion:
 
196
            encodeVersion(detail, &generatedProperties, &processedFields);
 
197
            break;
 
198
        default:
 
199
            break;
 
200
        }
 
201
 
 
202
        // run plugin handlers
 
203
        foreach (QVersitContactExporterDetailHandlerV2* handler, mPluginDetailHandlers) {
 
204
            handler->detailProcessed(contact, detail, document,
 
205
                                     &processedFields, &removedProperties, &generatedProperties);
 
206
        }
 
207
        // run the v2 handler, if set
 
208
        if (mDetailHandler2 && mDetailHandlerVersion > 1) {
 
209
            mDetailHandler2->detailProcessed(contact, detail, document,
 
210
                                             &processedFields, &removedProperties, &generatedProperties);
 
211
        }
 
212
 
 
213
        foreach(const QVersitProperty& property, removedProperties) {
 
214
            document.removeProperty(property);
 
215
        }
 
216
        foreach(const QVersitProperty& property, generatedProperties) {
 
217
            document.addProperty(property);
 
218
        }
 
219
 
 
220
        if (mDetailHandler && mDetailHandlerVersion == 1) {
 
221
            mDetailHandler->postProcessDetail(contact, detail, !processedFields.isEmpty(), &document);
 
222
        }
 
223
    }
 
224
 
 
225
    // run plugin handlers
 
226
    foreach (QVersitContactExporterDetailHandlerV2* handler, mPluginDetailHandlers) {
 
227
        handler->contactProcessed(contact, &document);
 
228
    }
 
229
    // run the v2 handler, if set
 
230
    if (mDetailHandler2 && mDetailHandlerVersion > 1) {
 
231
        mDetailHandler2->contactProcessed(contact, &document);
 
232
    }
 
233
 
 
234
    ensureDocumentContainsName(&document);
 
235
    return;
 
236
}
 
237
 
 
238
/*!
 
239
 * Adds to \a document an empty "N" property if it doesn't already have one.
 
240
 */
 
241
void QVersitContactExporterPrivate::ensureDocumentContainsName(QVersitDocument* document)
 
242
{
 
243
    bool containsN = false;
 
244
    foreach (const QVersitProperty& property, document->properties()) {
 
245
        const QString& name = property.name();
 
246
        if (name == QStringLiteral("N")) {
 
247
            containsN = true;
 
248
        }
 
249
    }
 
250
 
 
251
    if (!containsN) {
 
252
        QVersitProperty nProperty;
 
253
        nProperty.setValueType(QVersitProperty::CompoundType);
 
254
        nProperty.setName(QStringLiteral("N"));
 
255
        nProperty.setValue(QStringList() << QString() << QString()
 
256
                           << QString() << QString() << QString());
 
257
        document->addProperty(nProperty);
 
258
    }
 
259
}
 
260
 
 
261
/*!
 
262
 * Encode Contact Name Field Information into the Versit Document
 
263
 */
 
264
void QVersitContactExporterPrivate::encodeName(
 
265
    const QContactDetail& detail,
 
266
    const QVersitDocument& document,
 
267
    QList<QVersitProperty>* removedProperties,
 
268
    QList<QVersitProperty>* generatedProperties,
 
269
    QSet<int>* processedFields)
 
270
{
 
271
    Q_UNUSED(document);
 
272
    Q_UNUSED(removedProperties);
 
273
    const QContactName &contactName = static_cast<const QContactName &>(detail);
 
274
    if (!contactName.lastName().isEmpty()
 
275
        || !contactName.firstName().isEmpty()
 
276
        || !contactName.middleName().isEmpty()
 
277
        || !contactName.prefix().isEmpty()
 
278
        || !contactName.suffix().isEmpty()) {
 
279
        QVersitProperty property;
 
280
        property.setName(mPropertyMappings.value(detail.type()).second);
 
281
        property.setValue(QStringList()
 
282
                          << contactName.lastName()
 
283
                          << contactName.firstName()
 
284
                          << contactName.middleName()
 
285
                          << contactName.prefix()
 
286
                          << contactName.suffix());
 
287
        property.setValueType(QVersitProperty::CompoundType);
 
288
        *generatedProperties << property;
 
289
    }
 
290
 
 
291
    *processedFields << QContactName::FieldLastName
 
292
                     << QContactName::FieldFirstName
 
293
                     << QContactName::FieldMiddleName
 
294
                     << QContactName::FieldPrefix
 
295
                     << QContactName::FieldSuffix;
 
296
}
 
297
 
 
298
/*!
 
299
 * Encode Phone Number Field Information into the Versit Document
 
300
 */
 
301
void QVersitContactExporterPrivate::encodePhoneNumber(
 
302
    const QContactDetail& detail,
 
303
    QList<QVersitProperty>* generatedProperties,
 
304
    QSet<int>* processedFields)
 
305
{
 
306
    const QContactPhoneNumber &phoneNumber = static_cast<const QContactPhoneNumber &>(detail);
 
307
    QList<int> subTypes = phoneNumber.subTypes();
 
308
    QList<int> phoneNumberContextInt;
 
309
 
 
310
    for (int i=0; i<phoneNumber.contexts().count(); i++)
 
311
         phoneNumberContextInt << phoneNumber.contexts().at(i);
 
312
 
 
313
    QVersitProperty property;
 
314
    if (subTypes.contains(QContactPhoneNumber::SubTypeAssistant))
 
315
        property.setName(QStringLiteral("X-ASSISTANT-TEL"));
 
316
    else
 
317
        property.setName(QStringLiteral("TEL"));
 
318
    encodeParameters(property, detail.type(), phoneNumberContextInt, subTypes);
 
319
    property.setValue(phoneNumber.number());
 
320
    *generatedProperties << property;
 
321
    *processedFields << QContactPhoneNumber::FieldContext
 
322
                      << QContactPhoneNumber::FieldSubTypes
 
323
                      << QContactPhoneNumber::FieldNumber;
 
324
}
 
325
 
 
326
/*!
 
327
 * Encode Email Field Information into the Versit Document
 
328
 */
 
329
void QVersitContactExporterPrivate::encodeEmail(
 
330
    const QContactDetail& detail,
 
331
    QList<QVersitProperty>* generatedProperties,
 
332
    QSet<int>* processedFields)
 
333
{
 
334
    const QContactEmailAddress &emailAddress = static_cast<const QContactEmailAddress &>(detail);
 
335
    QList<int> emailAddressContextInt;
 
336
 
 
337
    for (int i=0; i<emailAddress.contexts().count(); i++)
 
338
         emailAddressContextInt << emailAddress.contexts().at(i);
 
339
 
 
340
    QVersitProperty property;
 
341
    property.setName(mPropertyMappings.value(detail.type()).second);
 
342
    encodeParameters(property, detail.type(), emailAddressContextInt);
 
343
    property.setValue(emailAddress.emailAddress());
 
344
    *generatedProperties << property;
 
345
    *processedFields << QContactEmailAddress::FieldContext
 
346
                      << QContactEmailAddress::FieldEmailAddress;
 
347
}
 
348
 
 
349
/*!
 
350
 * Encode Address Field Information into the Versit Document
 
351
 */
 
352
void QVersitContactExporterPrivate::encodeAddress(
 
353
    const QContactDetail& detail,
 
354
    QList<QVersitProperty>* generatedProperties,
 
355
    QSet<int>* processedFields)
 
356
{
 
357
    const QContactAddress &address = static_cast<const QContactAddress &>(detail);
 
358
    QList<int> addressContextInt;
 
359
 
 
360
    for (int i=0; i<address.contexts().count(); i++)
 
361
         addressContextInt << address.contexts().at(i);
 
362
 
 
363
    QVersitProperty property;
 
364
    property.setName(mPropertyMappings.value(detail.type()).second);
 
365
    encodeParameters(property, detail.type(), addressContextInt, address.subTypes());
 
366
    property.setValue(QStringList()
 
367
                      << address.postOfficeBox()
 
368
                      << QString() // Leave out the extended address field
 
369
                      << address.street()
 
370
                      << address.locality()
 
371
                      << address.region()
 
372
                      << address.postcode()
 
373
                      << address.country());
 
374
    property.setValueType(QVersitProperty::CompoundType);
 
375
    *generatedProperties << property;
 
376
    *processedFields << QContactAddress::FieldContext
 
377
                      << QContactAddress::FieldSubTypes
 
378
                      << QContactAddress::FieldPostOfficeBox
 
379
                      << QContactAddress::FieldStreet
 
380
                      << QContactAddress::FieldLocality
 
381
                      << QContactAddress::FieldRegion
 
382
                      << QContactAddress::FieldPostcode
 
383
                      << QContactAddress::FieldCountry;
 
384
}
 
385
 
 
386
/*!
 
387
 * Encode URL Field Information into the Versit Document
 
388
 */
 
389
void QVersitContactExporterPrivate::encodeUrl(
 
390
    const QContactDetail& detail,
 
391
    QList<QVersitProperty>* generatedProperties,
 
392
    QSet<int>* processedFields)
 
393
{
 
394
    const QContactUrl &contactUrl = static_cast<const QContactUrl &>(detail);
 
395
    QList<int> contactUrlContextInt;
 
396
 
 
397
    for (int i=0; i<contactUrl.contexts().count(); i++)
 
398
         contactUrlContextInt << contactUrl.contexts().at(i);
 
399
 
 
400
    QVersitProperty property;
 
401
    property.setName(mPropertyMappings.value(detail.type()).second);
 
402
    encodeParameters(property, detail.type(), contactUrlContextInt);
 
403
    // The vCard specifications do not define any TYPEs for URL property.
 
404
    // No need to try to convert the subtypes to TYPEs.
 
405
    property.setValue(contactUrl.url());
 
406
    *generatedProperties << property;
 
407
    *processedFields << QContactUrl::FieldContext
 
408
                      << QContactUrl::FieldUrl;
 
409
}
 
410
 
 
411
/*!
 
412
 * Encode Uid Field Information into the Versit Document
 
413
 */
 
414
void QVersitContactExporterPrivate::encodeUid(
 
415
    const QContactDetail& detail,
 
416
    QList<QVersitProperty>* generatedProperties,
 
417
    QSet<int>* processedFields)
 
418
{
 
419
    const QContactGuid &uid = static_cast<const QContactGuid &>(detail);
 
420
    QVersitProperty property;
 
421
    property.setName(mPropertyMappings.value(detail.type()).second);
 
422
    property.setValue(uid.guid());
 
423
    *generatedProperties << property;
 
424
    *processedFields << QContactGuid::FieldGuid;
 
425
}
 
426
 
 
427
/*!
 
428
 * Encode REV Field Information into the Versit Document
 
429
 */
 
430
void QVersitContactExporterPrivate::encodeRev(
 
431
    const QContactDetail& detail,
 
432
    QList<QVersitProperty>* generatedProperties,
 
433
    QSet<int>* processedFields)
 
434
{
 
435
    const QContactTimestamp &rev = static_cast<const QContactTimestamp &>(detail);
 
436
    QString value;
 
437
    QVersitProperty property;
 
438
    property.setName(mPropertyMappings.value(detail.type()).second);
 
439
    if ( rev.lastModified().toString(Qt::ISODate).size() ) {
 
440
        if ( rev.lastModified().timeSpec() == Qt::UTC ) {
 
441
            value = rev.lastModified().toString(Qt::ISODate);
 
442
            if( !value.endsWith(QLatin1Char('Z'), Qt::CaseInsensitive) ) {
 
443
                value += QLatin1Char('Z');
 
444
            }
 
445
        }
 
446
        else {
 
447
            value = rev.lastModified().toString(Qt::ISODate);
 
448
        }
 
449
        property.setValue(value);
 
450
        *generatedProperties << property;
 
451
        *processedFields << QContactTimestamp::FieldModificationTimestamp;
 
452
    } else if ( rev.created().toString(Qt::ISODate).size()) {
 
453
        if ( rev.created().timeSpec() == Qt::UTC ) {
 
454
            value = rev.created().toString(Qt::ISODate);
 
455
            if( !value.endsWith(QLatin1Char('Z'), Qt::CaseInsensitive) ) {
 
456
                value += QLatin1Char('Z');
 
457
            }
 
458
        }
 
459
        else {
 
460
            value = rev.created().toString(Qt::ISODate);
 
461
        }
 
462
        property.setValue(value);
 
463
        *generatedProperties << property;
 
464
        *processedFields << QContactTimestamp::FieldCreationTimestamp;
 
465
    }
 
466
}
 
467
 
 
468
/*!
 
469
 * Encode Contact Version Field Information into the Versit Document
 
470
 */
 
471
void QVersitContactExporterPrivate::encodeVersion(
 
472
    const QContactDetail& detail,
 
473
    QList<QVersitProperty>* generatedProperties,
 
474
    QSet<int>* processedFields)
 
475
{
 
476
    const QContactVersion &version = static_cast<const QContactVersion &>(detail);
 
477
    QVersitProperty property;
 
478
    property.setName(mPropertyMappings.value(detail.type()).second);
 
479
    QStringList values(QString::number(version.sequenceNumber()));
 
480
    values.append(QString::fromLocal8Bit(version.extendedVersion()));
 
481
    property.setValue(values);
 
482
    property.setValueType(QVersitProperty::CompoundType);
 
483
    *generatedProperties << property;
 
484
    *processedFields << QContactVersion::FieldSequenceNumber
 
485
                      << QContactVersion::FieldExtendedVersion;
 
486
}
 
487
 
 
488
/*!
 
489
 * Encode BirthDay Field Information into the Versit Document
 
490
 */
 
491
void QVersitContactExporterPrivate::encodeBirthDay(
 
492
    const QContactDetail& detail,
 
493
    QList<QVersitProperty>* generatedProperties,
 
494
    QSet<int>* processedFields)
 
495
{
 
496
    const QContactBirthday &bday = static_cast<const QContactBirthday &>(detail);
 
497
    QVersitProperty property;
 
498
    property.setName(mPropertyMappings.value(detail.type()).second);
 
499
    QVariant variant = bday.value(QContactBirthday::FieldBirthday);
 
500
    QString value;
 
501
    if (variant.type() == QVariant::Date) {
 
502
        value = variant.toDate().toString(Qt::ISODate);
 
503
    } else if (variant.type() == QVariant::DateTime) {
 
504
        value = variant.toDateTime().toString(Qt::ISODate);
 
505
    } else {
 
506
        return;
 
507
    }
 
508
    property.setValue(value);
 
509
    *generatedProperties << property;
 
510
    *processedFields << QContactBirthday::FieldBirthday;
 
511
}
 
512
 
 
513
/*!
 
514
 * Encodes displaylabel property information into the Versit Document
 
515
 */
 
516
void QVersitContactExporterPrivate::encodeDisplayLabel(
 
517
    const QContactDetail &detail,
 
518
    const QVersitDocument& document,
 
519
    QList<QVersitProperty>* removedProperties,
 
520
    QList<QVersitProperty>* generatedProperties,
 
521
    QSet<int>* processedFields)
 
522
{
 
523
    const QContactDisplayLabel &displaylabelDetail = static_cast<const QContactDisplayLabel &>(detail);
 
524
    QVersitProperty property =
 
525
        VersitUtils::takeProperty(document, QStringLiteral("FN"), removedProperties);
 
526
    property.setName(QStringLiteral("FN"));
 
527
    QStringList value(property.variantValue().toStringList());
 
528
    value.append(displaylabelDetail.label());
 
529
    property.setValue(value);
 
530
    *generatedProperties << property;
 
531
    *processedFields << QContactDisplayLabel::FieldLabel;
 
532
}
 
533
 
 
534
/*!
 
535
 * Encode Comment i.e. Note Field Information into the Versit Document
 
536
 */
 
537
void QVersitContactExporterPrivate::encodeNote(
 
538
    const QContactDetail& detail,
 
539
    QList<QVersitProperty>* generatedProperties,
 
540
    QSet<int>* processedFields)
 
541
{
 
542
    const QContactNote &contactNote = static_cast<const QContactNote &>(detail);
 
543
    QVersitProperty property;
 
544
    property.setName(mPropertyMappings.value(detail.type()).second);
 
545
    property.setValue(contactNote.note());
 
546
    *generatedProperties << property;
 
547
    *processedFields << QContactNote::FieldNote;
 
548
}
 
549
 
 
550
/*!
 
551
 * Encode Geo Prpoperties Field Information into the Versit Document
 
552
 */
 
553
void QVersitContactExporterPrivate::encodeGeoLocation(
 
554
    const QContactDetail& detail,
 
555
    QList<QVersitProperty>* generatedProperties,
 
556
    QSet<int>* processedFields)
 
557
{
 
558
    const QContactGeoLocation &geoLocation = static_cast<const QContactGeoLocation &>(detail);
 
559
    QVersitProperty property;
 
560
    property.setName(mPropertyMappings.value(detail.type()).second);
 
561
    property.setValue(QStringList() << QString::number(geoLocation.latitude())
 
562
                      << QString::number(geoLocation.longitude()));
 
563
    property.setValueType(QVersitProperty::CompoundType);
 
564
    *generatedProperties << property;
 
565
    *processedFields << QContactGeoLocation::FieldLongitude
 
566
                      << QContactGeoLocation::FieldLatitude;
 
567
}
 
568
 
 
569
/*!
 
570
 * Encode organization properties to the versit document
 
571
 */
 
572
void QVersitContactExporterPrivate::encodeOrganization(
 
573
    const QContactDetail& detail,
 
574
    QList<QVersitProperty>* generatedProperties,
 
575
    QSet<int>* processedFields)
 
576
{
 
577
    const QContactOrganization &organization = static_cast<const QContactOrganization &>(detail);
 
578
    if (organization.title().length() > 0) {
 
579
        QVersitProperty property;
 
580
        property.setName(QStringLiteral("TITLE"));
 
581
        property.setValue(organization.title());
 
582
        *generatedProperties << property;
 
583
        *processedFields << QContactOrganization::FieldTitle;
 
584
    }
 
585
    if (organization.name().length() > 0 || organization.department().size() > 0) {
 
586
        QVersitProperty property;
 
587
        property.setName(QStringLiteral("ORG"));
 
588
        QStringList values(organization.name());
 
589
        values.append(organization.department());
 
590
        property.setValue(values);
 
591
        property.setValueType(QVersitProperty::CompoundType);
 
592
        *generatedProperties << property;
 
593
        *processedFields << QContactOrganization::FieldName
 
594
                          << QContactOrganization::FieldDepartment;
 
595
    }
 
596
    if (organization.logoUrl().isValid()) {
 
597
        QVersitProperty property;
 
598
        if (encodeContentFromFile(organization.logoUrl().toString(), property)) {
 
599
            property.setName(QStringLiteral("LOGO"));
 
600
            *generatedProperties << property;
 
601
            *processedFields << QContactOrganization::FieldLogoUrl;
 
602
        }
 
603
    }
 
604
    if (organization.assistantName().length() > 0) {
 
605
        QVersitProperty property;
 
606
        property.setName(QStringLiteral("X-ASSISTANT"));
 
607
        property.setValue(organization.assistantName());
 
608
        *generatedProperties << property;
 
609
        *processedFields << QContactOrganization::FieldAssistantName;
 
610
    }
 
611
 
 
612
    if (organization.role().length() > 0) {
 
613
        QVersitProperty property;
 
614
        property.setName(QStringLiteral("ROLE"));
 
615
        property.setValue(organization.role());
 
616
        *generatedProperties << property;
 
617
        *processedFields << QContactOrganization::FieldRole;
 
618
    }
 
619
}
 
620
 
 
621
void QVersitContactExporterPrivate::encodeRingtone(
 
622
    const QContactDetail &detail,
 
623
    QList<QVersitProperty>* generatedProperties,
 
624
    QSet<int>* processedFields)
 
625
{
 
626
    const QContactRingtone &ringtone = static_cast<const QContactRingtone &>(detail);
 
627
    QVersitProperty property;
 
628
    property.setName(mPropertyMappings.value(detail.type()).second);
 
629
    QUrl audioUrl(ringtone.audioRingtoneUrl());
 
630
    // Url value
 
631
    if (!audioUrl.scheme().isEmpty() && !audioUrl.host().isEmpty() &&
 
632
            audioUrl.scheme() != QStringLiteral("file")) {
 
633
        property.insertParameter(QStringLiteral("VALUE"), QStringLiteral("URL"));
 
634
        property.setValue(audioUrl.toString());
 
635
        *generatedProperties << property;
 
636
        *processedFields << QContactRingtone::FieldAudioRingtoneUrl;
 
637
    // Local value
 
638
    } else if (encodeContentFromFile(ringtone.audioRingtoneUrl().toLocalFile(), property)) {
 
639
        *generatedProperties << property;
 
640
        *processedFields << QContactRingtone::FieldAudioRingtoneUrl;
 
641
    }
 
642
}
 
643
 
 
644
/*!
 
645
 * Encode avatar URIs into the Versit Document
 
646
 */
 
647
void QVersitContactExporterPrivate::encodeAvatar(
 
648
    const QContactDetail &detail,
 
649
    QList<QVersitProperty>* generatedProperties,
 
650
    QSet<int>* processedFields)
 
651
{
 
652
    QVersitProperty property;
 
653
    property.setName(QStringLiteral("PHOTO"));
 
654
    const QContactAvatar &contactAvatar = static_cast<const QContactAvatar &>(detail);
 
655
    QUrl imageUrl(contactAvatar.imageUrl());
 
656
    // XXX: fix up this mess: checking the scheme here and in encodeContentFromFile,
 
657
    // organisation logo and ringtone are QStrings but avatar is a QUrl
 
658
    if (!imageUrl.scheme().isEmpty()
 
659
            && !imageUrl.host().isEmpty()
 
660
            && imageUrl.scheme() != QStringLiteral("file")) {
 
661
        property.insertParameter(QStringLiteral("VALUE"), QStringLiteral("URL"));
 
662
        property.setValue(imageUrl.toString());
 
663
        *generatedProperties << property;
 
664
        *processedFields << QContactAvatar::FieldImageUrl;
 
665
    } else {
 
666
        if (encodeContentFromFile(contactAvatar.imageUrl().toLocalFile(), property)) {
 
667
            *generatedProperties << property;
 
668
            *processedFields << QContactAvatar::FieldImageUrl;
 
669
        }
 
670
    }
 
671
}
 
672
 
 
673
/*!
 
674
 * Encode gender property information into Versit Document
 
675
 */
 
676
void QVersitContactExporterPrivate::encodeGender(
 
677
    const QContactDetail &detail,
 
678
    QList<QVersitProperty>* generatedProperties,
 
679
    QSet<int>* processedFields)
 
680
{
 
681
    const QContactGender &gender = static_cast<const QContactGender &>(detail);
 
682
    if (!gender.gender())
 
683
        return;
 
684
 
 
685
    QVersitProperty property;
 
686
    property.setName(mPropertyMappings.value(detail.type()).second);
 
687
    switch (gender.gender()) {
 
688
    case QContactGender::GenderMale:
 
689
        property.setValue(QStringLiteral("Male"));
 
690
        break;
 
691
    case QContactGender::GenderFemale:
 
692
        property.setValue(QStringLiteral("Female"));
 
693
        break;
 
694
    case QContactGender::GenderUnspecified:
 
695
        property.setValue(QStringLiteral("Unspecified"));
 
696
        break;
 
697
    default:
 
698
        // May only happen if new gender values are added to QContactGender
 
699
        // without adding them support above.
 
700
        qWarning() << "Trying to encode unknown gender value.";
 
701
        return;
 
702
    }
 
703
    *generatedProperties << property;
 
704
    *processedFields << QContactGender::FieldGender;
 
705
}
 
706
 
 
707
/*!
 
708
 * Encodes nickname property information into the Versit Document
 
709
 */
 
710
void QVersitContactExporterPrivate::encodeNickname(
 
711
    const QContactDetail &detail,
 
712
    const QVersitDocument& document,
 
713
    QList<QVersitProperty>* removedProperties,
 
714
    QList<QVersitProperty>* generatedProperties,
 
715
    QSet<int>* processedFields)
 
716
{
 
717
    const QContactNickname &nicknameDetail = static_cast<const QContactNickname &>(detail);
 
718
    QVersitProperty property =
 
719
        VersitUtils::takeProperty(document, QStringLiteral("X-NICKNAME"), removedProperties);
 
720
    property.setName(QStringLiteral("X-NICKNAME"));
 
721
    QStringList value(property.variantValue().toStringList());
 
722
    value.append(nicknameDetail.nickname());
 
723
    property.setValue(value);
 
724
    property.setValueType(QVersitProperty::ListType);
 
725
    *generatedProperties << property;
 
726
    *processedFields << QContactNickname::FieldNickname;
 
727
}
 
728
 
 
729
/*!
 
730
 * Encodes a contact tag into the Versit Document
 
731
 */
 
732
void QVersitContactExporterPrivate::encodeTag(
 
733
    const QContactDetail &detail,
 
734
    const QVersitDocument& document,
 
735
    QList<QVersitProperty>* removedProperties,
 
736
    QList<QVersitProperty>* generatedProperties,
 
737
    QSet<int>* processedFields)
 
738
{
 
739
    const QContactTag &tagDetail = static_cast<const QContactTag &>(detail);
 
740
    QVersitProperty property =
 
741
        VersitUtils::takeProperty(document, QStringLiteral("CATEGORIES"), removedProperties);
 
742
    property.setName(QStringLiteral("CATEGORIES"));
 
743
    QStringList value(property.variantValue().toStringList());
 
744
    value.append(tagDetail.tag());
 
745
    property.setValue(value);
 
746
    property.setValueType(QVersitProperty::ListType);
 
747
    *generatedProperties << property;
 
748
    *processedFields << QContactTag::FieldTag;
 
749
}
 
750
 
 
751
/*!
 
752
 * Encode anniversary information into Versit Document
 
753
 */
 
754
void QVersitContactExporterPrivate::encodeAnniversary(
 
755
    const QContactDetail &detail,
 
756
    QList<QVersitProperty>* generatedProperties,
 
757
    QSet<int>* processedFields)
 
758
{
 
759
    const QContactAnniversary &anniversary = static_cast<const QContactAnniversary &>(detail);
 
760
    QVersitProperty property;
 
761
    property.setName(mPropertyMappings.value(detail.type()).second);
 
762
    property.setValue(anniversary.originalDate().toString(Qt::ISODate));
 
763
    *generatedProperties << property;
 
764
    *processedFields << QContactAnniversary::FieldOriginalDate;
 
765
}
 
766
 
 
767
/*!
 
768
 * Encode online account information into the Versit Document
 
769
 */
 
770
void QVersitContactExporterPrivate::encodeOnlineAccount(
 
771
    const QContactDetail &detail,
 
772
    QList<QVersitProperty>* generatedProperties,
 
773
    QSet<int>* processedFields)
 
774
{
 
775
    const QContactOnlineAccount &onlineAccount = static_cast<const QContactOnlineAccount &>(detail);
 
776
    QList<int> subTypes = onlineAccount.subTypes();
 
777
 
 
778
    QContactOnlineAccount::Protocol protocol = onlineAccount.protocol();
 
779
 
 
780
    QString propertyName;
 
781
 
 
782
    if (protocol == QContactOnlineAccount::ProtocolJabber) {
 
783
        propertyName = QStringLiteral("X-JABBER");
 
784
    } else if (protocol == QContactOnlineAccount::ProtocolAim) {
 
785
        propertyName = QStringLiteral("X-AIM");
 
786
    } else if (protocol == QContactOnlineAccount::ProtocolIcq) {
 
787
        propertyName = QStringLiteral("X-ICQ");
 
788
    } else if (protocol == QContactOnlineAccount::ProtocolMsn) {
 
789
        propertyName = QStringLiteral("X-MSN");
 
790
    } else if (protocol == QContactOnlineAccount::ProtocolQq) {
 
791
        propertyName = QStringLiteral("X-QQ");
 
792
    } else if (protocol == QContactOnlineAccount::ProtocolYahoo) {
 
793
        propertyName = QStringLiteral("X-YAHOO");
 
794
    } else if (protocol == QContactOnlineAccount::ProtocolSkype) {
 
795
        propertyName = QStringLiteral("X-SKYPE");
 
796
    } else if (subTypes.contains(QContactOnlineAccount::SubTypeSip) ||
 
797
               subTypes.contains(QContactOnlineAccount::SubTypeSipVoip) ||
 
798
               subTypes.contains(QContactOnlineAccount::SubTypeVideoShare)) {
 
799
        propertyName = QStringLiteral("X-SIP");
 
800
    } else if (subTypes.contains(QContactOnlineAccount::SubTypeImpp)) {
 
801
        propertyName = QStringLiteral("X-IMPP");
 
802
    }
 
803
 
 
804
    if (!propertyName.isEmpty()) {
 
805
        QList<int> onlineAccountContextInt;
 
806
 
 
807
        for (int i=0; i<onlineAccount.contexts().count(); i++)
 
808
             onlineAccountContextInt << onlineAccount.contexts().at(i);
 
809
 
 
810
        QVersitProperty property;
 
811
        encodeParameters(property, detail.type(), onlineAccountContextInt, subTypes);
 
812
        property.setName(propertyName);
 
813
        property.setValue(onlineAccount.accountUri());
 
814
        *generatedProperties << property;
 
815
        *processedFields << QContactOnlineAccount::FieldSubTypes
 
816
                         << QContactOnlineAccount::FieldAccountUri;
 
817
    }
 
818
}
 
819
 
 
820
/*!
 
821
 * Encode family versit property if its supported in Versit Document
 
822
 */
 
823
void QVersitContactExporterPrivate::encodeFamily(
 
824
    const QContactDetail &detail,
 
825
    QList<QVersitProperty>* generatedProperties,
 
826
    QSet<int>* processedFields)
 
827
{
 
828
    const QContactFamily &family = static_cast<const QContactFamily &>(detail);
 
829
 
 
830
    if (family.spouse().size()) {
 
831
        QVersitProperty property;
 
832
        property.setName(QStringLiteral("X-SPOUSE"));
 
833
        property.setValue(family.spouse());
 
834
        *generatedProperties << property;
 
835
        *processedFields << QContactFamily::FieldSpouse;
 
836
    }
 
837
 
 
838
    if (family.children().size()) {
 
839
        QVersitProperty property;
 
840
        property.setName(QStringLiteral("X-CHILDREN"));
 
841
        property.setValue(family.children());
 
842
        property.setValueType(QVersitProperty::ListType);
 
843
        *generatedProperties << property;
 
844
        *processedFields << QContactFamily::FieldChildren;
 
845
    }
 
846
}
 
847
 
 
848
/*!
 
849
 * Encode favorite versit property if its supported in Versit Document
 
850
 */
 
851
void QVersitContactExporterPrivate::encodeFavorite(
 
852
        const QContactDetail &detail,
 
853
        QList<QVersitProperty>* generatedProperties,
 
854
        QSet<int>* processedFields)
 
855
{
 
856
    const QContactFavorite &favorite = static_cast<const QContactFavorite &>(detail);
 
857
    QVersitProperty property;
 
858
    property.setName(mPropertyMappings.value(detail.type()).second);
 
859
    QString isFavorite = favorite.isFavorite() ? QStringLiteral("true") : QStringLiteral("false");
 
860
    property.setValue(QStringList() << isFavorite
 
861
                      << QString::number(favorite.index()));
 
862
    property.setValueType(QVersitProperty::CompoundType);
 
863
    *generatedProperties << property;
 
864
    *processedFields << QContactFavorite::FieldFavorite
 
865
                     << QContactFavorite::FieldIndex;
 
866
}
 
867
 
 
868
/*!
 
869
 * Encode extended detail into the Versit Document
 
870
 */
 
871
void QVersitContactExporterPrivate::encodeExtendedDetail(
 
872
    const QContactDetail &detail,
 
873
    QList<QVersitProperty>* generatedProperties,
 
874
    QSet<int>* processedFields)
 
875
{
 
876
    const QContactExtendedDetail &extendedDetail =
 
877
            static_cast<const QContactExtendedDetail &>(detail);
 
878
    QVersitProperty property;
 
879
    property.setName(mPropertyMappings.value(extendedDetail.type()).second);
 
880
    QString dataAsJson;
 
881
    if (VersitUtils::convertToJson(extendedDetail.data(), &dataAsJson)) {
 
882
        property.setValue(QStringList() << extendedDetail.name() << dataAsJson);
 
883
    } else {
 
884
        qWarning() << Q_FUNC_INFO << "Failed to export an extended detail";
 
885
        return;
 
886
    }
 
887
    property.setValueType(QVersitProperty::CompoundType);
 
888
    *generatedProperties << property;
 
889
    *processedFields << QContactExtendedDetail::FieldName
 
890
                     << QContactExtendedDetail::FieldData;
 
891
}
 
892
 
 
893
/*!
 
894
 * Check if \a resourceIdentifier represents a valid remote resource
 
895
 */
 
896
bool QVersitContactExporterPrivate::isValidRemoteUrl(
 
897
    const QString& resourceIdentifier)
 
898
{
 
899
    QUrl remoteResource(resourceIdentifier);
 
900
    if ((!remoteResource.scheme().isEmpty() &&
 
901
         !remoteResource.host().isEmpty()) ||
 
902
        resourceIdentifier.contains(QStringLiteral("www."), Qt::CaseInsensitive))
 
903
        return true;
 
904
    return false;
 
905
}
 
906
 
 
907
/*!
 
908
 * Encode parameters to \a property
 
909
 */
 
910
void QVersitContactExporterPrivate::encodeParameters(
 
911
    QVersitProperty& property,
 
912
    const QContactDetail::DetailType detailType,
 
913
    const QList<int>& contexts,
 
914
    const QList<int>& subTypes)
 
915
{
 
916
    QList<int> contextsList(contexts); // Contexts should be encoded first
 
917
    QList<int> subtypesList(subTypes); // Contexts should be encoded first
 
918
 
 
919
    while (!contextsList.isEmpty()) {
 
920
        int value = contextsList.takeLast();
 
921
        QString mappedValue = mContextMappings.value(value);
 
922
        if (mappedValue.length() > 0) {
 
923
            // QVersitProperty::addParameter inserts into beginning.
 
924
            // This is why the last value is taken from the list
 
925
            property.insertParameter(QStringLiteral("TYPE"),mappedValue);
 
926
        }
 
927
    }
 
928
 
 
929
    while (!subtypesList.isEmpty()) {
 
930
        int value = subtypesList.takeLast();
 
931
        QString mappedValue = mSubTypeMappings.value(QPair<QContactDetail::DetailType, int>(
 
932
                                                          detailType, value));
 
933
        if (mappedValue.length() > 0) {
 
934
            // QVersitProperty::addParameter inserts into beginning.
 
935
            // This is why the last value is taken from the list
 
936
            property.insertParameter(QStringLiteral("TYPE"),mappedValue);
 
937
        }
 
938
    }
 
939
}
 
940
 
 
941
/*!
 
942
 * Encode embedded content from the given \a resourcePath into \a property.
 
943
 */
 
944
bool QVersitContactExporterPrivate::encodeContentFromFile(const QString& resourcePath,
 
945
                                                          QVersitProperty& property)
 
946
{
 
947
    bool encodeContent = false;
 
948
    QVariant value;
 
949
    QByteArray imageData;
 
950
    QString mimeType;
 
951
    if (isValidRemoteUrl( resourcePath )) {
 
952
        encodeContent = true;
 
953
        value.setValue(resourcePath);
 
954
        property.insertParameter(QStringLiteral("VALUE"), QStringLiteral("uri"));
 
955
    } else if (mResourceHandler
 
956
               && mResourceHandler->loadResource(resourcePath, &imageData, &mimeType)) {
 
957
        value.setValue(imageData);
 
958
        if (!mimeType.isEmpty()) {
 
959
            // If mimeType is (eg.) "image/jpeg", set type parameter to "JPEG"
 
960
            int slashIndex = mimeType.indexOf(QLatin1Char('/'));
 
961
            if (slashIndex >= 0)
 
962
                property.insertParameter(QStringLiteral("TYPE"),
 
963
                                         mimeType.remove(0, slashIndex+1).toUpper());
 
964
        }
 
965
        encodeContent = true;
 
966
    } else {
 
967
        // The file doesn't exist. Don't encode the path to a local file.
 
968
    }
 
969
    property.setValue(value);
 
970
    return encodeContent;
 
971
}
 
972
 
 
973
QT_END_NAMESPACE_VERSIT