diff --git a/src/seasideexport.cpp b/src/seasideexport.cpp new file mode 100644 index 0000000..8039935 --- /dev/null +++ b/src/seasideexport.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 Jolla Ltd. + * Contact: Matt Vogt + * + * 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 + +QList SeasideExport::buildExportContacts(const QList &contacts) +{ + SeasidePropertyHandler propertyHandler; + + QVersitContactExporter exporter; + exporter.setDetailHandler(&propertyHandler); + exporter.exportContacts(contacts); + + return exporter.documents(); +} + diff --git a/src/seasideexport.h b/src/seasideexport.h new file mode 100644 index 0000000..912d85f --- /dev/null +++ b/src/seasideexport.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 Jolla Ltd. + * Contact: Matt Vogt + * + * 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 +#include + +QTCONTACTS_USE_NAMESPACE +QTVERSIT_USE_NAMESPACE + +class CONTACTCACHE_EXPORT SeasideExport +{ + SeasideExport(); + ~SeasideExport(); + +public: + static QList buildExportContacts(const QList &contacts); +}; + +#endif diff --git a/src/seasideimport.cpp b/src/seasideimport.cpp index f12d7bb..11f65d7 100644 --- a/src/seasideimport.cpp +++ b/src/seasideimport.cpp @@ -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 SeasideImport::buildImportContacts(const QList 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 SeasideImport::buildImportContacts(const QList // 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(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); } diff --git a/src/seasidepropertyhandler.cpp b/src/seasidepropertyhandler.cpp index 4c60e5c..0108fe0 100644 --- a/src/seasidepropertyhandler.cpp +++ b/src/seasidepropertyhandler.cpp @@ -35,25 +35,13 @@ #include #include #include +#include #include #include #include #include -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 * updatedDetails) @@ -188,14 +176,93 @@ void processOnlineAccount(const QVersitProperty &property, bool *alreadyProcesse } } +void processSyncTarget(const QVersitProperty &property, bool *alreadyProcessed, QList * 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::iterator it = updatedDetails->begin(), end = updatedDetails->end(); + for ( ; it != end; ++it) { + if ((*it).type() == QContactSyncTarget::Type) + break; + } + if (it != end) { + QContactSyncTarget &syncTarget(static_cast(*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 * updatedDetails) +void processSyncTarget(const QContactSyncTarget &detail, QSet * processedFields, QList * toBeRemoved, QList * 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 * 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 * processedFields, QList * toBeRemoved, QList * toBeAdded) +{ + const QContactDetail::DetailType detailType(detail.type()); + + if (detailType == QContactSyncTarget::Type) { + processSyncTarget(static_cast(detail), processedFields, toBeRemoved, toBeAdded); } } diff --git a/src/seasidepropertyhandler.h b/src/seasidepropertyhandler.h index d0c2f41..9e7f67d 100644 --- a/src/seasidepropertyhandler.h +++ b/src/seasidepropertyhandler.h @@ -40,7 +40,7 @@ #include -#include +#include #include #include #include @@ -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 @@ class CONTACTCACHE_EXPORT SeasidePropertyHandler : public QVersitContactImporter void documentProcessed(const QVersitDocument &, QContact *); void propertyProcessed(const QVersitDocument &, const QVersitProperty &property, const QContact &, bool *alreadyProcessed, QList * updatedDetails); + + // QVersitContactExporterDetailHandlerV2 + void contactProcessed(const QContact &, QVersitDocument *); + void detailProcessed(const QContact &, const QContactDetail &detail, + const QVersitDocument &, QSet * processedFields, QList * toBeRemoved, QList * toBeAdded); }; #endif // PROPERTYHANDLER_H diff --git a/src/src.pro b/src/src.pro index 7a2f4ed..2394956 100644 --- a/src/src.pro +++ b/src/src.pro @@ -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 \