qtmobility/tests/auto/qversit/tst_qversit.cpp
changeset 14 6fbed849b4f4
parent 11 06b8e2af4411
--- a/qtmobility/tests/auto/qversit/tst_qversit.cpp	Fri Jun 11 14:26:25 2010 +0300
+++ b/qtmobility/tests/auto/qversit/tst_qversit.cpp	Wed Jun 23 19:08:38 2010 +0300
@@ -43,6 +43,7 @@
 #include "tst_qversit.h"
 #include "qversitreader.h"
 #include "qversitreader_p.h"
+#include "qversitcontactexporter.h"
 #include "qversitcontactimporter.h"
 #include "qcontact.h"
 #include "qcontactmanager.h"
@@ -81,6 +82,102 @@
     int mIndex;
     QMap<QString, QByteArray> mObjects;
 };
+
+
+class MyDetailHandler : public QVersitContactExporterDetailHandler {
+public:
+    MyDetailHandler() : detailNumber(0) {}
+    bool preProcessDetail(const QContact& contact, const QContactDetail& detail,
+                          QVersitDocument* document) {
+        Q_UNUSED(contact) Q_UNUSED(detail) Q_UNUSED(document)
+        return false;
+    }
+    /* eg. a detail with definition name "Detail" and fields "Field1"="Value1" and
+     * "Field2"="Value2" will be exported to the vCard properties:
+     * G0.DETAIL-FIELD1:Value1
+     * G0.DETAIL-FIELD2:Value2
+     * And the next detail (say, "Detail" with a field "Field1"="Value3" will generate:
+     * G1.DETAIL-FIELD1:Value3
+     * ie. Different details will have different vCard groups.
+     */
+    bool postProcessDetail(const QContact& contact, const QContactDetail& detail,
+                           bool alreadyProcessed, QVersitDocument* document) {
+        Q_UNUSED(contact)
+        // beware: if the base implementation exports some but not all fields, alreadyProcessed
+        // will be true and the unprocessed fields won't be exported
+        if (alreadyProcessed)
+            return false;
+        if (detail.definitionName() == QContactType::DefinitionName)
+            return false; // special case of an unhandled detail that we don't export
+        QVersitProperty property;
+        QVariantMap fields = detail.variantValues();
+        // fields from the same detail have the same group so the importer can collate them
+        QString detailGroup = QLatin1String("G") + QString::number(detailNumber++);
+        for (QVariantMap::const_iterator it = fields.constBegin();
+                it != fields.constEnd();
+                it++) {
+            property.setGroups(QStringList(detailGroup));
+            // beware: detail.definitionName and the field name will be made uppercase on export
+            property.setName(QLatin1String("X-QCONTACTDETAIL-")
+                             + detail.definitionName()
+                             + QLatin1String("-")
+                             + it.key());
+            // beware: this might not handle nonstring values properly:
+            property.setValue(it.value());
+            document->addProperty(property);
+        }
+        return true;
+    }
+private:
+    int detailNumber;
+};
+
+class MyPropertyHandler : public QVersitContactImporterPropertyHandler {
+public:
+    bool preProcessProperty(const QVersitDocument& document, const QVersitProperty& property,
+                            int contactIndex, QContact* contact) {
+        Q_UNUSED(document) Q_UNUSED(property) Q_UNUSED(contactIndex) Q_UNUSED(contact)
+        return false;
+    }
+    /* eg. if the document has the properties:
+     * G0.DETAIL-FIELD1:Value1
+     * G0.DETAIL-FIELD2:Value2
+     * G1.DETAIL-FIELD1:Value3
+     * This will generate two details - the first with fields "FIELD1"="Value1" and
+     * "FIELD2"="Value2" and the second with "FIELD1"="Value3"
+     * ie. the vCard groups determine which properties form a single detail.
+     */
+    bool postProcessProperty(const QVersitDocument& document, const QVersitProperty& property,
+                             bool alreadyProcessed, int contactIndex, QContact* contact) {
+        Q_UNUSED(document) Q_UNUSED(contactIndex)
+        const QString prefix = QLatin1String("X-QCONTACTDETAIL-");
+        if (alreadyProcessed)
+            return false;
+        if (!property.name().startsWith(prefix))
+            return false;
+        QString detailAndField = property.name().mid(prefix.size());
+        QStringList detailAndFieldParts = detailAndField.split(QLatin1Char('-'),
+                                                               QString::SkipEmptyParts);
+        if (detailAndFieldParts.size() != 2)
+            return false;
+        QString definitionName = detailAndFieldParts.at(0);
+        QString fieldName = detailAndFieldParts.at(1);
+        if (property.groups().size() != 1)
+            return false;
+        QString group = property.groups().first();
+        // find a detail generated from the a property with the same group
+        QContactDetail detail = handledDetails.value(group);
+        // make sure the the existing detail has the same definition name
+        if (detail.definitionName() != definitionName)
+            detail = QContactDetail(definitionName);
+        detail.setValue(fieldName, property.value());
+        contact->saveDetail(&detail);
+        handledDetails.insert(group, detail);
+        return false;
+    }
+    QMap<QString, QContactDetail> handledDetails; // map from group name to detail
+};
+
 QTM_END_NAMESPACE
 
 QTM_USE_NAMESPACE
