--- 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)