Commit 2e5769ef authored by mvogt's avatar mvogt

[libcontacts] Preserve some syncTarget values in backup/restore

Contacts with 'bluetooth' or 'was_local' sync target values should
preserve these properties during export/import.
parent 4eaf7126
/*
* Copyright (C) 2014 Jolla Ltd.
* Contact: Matt Vogt <matthew.vogt@jollamobile.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
#include "seasideexport.h"
#include "seasidepropertyhandler.h"
#include <QVersitContactExporter>
QList<QVersitDocument> SeasideExport::buildExportContacts(const QList<QContact> &contacts)
{
SeasidePropertyHandler propertyHandler;
QVersitContactExporter exporter;
exporter.setDetailHandler(&propertyHandler);
exporter.exportContacts(contacts);
return exporter.documents();
}
/*
* Copyright (C) 2014 Jolla Ltd.
* Contact: Matt Vogt <matthew.vogt@jollamobile.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
#ifndef SEASIDEEXPORT_H
#define SEASIDEEXPORT_H
#include "contactcacheexport.h"
#include <QContact>
#include <QVersitDocument>
QTCONTACTS_USE_NAMESPACE
QTVERSIT_USE_NAMESPACE
class CONTACTCACHE_EXPORT SeasideExport
{
SeasideExport();
~SeasideExport();
public:
static QList<QVersitDocument> buildExportContacts(const QList<QContact> &contacts);
};
#endif
......@@ -83,12 +83,14 @@ QContactFetchHint basicFetchHint()
QContactFilter localContactFilter()
{
// Contacts that are local to the device have sync target 'local' or 'was_local'
QContactDetailFilter filterLocal, filterWasLocal;
// Contacts that are local to the device have sync target 'local' or 'was_local' or 'bluetooth'
QContactDetailFilter filterLocal, filterWasLocal, filterBluetooth;
filterLocal.setDetailType(QContactSyncTarget::Type, QContactSyncTarget::FieldSyncTarget);
filterWasLocal.setDetailType(QContactSyncTarget::Type, QContactSyncTarget::FieldSyncTarget);
filterBluetooth.setDetailType(QContactSyncTarget::Type, QContactSyncTarget::FieldSyncTarget);
filterLocal.setValue(QString::fromLatin1("local"));
filterWasLocal.setValue(QString::fromLatin1("was_local"));
filterBluetooth.setValue(QString::fromLatin1("bluetooth"));
return filterLocal | filterWasLocal;
}
......@@ -315,7 +317,6 @@ QList<QContact> SeasideImport::buildImportContacts(const QList<QVersitDocument>
unimportableDetailTypes.insert(QContactDetail::TypeFamily);
unimportableDetailTypes.insert(QContactDetail::TypeGeoLocation);
unimportableDetailTypes.insert(QContactDetail::TypeGlobalPresence);
unimportableDetailTypes.insert(QContactDetail::TypeSyncTarget);
unimportableDetailTypes.insert(QContactDetail::TypeVersion);
// Merge any duplicates in the import list
......@@ -325,7 +326,17 @@ QList<QContact> SeasideImport::buildImportContacts(const QList<QVersitDocument>
// Remove any details that our backend can't store
foreach (QContactDetail detail, contact.details()) {
if (unimportableDetailTypes.contains(detail.type())) {
if (detail.type() == QContactSyncTarget::Type) {
// We allow some syncTarget values
const QString syncTarget(detail.value<QString>(QContactSyncTarget::FieldSyncTarget));
if (syncTarget == QStringLiteral("was_local") ||
syncTarget == QStringLiteral("bluetooth")) {
// These values are permissible
} else {
qDebug() << " Removing unimportable syncTarget:" << syncTarget;
contact.removeDetail(&detail);
}
} else if (unimportableDetailTypes.contains(detail.type())) {
qDebug() << " Removing unimportable detail:" << detail;
contact.removeDetail(&detail);
}
......
......@@ -35,25 +35,13 @@
#include <QContactAvatar>
#include <QContactOnlineAccount>
#include <QContactPresence>
#include <QContactSyncTarget>
#include <QCryptographicHash>
#include <QDir>
#include <QImage>
#include <qtcontacts-extensions.h>
SeasidePropertyHandler::SeasidePropertyHandler()
{
}
SeasidePropertyHandler::~SeasidePropertyHandler()
{
}
void SeasidePropertyHandler::documentProcessed(const QVersitDocument &, QContact *)
{
// do nothing, have no state to clean.
}
namespace {
void processPhoto(const QVersitProperty &property, bool *alreadyProcessed, QList<QContactDetail> * updatedDetails)
......@@ -188,14 +176,93 @@ void processOnlineAccount(const QVersitProperty &property, bool *alreadyProcesse
}
}
void processSyncTarget(const QVersitProperty &property, bool *alreadyProcessed, QList<QContactDetail> * updatedDetails)
{
// Set the sync target for this contact, if appropriate
// Try to interpret the data as a string
const QString data(property.variantValue().toString().toLower());
if (data == QString::fromLatin1("bluetooth") || data == QString::fromLatin1("was_local")) {
QList<QContactDetail>::iterator it = updatedDetails->begin(), end = updatedDetails->end();
for ( ; it != end; ++it) {
if ((*it).type() == QContactSyncTarget::Type)
break;
}
if (it != end) {
QContactSyncTarget &syncTarget(static_cast<QContactSyncTarget &>(*it));
syncTarget.setSyncTarget(data);
} else {
QContactSyncTarget syncTarget;
syncTarget.setSyncTarget(data);
updatedDetails->append(syncTarget);
}
*alreadyProcessed = true;
} else {
qWarning() << "Invalid syncTarget data:" << data;
}
}
void SeasidePropertyHandler::propertyProcessed(const QVersitDocument &, const QVersitProperty &property, const QContact &, bool *alreadyProcessed, QList<QContactDetail> * updatedDetails)
void processSyncTarget(const QContactSyncTarget &detail, QSet<int> * processedFields, QList<QVersitProperty> * toBeRemoved, QList<QVersitProperty> * toBeAdded)
{
if (property.name().toLower() == QLatin1String("photo")) {
Q_UNUSED(processedFields)
Q_UNUSED(toBeRemoved)
// Include the sync target in the export if it is not 'local' but is exportable
const QString syncTarget(detail.syncTarget());
if (syncTarget == QString::fromLatin1("bluetooth") || syncTarget == QString::fromLatin1("was_local")) {
QVersitProperty stProperty;
stProperty.setName(QString::fromLatin1("X-NEMOMOBILE-SYNCTARGET"));
stProperty.setValue(syncTarget);
toBeAdded->append(stProperty);
} else if (!syncTarget.isEmpty() && syncTarget != QString::fromLatin1("local")) {
qWarning() << "Invalid syncTarget for export:" << syncTarget;
}
}
}
SeasidePropertyHandler::SeasidePropertyHandler()
{
}
SeasidePropertyHandler::~SeasidePropertyHandler()
{
}
void SeasidePropertyHandler::documentProcessed(const QVersitDocument &, QContact *)
{
// do nothing, have no state to clean.
}
void SeasidePropertyHandler::propertyProcessed(const QVersitDocument &, const QVersitProperty &property,
const QContact &, bool *alreadyProcessed, QList<QContactDetail> * updatedDetails)
{
const QString propertyName(property.name().toLower());
if (propertyName == QLatin1String("photo")) {
processPhoto(property, alreadyProcessed, updatedDetails);
} else if (property.name().toLower() == QLatin1String("x-nemomobile-onlineaccount-demo")) {
} else if (propertyName == QLatin1String("x-nemomobile-onlineaccount-demo")) {
processOnlineAccount(property, alreadyProcessed, updatedDetails);
} else if (propertyName == QLatin1String("x-nemomobile-synctarget")) {
processSyncTarget(property, alreadyProcessed, updatedDetails);
}
}
void SeasidePropertyHandler::contactProcessed(const QContact &c, QVersitDocument *)
{
}
void SeasidePropertyHandler::detailProcessed(const QContact &, const QContactDetail &detail,
const QVersitDocument &, QSet<int> * processedFields, QList<QVersitProperty> * toBeRemoved, QList<QVersitProperty> * toBeAdded)
{
const QContactDetail::DetailType detailType(detail.type());
if (detailType == QContactSyncTarget::Type) {
processSyncTarget(static_cast<const QContactSyncTarget &>(detail), processedFields, toBeRemoved, toBeAdded);
}
}
......@@ -40,7 +40,7 @@
#include <QContact>
#include <QVersitContactImporterPropertyHandler>
#include <QVersitContactHandler>
#include <QVersitResourceHandler>
#include <QVersitDocument>
#include <QVersitProperty>
......@@ -56,10 +56,13 @@ QTVERSIT_USE_NAMESPACE
a file, and then the path to the file needs to be saved
to the backend as a contact avatar url detail.
The X-NEMOMOBILE-SYNCTARGET property is supported for specifying
the sync target of a contact.
Also support the X-NEMOMOBILE-ONLINEACCOUNT-DEMO property
for loading demo online account data.
*/
class CONTACTCACHE_EXPORT SeasidePropertyHandler : public QVersitContactImporterPropertyHandlerV2
class CONTACTCACHE_EXPORT SeasidePropertyHandler : public QVersitContactHandler
{
public:
SeasidePropertyHandler();
......@@ -69,6 +72,11 @@ public:
void documentProcessed(const QVersitDocument &, QContact *);
void propertyProcessed(const QVersitDocument &, const QVersitProperty &property,
const QContact &, bool *alreadyProcessed, QList<QContactDetail> * updatedDetails);
// QVersitContactExporterDetailHandlerV2
void contactProcessed(const QContact &, QVersitDocument *);
void detailProcessed(const QContact &, const QContactDetail &detail,
const QVersitDocument &, QSet<int> * processedFields, QList<QVersitProperty> * toBeRemoved, QList<QVersitProperty> * toBeAdded);
};
#endif // PROPERTYHANDLER_H
......@@ -37,6 +37,7 @@ HEADERS += contactmanagerengine.h
SOURCES += \
$$PWD/cacheconfiguration.cpp \
$$PWD/seasidecache.cpp \
$$PWD/seasideexport.cpp \
$$PWD/seasideimport.cpp \
$$PWD/seasidepropertyhandler.cpp
......@@ -44,6 +45,7 @@ HEADERS += \
$$PWD/cacheconfiguration.h \
$$PWD/contactcacheexport.h \
$$PWD/seasidecache.h \
$$PWD/seasideexport.h \
$$PWD/seasideimport.h \
$$PWD/synchronizelists.h \
$$PWD/seasidenamegrouper.h \
......@@ -53,6 +55,7 @@ headers.files = \
$$PWD/cacheconfiguration.h \
$$PWD/contactcacheexport.h \
$$PWD/seasidecache.h \
$$PWD/seasideexport.h \
$$PWD/seasideimport.h \
$$PWD/synchronizelists.h \
$$PWD/seasidenamegrouper.h \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment