--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qtmobility/src/versit/qvcardbackuphandlers_p.cpp Tue Jul 06 15:12:50 2010 +0300
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QList>
+#include <QString>
+#include <QTextStream>
+#include <QUrl>
+#include "qvcardbackuphandlers_p.h"
+#include "qcontact.h"
+#include "qcontactdetail.h"
+#include "qversitdocument.h"
+#include "qversitproperty.h"
+
+QTM_USE_NAMESPACE
+
+QTM_BEGIN_NAMESPACE
+
+Q_DEFINE_LATIN1_CONSTANT(PropertyName, "X-NOKIA-QCONTACTFIELD");
+Q_DEFINE_LATIN1_CONSTANT(DetailDefinitionParameter, "DETAIL");
+Q_DEFINE_LATIN1_CONSTANT(FieldParameter, "FIELD");
+Q_DEFINE_LATIN1_CONSTANT(DatatypeParameter, "DATATYPE");
+Q_DEFINE_LATIN1_CONSTANT(DatatypeParameterVariant, "VARIANT");
+Q_DEFINE_LATIN1_CONSTANT(DatatypeParameterDate, "DATE");
+Q_DEFINE_LATIN1_CONSTANT(DatatypeParameterDateTime, "DATETIME");
+Q_DEFINE_LATIN1_CONSTANT(DatatypeParameterTime, "TIME");
+Q_DEFINE_LATIN1_CONSTANT(DatatypeParameterBool, "BOOL");
+Q_DEFINE_LATIN1_CONSTANT(DatatypeParameterInt, "INT");
+Q_DEFINE_LATIN1_CONSTANT(DatatypeParameterUInt, "UINT");
+Q_DEFINE_LATIN1_CONSTANT(DatatypeParameterUrl, "URL");
+Q_DEFINE_LATIN1_CONSTANT(GroupPrefix, "G");
+
+QTM_END_NAMESPACE
+
+/*
+ * Returns a list of details generated from a Versit group.
+ */
+QList<QContactDetail> DetailGroupMap::detailsInGroup(const QString& groupName) const
+{
+ QList<int> detailIds = mDetailGroupName.keys(groupName);
+ QList<QContactDetail> details;
+ foreach (int detailId, detailIds) {
+ details << mDetailById[detailId];
+ }
+ return details;
+}
+
+/*
+ * Inserts the association between \a detail and \a groupName to the map.
+ * The detail must have a key (ie. have already been saved in a contact) and the group name must not
+ * be the empty string.
+ */
+void DetailGroupMap::insert(const QString& groupName, const QContactDetail& detail)
+{
+ Q_ASSERT(!groupName.isEmpty());
+ mDetailGroupName[detail.key()] = groupName;
+ mDetailById[detail.key()] = detail;
+}
+
+/*
+ * Replaces the detail currently in the map with \a detail.
+ * The detail must have a key (ie. have already been saved in a contact).
+ */
+void DetailGroupMap::update(const QContactDetail& detail)
+{
+ Q_ASSERT(detail.key());
+ mDetailById[detail.key()] = detail;
+}
+
+/*!
+ * Removes details and groups from the map.
+ */
+void DetailGroupMap::clear()
+{
+ mDetailGroupName.clear();
+ mDetailById.clear();
+}
+
+
+QVCardImporterBackupHandler::QVCardImporterBackupHandler()
+{
+}
+
+void QVCardImporterBackupHandler::propertyProcessed(
+ const QVersitDocument& document,
+ const QVersitProperty& property,
+ bool alreadyProcessed,
+ const QContact& contact,
+ QList<QContactDetail>* updatedDetails)
+{
+ Q_UNUSED(document)
+ Q_UNUSED(contact)
+ QString group;
+ if (!property.groups().isEmpty())
+ group = property.groups().first();
+ if (!alreadyProcessed) {
+ if (property.name() != PropertyName)
+ return;
+ if (property.groups().size() != 1)
+ return;
+ QMultiHash<QString,QString> parameters = property.parameters();
+ QString definitionName = parameters.value(DetailDefinitionParameter);
+ QString fieldName = parameters.value(FieldParameter);
+
+ // Find a detail previously seen with the same definitionName, which was generated from
+ // a property from the same group
+ QContactDetail detail(definitionName);
+ foreach (const QContactDetail& previousDetail, mDetailGroupMap.detailsInGroup(group)) {
+ if (previousDetail.definitionName() == definitionName) {
+ detail = previousDetail;
+ }
+ }
+ // If not found, it's a new empty detail with the definitionName set.
+
+ detail.setValue(fieldName, deserializeValue(property));
+
+ // Replace the equivalent detail in updatedDetails with the new one
+ QMutableListIterator<QContactDetail> it(*updatedDetails);
+ while (it.hasNext()) {
+ if (it.next().key() == detail.key()) {
+ it.remove();
+ break;
+ }
+ }
+ updatedDetails->append(detail);
+ }
+ if (!group.isEmpty()) {
+ // Keep track of which details were generated from which Versit groups
+ foreach (const QContactDetail& detail, *updatedDetails) {
+ mDetailGroupMap.insert(group, detail);
+ }
+ }
+}
+
+QVariant QVCardImporterBackupHandler::deserializeValue(const QVersitProperty& property)
+{
+ // Import the field
+ if (property.parameters().contains(DatatypeParameter, DatatypeParameterVariant)) {
+ // The value was stored as a QVariant serialized in a QByteArray
+ QDataStream stream(property.variantValue().toByteArray());
+ QVariant value;
+ stream >> value;
+ return value;
+ } else if (property.parameters().contains(DatatypeParameter, DatatypeParameterDate)) {
+ // The value was a QDate serialized as a string
+ return QDate::fromString(property.value(), Qt::ISODate);
+ } else if (property.parameters().contains(DatatypeParameter, DatatypeParameterTime)) {
+ // The value was a QTime serialized as a string
+ return QTime::fromString(property.value(), Qt::ISODate);
+ } else if (property.parameters().contains(DatatypeParameter, DatatypeParameterDateTime)) {
+ // The value was a QDateTime serialized as a string
+ return QDateTime::fromString(property.value(), Qt::ISODate);
+ } else if (property.parameters().contains(DatatypeParameter, DatatypeParameterBool)) {
+ // The value was a bool serialized as a string
+ return property.value().toInt() != 0;
+ } else if (property.parameters().contains(DatatypeParameter, DatatypeParameterInt)) {
+ // The value was an int serialized as a string
+ return property.value().toInt();
+ } else if (property.parameters().contains(DatatypeParameter, DatatypeParameterUInt)) {
+ // The value was a uint serialized as a string
+ return property.value().toUInt();
+ } else if (property.parameters().contains(DatatypeParameter, DatatypeParameterUrl)) {
+ // The value was a QUrl serialized as a string
+ return QUrl(property.value());
+ } else {
+ // The value was stored as a QString or QByteArray
+ return property.variantValue();
+ }
+}
+
+void QVCardImporterBackupHandler::documentProcessed(
+ const QVersitDocument& document,
+ QContact* contact)
+{
+ Q_UNUSED(document)
+ Q_UNUSED(contact)
+ mDetailGroupMap.clear();
+}
+
+QVCardExporterBackupHandler::QVCardExporterBackupHandler()
+ : mDetailNumber(0)
+{
+}
+
+void QVCardExporterBackupHandler::detailProcessed(
+ const QContact& contact,
+ const QContactDetail& detail,
+ const QSet<QString>& processedFields,
+ const QVersitDocument& document,
+ QList<QVersitProperty>* toBeRemoved,
+ QList<QVersitProperty>* toBeAdded)
+{
+ Q_UNUSED(contact)
+ Q_UNUSED(document)
+ Q_UNUSED(toBeRemoved)
+ if (detail.accessConstraints().testFlag(QContactDetail::ReadOnly))
+ return;
+ QVariantMap fields = detail.variantValues();
+ // fields from the same detail have the same group so the importer can collate them
+ QString detailGroup = GroupPrefix + QString::number(mDetailNumber++);
+ int toBeAddedCount = toBeAdded->count();
+ bool propertiesSynthesized = false;
+ for (QVariantMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); it++) {
+ if (!processedFields.contains(it.key()) && !it.value().toString().isEmpty()) {
+ // Generate a property for the unknown field
+ QVersitProperty property;
+ property.setGroups(QStringList(detailGroup));
+ property.setName(PropertyName);
+ property.insertParameter(DetailDefinitionParameter, detail.definitionName());
+ property.insertParameter(FieldParameter, it.key());
+
+ serializeValue(&property, it.value());
+
+ toBeAdded->append(property);
+ propertiesSynthesized = true;
+ }
+ }
+ if (propertiesSynthesized) {
+ // We need to group the already-generated properties with the newly synthesized ones
+ for (int i = 0; i < toBeAddedCount; i++) {
+ QVersitProperty& property = (*toBeAdded)[i];
+ property.setGroups(property.groups() << detailGroup);
+ }
+ }
+}
+
+void QVCardExporterBackupHandler::serializeValue(QVersitProperty* property, const QVariant& value)
+{
+ // serialize the value
+ if (value.type() == QVariant::String
+ || value.type() == QVariant::ByteArray) {
+ // store QStrings and QByteArrays as-is
+ property->setValue(value);
+ } else if (value.type() == QVariant::Date) {
+ // Store a QDate as a string
+ QString valueString(value.toDate().toString(Qt::ISODate));
+ property->insertParameter(DatatypeParameter, DatatypeParameterDate);
+ property->setValue(valueString);
+ } else if (value.type() == QVariant::Time) {
+ // Store a QTime as a string
+ QString valueString(value.toTime().toString(Qt::ISODate));
+ property->insertParameter(DatatypeParameter, DatatypeParameterTime);
+ property->setValue(valueString);
+ } else if (value.type() == QVariant::DateTime) {
+ // Store a QDateTime as a string
+ QString valueString(value.toDateTime().toString(Qt::ISODate));
+ property->insertParameter(DatatypeParameter, DatatypeParameterDateTime);
+ property->setValue(valueString);
+ } else if (value.type() == QVariant::Bool) {
+ // Store an int as a string
+ QString valueString(QString::number(value.toBool() ? 1 : 0));
+ property->insertParameter(DatatypeParameter, DatatypeParameterBool);
+ property->setValue(valueString);
+ } else if (value.type() == QVariant::Int) {
+ // Store an int as a string
+ QString valueString(QString::number(value.toInt()));
+ property->insertParameter(DatatypeParameter, DatatypeParameterInt);
+ property->setValue(valueString);
+ } else if (value.type() == QVariant::UInt) {
+ // Store a uint as a string
+ QString valueString(QString::number(value.toUInt()));
+ property->insertParameter(DatatypeParameter, DatatypeParameterUInt);
+ property->setValue(valueString);
+ } else if (value.type() == QVariant::Url) {
+ // Store a QUrl as a string
+ QString valueString(value.toUrl().toString());
+ property->insertParameter(DatatypeParameter, DatatypeParameterUrl);
+ property->setValue(valueString);
+ } else {
+ // Store other types by serializing the QVariant in a QByteArray
+ QByteArray valueBytes;
+ QDataStream stream(&valueBytes, QIODevice::WriteOnly);
+ stream << value;
+ property->insertParameter(DatatypeParameter, DatatypeParameterVariant);
+ property->setValue(valueBytes);
+ }
+}
+
+void QVCardExporterBackupHandler::contactProcessed(
+ const QContact& contact,
+ QVersitDocument* document)
+{
+ Q_UNUSED(contact)
+ Q_UNUSED(document)
+ mDetailNumber = 0;
+}