@@ -90,6 +187,7 @@
 #endif
 
 Q_DECLARE_METATYPE(QList<QContact>)
+Q_DECLARE_METATYPE(QContact)
 
 void tst_QVersit::testImportFiles()
 {
@@ -111,6 +209,8 @@
     QVersitContactImporter importer;
     MyQVersitResourceHandler resourceHandler;
     importer.setResourceHandler(&resourceHandler);
+    MyPropertyHandler propertyHandler;
+    importer.setPropertyHandler(&propertyHandler);
     QVERIFY(importer.importDocuments(documents));
     QList<QContact> contacts = importer.contacts();
 
@@ -161,7 +261,6 @@
         name.setCustomLabel(QLatin1String("Firstname Lastname"));
         name.setFirstName(QLatin1String("Firstname"));
         name.setLastName(QLatin1String("Lastname"));
-        name.setMiddleName(QString());
         name.setPrefix(QLatin1String("Title"));
         name.setSuffix(QLatin1String("Suffix"));
         contact.saveDetail(&name);
@@ -197,9 +296,6 @@
         name.setCustomLabel(QLatin1String("first last"));
         name.setFirstName(QLatin1String("first"));
         name.setLastName(QLatin1String("last"));
-        name.setMiddleName(QString());
-        name.setPrefix(QString());
-        name.setSuffix(QString());
         contact.saveDetail(&name);
         QContactOrganization org;
         org.setName(QLatin1String("Nokia"));
@@ -218,10 +314,6 @@
         QContact contact;
         QContactName name;
         name.setFirstName(QLatin1String("name"));
-        name.setLastName(QString());
-        name.setMiddleName(QString());
-        name.setPrefix(QString());
-        name.setSuffix(QString());
         contact.saveDetail(&name);
         QContactFamily family;
         family.setChildren(QStringList(QLatin1String("Child1")));
@@ -250,4 +342,51 @@
     }
 }
 
+void tst_QVersit::testExportImport()
+{
+    // Test that a contact, when exported, then imported again, is unaltered
+    QFETCH(QContact, contact);
+
+    QVersitContactExporter exporter;
+    MyDetailHandler detailHandler;
+    exporter.setDetailHandler(&detailHandler);
+    QVERIFY(exporter.exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
+    QList<QVersitDocument> documents = exporter.documents();
+    QCOMPARE(documents.size(), 1);
+
+    QVersitContactImporter importer;
+    MyPropertyHandler propertyHandler;
+    importer.setPropertyHandler(&propertyHandler);
+    QVERIFY(importer.importDocuments(documents));
+    QList<QContact> contacts = importer.contacts();
+    QCOMPARE(contacts.size(), 1);
+    // We can't do a deep compare because detail ids are different
+    QCOMPARE(contacts.first().details().count(), contact.details().count());
+}
+
+void tst_QVersit::testExportImport_data()
+{
+    QTest::addColumn<QContact>("contact");
+
+    QContact contact;
+    QContactName name;
+    name.setFirstName(QLatin1String("first"));
+    name.setLastName(QLatin1String("last"));
+    name.setCustomLabel(QLatin1String("custom"));
+    contact.saveDetail(&name);
+    // detail definition/field names are encoded as vCard property names, which must be uppercase,
+    // so only uppercase definition/field names work.
+    QContactDetail customDetail1("CUSTOMDETAIL");
+    customDetail1.setValue(QLatin1String("CUSTOMFIELD11"), QLatin1String("Value11"));
+    customDetail1.setValue(QLatin1String("CUSTOMFIELD12"), QLatin1String("Value12"));
+    contact.saveDetail(&customDetail1);
+    QContactDetail customDetail2("CUSTOMDETAIL");
+    customDetail2.setValue(QLatin1String("CUSTOMFIELD21"), QLatin1String("Value21"));
+    customDetail2.setValue(QLatin1String("CUSTOMFIELD22"), QLatin1String("Value22"));
+    contact.saveDetail(&customDetail2);
+    contact.setType(QContactType::TypeContact);
+
+    QTest::newRow("custom detail") << contact;
+}
+
 QTEST_MAIN(tst_QVersit)