diff -Nru address-book-service-0.1.1+14.04.20140325.2/3rd_party/folks/dummy/lib/dummy-backend.vala address-book-service-0.1.1+14.04.20140327/3rd_party/folks/dummy/lib/dummy-backend.vala --- address-book-service-0.1.1+14.04.20140325.2/3rd_party/folks/dummy/lib/dummy-backend.vala 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/3rd_party/folks/dummy/lib/dummy-backend.vala 2014-03-27 18:16:30.000000000 +0000 @@ -62,6 +62,28 @@ private HashMap _enabled_persona_stores; private Map _enabled_persona_stores_ro; + private const string[] _always_writable_properties = + { + "avatar", + "birthday", + "email-addresses", + "full-name", + "gender", + "im-addresses", + "is-favourite", + "nickname", + "phone-numbers", + "postal-addresses", + "roles", + "structured-name", + "local-ids", + "location", + "web-service-addresses", + "notes", + "groups", + null + }; + /** * {@inheritDoc} * @@ -169,10 +191,14 @@ if (!this._enabled_persona_stores.has_key (id)) { var store = this._all_persona_stores.get (id); - if (store != null) + if (store == null) { - this._enable_persona_store (store); + /* Create a new persona store. */ + store = new FolksDummy.PersonaStore (id, id, FolksDummy.Backend._always_writable_properties); + store.persona_type = typeof (FolksDummy.FullPersona); + this._all_persona_stores.set (store.id, store); } + this._enable_persona_store (store); } } diff -Nru address-book-service-0.1.1+14.04.20140325.2/CMakeLists.txt address-book-service-0.1.1+14.04.20140327/CMakeLists.txt --- address-book-service-0.1.1+14.04.20140325.2/CMakeLists.txt 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/CMakeLists.txt 2014-03-27 18:16:30.000000000 +0000 @@ -68,7 +68,7 @@ add_subdirectory(common) add_subdirectory(lib) add_subdirectory(src) -add_subdirectory(qcontacts) +add_subdirectory(contacts) add_subdirectory(data) if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc") # Some tests fail when running on PPPC check bug #1294229 diff -Nru address-book-service-0.1.1+14.04.20140325.2/common/CMakeLists.txt address-book-service-0.1.1+14.04.20140327/common/CMakeLists.txt --- address-book-service-0.1.1+14.04.20140325.2/common/CMakeLists.txt 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/common/CMakeLists.txt 2014-03-27 18:16:30.000000000 +0000 @@ -4,6 +4,7 @@ filter.cpp fetch-hint.cpp sort-clause.cpp + source.cpp vcard-parser.cpp ) @@ -11,6 +12,7 @@ filter.h fetch-hint.h sort-clause.h + source.h vcard-parser.h dbus-service-defs.h ) diff -Nru address-book-service-0.1.1+14.04.20140325.2/common/fetch-hint.cpp address-book-service-0.1.1+14.04.20140327/common/fetch-hint.cpp --- address-book-service-0.1.1+14.04.20140325.2/common/fetch-hint.cpp 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/common/fetch-hint.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -107,7 +107,7 @@ return map; } -QList FetchHint::parseFieldNames(QStringList fieldNames) +QList FetchHint::parseFieldNames(const QStringList &fieldNames) { QList result; const QMap map = contactFieldNames(); @@ -124,25 +124,27 @@ // Format: :VALUE0,VALUE1;:VALUE0,VALUE1 QtContacts::QContactFetchHint FetchHint::buildFilter(const QString &originalHint) { - QString hint = QString(originalHint).replace(" ",""); QContactFetchHint result; - QStringList groups = hint.split(";"); - Q_FOREACH(QString group, groups) { - QStringList values = group.split(":"); + if (!originalHint.isEmpty()) { + QString hint = QString(originalHint).replace(" ",""); + QStringList groups = hint.split(";"); + Q_FOREACH(QString group, groups) { + QStringList values = group.split(":"); - if (values.count() == 2) { - if (values[0] == "FIELDS") { - QList fields; - QMap map = contactFieldNames(); - Q_FOREACH(QString field, values[1].split(",")) { - if (map.contains(field)) { - fields << map[field]; + if (values.count() == 2) { + if (values[0] == "FIELDS") { + QList fields; + QMap map = contactFieldNames(); + Q_FOREACH(QString field, values[1].split(",")) { + if (map.contains(field)) { + fields << map[field]; + } } + result.setDetailTypesHint(fields); } - result.setDetailTypesHint(fields); + } else { + qWarning() << "invalid fech hint: " << values; } - } else { - qWarning() << "invalid fech hint: " << values; } } diff -Nru address-book-service-0.1.1+14.04.20140325.2/common/fetch-hint.h address-book-service-0.1.1+14.04.20140327/common/fetch-hint.h --- address-book-service-0.1.1+14.04.20140325.2/common/fetch-hint.h 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/common/fetch-hint.h 2014-03-27 18:16:30.000000000 +0000 @@ -39,7 +39,7 @@ QStringList fields() const; QtContacts::QContactFetchHint toContactFetchHint() const; static QMap contactFieldNames(); - static QList parseFieldNames(QStringList fieldNames); + static QList parseFieldNames(const QStringList &fieldNames); private: QtContacts::QContactFetchHint m_hint; diff -Nru address-book-service-0.1.1+14.04.20140325.2/common/filter.cpp address-book-service-0.1.1+14.04.20140327/common/filter.cpp --- address-book-service-0.1.1+14.04.20140325.2/common/filter.cpp 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/common/filter.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -57,6 +57,11 @@ return QContactManagerEngine::testFilter(m_filter, contact); } +bool Filter::isValid() const +{ + return (m_filter.type() != QContactFilter::InvalidFilter); +} + QString Filter::toString(const QtContacts::QContactFilter &filter) { QByteArray filterArray; diff -Nru address-book-service-0.1.1+14.04.20140325.2/common/filter.h address-book-service-0.1.1+14.04.20140327/common/filter.h --- address-book-service-0.1.1+14.04.20140325.2/common/filter.h 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/common/filter.h 2014-03-27 18:16:30.000000000 +0000 @@ -35,6 +35,7 @@ QString toString() const; QtContacts::QContactFilter toContactFilter() const; bool test(const QtContacts::QContact &contact) const; + bool isValid() const; private: QtContacts::QContactFilter m_filter; diff -Nru address-book-service-0.1.1+14.04.20140325.2/common/source.cpp address-book-service-0.1.1+14.04.20140327/common/source.cpp --- address-book-service-0.1.1+14.04.20140325.2/common/source.cpp 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/common/source.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -0,0 +1,129 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "source.h" + +namespace galera { + +Source::Source() + : m_isReadOnly(false) +{ +} + +Source::Source(const Source &other) + : m_id(other.id()), + m_displayName(other.displayLabel()), + m_isReadOnly(other.isReadOnly()), + m_isPrimary(other.isPrimary()) + +{ +} + +Source::Source(QString id, const QString &displayName, bool isReadOnly, bool isPrimary) + : m_id(id), + m_displayName(displayName), + m_isReadOnly(isReadOnly), + m_isPrimary(isPrimary) +{ + Q_ASSERT(displayName.isEmpty() == false); +} + +bool Source::isValid() const +{ + return !m_id.isEmpty(); +} + +bool Source::isPrimary() const +{ + return m_isPrimary; +} + +QString Source::id() const +{ + return m_id; +} + +QString Source::displayLabel() const +{ + return m_displayName; +} + +bool Source::isReadOnly() const +{ + return m_isReadOnly; +} + +void Source::registerMetaType() +{ + qRegisterMetaType("Source"); + qRegisterMetaType("SourceList"); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); +} + +QDBusArgument &operator<<(QDBusArgument &argument, const Source &source) +{ + argument.beginStructure(); + argument << source.m_id; + argument << source.m_displayName; + argument << source.m_isReadOnly; + argument << source.m_isPrimary; + argument.endStructure(); + + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, Source &source) +{ + argument.beginStructure(); + argument >> source.m_id; + argument >> source.m_displayName; + argument >> source.m_isReadOnly; + argument >> source.m_isPrimary; + argument.endStructure(); + + return argument; +} + +QDBusArgument &operator<<(QDBusArgument &argument, const SourceList &sources) +{ + argument.beginArray(qMetaTypeId()); + for(int i=0; i < sources.count(); ++i) { + argument << sources[i]; + } + argument.endArray(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, SourceList &sources) +{ + argument.beginArray(); + sources.clear(); + while(!argument.atEnd()) { + Source source; + argument >> source; + sources << source; + } + argument.endArray(); + return argument; +} + +} // namespace Galera + + + diff -Nru address-book-service-0.1.1+14.04.20140325.2/common/source.h address-book-service-0.1.1+14.04.20140327/common/source.h --- address-book-service-0.1.1+14.04.20140325.2/common/source.h 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/common/source.h 2014-03-27 18:16:30.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GALERA_SOURCE_H__ +#define __GALERA_SOURCE_H__ + +#include +#include + +namespace galera { + +class Source +{ +public: + Source(); + Source(const Source &other); + Source(QString id, const QString &displayName, bool isReadOnly, bool isPrimary); + friend QDBusArgument &operator<<(QDBusArgument &argument, const Source &source); + friend const QDBusArgument &operator>>(const QDBusArgument &argument, Source &source); + + static void registerMetaType(); + QString id() const; + QString displayLabel() const; + bool isReadOnly() const; + bool isValid() const; + bool isPrimary() const; + +private: + QString m_id; + QString m_displayName; + bool m_isReadOnly; + bool m_isPrimary; +}; + +typedef QList SourceList; + +QDBusArgument &operator<<(QDBusArgument &argument, const SourceList &sources); +const QDBusArgument &operator>>(const QDBusArgument &argument, SourceList &sources); + +} // namespace galera + +Q_DECLARE_METATYPE(galera::Source) +Q_DECLARE_METATYPE(galera::SourceList) + +#endif + diff -Nru address-book-service-0.1.1+14.04.20140325.2/common/vcard-parser.cpp address-book-service-0.1.1+14.04.20140327/common/vcard-parser.cpp --- address-book-service-0.1.1+14.04.20140325.2/common/vcard-parser.cpp 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/common/vcard-parser.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -49,18 +49,12 @@ Q_UNUSED(toBeRemoved); // Export custom property PIDMAP - if (detail.type() == QContactDetail::TypeExtendedDetail) { - const QContactExtendedDetail *extendedDetail = static_cast(&detail); - if (extendedDetail->name() == galera::VCardParser::PidMapFieldName) { - QVersitProperty prop; - prop.setName(extendedDetail->name()); - QStringList value; - value << extendedDetail->value(QContactExtendedDetail::FieldData).toString() - << extendedDetail->value(QContactExtendedDetail::FieldData + 1).toString(); - prop.setValueType(QVersitProperty::CompoundType); - prop.setValue(value); - *toBeAdded << prop; - } + if (detail.type() == QContactDetail::TypeSyncTarget) { + QContactSyncTarget syncTarget = static_cast(detail); + QVersitProperty prop; + prop.setName(galera::VCardParser::PidMapFieldName); + prop.setValue(syncTarget.syncTarget()); + *toBeAdded << prop; } if (toBeAdded->size() == 0) { @@ -138,12 +132,9 @@ Q_UNUSED(contact); if (!*alreadyProcessed && (property.name() == galera::VCardParser::PidMapFieldName)) { - QContactExtendedDetail detail; - detail.setName(property.name()); - QStringList value = property.value().split(";"); - detail.setValue(QContactExtendedDetail::FieldData, value[0]); - detail.setValue(QContactExtendedDetail::FieldData + 1, value[1]); - *updatedDetails << detail; + QContactSyncTarget target; + target.setSyncTarget(property.value()); + *updatedDetails << target; *alreadyProcessed = true; } diff -Nru address-book-service-0.1.1+14.04.20140325.2/common/vcard-parser.h address-book-service-0.1.1+14.04.20140327/common/vcard-parser.h --- address-book-service-0.1.1+14.04.20140325.2/common/vcard-parser.h 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/common/vcard-parser.h 2014-03-27 18:16:30.000000000 +0000 @@ -54,7 +54,7 @@ static QStringList contactToVcardSync(QList contacts); Q_SIGNALS: - void vcardParsed(QStringList vcards); + void vcardParsed(const QStringList &vcards); void contactsParsed(QList contacts); void finished(); diff -Nru address-book-service-0.1.1+14.04.20140325.2/config.h.in address-book-service-0.1.1+14.04.20140327/config.h.in --- address-book-service-0.1.1+14.04.20140325.2/config.h.in 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/config.h.in 2014-03-27 18:16:30.000000000 +0000 @@ -10,4 +10,6 @@ #define FOLKS_INDIVIDUAL_AGGREGATOR_DUP folks_individual_aggregator_dup #endif +#define QT_PLUGINS_BINARY_DIR "@CMAKE_BINARY_DIR@" + #endif diff -Nru address-book-service-0.1.1+14.04.20140325.2/contacts/CMakeLists.txt address-book-service-0.1.1+14.04.20140327/contacts/CMakeLists.txt --- address-book-service-0.1.1+14.04.20140325.2/contacts/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/contacts/CMakeLists.txt 2014-03-27 18:16:30.000000000 +0000 @@ -0,0 +1,42 @@ +project(qtcontacts_galera) + +set(QCONTACTS_BACKEND qtcontacts_galera) + +set(QCONTACTS_BACKEND_SRCS + qcontact-backend.cpp + qcontact-engineid.cpp + contacts-service.cpp + request-data.cpp +) + +set(QCONTACTS_BACKEND_HDRS + qcontact-backend.h + qcontact-engineid.h + contacts-service.h + request-data.h +) + +add_library(${QCONTACTS_BACKEND} MODULE + ${QCONTACTS_BACKEND_SRCS} + ${QCONTACTS_BACKEND_HDRS} +) + +include_directories( + ${CMAKE_SOURCE_DIR} +) + +target_link_libraries(${QCONTACTS_BACKEND} + galera-common +) + +qt5_use_modules(${QCONTACTS_BACKEND} Core Contacts DBus Versit) + +add_definitions(-std=gnu++11) + +execute_process( + COMMAND qmake -query QT_INSTALL_PLUGINS + OUTPUT_VARIABLE QT_INSTALL_PLUGINS + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +install(TARGETS ${QCONTACTS_BACKEND} LIBRARY DESTINATION ${QT_INSTALL_PLUGINS}/contacts) diff -Nru address-book-service-0.1.1+14.04.20140325.2/contacts/contacts-service.cpp address-book-service-0.1.1+14.04.20140327/contacts/contacts-service.cpp --- address-book-service-0.1.1+14.04.20140325.2/contacts/contacts-service.cpp 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/contacts/contacts-service.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -0,0 +1,776 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "contacts-service.h" +#include "qcontact-engineid.h" +#include "request-data.h" + +#include "common/vcard-parser.h" +#include "common/filter.h" +#include "common/fetch-hint.h" +#include "common/sort-clause.h" +#include "common/dbus-service-defs.h" +#include "common/source.h" + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define FETCH_PAGE_SIZE 100 + +using namespace QtVersit; +using namespace QtContacts; + + +namespace //private +{ + +static QContact parseSource(const galera::Source &source, const QString &managerUri) +{ + QContact contact; + + // contact group type + contact.setType(QContactType::TypeGroup); + + // id + galera::GaleraEngineId *engineId = new galera::GaleraEngineId(source.id(), managerUri); + QContactId newId = QContactId(engineId); + contact.setId(newId); + + // guid + QContactGuid guid; + guid.setGuid(source.id()); + contact.saveDetail(&guid); + + // display name + QContactDisplayLabel displayLabel; + displayLabel.setLabel(source.displayLabel()); + contact.saveDetail(&displayLabel); + + // read-only + QContactExtendedDetail readOnly; + readOnly.setName("READ-ONLY"); + readOnly.setData(source.isReadOnly()); + contact.saveDetail(&readOnly); + + // Primary + QContactExtendedDetail primary; + primary.setName("IS-PRIMARY"); + primary.setData(source.isPrimary()); + contact.saveDetail(&primary); + + return contact; +} + +} + +namespace galera +{ +GaleraContactsService::GaleraContactsService(const QString &managerUri) + : m_selfContactId(), + m_managerUri(managerUri), + m_serviceIsReady(false), + m_iface(0) +{ + RequestData::registerMetaType(); + Source::registerMetaType(); + + m_serviceWatcher = new QDBusServiceWatcher(CPIM_SERVICE_NAME, + QDBusConnection::sessionBus(), + QDBusServiceWatcher::WatchForOwnerChange, + this); + connect(m_serviceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), + this, SLOT(serviceOwnerChanged(QString,QString,QString))); + + initialize(); +} + +GaleraContactsService::GaleraContactsService(const GaleraContactsService &other) + : m_selfContactId(other.m_selfContactId), + m_managerUri(other.m_managerUri), + m_iface(other.m_iface) +{ +} + +GaleraContactsService::~GaleraContactsService() +{ + while(!m_pendingRequests.isEmpty()) { + QPointer request = m_pendingRequests.takeFirst(); + if (request) { + request->cancel(); + request->waitForFinished(); + } + } + m_runningRequests.clear(); + + delete m_serviceWatcher; +} + +void GaleraContactsService::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner) +{ + Q_UNUSED(oldOwner); + if (name == CPIM_SERVICE_NAME) { + if (!newOwner.isEmpty()) { + // service appear + initialize(); + } else if (!m_iface.isNull()) { + // lost service + deinitialize(); + } + } +} + +void GaleraContactsService::onServiceReady() +{ + m_serviceIsReady = true; + while(!m_pendingRequests.isEmpty()) { + QPointer request = m_pendingRequests.takeFirst(); + if (request) { + addRequest(request); + } + } +} + +void GaleraContactsService::initialize() +{ + if (m_iface.isNull()) { + m_iface = QSharedPointer(new QDBusInterface(CPIM_SERVICE_NAME, + CPIM_ADDRESSBOOK_OBJECT_PATH, + CPIM_ADDRESSBOOK_IFACE_NAME)); + if (!m_iface->lastError().isValid()) { + m_serviceIsReady = m_iface.data()->property("isReady").toBool(); + connect(m_iface.data(), SIGNAL(ready()), this, SLOT(onServiceReady())); + connect(m_iface.data(), SIGNAL(contactsAdded(QStringList)), this, SLOT(onContactsAdded(QStringList))); + connect(m_iface.data(), SIGNAL(contactsRemoved(QStringList)), this, SLOT(onContactsRemoved(QStringList))); + connect(m_iface.data(), SIGNAL(contactsUpdated(QStringList)), this, SLOT(onContactsUpdated(QStringList))); + } else { + qWarning() << "Fail to connect with service:" << m_iface->lastError(); + m_iface.clear(); + } + } +} + +void GaleraContactsService::deinitialize() +{ + Q_FOREACH(RequestData* rData, m_runningRequests) { + rData->cancel(); + rData->request()->waitForFinished(); + rData->setError(QContactManager::UnspecifiedError); + } + + if (!m_iface.isNull()) { + m_id.clear(); + Q_EMIT serviceChanged(); + } + + // this will make the service re-initialize + QDBusMessage result = m_iface->call("ping"); + if (result.type() == QDBusMessage::ErrorMessage) { + qWarning() << result.errorName() << result.errorMessage(); + m_serviceIsReady = false; + } else { + m_serviceIsReady = m_iface.data()->property("isReady").toBool(); + } +} + +bool GaleraContactsService::isOnline() const +{ + return !m_iface.isNull(); +} + +void GaleraContactsService::fetchContactsById(QtContacts::QContactFetchByIdRequest *request) +{ + if (!isOnline()) { + qWarning() << "Server is not online"; + RequestData::setError(request); + return; + } + + QContactIdFilter filter; + filter.setIds(request->contactIds()); + QString filterStr = Filter(filter).toString(); + QDBusMessage result = m_iface->call("query", filterStr, "", QStringList()); + if (result.type() == QDBusMessage::ErrorMessage) { + qWarning() << result.errorName() << result.errorMessage(); + RequestData::setError(request); + return; + } + QDBusObjectPath viewObjectPath = result.arguments()[0].value(); + QDBusInterface *view = new QDBusInterface(CPIM_SERVICE_NAME, + viewObjectPath.path(), + CPIM_ADDRESSBOOK_VIEW_IFACE_NAME); + + RequestData *requestData = new RequestData(request, view, FetchHint()); + m_runningRequests << requestData; + QMetaObject::invokeMethod(this, "fetchContactsPage", Qt::QueuedConnection, Q_ARG(galera::RequestData*, requestData)); +} + +void GaleraContactsService::fetchContacts(QtContacts::QContactFetchRequest *request) +{ + if (!isOnline()) { + qWarning() << "Server is not online"; + RequestData::setError(request); + return; + } + + // Only return the sources names if the filter is set as contact group type + if (request->filter().type() == QContactFilter::ContactDetailFilter) { + QContactDetailFilter dFilter = static_cast(request->filter()); + + if ((dFilter.detailType() == QContactDetail::TypeType) && + (dFilter.detailField() == QContactType::FieldType) && + (dFilter.value() == QContactType::TypeGroup)) { + + QDBusPendingCall pcall = m_iface->asyncCall("availableSources"); + if (pcall.isError()) { + qWarning() << pcall.error().name() << pcall.error().message(); + RequestData::setError(request); + return; + } + + RequestData *requestData = new RequestData(request); + m_runningRequests << requestData; + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, + [=](QDBusPendingCallWatcher *call) { + this->fetchContactsGroupsContinue(requestData, call); + }); + return; + } + } + + QString sortStr = SortClause(request->sorting()).toString(); + QString filterStr = Filter(request->filter()).toString(); + FetchHint fetchHint = FetchHint(request->fetchHint()).toString(); + + QDBusPendingCall pcall = m_iface->asyncCall("query", filterStr, sortStr, QStringList()); + if (pcall.isError()) { + qWarning() << pcall.error().name() << pcall.error().message(); + RequestData::setError(request); + return; + } + + RequestData *requestData = new RequestData(request, 0, fetchHint); + m_runningRequests << requestData; + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, + [=](QDBusPendingCallWatcher *call) { + this->fetchContactsContinue(requestData, call); + }); +} + + +void GaleraContactsService::fetchContactsContinue(RequestData *request, + QDBusPendingCallWatcher *call) +{ + if (!request->isLive()) { + destroyRequest(request); + return; + } + + QDBusPendingReply reply = *call; + + if (reply.isError()) { + qWarning() << reply.error().name() << reply.error().message(); + destroyRequest(request); + } else { + QDBusObjectPath viewObjectPath = reply.value(); + QDBusInterface *view = new QDBusInterface(CPIM_SERVICE_NAME, + viewObjectPath.path(), + CPIM_ADDRESSBOOK_VIEW_IFACE_NAME); + request->updateView(view); + QMetaObject::invokeMethod(this, "fetchContactsPage", Qt::QueuedConnection, Q_ARG(galera::RequestData*, request)); + } +} + +void GaleraContactsService::fetchContactsPage(RequestData *request) +{ + if (!isOnline() || !request->isLive()) { + qWarning() << "Server is not online"; + destroyRequest(request); + return; + } + + // Load contacs async + QDBusPendingCall pcall = request->view()->asyncCall("contactsDetails", + request->fields(), + request->offset(), + FETCH_PAGE_SIZE); + if (pcall.isError()) { + qWarning() << pcall.error().name() << pcall.error().message(); + request->setError(QContactManager::UnspecifiedError); + destroyRequest(request); + return; + } + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); + request->updateWatcher(watcher); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, + [=](QDBusPendingCallWatcher *call) { + this->fetchContactsDone(request, call); + }); +} + +void GaleraContactsService::fetchContactsDone(RequestData *request, QDBusPendingCallWatcher *call) +{ + if (!request->isLive()) { + destroyRequest(request); + return; + } + + QContactManager::Error opError = QContactManager::NoError; + QContactAbstractRequest::State opState = QContactAbstractRequest::FinishedState; + QDBusPendingReply reply = *call; + if (reply.isError()) { + qWarning() << reply.error().name() << reply.error().message(); + + request->update(QList(), + QContactAbstractRequest::FinishedState, + QContactManager::UnspecifiedError); + destroyRequest(request); + } else { + const QStringList vcards = reply.value(); + if (vcards.size()) { + VCardParser *parser = new VCardParser(this); + parser->setProperty("DATA", QVariant::fromValue(request)); + connect(parser, &VCardParser::contactsParsed, + this, &GaleraContactsService::onVCardsParsed); + parser->vcardToContact(vcards); + } else { + request->update(QList(), QContactAbstractRequest::FinishedState); + destroyRequest(request); + } + } +} + + +void GaleraContactsService::onVCardsParsed(QList contacts) +{ + QObject *sender = QObject::sender(); + RequestData *request = static_cast(sender->property("DATA").value()); + if (!request->isLive()) { + destroyRequest(request); + return; + } + + QList::iterator contact; + for (contact = contacts.begin(); contact != contacts.end(); ++contact) { + if (!contact->isEmpty()) { + QContactGuid detailId = contact->detail(); + GaleraEngineId *engineId = new GaleraEngineId(detailId.guid(), m_managerUri); + QContactId newId = QContactId(engineId); + contact->setId(newId); + // set tag to be used when creating sections + QContactName detailName = contact->detail(); + if (!detailName.firstName().isEmpty() && QString(detailName.firstName().at(0)).contains(QRegExp("([a-z]|[A-Z])"))) { + contact->addTag(detailName.firstName().at(0).toUpper()); + } else if (!detailName.lastName().isEmpty() && QString(detailName.lastName().at(0)).contains(QRegExp("([a-z]|[A-Z])"))) { + contact->addTag(detailName.lastName().at(0).toUpper()); + } else { + contact->addTag("#"); + } + } + } + + if (contacts.size() == FETCH_PAGE_SIZE) { + request->update(contacts, QContactAbstractRequest::ActiveState); + request->updateOffset(FETCH_PAGE_SIZE); + request->updateWatcher(0); + QMetaObject::invokeMethod(this, "fetchContactsPage", Qt::QueuedConnection, Q_ARG(galera::RequestData*, request)); + } else { + request->update(contacts, QContactAbstractRequest::FinishedState); + destroyRequest(request); + } + + sender->deleteLater(); +} + +void GaleraContactsService::fetchContactsGroupsContinue(RequestData *request, + QDBusPendingCallWatcher *call) +{ + if (!request->isLive()) { + destroyRequest(request); + return; + } + + QList contacts; + QContactManager::Error opError = QContactManager::NoError; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qWarning() << reply.error().name() << reply.error().message(); + opError = QContactManager::UnspecifiedError; + } else { + Q_FOREACH(const Source &source, reply.value()) { + QContact c = parseSource(source, m_managerUri); + if (source.isPrimary()) { + contacts.prepend(c); + } else { + contacts << c; + } + } + } + + request->update(contacts, QContactAbstractRequest::FinishedState, opError); + destroyRequest(request); +} + +void GaleraContactsService::saveContact(QtContacts::QContactSaveRequest *request) +{ + QList contacts = request->contacts(); + QStringList oldContacts; + QStringList newContacts; + QStringList sources; + QStringList newSources; + + Q_FOREACH(const QContact &contact, contacts) { + if (contact.id().isNull()) { + if (contact.type() == QContactType::TypeGroup) { + newSources << contact.detail().label(); + } else { + newContacts << VCardParser::contactToVcard(contact); + + // sources where the new contacts will be saved + QContactSyncTarget syncTarget = contact.detail(); + sources << syncTarget.syncTarget(); + } + } else { + oldContacts << VCardParser::contactToVcard(contact); + } + } + + if (!oldContacts.isEmpty()) { + updateContacts(request, oldContacts); + } + + if (!newContacts.isEmpty()) { + createContacts(request, newContacts, sources); + } + + if (!newSources.isEmpty()) { + createSources(request, newSources); + } +} +void GaleraContactsService::createContacts(QtContacts::QContactSaveRequest *request, QStringList contacts, QStringList sources) +{ + if (!isOnline()) { + qWarning() << "Server is not online"; + RequestData::setError(request); + return; + } + + if (contacts.count() > 1) { + qWarning() << "TODO: implement contact creation support to more then one contact."; + return; + } + + int i = 0; + Q_FOREACH(QString contact, contacts) { + QDBusPendingCall pcall = m_iface->asyncCall("createContact", contact, sources[i++]); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); + RequestData *requestData = new RequestData(request, watcher); + m_runningRequests << requestData; + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, + [=](QDBusPendingCallWatcher *call) { + this->createContactsDone(requestData, call); + }); + + } +} + +void GaleraContactsService::createContactsDone(RequestData *request, QDBusPendingCallWatcher *call) +{ + if (!request->isLive()) { + destroyRequest(request); + return; + } + + QDBusPendingReply reply = *call; + QList contacts; + QContactManager::Error opError = QContactManager::NoError; + + if (reply.isError()) { + qWarning() << reply.error().name() << reply.error().message(); + opError = QContactManager::UnspecifiedError; + } else { + const QString vcard = reply.value(); + if (!vcard.isEmpty()) { + contacts = static_cast(request->request())->contacts(); + QContact contact = VCardParser::vcardToContact(vcard); + QContactGuid detailId = contact.detail(); + GaleraEngineId *engineId = new GaleraEngineId(detailId.guid(), m_managerUri); + QContactId newId = QContactId(engineId); + contact.setId(newId); + contacts.insert(0, contact); + } else { + opError = QContactManager::UnspecifiedError; + } + } + + request->update(contacts, QContactAbstractRequest::FinishedState, opError); + destroyRequest(request); +} + +void GaleraContactsService::createSources(QtContacts::QContactSaveRequest *request, QStringList &sources) +{ + if (!isOnline()) { + qWarning() << "Server is not online"; + RequestData::setError(request); + return; + } + + QList contacts; + QMap errorMap; + + int index = 0; + Q_FOREACH(QString sourceName, sources) { + QDBusReply result = m_iface->call("createSource", sourceName); + if (result.isValid()) { + contacts << parseSource(result.value(), m_managerUri); + } else { + errorMap.insert(index, QContactManager::UnspecifiedError); + } + index++; + } + + QContactManagerEngine::updateContactSaveRequest(request, + contacts, + QContactManager::NoError, + errorMap, + QContactAbstractRequest::FinishedState); +} + +void GaleraContactsService::removeContact(QContactRemoveRequest *request) +{ + if (!isOnline()) { + qWarning() << "Server is not online"; + RequestData::setError(request); + return; + } + + QStringList ids; + + Q_FOREACH(QContactId contactId, request->contactIds()) { + // TODO: find a better way to get the contactId + ids << contactId.toString().split(":").last(); + } + + QDBusPendingCall pcall = m_iface->asyncCall("removeContacts", ids); + if (pcall.isError()) { + qWarning() << "Error" << pcall.error().name() << pcall.error().message(); + RequestData::setError(request); + } else { + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); + RequestData *requestData = new RequestData(request, watcher); + m_runningRequests << requestData; + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, + [=](QDBusPendingCallWatcher *call) { + this->removeContactDone(requestData, call); + }); + } +} + +void GaleraContactsService::removeContactDone(RequestData *request, QDBusPendingCallWatcher *call) +{ + if (!request->isLive()) { + destroyRequest(request); + return; + } + + QDBusPendingReply reply = *call; + QContactManager::Error opError = QContactManager::NoError; + QMap errorMap; + + if (reply.isError()) { + qWarning() << reply.error().name() << reply.error().message(); + opError = QContactManager::UnspecifiedError; + } + + request->update(QContactAbstractRequest::FinishedState, opError); + destroyRequest(request); +} + +void GaleraContactsService::updateContacts(QtContacts::QContactSaveRequest *request, QStringList contacts) +{ + if (!isOnline()) { + qWarning() << "Server is not online"; + RequestData::setError(request); + return; + } + + QDBusPendingCall pcall = m_iface->asyncCall("updateContacts", contacts); + if (pcall.isError()) { + qWarning() << "Error" << pcall.error().name() << pcall.error().message(); + RequestData::setError(request); + } else { + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); + RequestData *requestData = new RequestData(request, watcher); + m_runningRequests << requestData; + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, + [=](QDBusPendingCallWatcher *call) { + this->updateContactDone(requestData, call); + }); + } +} + + +void GaleraContactsService::updateContactDone(RequestData *request, QDBusPendingCallWatcher *call) +{ + if (!request->isLive()) { + destroyRequest(request); + return; + } + + QDBusPendingReply reply = *call; + QList contacts; + QMap saveError; + QContactManager::Error opError = QContactManager::NoError; + + if (reply.isError()) { + qWarning() << reply.error().name() << reply.error().message(); + opError = QContactManager::UnspecifiedError; + } else { + const QStringList vcards = reply.value(); + if (!vcards.isEmpty()) { + QMap importErrors; + //TODO report parse errors + contacts = VCardParser::vcardToContactSync(vcards); + Q_FOREACH(int key, importErrors.keys()) { + saveError.insert(key, QContactManager::BadArgumentError); + } + } + } + + request->update(contacts, QContactAbstractRequest::FinishedState, opError, saveError); + destroyRequest(request); +} + +void GaleraContactsService::cancelRequest(QtContacts::QContactAbstractRequest *request) +{ + Q_FOREACH(RequestData* rData, m_runningRequests) { + if (rData->request() == request) { + rData->cancel(); + return; + } + } +} + +void GaleraContactsService::waitRequest(QtContacts::QContactAbstractRequest *request) +{ + Q_FOREACH(RequestData* rData, m_runningRequests) { + if (rData->request() == request) { + rData->wait(); + return; + } + } +} + +void GaleraContactsService::addRequest(QtContacts::QContactAbstractRequest *request) +{ + if (!m_serviceIsReady) { + m_pendingRequests << QPointer(request); + return; + } + + if (!isOnline()) { + qWarning() << "Server is not online"; + QContactManagerEngine::updateRequestState(request, QContactAbstractRequest::FinishedState); + return; + } + + Q_ASSERT(request->state() == QContactAbstractRequest::ActiveState); + switch (request->type()) { + case QContactAbstractRequest::ContactFetchRequest: + fetchContacts(static_cast(request)); + break; + case QContactAbstractRequest::ContactFetchByIdRequest: + fetchContactsById(static_cast(request)); + break; + case QContactAbstractRequest::ContactIdFetchRequest: + qWarning() << "Not implemented: ContactIdFetchRequest"; + break; + case QContactAbstractRequest::ContactSaveRequest: + saveContact(static_cast(request)); + break; + case QContactAbstractRequest::ContactRemoveRequest: + removeContact(static_cast(request)); + break; + case QContactAbstractRequest::RelationshipFetchRequest: + qWarning() << "Not implemented: RelationshipFetchRequest"; + break; + case QContactAbstractRequest::RelationshipRemoveRequest: + qWarning() << "Not implemented: RelationshipRemoveRequest"; + break; + case QContactAbstractRequest::RelationshipSaveRequest: + qWarning() << "Not implemented: RelationshipSaveRequest"; + break; + break; + + default: // unknown request type. + break; + } +} + +void GaleraContactsService::destroyRequest(RequestData *request) +{ + m_runningRequests.remove(request); + delete request; +} + +QList GaleraContactsService::parseIds(const QStringList &ids) const +{ + QList contactIds; + Q_FOREACH(QString id, ids) { + GaleraEngineId *engineId = new GaleraEngineId(id, m_managerUri); + contactIds << QContactId(engineId); + } + return contactIds; +} + +void GaleraContactsService::onContactsAdded(const QStringList &ids) +{ + Q_EMIT contactsAdded(parseIds(ids)); +} + +void GaleraContactsService::onContactsRemoved(const QStringList &ids) +{ + Q_EMIT contactsRemoved(parseIds(ids)); +} + +void GaleraContactsService::onContactsUpdated(const QStringList &ids) +{ + Q_EMIT contactsUpdated(parseIds(ids)); +} + +} //namespace diff -Nru address-book-service-0.1.1+14.04.20140325.2/contacts/contacts-service.h address-book-service-0.1.1+14.04.20140327/contacts/contacts-service.h --- address-book-service-0.1.1+14.04.20140325.2/contacts/contacts-service.h 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/contacts/contacts-service.h 2014-03-27 18:16:30.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __CONTACTS_SERVICE_H__ +#define __CONTACTS_SERVICE_H__ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +class QDBusInterface; +using namespace QtContacts; // necessary for signal signatures + +namespace galera { +class RequestData; + +class GaleraContactsService : public QObject +{ + Q_OBJECT +public: + GaleraContactsService(const QString &managerUri); + GaleraContactsService(const GaleraContactsService &other); + ~GaleraContactsService(); + + QList engines() const; + void appendEngine(QtContacts::QContactManagerEngine *engine); + void removeEngine(QtContacts::QContactManagerEngine *engine); + + QList relationships() const; + + void addRequest(QtContacts::QContactAbstractRequest *request); + void cancelRequest(QtContacts::QContactAbstractRequest *request); + void waitRequest(QtContacts::QContactAbstractRequest *request); + +Q_SIGNALS: + void contactsAdded(QList ids); + void contactsRemoved(QList ids); + void contactsUpdated(QList ids); + void serviceChanged(); + +private Q_SLOTS: + void onContactsAdded(const QStringList &ids); + void onContactsRemoved(const QStringList &ids); + void onContactsUpdated(const QStringList &ids); + void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); + void onServiceReady(); + void onVCardsParsed(QList contacts); + + void fetchContactsDone(RequestData *request, QDBusPendingCallWatcher *call); + +private: + QString m_id; + QtContacts::QContactId m_selfContactId; // the "MyCard" contact id + QString m_managerUri; // for faster lookup. + QDBusServiceWatcher *m_serviceWatcher; + bool m_serviceIsReady; + + QSharedPointer m_iface; + QSet m_runningRequests; + QQueue > m_pendingRequests; + + Q_INVOKABLE void initialize(); + Q_INVOKABLE void deinitialize(); + + bool isOnline() const; + + void fetchContacts(QtContacts::QContactFetchRequest *request); + void fetchContactsContinue(RequestData *request, + QDBusPendingCallWatcher *call); + void fetchContactsGroupsContinue(RequestData *request, + QDBusPendingCallWatcher *call); + void fetchContactsById(QtContacts::QContactFetchByIdRequest *request); + Q_INVOKABLE void fetchContactsPage(galera::RequestData *request); + + + void saveContact(QtContacts::QContactSaveRequest *request); + void createContacts(QtContacts::QContactSaveRequest *request, QStringList contacts, QStringList sources); + void createSources(QtContacts::QContactSaveRequest *request, QStringList &sources); + void updateContacts(QtContacts::QContactSaveRequest *request, QStringList contacts); + void updateContactDone(RequestData *request, QDBusPendingCallWatcher *call); + void createContactsDone(RequestData *request, QDBusPendingCallWatcher *call); + + void removeContact(QtContacts::QContactRemoveRequest *request); + void removeContactDone(RequestData *request, QDBusPendingCallWatcher *call); + + void destroyRequest(RequestData *request); + + QList parseIds(const QStringList &ids) const; +}; + +} + +#endif diff -Nru address-book-service-0.1.1+14.04.20140325.2/contacts/galera.json address-book-service-0.1.1+14.04.20140327/contacts/galera.json --- address-book-service-0.1.1+14.04.20140325.2/contacts/galera.json 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/contacts/galera.json 2014-03-27 18:16:17.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "Keys": [ "galera" ] +} diff -Nru address-book-service-0.1.1+14.04.20140325.2/contacts/qcontact-backend.cpp address-book-service-0.1.1+14.04.20140327/contacts/qcontact-backend.cpp --- address-book-service-0.1.1+14.04.20140325.2/contacts/qcontact-backend.cpp 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/contacts/qcontact-backend.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -0,0 +1,371 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "qcontact-backend.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "contacts-service.h" +#include "qcontact-engineid.h" + +using namespace QtContacts; + +namespace galera +{ + +QtContacts::QContactManagerEngine* GaleraEngineFactory::engine(const QMap ¶meters, QtContacts::QContactManager::Error *error) +{ + Q_UNUSED(error); + + GaleraManagerEngine *engine = GaleraManagerEngine::createEngine(parameters); + return engine; +} + +QtContacts::QContactEngineId* GaleraEngineFactory::createContactEngineId(const QMap ¶meters, + const QString &engineIdString) const +{ + return new GaleraEngineId(parameters, engineIdString); +} + +QString GaleraEngineFactory::managerName() const +{ + return QString::fromLatin1("galera"); +} + +GaleraManagerEngine* GaleraManagerEngine::createEngine(const QMap ¶meters) +{ + GaleraManagerEngine *engine = new GaleraManagerEngine(); + return engine; +} + +/*! + * Constructs a new in-memory backend which shares the given \a data with + * other shared memory engines. + */ +GaleraManagerEngine::GaleraManagerEngine() + : m_service(new GaleraContactsService(managerUri())) +{ + connect(m_service, SIGNAL(contactsAdded(QList)), this, SIGNAL(contactsAdded(QList))); + connect(m_service, SIGNAL(contactsRemoved(QList)), this, SIGNAL(contactsRemoved(QList))); + connect(m_service, SIGNAL(contactsUpdated(QList)), this, SIGNAL(contactsChanged(QList))); + connect(m_service, SIGNAL(serviceChanged()), this, SIGNAL(dataChanged())); +} + +/*! Frees any memory used by this engine */ +GaleraManagerEngine::~GaleraManagerEngine() +{ + delete m_service; +} + +/* URI reporting */ +QString GaleraManagerEngine::managerName() const +{ + return "galera"; +} + +QMap GaleraManagerEngine::managerParameters() const +{ + QMap parameters; + return parameters; +} + +int GaleraManagerEngine::managerVersion() const +{ + return 1; +} + +/* Filtering */ +QList GaleraManagerEngine::contactIds(const QtContacts::QContactFilter &filter, const QList &sortOrders, QtContacts::QContactManager::Error *error) const +{ + QContactFetchHint hint; + hint.setDetailTypesHint(QList() << QContactDetail::TypeGuid); + QList clist = contacts(filter, sortOrders, hint, error); + + /* Extract the ids */ + QList ids; + Q_FOREACH(const QContact &c, clist) + ids.append(c.id()); + + return ids; +} + +QList GaleraManagerEngine::contacts(const QtContacts::QContactFilter &filter, + const QList& sortOrders, + const QContactFetchHint &fetchHint, QtContacts::QContactManager::Error *error) const +{ + Q_UNUSED(fetchHint); + Q_UNUSED(error); + + QContactFetchRequest request; + request.setFilter(filter); + request.setSorting(sortOrders); + + const_cast(this)->startRequest(&request); + const_cast(this)->waitForRequestFinished(&request, -1); + + if (error) { + *error = request.error(); + } + + return request.contacts(); +} + +QList GaleraManagerEngine::contacts(const QList &contactIds, const QContactFetchHint &fetchHint, QMap *errorMap, QContactManager::Error *error) const +{ + QContactFetchByIdRequest request; + request.setIds(contactIds); + request.setFetchHint(fetchHint); + + const_cast(this)->startRequest(&request); + const_cast(this)->waitForRequestFinished(&request, -1); + + if (errorMap) { + *errorMap = request.errorMap(); + } + + if (error) { + *error = request.error(); + } + + return request.contacts(); +} + +QContact GaleraManagerEngine::contact(const QContactId &contactId, const QContactFetchHint &fetchHint, QContactManager::Error *error) const +{ + QContactFetchByIdRequest request; + request.setIds(QList() << contactId); + request.setFetchHint(fetchHint); + + const_cast(this)->startRequest(&request); + const_cast(this)->waitForRequestFinished(&request, -1); + + if (error) { + *error = request.error(); + } + + return request.contacts().value(0, QContact()); +} + +bool GaleraManagerEngine::saveContact(QtContacts::QContact *contact, QtContacts::QContactManager::Error *error) +{ + QContactSaveRequest request; + + request.setContact(*contact); + startRequest(&request); + waitForRequestFinished(&request, -1); + *error = QContactManager::NoError; + + // FIXME: GaleraContactsService::updateContactDone doesn't return contacts + if (contact->id().isNull()) { + *contact = request.contacts()[0]; + } + + return true; +} + +bool GaleraManagerEngine::removeContact(const QtContacts::QContactId &contactId, QtContacts::QContactManager::Error *error) +{ + *error = QContactManager::NoError; + contact(contactId, QContactFetchHint(), error); + if (*error == QContactManager::DoesNotExistError) { + return false; + } + + QContactRemoveRequest request; + + request.setContactId(contactId); + startRequest(&request); + waitForRequestFinished(&request, -1); + *error = QContactManager::NoError; + + return true; +} + +bool GaleraManagerEngine::saveRelationship(QtContacts::QContactRelationship *relationship, QtContacts::QContactManager::Error *error) +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return true; +} + +bool GaleraManagerEngine::removeRelationship(const QtContacts::QContactRelationship &relationship, QtContacts::QContactManager::Error *error) +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return true; +} + + +bool GaleraManagerEngine::saveContacts(QList *contacts, QMap *errorMap, QtContacts::QContactManager::Error *error) +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return true; +} + +bool GaleraManagerEngine::saveContacts(QList *contacts, const QList &typeMask, QMap *errorMap, QtContacts::QContactManager::Error *error) +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return true; +} + +bool GaleraManagerEngine::removeContacts(const QList &contactIds, QMap *errorMap, QtContacts::QContactManager::Error *error) +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return true; +} + +/* "Self" contact id (MyCard) */ +bool GaleraManagerEngine::setSelfContactId(const QtContacts::QContactId &contactId, QtContacts::QContactManager::Error *error) +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return true; +} + +QtContacts::QContactId GaleraManagerEngine::selfContactId(QtContacts::QContactManager::Error *error) const +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return QContactId(); +} + +/* Relationships between contacts */ +QList GaleraManagerEngine::relationships(const QString &relationshipType, const QContact& participant, QContactRelationship::Role role, QtContacts::QContactManager::Error *error) const +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return QList(); +} + +bool GaleraManagerEngine::saveRelationships(QList *relationships, QMap* errorMap, QtContacts::QContactManager::Error *error) +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return true; +} + +bool GaleraManagerEngine::removeRelationships(const QList &relationships, QMap *errorMap, QtContacts::QContactManager::Error *error) +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return true; +} + +/* Validation for saving */ +bool GaleraManagerEngine::validateContact(const QtContacts::QContact &contact, QtContacts::QContactManager::Error *error) const +{ + qDebug() << Q_FUNC_INFO; + + *error = QContactManager::NoError; + return true; +} + +/* Asynchronous Request Support */ +void GaleraManagerEngine::requestDestroyed(QtContacts::QContactAbstractRequest *req) +{ +} + +bool GaleraManagerEngine::startRequest(QtContacts::QContactAbstractRequest *req) +{ + if (!req) { + return false; + } + + QPointer checkDeletion(req); + updateRequestState(req, QContactAbstractRequest::ActiveState); + if (!checkDeletion.isNull()) { + m_service->addRequest(req); + } + return true; +} + +bool GaleraManagerEngine::cancelRequest(QtContacts::QContactAbstractRequest *req) +{ + if (req) { + m_service->cancelRequest(req); + return true; + } else { + return false; + } +} + +bool GaleraManagerEngine::waitForRequestFinished(QtContacts::QContactAbstractRequest *req, int msecs) +{ + Q_UNUSED(msecs); + m_service->waitRequest(req); + return true; +} + +/* Capabilities reporting */ +bool GaleraManagerEngine::isRelationshipTypeSupported(const QString &relationshipType, QtContacts::QContactType::TypeValues contactType) const +{ + qDebug() << Q_FUNC_INFO; + return true; +} + +bool GaleraManagerEngine::isFilterSupported(const QtContacts::QContactFilter &filter) const +{ + qDebug() << Q_FUNC_INFO; + return true; +} + +QList GaleraManagerEngine::supportedDataTypes() const +{ + QList st; + st.append(QVariant::String); + st.append(QVariant::Date); + st.append(QVariant::DateTime); + st.append(QVariant::Time); + st.append(QVariant::Bool); + st.append(QVariant::Char); + st.append(QVariant::Int); + st.append(QVariant::UInt); + st.append(QVariant::LongLong); + st.append(QVariant::ULongLong); + st.append(QVariant::Double); + + return st; +} + +} // namespace diff -Nru address-book-service-0.1.1+14.04.20140325.2/contacts/qcontact-backend.h address-book-service-0.1.1+14.04.20140327/contacts/qcontact-backend.h --- address-book-service-0.1.1+14.04.20140325.2/contacts/qcontact-backend.h 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/contacts/qcontact-backend.h 2014-03-27 18:16:30.000000000 +0000 @@ -0,0 +1,110 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef __GALER_QCONTACT_BACKEND_H__ +#define __GALER_QCONTACT_BACKEND_H__ + +#include +#include +#include +#include +#include + +#include + +namespace galera +{ +class GaleraContactsService; + +class GaleraEngineFactory : public QtContacts::QContactManagerEngineFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QContactManagerEngineFactoryInterface" FILE "galera.json") +public: + QtContacts::QContactManagerEngine* engine(const QMap ¶meters, QtContacts::QContactManager::Error*); + QString managerName() const; + QtContacts::QContactEngineId* createContactEngineId(const QMap ¶meters, const QString &engineIdString) const; +}; + +class GaleraManagerEngine : public QtContacts::QContactManagerEngine +{ + Q_OBJECT + +public: + static GaleraManagerEngine *createEngine(const QMap ¶meters); + + ~GaleraManagerEngine(); + + /* URI reporting */ + QString managerName() const; + QMap managerParameters() const; + + /*! \reimp */ + int managerVersion() const; + + /* Filtering */ + virtual QList contactIds(const QtContacts::QContactFilter &filter, const QList &sortOrders, QtContacts::QContactManager::Error *error) const; + virtual QList contacts(const QtContacts::QContactFilter &filter, const QList& sortOrders, const QtContacts::QContactFetchHint &fetchHint, QtContacts::QContactManager::Error *error) const; + virtual QList contacts(const QList &contactIds, const QtContacts::QContactFetchHint& fetchHint, QMap *errorMap, QtContacts::QContactManager::Error *error) const; + virtual QtContacts::QContact contact(const QtContacts::QContactId &contactId, const QtContacts::QContactFetchHint &fetchHint, QtContacts::QContactManager::Error *error) const; + + virtual bool saveContact(QtContacts::QContact *contact, QtContacts::QContactManager::Error *error); + virtual bool removeContact(const QtContacts::QContactId &contactId, QtContacts::QContactManager::Error *error); + virtual bool saveRelationship(QtContacts::QContactRelationship *relationship, QtContacts::QContactManager::Error *error); + virtual bool removeRelationship(const QtContacts::QContactRelationship &relationship, QtContacts::QContactManager::Error *error); + + virtual bool saveContacts(QList *contacts, QMap *errorMap, QtContacts::QContactManager::Error *error); + virtual bool saveContacts(QList *contacts, const QList &typeMask, QMap *errorMap, QtContacts::QContactManager::Error *error); + virtual bool removeContacts(const QList &contactIds, QMap *errorMap, QtContacts::QContactManager::Error *error); + + /* "Self" contact id (MyCard) */ + virtual bool setSelfContactId(const QtContacts::QContactId &contactId, QtContacts::QContactManager::Error *error); + virtual QtContacts::QContactId selfContactId(QtContacts::QContactManager::Error *error) const; + + /* Relationships between contacts */ + virtual QList relationships(const QString &relationshipType, const QtContacts::QContact& participant, QtContacts::QContactRelationship::Role role, QtContacts::QContactManager::Error *error) const; + virtual bool saveRelationships(QList *relationships, QMap* errorMap, QtContacts::QContactManager::Error *error); + virtual bool removeRelationships(const QList &relationships, QMap *errorMap, QtContacts::QContactManager::Error *error); + + /* Validation for saving */ + virtual bool validateContact(const QtContacts::QContact &contact, QtContacts::QContactManager::Error *error) const; + + /* Asynchronous Request Support */ + virtual void requestDestroyed(QtContacts::QContactAbstractRequest *req); + virtual bool startRequest(QtContacts::QContactAbstractRequest *req); + virtual bool cancelRequest(QtContacts::QContactAbstractRequest *req); + virtual bool waitForRequestFinished(QtContacts::QContactAbstractRequest *req, int msecs); + + /* Capabilities reporting */ + virtual bool isRelationshipTypeSupported(const QString &relationshipType, QtContacts::QContactType::TypeValues contactType) const; + virtual bool isFilterSupported(const QtContacts::QContactFilter &filter) const; + virtual QList supportedDataTypes() const; + +private: + GaleraManagerEngine(); + + QList contactIds(const QList &contacts) const; + + GaleraContactsService *m_service; +}; + +} //namespace + +#endif + diff -Nru address-book-service-0.1.1+14.04.20140325.2/contacts/qcontact-engineid.cpp address-book-service-0.1.1+14.04.20140327/contacts/qcontact-engineid.cpp --- address-book-service-0.1.1+14.04.20140325.2/contacts/qcontact-engineid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/contacts/qcontact-engineid.cpp 2014-03-27 18:16:17.000000000 +0000 @@ -0,0 +1,121 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "qcontact-engineid.h" + +#include + +using namespace QtContacts; + +namespace galera +{ + +GaleraEngineId::GaleraEngineId() + : m_contactId("") +{ +} + +GaleraEngineId::GaleraEngineId(const QString &contactId, const QString &managerUri) + : m_contactId(contactId), + m_managerUri(managerUri) +{ +} + +GaleraEngineId::~GaleraEngineId() +{ +} + +GaleraEngineId::GaleraEngineId(const GaleraEngineId &other) + : m_contactId(other.m_contactId), + m_managerUri(other.m_managerUri) +{ +} + +GaleraEngineId::GaleraEngineId(const QMap ¶meters, const QString &engineIdString) +{ + m_contactId = engineIdString; + m_managerUri = QContactManager::buildUri("galera", parameters); +} + +bool GaleraEngineId::isEqualTo(const QtContacts::QContactEngineId *other) const +{ + if (m_contactId != static_cast(other)->m_contactId) + return false; + return true; +} + +bool GaleraEngineId::isLessThan(const QtContacts::QContactEngineId *other) const +{ + const GaleraEngineId *otherPtr = static_cast(other); + if (m_managerUri < otherPtr->m_managerUri) + return true; + if (m_contactId < otherPtr->m_contactId) + return true; + return false; +} + +QString GaleraEngineId::managerUri() const +{ + return m_managerUri; +} + +QString GaleraEngineId::toString() const +{ + return m_contactId; +} + +QtContacts::QContactEngineId* GaleraEngineId::clone() const +{ + return new GaleraEngineId(m_contactId, m_managerUri); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug& GaleraEngineId::debugStreamOut(QDebug &dbg) const +{ + dbg.nospace() << "EngineId(" << m_managerUri << "," << m_contactId << ")"; + return dbg.maybeSpace(); +} +#endif + +uint GaleraEngineId::hash() const +{ + return qHash(m_contactId); +} + +#ifndef QT_NO_DATASTREAM +QDataStream& operator<<(QDataStream& out, const GaleraEngineId& engineId) +{ + out << engineId.m_managerUri << engineId.m_contactId; + return out; +} + +QDataStream& operator>>(QDataStream& in, GaleraEngineId& engineId) +{ + QString managerUri; + QString contactId; + + in >> managerUri; + in >> contactId; + + engineId.m_contactId = contactId; + engineId.m_managerUri = managerUri; //= GaleraEngineId(contactId, managerUri); + return in; +} +#endif + +} diff -Nru address-book-service-0.1.1+14.04.20140325.2/contacts/qcontact-engineid.h address-book-service-0.1.1+14.04.20140327/contacts/qcontact-engineid.h --- address-book-service-0.1.1+14.04.20140325.2/contacts/qcontact-engineid.h 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/contacts/qcontact-engineid.h 2014-03-27 18:16:17.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GALERA_QCONTACT_ENGINEID_H__ +#define __GALERA_QCONTACT_ENGINEID_H__ + +#include + +namespace galera +{ + +class GaleraEngineId : public QtContacts::QContactEngineId +{ +public: + GaleraEngineId(); + ~GaleraEngineId(); + GaleraEngineId(const QString &contactId, const QString &managerUri); + GaleraEngineId(const GaleraEngineId &other); + GaleraEngineId(const QMap ¶meters, const QString &engineIdString); + + bool isEqualTo(const QtContacts::QContactEngineId *other) const; + bool isLessThan(const QtContacts::QContactEngineId *other) const; + + QString managerUri() const; + + QContactEngineId* clone() const; + + QString toString() const; + +#ifndef QT_NO_DEBUG_STREAM + QDebug& debugStreamOut(QDebug &dbg) const; +#endif +#ifndef QT_NO_DATASTREAM + friend QDataStream& operator<<(QDataStream& out, const GaleraEngineId& filter); + friend QDataStream& operator>>(QDataStream& in, GaleraEngineId& filter); +#endif + uint hash() const; + +private: + QString m_contactId; + QString m_managerUri; +}; + +} //namespace + +#endif diff -Nru address-book-service-0.1.1+14.04.20140325.2/contacts/request-data.cpp address-book-service-0.1.1+14.04.20140327/contacts/request-data.cpp --- address-book-service-0.1.1+14.04.20140325.2/contacts/request-data.cpp 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/contacts/request-data.cpp 2014-03-27 18:16:17.000000000 +0000 @@ -0,0 +1,242 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "request-data.h" + +#include +#include + +using namespace QtContacts; +namespace galera +{ + +RequestData::RequestData(QContactAbstractRequest *request, + QDBusInterface *view, + const FetchHint &hint, + QDBusPendingCallWatcher *watcher) + : m_offset(0), + m_hint(hint), + m_canceled(false), + m_eventLoop(0) +{ + init(request, view, watcher); +} + +RequestData::RequestData(QtContacts::QContactAbstractRequest *request, + QDBusPendingCallWatcher *watcher) + : m_offset(0), + m_canceled(false), + m_eventLoop(0) +{ + init(request, 0, watcher); +} + +RequestData::~RequestData() +{ + if (!m_request.isNull() && m_canceled) { + update(QContactAbstractRequest::CanceledState); + } + m_request.clear(); +} + +void RequestData::init(QtContacts::QContactAbstractRequest *request, + QDBusInterface *view, + QDBusPendingCallWatcher *watcher) +{ + m_request = request; + + if (view) { + updateView(view); + } + + if (watcher) { + m_watcher = QSharedPointer(watcher, RequestData::deleteWatcher); + } + +} + +QContactAbstractRequest* RequestData::request() const +{ + return m_request.data(); +} + +int RequestData::offset() const +{ + return m_offset; +} + +bool RequestData::isLive() const +{ + return !m_request.isNull() && + (m_request->state() == QContactAbstractRequest::ActiveState); +} + +void RequestData::cancel() +{ + m_watcher.clear(); + m_canceled = true; +} + +bool RequestData::canceled() const +{ + return m_canceled; +} + +void RequestData::wait() +{ + if (m_eventLoop) { + qWarning() << "Recursive wait call"; + Q_ASSERT(false); + } + + if (isLive()) { + QEventLoop eventLoop; + m_eventLoop = &eventLoop; + eventLoop.exec(); + m_eventLoop = 0; + } +} + +QDBusInterface* RequestData::view() const +{ + return m_view.data(); +} + +void RequestData::updateView(QDBusInterface* view) +{ + m_view = QSharedPointer(view, RequestData::deleteView); +} + +QStringList RequestData::fields() const +{ + return m_hint.fields(); +} + +void RequestData::updateWatcher(QDBusPendingCallWatcher *watcher) +{ + m_watcher.clear(); + if (watcher) { + m_watcher = QSharedPointer(watcher, RequestData::deleteWatcher); + } +} + +void RequestData::updateOffset(int offset) +{ + m_offset += offset; +} + +void RequestData::setError(QContactManager::Error error) +{ + m_result.clear(); + m_fullResult.clear(); + update(QContactAbstractRequest::FinishedState, error); + if (m_eventLoop) { + m_eventLoop->quit(); + } +} + +void RequestData::update(QList result, + QContactAbstractRequest::State state, + QContactManager::Error error, + QMap errorMap) +{ + m_fullResult += result; + m_result = result; + update(state, error, errorMap); +} + +void RequestData::update(QContactAbstractRequest::State state, + QContactManager::Error error, + QMap errorMap) +{ + if (!isLive()) { + return; + } + + QList result; + + // only send the full contact list at the finish state + if (false) { //state == QContactAbstractRequest::FinishedState) { + result = m_fullResult; + } else { + result = m_result; + } + + switch (m_request->type()) { + case QContactAbstractRequest::ContactFetchRequest: + QContactManagerEngine::updateContactFetchRequest(static_cast(m_request.data()), + m_fullResult, + error, + state); + break; + case QContactAbstractRequest::ContactFetchByIdRequest: + QContactManagerEngine::updateContactFetchByIdRequest(static_cast(m_request.data()), + m_fullResult, + error, + errorMap, + state); + break; + case QContactAbstractRequest::ContactSaveRequest: + QContactManagerEngine::updateContactSaveRequest(static_cast(m_request.data()), + m_result, + error, + QMap(), + state); + case QContactAbstractRequest::ContactRemoveRequest: + QContactManagerEngine::updateContactRemoveRequest(static_cast(m_request.data()), + error, + errorMap, + state); + break; + default: + break; + } + + if (m_eventLoop && (state != QContactAbstractRequest::ActiveState)) { + m_eventLoop->quit(); + } +} + + +void RequestData::registerMetaType() +{ + qRegisterMetaType(); +} + +void RequestData::setError(QContactAbstractRequest *request, QContactManager::Error error) +{ + RequestData r(request); + r.setError(error); +} + +void RequestData::deleteView(QDBusInterface *view) +{ + if (view) { + view->call("close"); + view->deleteLater(); + } +} + +void RequestData::deleteWatcher(QDBusPendingCallWatcher *watcher) +{ + if (watcher) { + watcher->deleteLater(); + } +} + +} //namespace diff -Nru address-book-service-0.1.1+14.04.20140325.2/contacts/request-data.h address-book-service-0.1.1+14.04.20140327/contacts/request-data.h --- address-book-service-0.1.1+14.04.20140325.2/contacts/request-data.h 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/contacts/request-data.h 2014-03-27 18:16:17.000000000 +0000 @@ -0,0 +1,99 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GALERA_REQUEST_DATA_H__ +#define __GALERA_REQUEST_DATA_H__ + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +namespace galera +{ +class RequestData +{ +public: + RequestData(QtContacts::QContactAbstractRequest *request, + QDBusInterface *view, + const FetchHint &hint, + QDBusPendingCallWatcher *watcher=0); + + RequestData(QtContacts::QContactAbstractRequest *request, + QDBusPendingCallWatcher *watcher=0); + + + ~RequestData(); + + QtContacts::QContactAbstractRequest* request() const; + QDBusInterface* view() const; + QStringList fields() const; + + + void updateWatcher(QDBusPendingCallWatcher *watcher); + void updateView(QDBusInterface* view); + + void updateOffset(int offset); + int offset() const; + bool isLive() const; + void cancel(); + bool canceled() const; + void wait(); + + void setError(QtContacts::QContactManager::Error error); + void update(QList result, + QtContacts::QContactAbstractRequest::State state, + QtContacts::QContactManager::Error error = QtContacts::QContactManager::NoError, + QMap errorMap = QMap()); + void update(QtContacts::QContactAbstractRequest::State state, + QtContacts::QContactManager::Error error = QtContacts::QContactManager::NoError, + QMap errorMap = QMap()); + + static void setError(QtContacts::QContactAbstractRequest *request, + QtContacts::QContactManager::Error error = QtContacts::QContactManager::UnspecifiedError); + static void registerMetaType(); + +private: + QPointer m_request; + QSharedPointer m_view; + QSharedPointer m_watcher; + QList m_result; + QList m_fullResult; + int m_offset; + FetchHint m_hint; + bool m_canceled; + QEventLoop *m_eventLoop; + + void init(QtContacts::QContactAbstractRequest *request, QDBusInterface *view, QDBusPendingCallWatcher *watcher); + static void deleteRequest(QtContacts::QContactAbstractRequest *obj); + static void deleteView(QDBusInterface *view); + static void deleteWatcher(QDBusPendingCallWatcher *watcher); +}; + +} + +Q_DECLARE_METATYPE(galera::RequestData*) + +#endif diff -Nru address-book-service-0.1.1+14.04.20140325.2/debian/changelog address-book-service-0.1.1+14.04.20140327/debian/changelog --- address-book-service-0.1.1+14.04.20140325.2/debian/changelog 2014-03-27 21:01:14.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/debian/changelog 2014-03-27 21:01:14.000000000 +0000 @@ -1,3 +1,12 @@ +address-book-service (0.1.1+14.04.20140327-0ubuntu1) trusty; urgency=low + + [ Renato Araujo Oliveira Filho ] + * Implemented tests for qtcontacts plugin. Implemented support to + query for eds addressbook as contact group. Fixed crash on service + exit. Implemented support to create contacts in a target source. + + -- Ubuntu daily release Thu, 27 Mar 2014 18:16:39 +0000 + address-book-service (0.1.1+14.04.20140325.2-0ubuntu1) trusty; urgency=low [ Renato Araujo Oliveira Filho ] diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/addressbook-adaptor.h address-book-service-0.1.1+14.04.20140327/lib/addressbook-adaptor.h --- address-book-service-0.1.1+14.04.20140325.2/lib/addressbook-adaptor.h 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/addressbook-adaptor.h 2014-03-27 18:16:30.000000000 +0000 @@ -25,7 +25,7 @@ #include #include -#include "source.h" +#include "common/source.h" #include "common/dbus-service-defs.h" namespace galera @@ -55,11 +55,11 @@ " \n" " \n" " \n" -" \n" +" \n" " \n" " \n" " \n" -" \n" +" \n" " \n" " \n" " \n" diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/addressbook.cpp address-book-service-0.1.1+14.04.20140327/lib/addressbook.cpp --- address-book-service-0.1.1+14.04.20140325.2/lib/addressbook.cpp 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/addressbook.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -232,9 +232,36 @@ data->m_addressbook = this; data->m_message = message; data->sourceName = sourceId; - edsf_persona_store_create_address_book(sourceId.toUtf8().data(), - (GAsyncReadyCallback) AddressBook::createSourceDone, - data); + FolksPersonaStore *store = folks_individual_aggregator_get_primary_store(m_individualAggregator); + QString personaStoreTypeId = QString::fromUtf8(folks_persona_store_get_type_id (store)); + if ( personaStoreTypeId == "dummy") { + FolksBackendStore *backendStore = folks_backend_store_dup(); + FolksBackend *dummy = folks_backend_store_dup_backend_by_name(backendStore, "dummy"); + + GeeMap *stores = folks_backend_get_persona_stores(dummy); + GeeSet *storesKeys = gee_map_get_keys(stores); + GeeSet *storesIds = (GeeSet*) gee_hash_set_new(G_TYPE_STRING, + (GBoxedCopyFunc) g_strdup, g_free, + NULL, NULL, NULL, NULL, NULL, NULL); + + gee_collection_add_all(GEE_COLLECTION(storesIds), GEE_COLLECTION(storesKeys)); + gee_collection_add(GEE_COLLECTION(storesIds), sourceId.toUtf8().constData()); + folks_backend_set_persona_stores(dummy, storesIds); + + g_object_unref(storesIds); + g_object_unref(backendStore); + g_object_unref(dummy); + + Source src(sourceId, sourceId, false, false); + QDBusMessage reply = message.createReply(QVariant::fromValue(src)); + QDBusConnection::sessionBus().send(reply); + } else if (personaStoreTypeId == "eds") { + edsf_persona_store_create_address_book(sourceId.toUtf8().data(), + (GAsyncReadyCallback) AddressBook::createSourceDone, + data); + } else { + qWarning() << "Not supported, create sources on persona store with type id:" << personaStoreTypeId; + } return Source(); } @@ -250,7 +277,7 @@ qWarning() << "Fail to create source" << error->message; g_error_free(error); } else { - src = Source(cData->sourceName, false); + src = Source(cData->sourceName, cData->sourceName, false, false); } QDBusMessage reply = cData->m_message.createReply(QVariant::fromValue(src)); QDBusConnection::sessionBus().send(reply); @@ -260,16 +287,21 @@ void AddressBook::addGlobalAntilink(FolksPersona *persona, GAsyncReadyCallback antilinkReady, void *data) { if (FOLKS_IS_ANTI_LINKABLE(persona)) { - GeeHashSet *antiLinks = gee_hash_set_new(G_TYPE_STRING, - (GBoxedCopyFunc) g_strdup, - g_free, - NULL, NULL, NULL, NULL, NULL, NULL); - gee_collection_add(GEE_COLLECTION(antiLinks), "*"); - folks_anti_linkable_change_anti_links(FOLKS_ANTI_LINKABLE(persona), - GEE_SET(antiLinks), - antilinkReady, - data); - g_object_unref(antiLinks); + GeeSet *oldAntiLinks = folks_anti_linkable_get_anti_links(FOLKS_ANTI_LINKABLE(persona)); + if (!gee_collection_contains(GEE_COLLECTION(oldAntiLinks), "*")) { + GeeHashSet *antiLinks = gee_hash_set_new(G_TYPE_STRING, + (GBoxedCopyFunc) g_strdup, + g_free, + NULL, NULL, NULL, NULL, NULL, NULL); + gee_collection_add(GEE_COLLECTION(antiLinks), "*"); + folks_anti_linkable_change_anti_links(FOLKS_ANTI_LINKABLE(persona), + GEE_SET(antiLinks), + antilinkReady, + data); + g_object_unref(antiLinks); + } + } else { + g_object_unref(persona); } } @@ -281,6 +313,7 @@ qWarning() << "Fail to anti link pesona" << folks_persona_get_display_id(FOLKS_PERSONA(antilinkable)) << error->message; g_error_free(error); } + g_object_unref(antilinkable); } void AddressBook::getSource(const QDBusMessage &message, bool onlyTheDefault) @@ -338,13 +371,27 @@ if (res) { folks_backend_store_prepare_finish(backendStore, res); } + static QStringList backendBlackList; + + // these backends are not fully supported yet + if (backendBlackList.isEmpty()) { + backendBlackList << "telepathy" + << "bluez" + << "ofono" + << "key-file"; + } GeeCollection *backends = folks_backend_store_list_backends(backendStore); + SourceList result; GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(backends)); while(gee_iterator_next(iter)) { FolksBackend *backend = FOLKS_BACKEND(gee_iterator_get(iter)); + QString backendName = QString::fromUtf8(folks_backend_get_name(backend)); + if (backendBlackList.contains(backendName)) { + continue; + } GeeMap *stores = folks_backend_get_persona_stores(backend); GeeCollection *values = gee_map_get_values(stores); @@ -354,8 +401,12 @@ FolksPersonaStore *store = FOLKS_PERSONA_STORE(gee_iterator_get(backendIter)); QString id = QString::fromUtf8(folks_persona_store_get_id(store)); - bool canWrite = folks_persona_store_get_is_writeable(store); - result << Source(id, !canWrite); + QString displayName = QString::fromUtf8(folks_persona_store_get_display_name(store)); + + bool canWrite = folks_persona_store_get_can_add_personas(store) && + folks_persona_store_get_can_remove_personas(store); + bool isPrimary = folks_persona_store_get_is_primary_store(store); + result << Source(id, displayName, !canWrite, isPrimary); g_object_unref(store); } @@ -378,17 +429,18 @@ if (!qcontact.isEmpty()) { if (!qcontact.isEmpty()) { GHashTable *details = QIndividual::parseDetails(qcontact); - //TOOD: lookup for source and use the correct store CreateContactData *data = new CreateContactData; data->m_message = message; data->m_addressbook = this; + FolksPersonaStore *store = getFolksStore(source); folks_individual_aggregator_add_persona_from_details(m_individualAggregator, NULL, //parent - folks_individual_aggregator_get_primary_store(m_individualAggregator), + store, details, (GAsyncReadyCallback) createContactDone, (void*) data); g_hash_table_destroy(details); + g_object_unref(store); return ""; } } @@ -399,6 +451,47 @@ return ""; } +FolksPersonaStore * AddressBook::getFolksStore(const QString &source) +{ + FolksPersonaStore *result = 0; + + if (!source.isEmpty()) { + FolksBackendStore *backendStore = folks_backend_store_dup(); + GeeCollection *backends = folks_backend_store_list_backends(backendStore); + + GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(backends)); + while((result == 0) && gee_iterator_next(iter)) { + FolksBackend *backend = FOLKS_BACKEND(gee_iterator_get(iter)); + GeeMap *stores = folks_backend_get_persona_stores(backend); + GeeCollection *values = gee_map_get_values(stores); + GeeIterator *backendIter = gee_iterable_iterator(GEE_ITERABLE(values)); + + while(gee_iterator_next(backendIter)) { + FolksPersonaStore *store = FOLKS_PERSONA_STORE(gee_iterator_get(backendIter)); + + QString id = QString::fromUtf8(folks_persona_store_get_id(store)); + if (id == source) { + result = store; + break; + } + g_object_unref(store); + } + + g_object_unref(backendIter); + g_object_unref(backend); + g_object_unref(values); + } + g_object_unref(iter); + g_object_unref(backendStore); + } + + if (!result) { + result = folks_individual_aggregator_get_primary_store(m_individualAggregator); + g_object_ref(result); + } + return result; +} + QString AddressBook::linkContacts(const QStringList &contacts) { //TODO @@ -592,23 +685,23 @@ entry->individual()->setIndividual(individual); } else { QIndividual *i = new QIndividual(individual, m_individualAggregator); - - // add anti lik for any new contact, if the contact is already linked ignore it - // because this could be manually linked before - GeeSet *personas = folks_individual_get_personas(individual); - if (gee_collection_get_size(GEE_COLLECTION(personas)) == 1) { - int size = 0; - FolksPersona **personasArray = (FolksPersona **) gee_collection_to_array(GEE_COLLECTION(personas), &size); - addGlobalAntilink(personasArray[0], - (GAsyncReadyCallback) AddressBook::addGlobalAntilinkDone, - 0); - g_object_unref(personasArray[0]); - g_free(personasArray); - } i->addListener(this, SLOT(individualChanged(QIndividual*))); m_contacts->insert(new ContactEntry(i)); //TODO: Notify view } + + // add anti lik for any new contact, if the contact is already linked ignore it + // because this could be manually linked before + GeeSet *personas = folks_individual_get_personas(individual); + int size = 0; + FolksPersona **personasArray = (FolksPersona **) gee_collection_to_array(GEE_COLLECTION(personas), &size); + if (gee_collection_get_size(GEE_COLLECTION(personas)) == 1) { + FolksPersona **personasArray = (FolksPersona **) gee_collection_to_array(GEE_COLLECTION(personas), &size); + addGlobalAntilink(personasArray[0], + (GAsyncReadyCallback) AddressBook::addGlobalAntilinkDone, + 0); + } + g_free(personasArray); return id; } @@ -716,15 +809,15 @@ } else if (persona == NULL) { qWarning() << "Failed to create individual from contact: Persona already exists"; reply = createData->m_message.createErrorReply("Failed to create individual from contact", "Contact already exists"); - } else if (QIndividual::autoLinkEnabled()){ - FolksIndividual *individual = folks_persona_get_individual(persona); - reply = createData->m_message.createReply(QString::fromUtf8(folks_individual_get_id(individual))); } else { - // avoid the new persona get linked - addGlobalAntilink(persona, - (GAsyncReadyCallback) addAntiLinksDone, - data); - return; + FolksIndividual *individual = folks_persona_get_individual(persona); + ContactEntry *entry = createData->m_addressbook->m_contacts->value(QString::fromUtf8(folks_individual_get_id(individual))); + if (entry) { + QString vcard = VCardParser::contactToVcard(entry->individual()->contact()); + reply = createData->m_message.createReply(vcard); + } else { + reply = createData->m_message.createErrorReply("Failed to retrieve the new contact", error->message); + } } //TODO: use dbus connection QDBusConnection::sessionBus().send(reply); diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/addressbook.h address-book-service-0.1.1+14.04.20140327/lib/addressbook.h --- address-book-service-0.1.1+14.04.20140325.2/lib/addressbook.h 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/addressbook.h 2014-03-27 18:16:30.000000000 +0000 @@ -19,7 +19,7 @@ #ifndef __GALERA_ADDRESSBOOK_H__ #define __GALERA_ADDRESSBOOK_H__ -#include "source.h" +#include "common/source.h" #include #include @@ -120,6 +120,7 @@ bool registerObject(QDBusConnection &connection); QString removeContact(FolksIndividual *individual); QString addContact(FolksIndividual *individual); + FolksPersonaStore *getFolksStore(const QString &source); static void availableSourcesDoneListAllSources(FolksBackendStore *backendStore, GAsyncResult *res, diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/CMakeLists.txt address-book-service-0.1.1+14.04.20140327/lib/CMakeLists.txt --- address-book-service-0.1.1+14.04.20140325.2/lib/CMakeLists.txt 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/CMakeLists.txt 2014-03-27 18:16:30.000000000 +0000 @@ -10,7 +10,6 @@ dirtycontact-notify.cpp gee-utils.cpp qindividual.cpp - source.cpp update-contact-request.cpp view.cpp view-adaptor.cpp @@ -24,7 +23,6 @@ dirtycontact-notify.h gee-utils.h qindividual.h - source.h update-contact-request.h view.h view-adaptor.h diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/contacts-map.h address-book-service-0.1.1+14.04.20140327/lib/contacts-map.h --- address-book-service-0.1.1+14.04.20140325.2/lib/contacts-map.h 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/contacts-map.h 2014-03-27 18:16:30.000000000 +0000 @@ -20,7 +20,6 @@ #define __GALERA_CONTACTS_MAP_PRIV_H__ #include -#include #include #include diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/detail-context-parser.cpp address-book-service-0.1.1+14.04.20140327/lib/detail-context-parser.cpp --- address-book-service-0.1.1+14.04.20140325.2/lib/detail-context-parser.cpp 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/detail-context-parser.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -257,7 +257,7 @@ params.removeOne(VCardParser::PrefParamName.toLower()); } } - QList context = contextsFromParameters(params); + QList context = contextsFromParameters(¶ms); if (!context.isEmpty()) { detail.setContexts(context); } @@ -280,7 +280,7 @@ } } -QList DetailContextParser::contextsFromParameters(QStringList ¶meters) +QList DetailContextParser::contextsFromParameters(QStringList *parameters) { static QMap map; @@ -293,7 +293,7 @@ QList values; QStringList accepted; - Q_FOREACH(const QString ¶m, parameters) { + Q_FOREACH(const QString ¶m, *parameters) { if (map.contains(param.toLower())) { accepted << param; values << map[param.toLower()]; @@ -301,7 +301,7 @@ } Q_FOREACH(const QString ¶m, accepted) { - parameters.removeOne(param); + parameters->removeOne(param); } return values; diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/detail-context-parser.h address-book-service-0.1.1+14.04.20140327/lib/detail-context-parser.h --- address-book-service-0.1.1+14.04.20140325.2/lib/detail-context-parser.h 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/detail-context-parser.h 2014-03-27 18:16:30.000000000 +0000 @@ -40,7 +40,7 @@ static QStringList listParameters(FolksAbstractFieldDetails *details); static void parseParameters(QtContacts::QContactDetail &detail, FolksAbstractFieldDetails *fd, bool *isPref); - static QList contextsFromParameters(QStringList ¶meters); + static QList contextsFromParameters(QStringList *parameters); static void parsePhoneParameters(QtContacts::QContactDetail &phone, const QStringList ¶ms); static void parseAddressParameters(QtContacts::QContactDetail &address, const QStringList ¶meters); static int accountProtocolFromString(const QString &protocol); diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/dirtycontact-notify.h address-book-service-0.1.1+14.04.20140327/lib/dirtycontact-notify.h --- address-book-service-0.1.1+14.04.20140325.2/lib/dirtycontact-notify.h 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/dirtycontact-notify.h 2014-03-27 18:16:30.000000000 +0000 @@ -23,7 +23,6 @@ #include #include #include -#include namespace galera { @@ -38,7 +37,7 @@ Q_OBJECT public: - DirtyContactsNotify(AddressBookAdaptor *adaptor, QObject *parent=0); + DirtyContactsNotify(AddressBookAdaptor *adaptor, QObject *parent=0); void insertChangedContacts(QSet ids); void insertRemovedContacts(QSet ids); void insertAddedContacts(QSet ids); diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/qindividual.cpp address-book-service-0.1.1+14.04.20140327/lib/qindividual.cpp --- address-book-service-0.1.1+14.04.20140325.2/lib/qindividual.cpp 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/qindividual.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -165,18 +165,19 @@ return uid; } -QList QIndividual::getClientPidMap() const +QList QIndividual::getSyncTargets() const { - int index = 1; QList details; - Q_FOREACH(const QString id, m_personas.keys()) { - QContactExtendedDetail detail; + QContactSyncTarget target; - detail.setName("CLIENTPIDMAP"); - detail.setValue(QContactExtendedDetail::FieldData, index++); - detail.setValue(QContactExtendedDetail::FieldData + 1, id); - details << detail; + FolksPersona *p = m_personas[id]; + FolksPersonaStore *ps = folks_persona_get_store(p); + QString displayName = folks_persona_store_get_display_name(ps); + + target.setDetailUri(QString(id).replace(":",".")); + target.setSyncTarget(displayName); + details << target; } return details; } @@ -691,6 +692,11 @@ details << det; } + // sync targets + Q_FOREACH(QContactDetail det, fullContact.details()) { + details << det; + } + if (fields.contains(QContactDetail::TypeName)) { details << fullContact.detail(); } @@ -805,7 +811,7 @@ } m_contact->appendDetail(getUid()); - Q_FOREACH(QContactDetail detail, getClientPidMap()) { + Q_FOREACH(QContactDetail detail, getSyncTargets()) { m_contact->appendDetail(detail); } diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/qindividual.h address-book-service-0.1.1+14.04.20140327/lib/qindividual.h --- address-book-service-0.1.1+14.04.20140325.2/lib/qindividual.h 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/qindividual.h 2014-03-27 18:16:30.000000000 +0000 @@ -96,13 +96,13 @@ // QContact QtContacts::QContactDetail getUid() const; - QList getClientPidMap() const; + QList getSyncTargets() const; QtContacts::QContactDetail getPersonaName (FolksPersona *persona, int index) const; QtContacts::QContactDetail getPersonaFullName (FolksPersona *persona, int index) const; QtContacts::QContactDetail getPersonaNickName (FolksPersona *persona, int index) const; QtContacts::QContactDetail getPersonaBirthday (FolksPersona *persona, int index) const; QtContacts::QContactDetail getPersonaPhoto (FolksPersona *persona, int index) const; - QtContacts::QContactDetail getPersonaFavorite (FolksPersona *persona, int index) const; + QtContacts::QContactDetail getPersonaFavorite (FolksPersona *persona, int index) const; QList getPersonaRoles (FolksPersona *persona, QtContacts::QContactDetail *preferredRole, int index) const; diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/source.cpp address-book-service-0.1.1+14.04.20140327/lib/source.cpp --- address-book-service-0.1.1+14.04.20140325.2/lib/source.cpp 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/source.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This file is part of contact-service-app. - * - * contact-service-app is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * contact-service-app is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "source.h" - -namespace galera { - -Source::Source() - : m_isReadOnly(false) -{ -} - -Source::Source(const Source &other) - : m_id(other.id()), - m_isReadOnly(other.isReadOnly()) -{ -} - -Source::Source(QString id, bool isReadOnly) - : m_id(id), - m_isReadOnly(isReadOnly) -{ -} - -bool Source::isValid() const -{ - return !m_id.isEmpty(); -} - -QString Source::id() const -{ - return m_id; -} - -bool Source::isReadOnly() const -{ - return m_isReadOnly; -} - -void Source::registerMetaType() -{ - qRegisterMetaType("Source"); - qRegisterMetaType("SourceList"); - qDBusRegisterMetaType(); - qDBusRegisterMetaType(); -} - -QDBusArgument &operator<<(QDBusArgument &argument, const Source &source) -{ - argument.beginStructure(); - argument << source.m_id; - argument << source.m_isReadOnly; - argument.endStructure(); - - return argument; -} - -const QDBusArgument &operator>>(const QDBusArgument &argument, Source &source) -{ - argument.beginStructure(); - argument >> source.m_id; - argument >> source.m_isReadOnly; - argument.endStructure(); - - return argument; -} - -QDBusArgument &operator<<(QDBusArgument &argument, const SourceList &sources) -{ - argument.beginArray(qMetaTypeId()); - for(int i=0; i < sources.count(); ++i) { - argument << sources[i]; - } - argument.endArray(); - return argument; -} - -const QDBusArgument &operator>>(const QDBusArgument &argument, SourceList &sources) -{ - argument.beginArray(); - sources.clear(); - while(!argument.atEnd()) { - Source source; - argument >> source; - sources << source; - } - argument.endArray(); - return argument; -} - -} // namespace Galera - - - diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/source.h address-book-service-0.1.1+14.04.20140327/lib/source.h --- address-book-service-0.1.1+14.04.20140325.2/lib/source.h 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/source.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This file is part of contact-service-app. - * - * contact-service-app is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * contact-service-app is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __GALERA_SOURCE_H__ -#define __GALERA_SOURCE_H__ - -#include -#include - -namespace galera { - -class Source -{ -public: - Source(); - Source(const Source &other); - Source(QString id, bool isReadOnly); - friend QDBusArgument &operator<<(QDBusArgument &argument, const Source &source); - friend const QDBusArgument &operator>>(const QDBusArgument &argument, Source &source); - - static void registerMetaType(); - QString id() const; - bool isReadOnly() const; - bool isValid() const; - -private: - QString m_id; - bool m_isReadOnly; -}; - -typedef QList SourceList; - -QDBusArgument &operator<<(QDBusArgument &argument, const SourceList &sources); -const QDBusArgument &operator>>(const QDBusArgument &argument, SourceList &sources); - -} // namespace galera - -Q_DECLARE_METATYPE(galera::Source) -Q_DECLARE_METATYPE(galera::SourceList) - -#endif - diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/view.cpp address-book-service-0.1.1+14.04.20140327/lib/view.cpp --- address-book-service-0.1.1+14.04.20140325.2/lib/view.cpp 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/view.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -110,20 +110,27 @@ void run() { m_allContacts->lock(); - Q_FOREACH(ContactEntry *entry, m_allContacts->values()) - { - m_stoppedLock.lockForRead(); - if (m_stopped) { + + // filter contacts if necessary + if (m_filter.isValid()) { + Q_FOREACH(ContactEntry *entry, m_allContacts->values()) + { + m_stoppedLock.lockForRead(); + if (m_stopped) { + m_stoppedLock.unlock(); + m_allContacts->unlock(); + return; + } m_stoppedLock.unlock(); - m_allContacts->unlock(); - return; - } - m_stoppedLock.unlock(); - if (checkContact(entry)) { - m_contacts << entry; + if (checkContact(entry)) { + m_contacts << entry; + } } + } else { + m_contacts = m_allContacts->values(); } + chageSort(m_sortClause); m_allContacts->unlock(); } @@ -142,7 +149,7 @@ } }; -View::View(QString clause, QString sort, QStringList sources, ContactsMap *allContacts, QObject *parent) +View::View(const QString &clause, const QString &sort, const QStringList &sources, ContactsMap *allContacts, QObject *parent) : QObject(parent), m_sources(sources), m_filterThread(new FilterThread(clause, sort, allContacts)), @@ -170,17 +177,19 @@ m_adaptor = 0; } - if (m_filterThread->isRunning()) { - m_filterThread->stop(); - m_filterThread->wait(); + if (m_filterThread) { + if (m_filterThread->isRunning()) { + m_filterThread->stop(); + m_filterThread->wait(); + } + delete m_filterThread; + m_filterThread = 0; } - - delete m_filterThread; - m_filterThread = 0; } QString View::contactDetails(const QStringList &fields, const QString &id) { + Q_ASSERT(FALSE); return QString(); } @@ -209,11 +218,10 @@ connect(parser, &VCardParser::vcardParsed, this, &View::onVCardParsed); parser->contactToVcard(contacts); - return QStringList(); } -void View::onVCardParsed(QStringList vcards) +void View::onVCardParsed(const QStringList &vcards) { QObject *sender = QObject::sender(); QDBusMessage reply = sender->property("DATA").value().createReply(vcards); diff -Nru address-book-service-0.1.1+14.04.20140325.2/lib/view.h address-book-service-0.1.1+14.04.20140327/lib/view.h --- address-book-service-0.1.1+14.04.20140325.2/lib/view.h 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/lib/view.h 2014-03-27 18:16:30.000000000 +0000 @@ -42,7 +42,7 @@ Q_PROPERTY(int count READ count NOTIFY countChanged) public: - View(QString clause, QString sort, QStringList sources, ContactsMap *allContacts, QObject *parent); + View(const QString &clause, const QString &sort, const QStringList &sources, ContactsMap *allContacts, QObject *parent); ~View(); static QString objectPath(); @@ -65,7 +65,7 @@ QStringList contactsDetails(const QStringList &fields, int startIndex, int pageSize, const QDBusMessage &message); private Q_SLOTS: - void onVCardParsed(QStringList vcards); + void onVCardParsed(const QStringList &vcards); Q_SIGNALS: void closed(); diff -Nru address-book-service-0.1.1+14.04.20140325.2/qcontacts/CMakeLists.txt address-book-service-0.1.1+14.04.20140327/qcontacts/CMakeLists.txt --- address-book-service-0.1.1+14.04.20140325.2/qcontacts/CMakeLists.txt 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/qcontacts/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -set(QCONTACTS_BACKEND qtcontacts_galera) - -set(QCONTACTS_BACKEND_SRCS - qcontact-backend.cpp - qcontact-engineid.cpp - contacts-service.cpp - request-data.cpp -) - -set(QCONTACTS_BACKEND_HDRS - qcontact-backend.h - qcontact-engineid.h - contacts-service.h - request-data.h -) - -add_library(${QCONTACTS_BACKEND} MODULE - ${QCONTACTS_BACKEND_SRCS} - ${QCONTACTS_BACKEND_HDRS} -) - -include_directories( - ${CMAKE_SOURCE_DIR} -) - -target_link_libraries(${QCONTACTS_BACKEND} - galera-common -) - -qt5_use_modules(${QCONTACTS_BACKEND} Core Contacts DBus Versit) - -add_definitions(-std=gnu++11) - -execute_process( - COMMAND qmake -query QT_INSTALL_PLUGINS - OUTPUT_VARIABLE QT_INSTALL_PLUGINS - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -install(TARGETS ${QCONTACTS_BACKEND} LIBRARY DESTINATION ${QT_INSTALL_PLUGINS}/contacts) diff -Nru address-book-service-0.1.1+14.04.20140325.2/qcontacts/contacts-service.cpp address-book-service-0.1.1+14.04.20140327/qcontacts/contacts-service.cpp --- address-book-service-0.1.1+14.04.20140325.2/qcontacts/contacts-service.cpp 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/qcontacts/contacts-service.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,620 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This file is part of contact-service-app. - * - * contact-service-app is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * contact-service-app is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "contacts-service.h" -#include "qcontact-engineid.h" -#include "request-data.h" - -#include "common/vcard-parser.h" -#include "common/filter.h" -#include "common/fetch-hint.h" -#include "common/sort-clause.h" -#include "common/dbus-service-defs.h" - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#define FETCH_PAGE_SIZE 100 - -using namespace QtVersit; -using namespace QtContacts; - -namespace galera -{ -GaleraContactsService::GaleraContactsService(const QString &managerUri) - : m_selfContactId(), - m_managerUri(managerUri), - m_serviceIsReady(false), - m_iface(0) -{ - RequestData::registerMetaType(); - - m_serviceWatcher = new QDBusServiceWatcher(CPIM_SERVICE_NAME, - QDBusConnection::sessionBus(), - QDBusServiceWatcher::WatchForOwnerChange, - this); - connect(m_serviceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), - this, SLOT(serviceOwnerChanged(QString,QString,QString))); - - initialize(); -} - -GaleraContactsService::GaleraContactsService(const GaleraContactsService &other) - : m_selfContactId(other.m_selfContactId), - m_managerUri(other.m_managerUri), - m_iface(other.m_iface) -{ -} - -GaleraContactsService::~GaleraContactsService() -{ - while(!m_pendingRequests.isEmpty()) { - QPointer request = m_pendingRequests.takeFirst(); - if (request) { - request->cancel(); - request->waitForFinished(); - } - } - m_runningRequests.clear(); - - delete m_serviceWatcher; -} - -void GaleraContactsService::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner) -{ - Q_UNUSED(oldOwner); - if (name == CPIM_SERVICE_NAME) { - if (!newOwner.isEmpty()) { - // service appear - initialize(); - } else if (!m_iface.isNull()) { - // lost service - deinitialize(); - } - } -} - -void GaleraContactsService::onServiceReady() -{ - m_serviceIsReady = true; - while(!m_pendingRequests.isEmpty()) { - QPointer request = m_pendingRequests.takeFirst(); - if (request) { - addRequest(request); - } - } -} - -void GaleraContactsService::initialize() -{ - if (m_iface.isNull()) { - m_iface = QSharedPointer(new QDBusInterface(CPIM_SERVICE_NAME, - CPIM_ADDRESSBOOK_OBJECT_PATH, - CPIM_ADDRESSBOOK_IFACE_NAME)); - if (!m_iface->lastError().isValid()) { - m_serviceIsReady = m_iface.data()->property("isReady").toBool(); - connect(m_iface.data(), SIGNAL(ready()), this, SLOT(onServiceReady())); - connect(m_iface.data(), SIGNAL(contactsAdded(QStringList)), this, SLOT(onContactsAdded(QStringList))); - connect(m_iface.data(), SIGNAL(contactsRemoved(QStringList)), this, SLOT(onContactsRemoved(QStringList))); - connect(m_iface.data(), SIGNAL(contactsUpdated(QStringList)), this, SLOT(onContactsUpdated(QStringList))); - } else { - qWarning() << "Fail to connect with service:" << m_iface->lastError(); - m_iface.clear(); - } - } -} - -void GaleraContactsService::deinitialize() -{ - Q_FOREACH(RequestData* rData, m_runningRequests) { - rData->cancel(); - rData->request()->waitForFinished(); - rData->setError(QContactManager::UnspecifiedError); - } - - if (!m_iface.isNull()) { - m_id.clear(); - Q_EMIT serviceChanged(); - } - - // this will make the service re-initialize - QDBusMessage result = m_iface->call("ping"); - if (result.type() == QDBusMessage::ErrorMessage) { - qWarning() << result.errorName() << result.errorMessage(); - m_serviceIsReady = false; - } else { - m_serviceIsReady = m_iface.data()->property("isReady").toBool(); - } -} - -bool GaleraContactsService::isOnline() const -{ - return !m_iface.isNull(); -} - -void GaleraContactsService::fetchContactsById(QtContacts::QContactFetchByIdRequest *request) -{ - if (!isOnline()) { - qWarning() << "Server is not online"; - RequestData::setError(request); - return; - } - - QContactIdFilter filter; - filter.setIds(request->contactIds()); - QString filterStr = Filter(filter).toString(); - QDBusMessage result = m_iface->call("query", filterStr, "", QStringList()); - if (result.type() == QDBusMessage::ErrorMessage) { - qWarning() << result.errorName() << result.errorMessage(); - RequestData::setError(request); - return; - } - QDBusObjectPath viewObjectPath = result.arguments()[0].value(); - QDBusInterface *view = new QDBusInterface(CPIM_SERVICE_NAME, - viewObjectPath.path(), - CPIM_ADDRESSBOOK_VIEW_IFACE_NAME); - - RequestData *requestData = new RequestData(request, view, FetchHint()); - m_runningRequests << requestData; - QMetaObject::invokeMethod(this, "fetchContactsPage", Qt::QueuedConnection, Q_ARG(galera::RequestData*, requestData)); -} - -void GaleraContactsService::fetchContacts(QtContacts::QContactFetchRequest *request) -{ - if (!isOnline()) { - qWarning() << "Server is not online"; - RequestData::setError(request); - return; - } - QString sortStr = SortClause(request->sorting()).toString(); - QString filterStr = Filter(request->filter()).toString(); - FetchHint fetchHint = FetchHint(request->fetchHint()).toString(); - - QDBusPendingCall pcall = m_iface->asyncCall("query", filterStr, sortStr, QStringList()); - if (pcall.isError()) { - qWarning() << pcall.error().name() << pcall.error().message(); - RequestData::setError(request); - return; - } - - RequestData *requestData = new RequestData(request, 0, fetchHint); - m_runningRequests << requestData; - - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); - QObject::connect(watcher, &QDBusPendingCallWatcher::finished, - [=](QDBusPendingCallWatcher *call) { - this->fetchContactsContinue(requestData, call); - }); -} - - -void GaleraContactsService::fetchContactsContinue(RequestData *request, - QDBusPendingCallWatcher *call) -{ - if (!request->isLive()) { - destroyRequest(request); - return; - } - - QDBusPendingReply reply = *call; - - if (reply.isError()) { - qWarning() << reply.error().name() << reply.error().message(); - destroyRequest(request); - } else { - QDBusObjectPath viewObjectPath = reply.value(); - QDBusInterface *view = new QDBusInterface(CPIM_SERVICE_NAME, - viewObjectPath.path(), - CPIM_ADDRESSBOOK_VIEW_IFACE_NAME); - request->updateView(view); - QMetaObject::invokeMethod(this, "fetchContactsPage", Qt::QueuedConnection, Q_ARG(galera::RequestData*, request)); - } -} - -void GaleraContactsService::fetchContactsPage(RequestData *request) -{ - if (!isOnline() || !request->isLive()) { - qWarning() << "Server is not online"; - destroyRequest(request); - return; - } - - // Load contacs async - QDBusPendingCall pcall = request->view()->asyncCall("contactsDetails", - request->fields(), - request->offset(), - FETCH_PAGE_SIZE); - if (pcall.isError()) { - qWarning() << pcall.error().name() << pcall.error().message(); - request->setError(QContactManager::UnspecifiedError); - destroyRequest(request); - return; - } - - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); - request->updateWatcher(watcher); - QObject::connect(watcher, &QDBusPendingCallWatcher::finished, - [=](QDBusPendingCallWatcher *call) { - this->fetchContactsDone(request, call); - }); -} - -void GaleraContactsService::fetchContactsDone(RequestData *request, QDBusPendingCallWatcher *call) -{ - if (!request->isLive()) { - destroyRequest(request); - return; - } - - QDBusPendingReply reply = *call; - if (reply.isError()) { - qWarning() << reply.error().name() << reply.error().message(); - - request->update(QList(), - QContactAbstractRequest::FinishedState, - QContactManager::UnspecifiedError); - destroyRequest(request); - } else { - const QStringList vcards = reply.value(); - if (vcards.size()) { - VCardParser *parser = new VCardParser(this); - parser->setProperty("DATA", QVariant::fromValue(request)); - connect(parser, &VCardParser::contactsParsed, - this, &GaleraContactsService::onVCardsParsed); - parser->vcardToContact(vcards); - } else { - request->update(QList(), QContactAbstractRequest::FinishedState); - destroyRequest(request); - } - } -} - -void GaleraContactsService::onVCardsParsed(QList contacts) -{ - QObject *sender = QObject::sender(); - RequestData *request = static_cast(sender->property("DATA").value()); - - QList::iterator contact; - for (contact = contacts.begin(); contact != contacts.end(); ++contact) { - if (!contact->isEmpty()) { - QContactGuid detailId = contact->detail(); - GaleraEngineId *engineId = new GaleraEngineId(detailId.guid(), m_managerUri); - QContactId newId = QContactId(engineId); - contact->setId(newId); - // set tag to be used when creating sections - QContactName detailName = contact->detail(); - if (!detailName.firstName().isEmpty() && QString(detailName.firstName().at(0)).contains(QRegExp("([a-z]|[A-Z])"))) { - contact->addTag(detailName.firstName().at(0).toUpper()); - } else if (!detailName.lastName().isEmpty() && QString(detailName.lastName().at(0)).contains(QRegExp("([a-z]|[A-Z])"))) { - contact->addTag(detailName.lastName().at(0).toUpper()); - } else { - contact->addTag("#"); - } - } - } - - if (contacts.size() == FETCH_PAGE_SIZE) { - request->update(contacts, QContactAbstractRequest::ActiveState); - request->updateOffset(FETCH_PAGE_SIZE); - request->updateWatcher(0); - QMetaObject::invokeMethod(this, "fetchContactsPage", Qt::QueuedConnection, Q_ARG(galera::RequestData*, request)); - } else { - request->update(contacts, QContactAbstractRequest::FinishedState); - destroyRequest(request); - } - - sender->deleteLater(); -} - -void GaleraContactsService::saveContact(QtContacts::QContactSaveRequest *request) -{ - QList contacts = request->contacts(); - QStringList oldContacts; - QStringList newContacts; - - Q_FOREACH(const QContact &contact, contacts) { - if (contact.id().isNull()) { - newContacts << VCardParser::contactToVcard(contact); - } else { - oldContacts << VCardParser::contactToVcard(contact); - } - } - - if (!oldContacts.isEmpty()) { - updateContacts(request, oldContacts); - } - - if (!newContacts.isEmpty()) { - createContacts(request, newContacts); - } -} -void GaleraContactsService::createContacts(QtContacts::QContactSaveRequest *request, QStringList &contacts) -{ - if (!isOnline()) { - qWarning() << "Server is not online"; - RequestData::setError(request); - return; - } - - if (contacts.count() > 1) { - qWarning() << "TODO: implement contact creation support to more then one contact."; - return; - } - - Q_FOREACH(QString contact, contacts) { - QDBusPendingCall pcall = m_iface->asyncCall("createContact", contact, ""); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); - RequestData *requestData = new RequestData(request, watcher); - m_runningRequests << requestData; - QObject::connect(watcher, &QDBusPendingCallWatcher::finished, - [=](QDBusPendingCallWatcher *call) { - this->createContactsDone(requestData, call); - }); - - } -} - -void GaleraContactsService::createContactsDone(RequestData *request, QDBusPendingCallWatcher *call) -{ - if (!request->isLive()) { - destroyRequest(request); - return; - } - - QDBusPendingReply reply = *call; - QList contacts; - QContactManager::Error opError = QContactManager::NoError; - - if (reply.isError()) { - qWarning() << reply.error().name() << reply.error().message(); - opError = QContactManager::UnspecifiedError; - } else { - const QString id = reply.value(); - if (!id.isEmpty()) { - contacts = static_cast(request->request())->contacts(); - GaleraEngineId *engineId = new GaleraEngineId(id, m_managerUri); - QContactId contactId(engineId); - contacts[0].setId(QContactId(contactId)); - } else { - opError = QContactManager::UnspecifiedError; - } - } - - request->update(contacts, QContactAbstractRequest::FinishedState, opError); - destroyRequest(request); -} - -void GaleraContactsService::removeContact(QContactRemoveRequest *request) -{ - if (!isOnline()) { - qWarning() << "Server is not online"; - RequestData::setError(request); - return; - } - - QStringList ids; - - Q_FOREACH(QContactId contactId, request->contactIds()) { - // TODO: find a better way to get the contactId - ids << contactId.toString().split(":").last(); - } - - QDBusPendingCall pcall = m_iface->asyncCall("removeContacts", ids); - if (pcall.isError()) { - qWarning() << "Error" << pcall.error().name() << pcall.error().message(); - RequestData::setError(request); - } else { - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); - RequestData *requestData = new RequestData(request, watcher); - m_runningRequests << requestData; - QObject::connect(watcher, &QDBusPendingCallWatcher::finished, - [=](QDBusPendingCallWatcher *call) { - this->removeContactDone(requestData, call); - }); - } -} - -void GaleraContactsService::removeContactDone(RequestData *request, QDBusPendingCallWatcher *call) -{ - if (!request->isLive()) { - destroyRequest(request); - return; - } - - QDBusPendingReply reply = *call; - QContactManager::Error opError = QContactManager::NoError; - QMap errorMap; - - if (reply.isError()) { - qWarning() << reply.error().name() << reply.error().message(); - opError = QContactManager::UnspecifiedError; - } - - request->update(QContactAbstractRequest::FinishedState, opError); - destroyRequest(request); -} - -void GaleraContactsService::updateContacts(QtContacts::QContactSaveRequest *request, QStringList &contacts) -{ - if (!isOnline()) { - qWarning() << "Server is not online"; - RequestData::setError(request); - return; - } - - QDBusPendingCall pcall = m_iface->asyncCall("updateContacts", contacts); - if (pcall.isError()) { - qWarning() << "Error" << pcall.error().name() << pcall.error().message(); - RequestData::setError(request); - } else { - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, 0); - RequestData *requestData = new RequestData(request, watcher); - m_runningRequests << requestData; - QObject::connect(watcher, &QDBusPendingCallWatcher::finished, - [=](QDBusPendingCallWatcher *call) { - this->updateContactDone(requestData, call); - }); - } -} - - -void GaleraContactsService::updateContactDone(RequestData *request, QDBusPendingCallWatcher *call) -{ - if (!request->isLive()) { - destroyRequest(request); - return; - } - - QDBusPendingReply reply = *call; - QList contacts; - QMap saveError; - QContactManager::Error opError = QContactManager::NoError; - - if (reply.isError()) { - qWarning() << reply.error().name() << reply.error().message(); - opError = QContactManager::UnspecifiedError; - } else { - const QStringList vcards = reply.value(); - if (!vcards.isEmpty()) { - QMap importErrors; - //TODO report parse errors - contacts = VCardParser::vcardToContactSync(vcards); - Q_FOREACH(int key, importErrors.keys()) { - saveError.insert(key, QContactManager::BadArgumentError); - } - } - } - - request->update(contacts, QContactAbstractRequest::FinishedState, opError, saveError); - destroyRequest(request); -} - -void GaleraContactsService::cancelRequest(QtContacts::QContactAbstractRequest *request) -{ - Q_FOREACH(RequestData* rData, m_runningRequests) { - if (rData->request() == request) { - rData->cancel(); - return; - } - } -} - -void GaleraContactsService::waitRequest(QtContacts::QContactAbstractRequest *request) -{ - Q_FOREACH(RequestData* rData, m_runningRequests) { - if (rData->request() == request) { - rData->wait(); - return; - } - } -} - -void GaleraContactsService::addRequest(QtContacts::QContactAbstractRequest *request) -{ - if (!m_serviceIsReady) { - m_pendingRequests << QPointer(request); - return; - } - - if (!isOnline()) { - qWarning() << "Server is not online"; - QContactManagerEngine::updateRequestState(request, QContactAbstractRequest::FinishedState); - return; - } - - Q_ASSERT(request->state() == QContactAbstractRequest::ActiveState); - switch (request->type()) { - case QContactAbstractRequest::ContactFetchRequest: - fetchContacts(static_cast(request)); - break; - case QContactAbstractRequest::ContactFetchByIdRequest: - fetchContactsById(static_cast(request)); - break; - case QContactAbstractRequest::ContactIdFetchRequest: - qWarning() << "Not implemented: ContactIdFetchRequest"; - break; - case QContactAbstractRequest::ContactSaveRequest: - saveContact(static_cast(request)); - break; - case QContactAbstractRequest::ContactRemoveRequest: - removeContact(static_cast(request)); - break; - case QContactAbstractRequest::RelationshipFetchRequest: - qWarning() << "Not implemented: RelationshipFetchRequest"; - break; - case QContactAbstractRequest::RelationshipRemoveRequest: - qWarning() << "Not implemented: RelationshipRemoveRequest"; - break; - case QContactAbstractRequest::RelationshipSaveRequest: - qWarning() << "Not implemented: RelationshipSaveRequest"; - break; - break; - - default: // unknown request type. - break; - } -} - -void GaleraContactsService::destroyRequest(RequestData *request) -{ - m_runningRequests.remove(request); - delete request; -} - -QList GaleraContactsService::parseIds(QStringList ids) const -{ - QList contactIds; - Q_FOREACH(QString id, ids) { - GaleraEngineId *engineId = new GaleraEngineId(id, m_managerUri); - contactIds << QContactId(engineId); - } - return contactIds; -} - - -void GaleraContactsService::onContactsAdded(QStringList ids) -{ - Q_EMIT contactsAdded(parseIds(ids)); -} - -void GaleraContactsService::onContactsRemoved(QStringList ids) -{ - Q_EMIT contactsRemoved(parseIds(ids)); -} - -void GaleraContactsService::onContactsUpdated(QStringList ids) -{ - Q_EMIT contactsUpdated(parseIds(ids)); -} - -} //namespace diff -Nru address-book-service-0.1.1+14.04.20140325.2/qcontacts/contacts-service.h address-book-service-0.1.1+14.04.20140327/qcontacts/contacts-service.h --- address-book-service-0.1.1+14.04.20140325.2/qcontacts/contacts-service.h 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/qcontacts/contacts-service.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This file is part of contact-service-app. - * - * contact-service-app is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * contact-service-app is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __CONTACTS_SERVICE_H__ -#define __CONTACTS_SERVICE_H__ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -class QDBusInterface; -using namespace QtContacts; // necessary for signal signatures - -namespace galera { -class RequestData; - -class GaleraContactsService : public QObject -{ - Q_OBJECT -public: - GaleraContactsService(const QString &managerUri); - GaleraContactsService(const GaleraContactsService &other); - ~GaleraContactsService(); - - QList engines() const; - void appendEngine(QtContacts::QContactManagerEngine *engine); - void removeEngine(QtContacts::QContactManagerEngine *engine); - - QList relationships() const; - - void addRequest(QtContacts::QContactAbstractRequest *request); - void cancelRequest(QtContacts::QContactAbstractRequest *request); - void waitRequest(QtContacts::QContactAbstractRequest *request); - -Q_SIGNALS: - void contactsAdded(QList ids); - void contactsRemoved(QList ids); - void contactsUpdated(QList ids); - void serviceChanged(); - -private Q_SLOTS: - void onContactsAdded(QStringList ids); - void onContactsRemoved(QStringList ids); - void onContactsUpdated(QStringList ids); - void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); - void onServiceReady(); - void onVCardsParsed(QList contacts); - - void fetchContactsDone(RequestData *request, QDBusPendingCallWatcher *call); - -private: - QString m_id; - QtContacts::QContactId m_selfContactId; // the "MyCard" contact id - QString m_managerUri; // for faster lookup. - QDBusServiceWatcher *m_serviceWatcher; - bool m_serviceIsReady; - - QSharedPointer m_iface; - QSet m_runningRequests; - QQueue > m_pendingRequests; - - Q_INVOKABLE void initialize(); - Q_INVOKABLE void deinitialize(); - - bool isOnline() const; - - void fetchContacts(QtContacts::QContactFetchRequest *request); - void fetchContactsContinue(RequestData *request, - QDBusPendingCallWatcher *call); - void fetchContactsById(QtContacts::QContactFetchByIdRequest *request); - Q_INVOKABLE void fetchContactsPage(galera::RequestData *request); - - - void saveContact(QtContacts::QContactSaveRequest *request); - void createContacts(QtContacts::QContactSaveRequest *request, QStringList &contacts); - void updateContacts(QtContacts::QContactSaveRequest *request, QStringList &contacts); - void updateContactDone(RequestData *request, QDBusPendingCallWatcher *call); - void createContactsDone(RequestData *request, QDBusPendingCallWatcher *call); - - void removeContact(QtContacts::QContactRemoveRequest *request); - void removeContactDone(RequestData *request, QDBusPendingCallWatcher *call); - - void destroyRequest(RequestData *request); - - QList parseIds(QStringList ids) const; -}; - -} - -#endif diff -Nru address-book-service-0.1.1+14.04.20140325.2/qcontacts/galera.json address-book-service-0.1.1+14.04.20140327/qcontacts/galera.json --- address-book-service-0.1.1+14.04.20140325.2/qcontacts/galera.json 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/qcontacts/galera.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -{ - "Keys": [ "galera" ] -} diff -Nru address-book-service-0.1.1+14.04.20140325.2/qcontacts/qcontact-backend.cpp address-book-service-0.1.1+14.04.20140327/qcontacts/qcontact-backend.cpp --- address-book-service-0.1.1+14.04.20140325.2/qcontacts/qcontact-backend.cpp 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/qcontacts/qcontact-backend.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,371 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This file is part of contact-service-app. - * - * contact-service-app is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * contact-service-app is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "qcontact-backend.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "contacts-service.h" -#include "qcontact-engineid.h" - -using namespace QtContacts; - -namespace galera -{ - -QtContacts::QContactManagerEngine* GaleraEngineFactory::engine(const QMap ¶meters, QtContacts::QContactManager::Error *error) -{ - Q_UNUSED(error); - - GaleraManagerEngine *engine = GaleraManagerEngine::createEngine(parameters); - return engine; -} - -QtContacts::QContactEngineId* GaleraEngineFactory::createContactEngineId(const QMap ¶meters, - const QString &engineIdString) const -{ - return new GaleraEngineId(parameters, engineIdString); -} - -QString GaleraEngineFactory::managerName() const -{ - return QString::fromLatin1("galera"); -} - -GaleraManagerEngine* GaleraManagerEngine::createEngine(const QMap ¶meters) -{ - GaleraManagerEngine *engine = new GaleraManagerEngine(); - return engine; -} - -/*! - * Constructs a new in-memory backend which shares the given \a data with - * other shared memory engines. - */ -GaleraManagerEngine::GaleraManagerEngine() - : m_service(new GaleraContactsService(managerUri())) -{ - connect(m_service, SIGNAL(contactsAdded(QList)), this, SIGNAL(contactsAdded(QList))); - connect(m_service, SIGNAL(contactsRemoved(QList)), this, SIGNAL(contactsRemoved(QList))); - connect(m_service, SIGNAL(contactsUpdated(QList)), this, SIGNAL(contactsChanged(QList))); - connect(m_service, SIGNAL(serviceChanged()), this, SIGNAL(dataChanged())); -} - -/*! Frees any memory used by this engine */ -GaleraManagerEngine::~GaleraManagerEngine() -{ - delete m_service; -} - -/* URI reporting */ -QString GaleraManagerEngine::managerName() const -{ - return "galera"; -} - -QMap GaleraManagerEngine::managerParameters() const -{ - QMap parameters; - return parameters; -} - -int GaleraManagerEngine::managerVersion() const -{ - return 1; -} - -/* Filtering */ -QList GaleraManagerEngine::contactIds(const QtContacts::QContactFilter &filter, const QList &sortOrders, QtContacts::QContactManager::Error *error) const -{ - QList clist = contacts(filter, sortOrders, QtContacts::QContactFetchHint(), error); - - /* Extract the ids */ - QList ids; - Q_FOREACH(const QContact &c, clist) - ids.append(c.id()); - - return ids; -} - -QList GaleraManagerEngine::contacts(const QtContacts::QContactFilter &filter, const QList& sortOrders, const QContactFetchHint &fetchHint, QtContacts::QContactManager::Error *error) const -{ - Q_UNUSED(fetchHint); - Q_UNUSED(error); - - QList sorted; - QList contactsList = contacts(); - - /* First filter out contacts - check for default filter first */ - if (filter.type() == QContactFilter::DefaultFilter) { - Q_FOREACH(const QtContacts::QContact&c, contactsList) { - QContactManagerEngine::addSorted(&sorted,c, sortOrders); - } - } else { - Q_FOREACH(const QContact&c, contactsList) { - if (QContactManagerEngine::testFilter(filter, c)) { - QContactManagerEngine::addSorted(&sorted,c, sortOrders); - } - } - } - - return sorted; -} - -QList GaleraManagerEngine::contactIds(const QList &contacts) const -{ - QList res; - for (const QContact &contact: contacts) { - res.push_back(contact.id()); - } - return res; -} - -QList GaleraManagerEngine::contacts() const -{ - QContactFetchRequest request; - const_cast(this)->startRequest(&request); - const_cast(this)->waitForRequestFinished(&request, -1); - - return request.contacts(); -} - -QContact GaleraManagerEngine::contact(const QtContacts::QContactId &contactId, const QContactFetchHint &fetchHint, QtContacts::QContactManager::Error *error) const -{ - Q_UNUSED(fetchHint); - - QList contactsList = contacts(); - - int index = contactIds(contactsList).indexOf(contactId); - - if (index != -1) { - // found the contact successfully. - *error = QContactManager::NoError; - return contactsList.at(index); - } - - *error = QContactManager::DoesNotExistError; - return QContact(); -} - -bool GaleraManagerEngine::saveContact(QtContacts::QContact *contact, QtContacts::QContactManager::Error *error) -{ - QContactSaveRequest request; - - request.setContact(*contact); - startRequest(&request); - waitForRequestFinished(&request, -1); - *error = QContactManager::NoError; - - // FIXME: GaleraContactsService::updateContactDone doesn't return contacts - if (contact->id().isNull()) - *contact = request.contacts()[0]; - - return true; -} - -bool GaleraManagerEngine::removeContact(const QtContacts::QContactId &contactId, QtContacts::QContactManager::Error *error) -{ - *error = QContactManager::NoError; - contact(contactId, QContactFetchHint(), error); - if (*error == QContactManager::DoesNotExistError) { - return false; - } - - QContactRemoveRequest request; - - request.setContactId(contactId); - startRequest(&request); - waitForRequestFinished(&request, -1); - *error = QContactManager::NoError; - - return true; -} - -bool GaleraManagerEngine::saveRelationship(QtContacts::QContactRelationship *relationship, QtContacts::QContactManager::Error *error) -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return true; -} - -bool GaleraManagerEngine::removeRelationship(const QtContacts::QContactRelationship &relationship, QtContacts::QContactManager::Error *error) -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return true; -} - - -bool GaleraManagerEngine::saveContacts(QList *contacts, QMap *errorMap, QtContacts::QContactManager::Error *error) -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return true; -} - -bool GaleraManagerEngine::saveContacts(QList *contacts, const QList &typeMask, QMap *errorMap, QtContacts::QContactManager::Error *error) -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return true; -} - -bool GaleraManagerEngine::removeContacts(const QList &contactIds, QMap *errorMap, QtContacts::QContactManager::Error *error) -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return true; -} - -/* "Self" contact id (MyCard) */ -bool GaleraManagerEngine::setSelfContactId(const QtContacts::QContactId &contactId, QtContacts::QContactManager::Error *error) -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return true; -} - -QtContacts::QContactId GaleraManagerEngine::selfContactId(QtContacts::QContactManager::Error *error) const -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return QContactId(); -} - -/* Relationships between contacts */ -QList GaleraManagerEngine::relationships(const QString &relationshipType, const QContact& participant, QContactRelationship::Role role, QtContacts::QContactManager::Error *error) const -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return QList(); -} - -bool GaleraManagerEngine::saveRelationships(QList *relationships, QMap* errorMap, QtContacts::QContactManager::Error *error) -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return true; -} - -bool GaleraManagerEngine::removeRelationships(const QList &relationships, QMap *errorMap, QtContacts::QContactManager::Error *error) -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return true; -} - -/* Validation for saving */ -bool GaleraManagerEngine::validateContact(const QtContacts::QContact &contact, QtContacts::QContactManager::Error *error) const -{ - qDebug() << Q_FUNC_INFO; - - *error = QContactManager::NoError; - return true; -} - -/* Asynchronous Request Support */ -void GaleraManagerEngine::requestDestroyed(QtContacts::QContactAbstractRequest *req) -{ -} - -bool GaleraManagerEngine::startRequest(QtContacts::QContactAbstractRequest *req) -{ - if (!req) { - return false; - } - - QPointer checkDeletion(req); - updateRequestState(req, QContactAbstractRequest::ActiveState); - if (!checkDeletion.isNull()) { - m_service->addRequest(req); - } - return true; -} - -bool GaleraManagerEngine::cancelRequest(QtContacts::QContactAbstractRequest *req) -{ - if (req) { - m_service->cancelRequest(req); - return true; - } else { - return false; - } -} - -bool GaleraManagerEngine::waitForRequestFinished(QtContacts::QContactAbstractRequest *req, int msecs) -{ - Q_UNUSED(msecs); - m_service->waitRequest(req); - return true; -} - -/* Capabilities reporting */ -bool GaleraManagerEngine::isRelationshipTypeSupported(const QString &relationshipType, QtContacts::QContactType::TypeValues contactType) const -{ - qDebug() << Q_FUNC_INFO; - return true; -} - -bool GaleraManagerEngine::isFilterSupported(const QtContacts::QContactFilter &filter) const -{ - qDebug() << Q_FUNC_INFO; - return true; -} - -QList GaleraManagerEngine::supportedDataTypes() const -{ - QList st; - st.append(QVariant::String); - st.append(QVariant::Date); - st.append(QVariant::DateTime); - st.append(QVariant::Time); - st.append(QVariant::Bool); - st.append(QVariant::Char); - st.append(QVariant::Int); - st.append(QVariant::UInt); - st.append(QVariant::LongLong); - st.append(QVariant::ULongLong); - st.append(QVariant::Double); - - return st; -} - -} // namespace diff -Nru address-book-service-0.1.1+14.04.20140325.2/qcontacts/qcontact-backend.h address-book-service-0.1.1+14.04.20140327/qcontacts/qcontact-backend.h --- address-book-service-0.1.1+14.04.20140325.2/qcontacts/qcontact-backend.h 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/qcontacts/qcontact-backend.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This file is part of contact-service-app. - * - * contact-service-app is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * contact-service-app is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#ifndef __GALER_QCONTACT_BACKEND_H__ -#define __GALER_QCONTACT_BACKEND_H__ - -#include -#include -#include -#include -#include - -#include - -namespace galera -{ -class GaleraContactsService; - -class GaleraEngineFactory : public QtContacts::QContactManagerEngineFactory -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QContactManagerEngineFactoryInterface" FILE "galera.json") -public: - QtContacts::QContactManagerEngine* engine(const QMap ¶meters, QtContacts::QContactManager::Error*); - QString managerName() const; - QtContacts::QContactEngineId* createContactEngineId(const QMap ¶meters, const QString &engineIdString) const; -}; - -class GaleraManagerEngine : public QtContacts::QContactManagerEngine -{ - Q_OBJECT - -public: - static GaleraManagerEngine *createEngine(const QMap ¶meters); - - ~GaleraManagerEngine(); - - /* URI reporting */ - QString managerName() const; - QMap managerParameters() const; - - /*! \reimp */ - int managerVersion() const; - - /* Filtering */ - virtual QList contactIds(const QtContacts::QContactFilter &filter, const QList &sortOrders, QtContacts::QContactManager::Error *error) const; - virtual QList contacts(const QtContacts::QContactFilter &filter, const QList& sortOrders, const QtContacts::QContactFetchHint &fetchHint, QtContacts::QContactManager::Error *error) const; - virtual QtContacts::QContact contact(const QtContacts::QContactId &contactId, const QtContacts::QContactFetchHint &fetchHint, QtContacts::QContactManager::Error *error) const; - - virtual bool saveContact(QtContacts::QContact *contact, QtContacts::QContactManager::Error *error); - virtual bool removeContact(const QtContacts::QContactId &contactId, QtContacts::QContactManager::Error *error); - virtual bool saveRelationship(QtContacts::QContactRelationship *relationship, QtContacts::QContactManager::Error *error); - virtual bool removeRelationship(const QtContacts::QContactRelationship &relationship, QtContacts::QContactManager::Error *error); - - virtual bool saveContacts(QList *contacts, QMap *errorMap, QtContacts::QContactManager::Error *error); - virtual bool saveContacts(QList *contacts, const QList &typeMask, QMap *errorMap, QtContacts::QContactManager::Error *error); - virtual bool removeContacts(const QList &contactIds, QMap *errorMap, QtContacts::QContactManager::Error *error); - - /* "Self" contact id (MyCard) */ - virtual bool setSelfContactId(const QtContacts::QContactId &contactId, QtContacts::QContactManager::Error *error); - virtual QtContacts::QContactId selfContactId(QtContacts::QContactManager::Error *error) const; - - /* Relationships between contacts */ - virtual QList relationships(const QString &relationshipType, const QtContacts::QContact& participant, QtContacts::QContactRelationship::Role role, QtContacts::QContactManager::Error *error) const; - virtual bool saveRelationships(QList *relationships, QMap* errorMap, QtContacts::QContactManager::Error *error); - virtual bool removeRelationships(const QList &relationships, QMap *errorMap, QtContacts::QContactManager::Error *error); - - /* Validation for saving */ - virtual bool validateContact(const QtContacts::QContact &contact, QtContacts::QContactManager::Error *error) const; - - /* Asynchronous Request Support */ - virtual void requestDestroyed(QtContacts::QContactAbstractRequest *req); - virtual bool startRequest(QtContacts::QContactAbstractRequest *req); - virtual bool cancelRequest(QtContacts::QContactAbstractRequest *req); - virtual bool waitForRequestFinished(QtContacts::QContactAbstractRequest *req, int msecs); - - /* Capabilities reporting */ - virtual bool isRelationshipTypeSupported(const QString &relationshipType, QtContacts::QContactType::TypeValues contactType) const; - virtual bool isFilterSupported(const QtContacts::QContactFilter &filter) const; - virtual QList supportedDataTypes() const; - -private: - GaleraManagerEngine(); - - QList contacts() const; - QList contactIds(const QList &contacts) const; - - GaleraContactsService *m_service; -}; - -} //namespace - -#endif - diff -Nru address-book-service-0.1.1+14.04.20140325.2/qcontacts/qcontact-engineid.cpp address-book-service-0.1.1+14.04.20140327/qcontacts/qcontact-engineid.cpp --- address-book-service-0.1.1+14.04.20140325.2/qcontacts/qcontact-engineid.cpp 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/qcontacts/qcontact-engineid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,121 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This file is part of contact-service-app. - * - * contact-service-app is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * contact-service-app is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "qcontact-engineid.h" - -#include - -using namespace QtContacts; - -namespace galera -{ - -GaleraEngineId::GaleraEngineId() - : m_contactId("") -{ -} - -GaleraEngineId::GaleraEngineId(const QString &contactId, const QString &managerUri) - : m_contactId(contactId), - m_managerUri(managerUri) -{ -} - -GaleraEngineId::~GaleraEngineId() -{ -} - -GaleraEngineId::GaleraEngineId(const GaleraEngineId &other) - : m_contactId(other.m_contactId), - m_managerUri(other.m_managerUri) -{ -} - -GaleraEngineId::GaleraEngineId(const QMap ¶meters, const QString &engineIdString) -{ - m_contactId = engineIdString; - m_managerUri = QContactManager::buildUri("galera", parameters); -} - -bool GaleraEngineId::isEqualTo(const QtContacts::QContactEngineId *other) const -{ - if (m_contactId != static_cast(other)->m_contactId) - return false; - return true; -} - -bool GaleraEngineId::isLessThan(const QtContacts::QContactEngineId *other) const -{ - const GaleraEngineId *otherPtr = static_cast(other); - if (m_managerUri < otherPtr->m_managerUri) - return true; - if (m_contactId < otherPtr->m_contactId) - return true; - return false; -} - -QString GaleraEngineId::managerUri() const -{ - return m_managerUri; -} - -QString GaleraEngineId::toString() const -{ - return m_contactId; -} - -QtContacts::QContactEngineId* GaleraEngineId::clone() const -{ - return new GaleraEngineId(m_contactId, m_managerUri); -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug& GaleraEngineId::debugStreamOut(QDebug &dbg) const -{ - dbg.nospace() << "EngineId(" << m_managerUri << "," << m_contactId << ")"; - return dbg.maybeSpace(); -} -#endif - -uint GaleraEngineId::hash() const -{ - return qHash(m_contactId); -} - -#ifndef QT_NO_DATASTREAM -QDataStream& operator<<(QDataStream& out, const GaleraEngineId& engineId) -{ - out << engineId.m_managerUri << engineId.m_contactId; - return out; -} - -QDataStream& operator>>(QDataStream& in, GaleraEngineId& engineId) -{ - QString managerUri; - QString contactId; - - in >> managerUri; - in >> contactId; - - engineId.m_contactId = contactId; - engineId.m_managerUri = managerUri; //= GaleraEngineId(contactId, managerUri); - return in; -} -#endif - -} diff -Nru address-book-service-0.1.1+14.04.20140325.2/qcontacts/qcontact-engineid.h address-book-service-0.1.1+14.04.20140327/qcontacts/qcontact-engineid.h --- address-book-service-0.1.1+14.04.20140325.2/qcontacts/qcontact-engineid.h 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/qcontacts/qcontact-engineid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This file is part of contact-service-app. - * - * contact-service-app is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * contact-service-app is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __GALERA_QCONTACT_ENGINEID_H__ -#define __GALERA_QCONTACT_ENGINEID_H__ - -#include - -namespace galera -{ - -class GaleraEngineId : public QtContacts::QContactEngineId -{ -public: - GaleraEngineId(); - ~GaleraEngineId(); - GaleraEngineId(const QString &contactId, const QString &managerUri); - GaleraEngineId(const GaleraEngineId &other); - GaleraEngineId(const QMap ¶meters, const QString &engineIdString); - - bool isEqualTo(const QtContacts::QContactEngineId *other) const; - bool isLessThan(const QtContacts::QContactEngineId *other) const; - - QString managerUri() const; - - QContactEngineId* clone() const; - - QString toString() const; - -#ifndef QT_NO_DEBUG_STREAM - QDebug& debugStreamOut(QDebug &dbg) const; -#endif -#ifndef QT_NO_DATASTREAM - friend QDataStream& operator<<(QDataStream& out, const GaleraEngineId& filter); - friend QDataStream& operator>>(QDataStream& in, GaleraEngineId& filter); -#endif - uint hash() const; - -private: - QString m_contactId; - QString m_managerUri; -}; - -} //namespace - -#endif diff -Nru address-book-service-0.1.1+14.04.20140325.2/qcontacts/request-data.cpp address-book-service-0.1.1+14.04.20140327/qcontacts/request-data.cpp --- address-book-service-0.1.1+14.04.20140325.2/qcontacts/request-data.cpp 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/qcontacts/request-data.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,242 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This file is part of contact-service-app. - * - * contact-service-app is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * contact-service-app is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "request-data.h" - -#include -#include - -using namespace QtContacts; -namespace galera -{ - -RequestData::RequestData(QContactAbstractRequest *request, - QDBusInterface *view, - const FetchHint &hint, - QDBusPendingCallWatcher *watcher) - : m_offset(0), - m_hint(hint), - m_canceled(false), - m_eventLoop(0) -{ - init(request, view, watcher); -} - -RequestData::RequestData(QtContacts::QContactAbstractRequest *request, - QDBusPendingCallWatcher *watcher) - : m_offset(0), - m_canceled(false), - m_eventLoop(0) -{ - init(request, 0, watcher); -} - -RequestData::~RequestData() -{ - if (!m_request.isNull() && m_canceled) { - update(QContactAbstractRequest::CanceledState); - } - m_request.clear(); -} - -void RequestData::init(QtContacts::QContactAbstractRequest *request, - QDBusInterface *view, - QDBusPendingCallWatcher *watcher) -{ - m_request = request; - - if (view) { - updateView(view); - } - - if (watcher) { - m_watcher = QSharedPointer(watcher, RequestData::deleteWatcher); - } - -} - -QContactAbstractRequest* RequestData::request() const -{ - return m_request.data(); -} - -int RequestData::offset() const -{ - return m_offset; -} - -bool RequestData::isLive() const -{ - return !m_request.isNull() && - (m_request->state() == QContactAbstractRequest::ActiveState); -} - -void RequestData::cancel() -{ - m_watcher.clear(); - m_canceled = true; -} - -bool RequestData::canceled() const -{ - return m_canceled; -} - -void RequestData::wait() -{ - if (m_eventLoop) { - qWarning() << "Recursive wait call"; - Q_ASSERT(false); - } - - if (isLive()) { - QEventLoop eventLoop; - m_eventLoop = &eventLoop; - eventLoop.exec(); - m_eventLoop = 0; - } -} - -QDBusInterface* RequestData::view() const -{ - return m_view.data(); -} - -void RequestData::updateView(QDBusInterface* view) -{ - m_view = QSharedPointer(view, RequestData::deleteView); -} - -QStringList RequestData::fields() const -{ - return m_hint.fields(); -} - -void RequestData::updateWatcher(QDBusPendingCallWatcher *watcher) -{ - m_watcher.clear(); - if (watcher) { - m_watcher = QSharedPointer(watcher, RequestData::deleteWatcher); - } -} - -void RequestData::updateOffset(int offset) -{ - m_offset += offset; -} - -void RequestData::setError(QContactManager::Error error) -{ - m_result.clear(); - m_fullResult.clear(); - update(QContactAbstractRequest::FinishedState, error); - if (m_eventLoop) { - m_eventLoop->quit(); - } -} - -void RequestData::update(QList result, - QContactAbstractRequest::State state, - QContactManager::Error error, - QMap errorMap) -{ - m_fullResult += result; - m_result = result; - update(state, error, errorMap); -} - -void RequestData::update(QContactAbstractRequest::State state, - QContactManager::Error error, - QMap errorMap) -{ - if (!isLive()) { - return; - } - - QList result; - - // only send the full contact list at the finish state - if (false) { //state == QContactAbstractRequest::FinishedState) { - result = m_fullResult; - } else { - result = m_result; - } - - switch (m_request->type()) { - case QContactAbstractRequest::ContactFetchRequest: - QContactManagerEngine::updateContactFetchRequest(static_cast(m_request.data()), - m_fullResult, - error, - state); - break; - case QContactAbstractRequest::ContactFetchByIdRequest: - QContactManagerEngine::updateContactFetchByIdRequest(static_cast(m_request.data()), - m_fullResult, - error, - errorMap, - state); - break; - case QContactAbstractRequest::ContactSaveRequest: - QContactManagerEngine::updateContactSaveRequest(static_cast(m_request.data()), - m_result, - error, - QMap(), - state); - case QContactAbstractRequest::ContactRemoveRequest: - QContactManagerEngine::updateContactRemoveRequest(static_cast(m_request.data()), - error, - errorMap, - state); - break; - default: - break; - } - - if (m_eventLoop && (state != QContactAbstractRequest::ActiveState)) { - m_eventLoop->quit(); - } -} - - -void RequestData::registerMetaType() -{ - qRegisterMetaType(); -} - -void RequestData::setError(QContactAbstractRequest *request, QContactManager::Error error) -{ - RequestData r(request); - r.setError(error); -} - -void RequestData::deleteView(QDBusInterface *view) -{ - if (view) { - view->call("close"); - view->deleteLater(); - } -} - -void RequestData::deleteWatcher(QDBusPendingCallWatcher *watcher) -{ - if (watcher) { - watcher->deleteLater(); - } -} - -} //namespace diff -Nru address-book-service-0.1.1+14.04.20140325.2/qcontacts/request-data.h address-book-service-0.1.1+14.04.20140327/qcontacts/request-data.h --- address-book-service-0.1.1+14.04.20140325.2/qcontacts/request-data.h 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/qcontacts/request-data.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This file is part of contact-service-app. - * - * contact-service-app is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3. - * - * contact-service-app is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __GALERA_REQUEST_DATA_H__ -#define __GALERA_REQUEST_DATA_H__ - -#include - -#include -#include -#include -#include - -#include - -#include -#include - -namespace galera -{ -class RequestData -{ -public: - RequestData(QtContacts::QContactAbstractRequest *request, - QDBusInterface *view, - const FetchHint &hint, - QDBusPendingCallWatcher *watcher=0); - - RequestData(QtContacts::QContactAbstractRequest *request, - QDBusPendingCallWatcher *watcher=0); - - - ~RequestData(); - - QtContacts::QContactAbstractRequest* request() const; - QDBusInterface* view() const; - QStringList fields() const; - - - void updateWatcher(QDBusPendingCallWatcher *watcher); - void updateView(QDBusInterface* view); - - void updateOffset(int offset); - int offset() const; - bool isLive() const; - void cancel(); - bool canceled() const; - void wait(); - - void setError(QtContacts::QContactManager::Error error); - void update(QList result, - QtContacts::QContactAbstractRequest::State state, - QtContacts::QContactManager::Error error = QtContacts::QContactManager::NoError, - QMap errorMap = QMap()); - void update(QtContacts::QContactAbstractRequest::State state, - QtContacts::QContactManager::Error error = QtContacts::QContactManager::NoError, - QMap errorMap = QMap()); - - static void setError(QtContacts::QContactAbstractRequest *request, - QtContacts::QContactManager::Error error = QtContacts::QContactManager::UnspecifiedError); - static void registerMetaType(); - -private: - QPointer m_request; - QSharedPointer m_view; - QSharedPointer m_watcher; - QList m_result; - QList m_fullResult; - int m_offset; - FetchHint m_hint; - bool m_canceled; - QEventLoop *m_eventLoop; - - void init(QtContacts::QContactAbstractRequest *request, QDBusInterface *view, QDBusPendingCallWatcher *watcher); - static void deleteRequest(QtContacts::QContactAbstractRequest *obj); - static void deleteView(QDBusInterface *view); - static void deleteWatcher(QDBusPendingCallWatcher *watcher); -}; - -} - -Q_DECLARE_METATYPE(galera::RequestData*) - -#endif diff -Nru address-book-service-0.1.1+14.04.20140325.2/tests/unittest/addressbook-test.cpp address-book-service-0.1.1+14.04.20140327/tests/unittest/addressbook-test.cpp --- address-book-service-0.1.1+14.04.20140325.2/tests/unittest/addressbook-test.cpp 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/tests/unittest/addressbook-test.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -17,7 +17,7 @@ */ #include "base-client-test.h" -#include "lib/source.h" +#include "common/source.h" #include "common/dbus-service-defs.h" #include "common/vcard-parser.h" @@ -166,6 +166,8 @@ QCOMPARE(list.count(), 1); galera::Source src = list[0]; QCOMPARE(src.id(), QStringLiteral("dummy-store")); + QCOMPARE(src.displayLabel(), QStringLiteral("Dummy personas")); + QCOMPARE(src.isReadOnly(), false); } @@ -177,12 +179,12 @@ // call create contact QDBusReply reply = m_serverIface->call("createContact", m_basicVcard, "dummy-store"); - // check if the returned id is valid - QString newContactId = reply.value(); - QVERIFY(!newContactId.isEmpty()); + // check if the returned contact is valid + QString vcard = reply.value(); + QVERIFY(!vcard.isEmpty()); // check if the cotact was created with the correct fields - QtContacts::QContact newContact = basicContactWithId(newContactId); + QtContacts::QContact newContact = galera::VCardParser::vcardToContact(vcard); QDBusReply reply2 = m_dummyIface->call("listContacts"); QCOMPARE(reply2.value().count(), 1); QList contactsCreated = galera::VCardParser::vcardToContactSync(reply2.value()); @@ -194,7 +196,7 @@ QList args = addedContactSpy.takeFirst(); QCOMPARE(args.count(), 1); QStringList ids = args[0].toStringList(); - QCOMPARE(ids[0], newContactId); + QCOMPARE(ids[0], newContact.detail().guid()); } @@ -210,8 +212,7 @@ QTRY_COMPARE(addedContactSpy.count(), 1); // user returned id to fill the new vcard - QString newContactId = reply.value(); - QString newVcard = m_resultBasicVcard.arg(newContactId).arg(0); + QString newVcard = reply.value(); // try create a contact with the same id QDBusReply reply2 = m_serverIface->call("createContact", newVcard, "dummy-store"); @@ -243,8 +244,7 @@ // create a basic contact QSignalSpy addedContactSpy(m_serverIface, SIGNAL(contactsAdded(QStringList))); QDBusReply replyAdd = m_serverIface->call("createContact", m_basicVcard, "dummy-store"); - QString newContactId = replyAdd.value(); - QTRY_COMPARE(addedContactSpy.count(), 1); + QString vcard = replyAdd.value(); // wait for added signal QTRY_COMPARE(addedContactSpy.count(), 1); @@ -253,6 +253,8 @@ QSignalSpy removedContactSpy(m_serverIface, SIGNAL(contactsRemoved(QStringList))); // try remove the contact created + QContact newContact = galera::VCardParser::vcardToContact(vcard); + QString newContactId = newContact.detail().guid(); QDBusReply replyRemove = m_serverIface->call("removeContacts", QStringList() << newContactId); QCOMPARE(replyRemove.value(), 1); @@ -272,11 +274,11 @@ { // create a basic contact QDBusReply replyAdd = m_serverIface->call("createContact", m_basicVcard, "dummy-store"); - QString newContactId = replyAdd.value(); - + QString vcard = replyAdd.value(); + QContact newContact = galera::VCardParser::vcardToContact(vcard); + QString newContactId = newContact.detail().guid(); // update the contact phone number - QString vcard = m_resultBasicVcard.arg(newContactId).arg(3); vcard = vcard.replace("8888888", "0000000"); QtContacts::QContact contactUpdated = galera::VCardParser::vcardToContact(vcard); diff -Nru address-book-service-0.1.1+14.04.20140325.2/tests/unittest/base-client-test.cpp address-book-service-0.1.1+14.04.20140327/tests/unittest/base-client-test.cpp --- address-book-service-0.1.1+14.04.20140325.2/tests/unittest/base-client-test.cpp 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/tests/unittest/base-client-test.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -21,8 +21,8 @@ #include "dummy-backend-defs.h" #include "common/dbus-service-defs.h" +#include "common/source.h" #include "lib/qindividual.h" -#include "lib/source.h" #include #include diff -Nru address-book-service-0.1.1+14.04.20140325.2/tests/unittest/CMakeLists.txt address-book-service-0.1.1+14.04.20140327/tests/unittest/CMakeLists.txt --- address-book-service-0.1.1+14.04.20140325.2/tests/unittest/CMakeLists.txt 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/tests/unittest/CMakeLists.txt 2014-03-27 18:16:30.000000000 +0000 @@ -74,6 +74,7 @@ declare_test(service-life-cycle-test True ${BASE_CLIENT_TEST_SRC}) declare_test(readonly-prop-test True ${BASE_CLIENT_TEST_SRC}) declare_test(contact-link-test True ${BASE_CLIENT_TEST_SRC}) + declare_test(qcontacts-test True ${BASE_CLIENT_TEST_SRC}) elseif() message(STATUS "DBus test runner not found. Some tests will be disabled") endif() diff -Nru address-book-service-0.1.1+14.04.20140325.2/tests/unittest/contact-link-test.cpp address-book-service-0.1.1+14.04.20140327/tests/unittest/contact-link-test.cpp --- address-book-service-0.1.1+14.04.20140325.2/tests/unittest/contact-link-test.cpp 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/tests/unittest/contact-link-test.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -17,8 +17,8 @@ */ #include "base-client-test.h" -#include "lib/source.h" #include "lib/qindividual.h" +#include "common/source.h" #include "common/dbus-service-defs.h" #include "common/vcard-parser.h" diff -Nru address-book-service-0.1.1+14.04.20140325.2/tests/unittest/dummy-backend.cpp address-book-service-0.1.1+14.04.20140327/tests/unittest/dummy-backend.cpp --- address-book-service-0.1.1+14.04.20140325.2/tests/unittest/dummy-backend.cpp 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/tests/unittest/dummy-backend.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -122,7 +122,34 @@ GeeCollection *personas = gee_map_get_values(map); folks_dummy_persona_store_unregister_personas(m_primaryPersonaStore, (GeeSet*)personas); g_object_unref(personas); + m_contacts.clear(); } + + // remove any extra collection/persona store + GeeHashSet *extraStores = gee_hash_set_new(FOLKS_TYPE_PERSONA_STORE, + (GBoxedCopyFunc) g_object_ref, g_object_unref, + NULL, NULL, NULL, NULL, NULL, NULL); + + GeeMap *currentStores = folks_backend_get_persona_stores(FOLKS_BACKEND(m_backend)); + GeeSet *keys = gee_map_get_keys(currentStores); + GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(keys)); + + while(gee_iterator_next(iter)) { + const gchar *key = (const gchar*) gee_iterator_get(iter); + if (strcmp(key, "dummy-store") != 0) { + FolksPersonaStore *store = FOLKS_PERSONA_STORE(gee_map_get(currentStores, key)); + gee_abstract_collection_add(GEE_ABSTRACT_COLLECTION(extraStores), store); + g_object_unref(store); + } + } + + if (gee_collection_get_size(GEE_COLLECTION(extraStores)) > 0) { + folks_dummy_backend_unregister_persona_stores(m_backend, GEE_SET(extraStores)); + } + + g_object_unref(extraStores); + g_object_unref(keys); + g_object_unref(iter); } void DummyBackendProxy::initFolks() @@ -148,7 +175,6 @@ folks_individual_aggregator_prepare(m_aggregator, (GAsyncReadyCallback) DummyBackendProxy::individualAggregatorPrepared, this); - } QString DummyBackendProxy::createContact(const QtContacts::QContact &qcontact) diff -Nru address-book-service-0.1.1+14.04.20140325.2/tests/unittest/qcontacts-test.cpp address-book-service-0.1.1+14.04.20140327/tests/unittest/qcontacts-test.cpp --- address-book-service-0.1.1+14.04.20140325.2/tests/unittest/qcontacts-test.cpp 1970-01-01 00:00:00.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/tests/unittest/qcontacts-test.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -0,0 +1,224 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This file is part of contact-service-app. + * + * contact-service-app is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "base-client-test.h" +#include "common/source.h" +#include "common/dbus-service-defs.h" +#include "common/vcard-parser.h" + +#include +#include +#include +#include +#include + +#include "config.h" + +using namespace QtContacts; + +class QContactsTest : public BaseClientTest +{ + Q_OBJECT +private: + QContactManager *m_manager; + + QContact testContact() + { + // create a contact + QContact contact; + + QContactName name; + name.setFirstName("Fulano"); + name.setMiddleName("de"); + name.setLastName("Tal"); + contact.saveDetail(&name); + + QContactEmailAddress email; + email.setEmailAddress("fulano@email.com"); + contact.saveDetail(&email); + + return contact; + } + +private Q_SLOTS: + void initTestCase() + { + BaseClientTest::initTestCase(); + QCoreApplication::setLibraryPaths(QStringList() << QT_PLUGINS_BINARY_DIR); + } + + void init() + { + BaseClientTest::init(); + m_manager = new QContactManager("galera"); + } + + void cleanup() + { + delete m_manager; + BaseClientTest::cleanup(); + } + + void testAvailableManager() + { + QVERIFY(QContactManager::availableManagers().contains("galera")); + } + + /* + * Test create a new contact + */ + void testCreateContact() + { + // filter all contacts + QContactFilter filter; + + // check result, must be empty + QList contacts = m_manager->contacts(filter); + QCOMPARE(contacts.size(), 0); + + // create a contact + QContact contact = testContact(); + QSignalSpy spyContactAdded(m_manager, SIGNAL(contactsAdded(QList))); + bool result = m_manager->saveContact(&contact); + QCOMPARE(result, true); + QTRY_COMPARE(spyContactAdded.count(), 1); + + // query for new contacts + contacts = m_manager->contacts(filter); + QCOMPARE(contacts.size(), 1); + + QContact createdContact = contacts[0]; + // id + QVERIFY(!createdContact.id().isNull()); + + // email + QContactEmailAddress email = contact.detail(); + QContactEmailAddress createdEmail = createdContact.detail(); + QCOMPARE(createdEmail.emailAddress(), email.emailAddress()); + + // name + QContactName name = contact.detail(); + QContactName createdName = createdContact.detail(); + QCOMPARE(createdName.firstName(), name.firstName()); + QCOMPARE(createdName.middleName(), name.middleName()); + QCOMPARE(createdName.lastName(), name.lastName()); + + QContactSyncTarget target = contact.detail(); + QCOMPARE(target.syncTarget(), QString("Dummy personas")); + } +#if 0 + /* + * Test create a new contact + */ + void testUpdateContact() + { + // filter all contacts + QContactFilter filter; + + // create a contact + QContact contact = testContact(); + QSignalSpy spyContactAdded(m_manager, SIGNAL(contactsAdded(QList))); + bool result = m_manager->saveContact(&contact); + QCOMPARE(result, true); + QTRY_COMPARE(spyContactAdded.count(), 1); + + QContactName name = contact.detail(); + name.setMiddleName("da"); + name.setLastName("Silva"); + contact.saveDetail(&name); + + QSignalSpy spyContactChanged(m_manager, SIGNAL(contactsChanged(QList))); + result = m_manager->saveContact(&contact); + QCOMPARE(result, true); + QTRY_COMPARE(spyContactChanged.count(), 1); + + // query for the contacts + QList contacts = m_manager->contacts(filter); + QCOMPARE(contacts.size(), 1); + QContact updatedContact = contacts[0]; + + // name + QContactName updatedName = updatedContact.detail(); + QCOMPARE(updatedName.firstName(), name.firstName()); + QCOMPARE(updatedName.middleName(), name.middleName()); + QCOMPARE(updatedName.lastName(), name.lastName()); + } + + /* + * Test create a contact source using the contact group + */ + void testCreateGroup() + { + QContactManager manager("galera"); + + // create a contact + QContact contact; + contact.setType(QContactType::TypeGroup); + + QContactDisplayLabel label; + label.setLabel("test group"); + contact.saveDetail(&label); + + bool result = manager.saveContact(&contact); + QCOMPARE(result, true); + + // query for new contacts + QContactDetailFilter filter; + filter.setDetailType(QContactDetail::TypeType, QContactType::FieldType); + filter.setValue(QContactType::TypeGroup); + QList contacts = manager.contacts(filter); + + // will be two sources since we have the main source already created + QCOMPARE(contacts.size(), 2); + + QContact createdContact = contacts[0]; + // id + QVERIFY(!createdContact.id().isNull()); + + // label + QContactDisplayLabel createdlabel = createdContact.detail(); + QCOMPARE(createdlabel.label(), label.label()); + } + + /* + * Test query a contact source using the contact group + */ + void testQueryGroups() + { + QContactManager manager("galera"); + + // filter all contact groups/addressbook + QContactDetailFilter filter; + filter.setDetailType(QContactDetail::TypeType, QContactType::FieldType); + filter.setValue(QContactType::TypeGroup); + + // check result + QList contacts = manager.contacts(filter); + QCOMPARE(contacts.size(), 1); + QCOMPARE(contacts[0].id().toString(), QStringLiteral("qtcontacts:galera::dummy-store")); + QCOMPARE(contacts[0].type(), QContactType::TypeGroup); + + QContactDisplayLabel label = contacts[0].detail(QContactDisplayLabel::Type); + QCOMPARE(label.label(), QStringLiteral("Dummy personas")); + } +#endif +}; + +QTEST_MAIN(QContactsTest) + +#include "qcontacts-test.moc" diff -Nru address-book-service-0.1.1+14.04.20140325.2/tests/unittest/readonly-prop-test.cpp address-book-service-0.1.1+14.04.20140327/tests/unittest/readonly-prop-test.cpp --- address-book-service-0.1.1+14.04.20140325.2/tests/unittest/readonly-prop-test.cpp 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/tests/unittest/readonly-prop-test.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -17,7 +17,7 @@ */ #include "base-client-test.h" -#include "lib/source.h" +#include "common/source.h" #include "common/dbus-service-defs.h" #include "common/vcard-parser.h" diff -Nru address-book-service-0.1.1+14.04.20140325.2/tests/unittest/service-life-cycle-test.cpp address-book-service-0.1.1+14.04.20140327/tests/unittest/service-life-cycle-test.cpp --- address-book-service-0.1.1+14.04.20140325.2/tests/unittest/service-life-cycle-test.cpp 2014-03-25 13:31:39.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/tests/unittest/service-life-cycle-test.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -28,7 +28,6 @@ { Q_OBJECT private Q_SLOTS: - void testServiceReady() { QTRY_COMPARE(m_serverIface->property("isReady").toBool(), true); diff -Nru address-book-service-0.1.1+14.04.20140325.2/tests/unittest/vcardparser-test.cpp address-book-service-0.1.1+14.04.20140327/tests/unittest/vcardparser-test.cpp --- address-book-service-0.1.1+14.04.20140325.2/tests/unittest/vcardparser-test.cpp 2014-03-25 13:31:53.000000000 +0000 +++ address-book-service-0.1.1+14.04.20140327/tests/unittest/vcardparser-test.cpp 2014-03-27 18:16:30.000000000 +0000 @@ -292,7 +292,63 @@ } + /* + * Test parse a vcard with sync target into a Contact + */ + void testVCardWithSyncTargetToContact() + { + QString vcard = QStringLiteral("BEGIN:VCARD\r\n" + "VERSION:3.0\r\n" + "CLIENTPIDMAP;PID=1.ADDRESSBOOKID0:ADDRESSBOOKNAME0\r\n" + "CLIENTPIDMAP;PID=2.ADDRESSBOOKID1:ADDRESSBOOKNAME1\r\n" + "N:Sauro;Dino;da Silva;;\r\n" + "EMAILPID=1.1;:dino@familiadinosauro.com.br\r\n" + "TEL;PID=1.1;TYPE=ISDN:33331410\r\n" + "TEL;PID=1.2;TYPE=CELL:8888888\r\n" + "END:VCARD\r\n"); + QContact contact = VCardParser::vcardToContact(vcard); + QList targets = contact.details(); + QCOMPARE(targets.size(), 2); + QContactSyncTarget target0; + QContactSyncTarget target1; + + // put the target in order + if (targets[0].detailUri().startsWith("1.")) { + target0 = targets[0]; + target1 = targets[1]; + } else { + target0 = targets[1]; + target1 = targets[2]; + } + + QCOMPARE(target0.detailUri(), QString("1.ADDRESSBOOKID0")); + QCOMPARE(target0.syncTarget(), QString("ADDRESSBOOKNAME0")); + QCOMPARE(target1.detailUri(), QString("2.ADDRESSBOOKID1")); + QCOMPARE(target1.syncTarget(), QString("ADDRESSBOOKNAME1")); + } + + /* + * Test parse a Contact with sync target into a vcard + */ + void testContactWithSyncTargetToVCard() + { + QContact c = m_contacts[0]; + + QContactSyncTarget target; + target.setDetailUri("1.ADDRESSBOOKID0"); + target.setSyncTarget("ADDRESSBOOKNAME0"); + c.saveDetail(&target); + + QContactSyncTarget target1; + target1.setDetailUri("2.ADDRESSBOOKID1"); + target1.setSyncTarget("ADDRESSBOOKNAME1"); + c.saveDetail(&target1); + + QString vcard = VCardParser::contactToVcard(c); + QVERIFY(vcard.contains("CLIENTPIDMAP;PID=1.ADDRESSBOOKID0:ADDRESSBOOKNAME0")); + QVERIFY(vcard.contains("CLIENTPIDMAP;PID=2.ADDRESSBOOKID1:ADDRESSBOOKNAME1")); + } }; QTEST_MAIN(VCardParseTest)