address-book-service-0.1.1+14.04.20140408.3/ 0000755 0000153 0177776 00000000000 12321057642 020267 5 ustar pbuser nogroup 0000000 0000000 address-book-service-0.1.1+14.04.20140408.3/contacts/ 0000755 0000153 0177776 00000000000 12321057642 022105 5 ustar pbuser nogroup 0000000 0000000 address-book-service-0.1.1+14.04.20140408.3/contacts/contacts-service.cpp 0000644 0000153 0177776 00000064545 12321057334 026101 0 ustar pbuser nogroup 0000000 0000000 /*
* 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)));
Q_EMIT serviceChanged();
} 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
m_iface->call("ping");
if (m_iface->lastError().isValid()) {
qWarning() << m_iface->lastError();
m_iface.clear();
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 (!isOnline()) {
qWarning() << "Server is not online";
QContactManagerEngine::updateRequestState(request, QContactAbstractRequest::FinishedState);
return;
}
if (!m_serviceIsReady) {
m_pendingRequests << QPointer(request);
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
address-book-service-0.1.1+14.04.20140408.3/contacts/qcontact-backend.h 0000644 0000153 0177776 00000013351 12321057324 025457 0 ustar pbuser nogroup 0000000 0000000 /*
* 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
address-book-service-0.1.1+14.04.20140408.3/contacts/contacts-service.h 0000644 0000153 0177776 00000010430 12321057324 025525 0 ustar pbuser nogroup 0000000 0000000 /*
* 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
address-book-service-0.1.1+14.04.20140408.3/contacts/qcontact-engineid.cpp 0000644 0000153 0177776 00000005602 12321057324 026205 0 ustar pbuser nogroup 0000000 0000000 /*
* 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
}
address-book-service-0.1.1+14.04.20140408.3/contacts/request-data.cpp 0000644 0000153 0177776 00000015105 12321057324 025207 0 ustar pbuser nogroup 0000000 0000000 /*
* 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
address-book-service-0.1.1+14.04.20140408.3/contacts/qcontact-backend.cpp 0000644 0000153 0177776 00000026006 12321057324 026013 0 ustar pbuser nogroup 0000000 0000000 /*
* 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
address-book-service-0.1.1+14.04.20140408.3/contacts/request-data.h 0000644 0000153 0177776 00000006506 12321057324 024661 0 ustar pbuser nogroup 0000000 0000000 /*
* 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
address-book-service-0.1.1+14.04.20140408.3/contacts/CMakeLists.txt 0000644 0000153 0177776 00000001530 12321057324 024641 0 ustar pbuser nogroup 0000000 0000000 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)
address-book-service-0.1.1+14.04.20140408.3/contacts/galera.json 0000644 0000153 0177776 00000000035 12321057324 024226 0 ustar pbuser nogroup 0000000 0000000 {
"Keys": [ "galera" ]
}
address-book-service-0.1.1+14.04.20140408.3/contacts/qcontact-engineid.h 0000644 0000153 0177776 00000003356 12321057324 025656 0 ustar pbuser nogroup 0000000 0000000 /*
* 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
address-book-service-0.1.1+14.04.20140408.3/cmake/ 0000755 0000153 0177776 00000000000 12321057642 021347 5 ustar pbuser nogroup 0000000 0000000 address-book-service-0.1.1+14.04.20140408.3/cmake/lcov.cmake 0000644 0000153 0177776 00000005060 12321057324 023312 0 ustar pbuser nogroup 0000000 0000000 # - This module creates a new 'lcov' target which generates
# a coverage analysis html output.
# LCOV is a graphical front-end for GCC's coverage testing tool gcov. Please see
# http://ltp.sourceforge.net/coverage/lcov.php
#
# Usage: you must add an option to your CMakeLists.txt to build your application
# with coverage support. Then you need to include this file to the lcov target.
#
# Example:
# IF(BUILD_WITH_COVERAGE)
# SET(CMAKE_C_FLAGS "-g -O0 -Wall -fprofile-arcs -ftest-coverage")
# SET(CMAKE_CXX_FLAGS "-g -O0 -Wall -fprofile-arcs -ftest-coverage")
# SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -lgcov")
# include(${CMAKE_SOURCE_DIR}/cmake/lcov.cmake)
# ENDIF(BUILD_WITH_COVERAGE)
#=============================================================================
# Copyright 2010 ascolab GmbH
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distributed this file outside of CMake, substitute the full
# License text for the above reference.)
set(REMOVE_PATTERN
q*.h
folks/*.h
dummy-*.c
internal_0_9_2.c
*.moc
moc_*.cpp
locale_facets.h
new
move.h)
## lcov target
ADD_CUSTOM_TARGET(lcov)
ADD_CUSTOM_COMMAND(TARGET lcov
COMMAND mkdir -p coverage
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
ADD_CUSTOM_COMMAND(TARGET lcov
COMMAND lcov --directory . --zerocounters
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
ADD_CUSTOM_COMMAND(TARGET lcov
COMMAND make test
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
ADD_CUSTOM_COMMAND(TARGET lcov
COMMAND lcov --directory . --capture --output-file ./coverage/stap_all.info --checksum -f
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
ADD_CUSTOM_COMMAND(TARGET lcov
COMMAND lcov --directory . -r ./coverage/stap_all.info ${REMOVE_PATTERN} --output-file ./coverage/stap.info
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
ADD_CUSTOM_COMMAND(TARGET lcov
COMMAND genhtml -o ./coverage --title "Code Coverage" --legend --show-details --demangle-cpp ./coverage/stap.info
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
ADD_CUSTOM_COMMAND(TARGET lcov
COMMAND echo "Open ${CMAKE_BINARY_DIR}/coverage/index.html to view the coverage analysis results."
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
address-book-service-0.1.1+14.04.20140408.3/cmake/vala/ 0000755 0000153 0177776 00000000000 12321057642 022272 5 ustar pbuser nogroup 0000000 0000000 address-book-service-0.1.1+14.04.20140408.3/cmake/vala/UseVala.cmake 0000644 0000153 0177776 00000015572 12321057324 024643 0 ustar pbuser nogroup 0000000 0000000 ##
# Compile vala files to their c equivalents for further processing.
#
# The "vala_precompile" function takes care of calling the valac executable on
# the given source to produce c files which can then be processed further using
# default cmake functions.
#
# The first parameter provided is a variable, which will be filled with a list
# of c files outputted by the vala compiler. This list can than be used in
# conjuction with functions like "add_executable" or others to create the
# neccessary compile rules with CMake.
#
# The following sections may be specified afterwards to provide certain options
# to the vala compiler:
#
# SOURCES
# A list of .vala files to be compiled. Please take care to add every vala
# file belonging to the currently compiled project or library as Vala will
# otherwise not be able to resolve all dependencies.
#
# PACKAGES
# A list of vala packages/libraries to be used during the compile cycle. The
# package names are exactly the same, as they would be passed to the valac
# "--pkg=" option.
#
# OPTIONS
# A list of optional options to be passed to the valac executable. This can be
# used to pass "--thread" for example to enable multi-threading support.
#
# DEFINITIONS
# A list of symbols to be used for conditional compilation. They are the same
# as they would be passed using the valac "--define=" option.
#
# CUSTOM_VAPIS
# A list of custom vapi files to be included for compilation. This can be
# useful to include freshly created vala libraries without having to install
# them in the system.
#
# GENERATE_VAPI
# Pass all the needed flags to the compiler to create a vapi for
# the compiled library. The provided name will be used for this and a
# .vapi file will be created.
#
# GENERATE_HEADER
# Let the compiler generate a header file for the compiled code. There will
# be a header file as well as an internal header file being generated called
# .h and _internal.h
#
# The following call is a simple example to the vala_precompile macro showing
# an example to every of the optional sections:
#
# find_package(Vala "0.12" REQUIRED)
# include(${VALA_USE_FILE})
#
# vala_precompile(VALA_C
# SOURCES
# source1.vala
# source2.vala
# source3.vala
# PACKAGES
# gtk+-2.0
# gio-1.0
# posix
# DIRECTORY
# gen
# OPTIONS
# --thread
# CUSTOM_VAPIS
# some_vapi.vapi
# GENERATE_VAPI
# myvapi
# GENERATE_HEADER
# myheader
# )
#
# Most important is the variable VALA_C which will contain all the generated c
# file names after the call.
##
##
# Copyright 2009-2010 Jakob Westhoff. All rights reserved.
# Copyright 2010-2011 Daniel Pfeifer
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY JAKOB WESTHOFF ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are those
# of the authors and should not be interpreted as representing official policies,
# either expressed or implied, of Jakob Westhoff
##
include(CMakeParseArguments)
function(vala_precompile output)
cmake_parse_arguments(ARGS "" "DIRECTORY;GENERATE_HEADER;GENERATE_VAPI"
"SOURCES;PACKAGES;OPTIONS;DEFINITIONS;CUSTOM_VAPIS" ${ARGN})
if(ARGS_DIRECTORY)
get_filename_component(DIRECTORY ${ARGS_DIRECTORY} ABSOLUTE)
else(ARGS_DIRECTORY)
set(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif(ARGS_DIRECTORY)
include_directories(${DIRECTORY})
set(vala_pkg_opts "")
foreach(pkg ${ARGS_PACKAGES})
list(APPEND vala_pkg_opts "--pkg=${pkg}")
endforeach(pkg ${ARGS_PACKAGES})
set(vala_define_opts "")
foreach(def ${ARGS_DEFINTIONS})
list(APPEND vala_define_opts "--define=${def}")
endforeach(def ${ARGS_DEFINTIONS})
set(in_files "")
set(out_files "")
foreach(src ${ARGS_SOURCES} ${ARGS_UNPARSED_ARGUMENTS})
list(APPEND in_files "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
string(REPLACE ".vala" ".c" src ${src})
string(REPLACE ".gs" ".c" src ${src})
set(out_file "${DIRECTORY}/${src}")
list(APPEND out_files "${DIRECTORY}/${src}")
endforeach(src ${ARGS_SOURCES} ${ARGS_UNPARSED_ARGUMENTS})
set(custom_vapi_arguments "")
if(ARGS_CUSTOM_VAPIS)
foreach(vapi ${ARGS_CUSTOM_VAPIS})
list(APPEND custom_vapi_arguments ${vapi})
endforeach(vapi ${ARGS_CUSTOM_VAPIS})
endif(ARGS_CUSTOM_VAPIS)
set(vapi_arguments "")
if(ARGS_GENERATE_VAPI)
list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_VAPI}.vapi")
set(vapi_arguments "--vapi=${ARGS_GENERATE_VAPI}.vapi")
# Header and internal header is needed to generate internal vapi
if (NOT ARGS_GENERATE_HEADER)
set(ARGS_GENERATE_HEADER ${ARGS_GENERATE_VAPI})
endif(NOT ARGS_GENERATE_HEADER)
endif(ARGS_GENERATE_VAPI)
set(header_arguments "")
if(ARGS_GENERATE_HEADER)
list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_HEADER}.h")
list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_HEADER}_internal.h")
list(APPEND header_arguments "--header=${DIRECTORY}/${ARGS_GENERATE_HEADER}.h")
list(APPEND header_arguments "--internal-header=${DIRECTORY}/${ARGS_GENERATE_HEADER}_internal.h")
endif(ARGS_GENERATE_HEADER)
add_custom_command(OUTPUT ${out_files}
COMMAND
${VALA_EXECUTABLE}
ARGS
"-C"
${header_arguments}
${vapi_arguments}
"-b" ${CMAKE_CURRENT_SOURCE_DIR}
"-d" ${DIRECTORY}
${vala_pkg_opts}
${vala_define_opts}
${ARGS_OPTIONS}
${in_files}
${custom_vapi_arguments}
DEPENDS
${in_files}
${ARGS_CUSTOM_VAPIS}
)
set(${output} ${out_files} PARENT_SCOPE)
endfunction(vala_precompile)
address-book-service-0.1.1+14.04.20140408.3/cmake/vala/FindVala.cmake 0000644 0000153 0177776 00000006113 12321057324 024756 0 ustar pbuser nogroup 0000000 0000000 ##
# Find module for the Vala compiler (valac)
#
# This module determines wheter a Vala compiler is installed on the current
# system and where its executable is.
#
# Call the module using "find_package(Vala) from within your CMakeLists.txt.
#
# The following variables will be set after an invocation:
#
# VALA_FOUND Whether the vala compiler has been found or not
# VALA_EXECUTABLE Full path to the valac executable if it has been found
# VALA_VERSION Version number of the available valac
# VALA_USE_FILE Include this file to define the vala_precompile function
##
##
# Copyright 2009-2010 Jakob Westhoff. All rights reserved.
# Copyright 2010-2011 Daniel Pfeifer
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY JAKOB WESTHOFF ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are those
# of the authors and should not be interpreted as representing official policies,
# either expressed or implied, of Jakob Westhoff
##
# Search for the valac executable in the usual system paths
# Some distributions rename the valac to contain the major.minor in the binary name
find_program(VALA_EXECUTABLE NAMES valac valac-0.20 valac-0.18 valac-0.16 valac-0.14 valac-0.12 valac-0.10)
mark_as_advanced(VALA_EXECUTABLE)
# Determine the valac version
if(VALA_EXECUTABLE)
execute_process(COMMAND ${VALA_EXECUTABLE} "--version"
OUTPUT_VARIABLE VALA_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE "Vala " "" VALA_VERSION "${VALA_VERSION}")
endif(VALA_EXECUTABLE)
# Handle the QUIETLY and REQUIRED arguments, which may be given to the find call.
# Furthermore set VALA_FOUND to TRUE if Vala has been found (aka.
# VALA_EXECUTABLE is set)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Vala
REQUIRED_VARS VALA_EXECUTABLE
VERSION_VAR VALA_VERSION)
set(VALA_USE_FILE "${CMAKE_CURRENT_LIST_DIR}/UseVala.cmake")
address-book-service-0.1.1+14.04.20140408.3/upstart/ 0000755 0000153 0177776 00000000000 12321057642 021771 5 ustar pbuser nogroup 0000000 0000000 address-book-service-0.1.1+14.04.20140408.3/upstart/address-book-service.conf 0000644 0000153 0177776 00000000327 12321057324 026652 0 ustar pbuser nogroup 0000000 0000000 description "address-book-service"
author "Bill Filler "
start on started unity8
stop on session-end
respawn
exec /usr/lib/arm-linux-gnueabihf/address-book-service/address-book-service
address-book-service-0.1.1+14.04.20140408.3/examples/ 0000755 0000153 0177776 00000000000 12321057642 022105 5 ustar pbuser nogroup 0000000 0000000 address-book-service-0.1.1+14.04.20140408.3/examples/contacts.py 0000644 0000153 0177776 00000006641 12321057324 024301 0 ustar pbuser nogroup 0000000 0000000 #!/usr/bin/env python3
# -*- encoding: utf-8 -*-
#
# Copyright 2013 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; version 3.
#
# This program 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see .
#
import dbus
import argparse
VCARD_JOE = """
BEGIN:VCARD
VERSION:3.0
N:Gump;Forrest
FN:Forrest Gump
TEL;TYPE=WORK,VOICE;PID=1.1:(111) 555-1212
TEL;TYPE=HOME,VOICE;PID=1.2:(404) 555-1212
EMAIL;TYPE=PREF,INTERNET;PID=1.1:forrestgump@example.com
END:VCARD
"""
class Contacts(object):
def __init__(self):
self.bus = None
self.addr = None
self.addr_iface = None
def connect(self):
self.bus = dbus.SessionBus()
self.addr = self.bus.get_object('com.canonical.pim',
'/com/canonical/pim/AddressBook')
self.addr_iface = dbus.Interface(self.addr,
dbus_interface='com.canonical.pim.AddressBook')
def query(self, fields = '', query = '', sources = []):
view_path = self.addr_iface.query(fields, query, [])
view = self.bus.get_object('com.canonical.pim',
view_path)
view_iface = dbus.Interface(view,
dbus_interface='com.canonical.pim.AddressBookView')
contacts = view_iface.contactsDetails([], 0, -1)
view.close()
return contacts
def update(self, vcard):
return self.addr_iface.updateContacts([vcard])
def create(self, vcard):
return self.addr_iface.createContact(vcard, "")
def delete(self, ids):
return self.addr_iface.removeContacts(ids)
service = Contacts()
service.connect()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('command', choices=['query','create','update',
'delete','load'])
parser.add_argument('filename', action='store', nargs='?')
args = parser.parse_args()
if args.command == 'query':
contacts = service.query()
if contacts:
for contact in contacts:
print (contact)
else:
print ("No contacts found")
if args.command == 'update':
vcard = VCARD_JOE
contactId = service.create(vcard)
vcard = vcard.replace("VERSION:3.0", "VERSION:3.0\nUID:%s" % (contactId))
vcard = vcard.replace("N:Gump;Forrest", "N:Hanks;Tom")
vcard = vcard.replace("FN:Forrest Gump", "FN:Tom Hanks")
print (service.update(vcard))
if args.command == 'create':
print ("New UID:", service.create(VCARD_JOE))
if args.command == 'delete':
vcard = VCARD_JOE
contactId = service.create(vcard)
print ("Deleted contact: %d" % service.delete([contactId]))
if args.command == 'load':
if args.filename:
f = open(args.filename, 'r')
vcard = f.read()
print ("New UID:", service.create(vcard))
else:
print ("You must supply a path to a VCARD")
address-book-service-0.1.1+14.04.20140408.3/tests/ 0000755 0000153 0177776 00000000000 12321057642 021431 5 ustar pbuser nogroup 0000000 0000000 address-book-service-0.1.1+14.04.20140408.3/tests/data/ 0000755 0000153 0177776 00000000000 12321057642 022342 5 ustar pbuser nogroup 0000000 0000000 address-book-service-0.1.1+14.04.20140408.3/tests/data/backend-store-key-file-data.ini 0000644 0000153 0177776 00000000255 12321057324 030175 0 ustar pbuser nogroup 0000000 0000000 #export FOLKS_BACKEND_KEY_FILE_PATH
[0]
__alias=Renato Araujo
msn=renato@msn.com
[1]
__alias=Rodrigo Almeida
msn=kiko@msn.com
[2]
__alias=Raphael Almeida
msn=rafa@msn.com
address-book-service-0.1.1+14.04.20140408.3/tests/data/CMakeLists.txt 0000644 0000153 0177776 00000000350 12321057324 025075 0 ustar pbuser nogroup 0000000 0000000 project(test-data)
set(FOLKS_BACKEND_CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/backend-store-key-file-only.ini" PARENT_SCOPE)
set(FOLKS_KEY_FILE_DATA_FILE "${CMAKE_CURRENT_SOURCE_DIR}/backend-store-key-file-data.ini" PARENT_SCOPE)
address-book-service-0.1.1+14.04.20140408.3/tests/CMakeLists.txt 0000644 0000153 0177776 00000000062 12321057324 024164 0 ustar pbuser nogroup 0000000 0000000 add_subdirectory(data)
add_subdirectory(unittest)
address-book-service-0.1.1+14.04.20140408.3/tests/unittest/ 0000755 0000153 0177776 00000000000 12321057642 023310 5 ustar pbuser nogroup 0000000 0000000 address-book-service-0.1.1+14.04.20140408.3/tests/unittest/dummy-backend.h 0000644 0000153 0177776 00000012010 12321057324 026170 0 ustar pbuser nogroup 0000000 0000000 /*
* 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 __DUMMY_BACKEND_TEST_H__
#define __DUMMY_BACKEND_TEST_H__
#include "dummy-backend-defs.h"
#include "lib/qindividual.h"
#include
#include
#include
#include
#include
#include
#include
#include
class DummyBackendAdaptor;
class DummyBackendProxy: public QObject
{
Q_OBJECT
public:
DummyBackendProxy();
~DummyBackendProxy();
void start(bool useDBus = false);
bool isReady() const;
QString createContact(const QtContacts::QContact &qcontact);
QString updateContact(const QString &contactId, const QtContacts::QContact &qcontact);
QList contacts() const;
QList individuals() const;
FolksIndividualAggregator *aggregator() const;
public Q_SLOTS:
void shutdown();
QStringList listContacts() const;
void reset();
void contactUpdated(const QString &contactId, const QString &errorMsg);
Q_SIGNALS:
void ready();
void stopped();
private:
QTemporaryDir m_tmpDir;
DummyBackendAdaptor *m_adaptor;
FolksDummyBackend *m_backend;
FolksDummyPersonaStore *m_primaryPersonaStore;
FolksBackendStore *m_backendStore;
QEventLoop *m_eventLoop;
FolksIndividualAggregator *m_aggregator;
bool m_isReady;
int m_individualsChangedDetailedId;
QHash m_contacts;
bool m_contactUpdated;
bool m_useDBus;
bool registerObject();
void initFolks();
void configurePrimaryStore();
void initEnviroment();
void prepareAggregator();
void mkpath(const QString &path) const;
static void checkError(GError *error);
static void backendEnabled(FolksBackendStore *backendStore,
GAsyncResult *res,
DummyBackendProxy *self);
static void backendStoreLoaded(FolksBackendStore *backendStore,
GAsyncResult *res,
DummyBackendProxy *self);
static void individualAggregatorPrepared(FolksIndividualAggregator *fia,
GAsyncResult *res,
DummyBackendProxy *self);
static void individualAggregatorAddedPersona(FolksIndividualAggregator *fia,
GAsyncResult *res,
DummyBackendProxy *self);
static void individualsChangedCb(FolksIndividualAggregator *individualAggregator,
GeeMultiMap *changes,
DummyBackendProxy *self);
};
class DummyBackendAdaptor: public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", DUMMY_IFACE_NAME)
Q_CLASSINFO("D-Bus Introspection", ""
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
" \n"
"")
Q_PROPERTY(bool isReady READ isReady NOTIFY ready)
public:
DummyBackendAdaptor(const QDBusConnection &connection, DummyBackendProxy *parent);
virtual ~DummyBackendAdaptor();
bool isReady();
public Q_SLOTS:
bool ping();
void quit();
void reset();
QStringList listContacts();
QString createContact(const QString &vcard);
QString updateContact(const QString &contactId, const QString &vcard);
void enableAutoLink(bool flag);
Q_SIGNALS:
void ready();
void stopped();
private:
QDBusConnection m_connection;
DummyBackendProxy *m_proxy;
};
#endif
address-book-service-0.1.1+14.04.20140408.3/tests/unittest/vcardparser-test.cpp 0000644 0000153 0177776 00000032525 12321057324 027311 0 ustar pbuser nogroup 0000000 0000000 /*
* 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
#include
#include
#include
#include "common/vcard-parser.h"
using namespace QtContacts;
using namespace galera;
typedef QList QContactList;
class VCardParseTest : public QObject
{
Q_OBJECT
private:
QStringList m_vcards;
QList m_contacts;
void compareContact(const QtContacts::QContact &contact, const QtContacts::QContact &other)
{
// name
QCOMPARE(contact.detail(QtContacts::QContactDetail::TypeName),
other.detail(QtContacts::QContactDetail::TypeName));
// phone - this is necessary because:
// 1 ) the QContactDetail::FieldDetailUri can change based on the detail order
// 2 ) the phone number can be returned in different order
QList phones = contact.details(QtContacts::QContactDetail::TypePhoneNumber);
QList otherPhones = other.details(QtContacts::QContactDetail::TypePhoneNumber);
QCOMPARE(phones.size(), otherPhones.size());
for(int i=0; i < phones.size(); i++) {
QtContacts::QContactDetail phone = phones[i];
bool found = false;
for(int x=0; x < otherPhones.size(); x++) {
QtContacts::QContactDetail otherPhone = otherPhones[x];
if (phone.value(QtContacts::QContactPhoneNumber::FieldNumber) ==
otherPhone.value(QtContacts::QContactPhoneNumber::FieldNumber)) {
found = true;
QList phoneTypes = phone.value(QtContacts::QContactPhoneNumber::FieldSubTypes).value< QList >();
QList otherPhoneTypes = otherPhone.value(QtContacts::QContactPhoneNumber::FieldSubTypes).value< QList >();
QCOMPARE(phoneTypes, otherPhoneTypes);
QCOMPARE(phone.value(QtContacts::QContactPhoneNumber::FieldContext),
otherPhone.value(QtContacts::QContactPhoneNumber::FieldContext));
break;
}
}
QVERIFY2(found, "Phone number is not equal");
}
// email same as phone number
QList emails = contact.details(QtContacts::QContactDetail::TypeEmailAddress);
QList otherEmails = other.details(QtContacts::QContactDetail::TypeEmailAddress);
QCOMPARE(emails.size(), otherEmails.size());
for(int i=0; i < emails.size(); i++) {
QtContacts::QContactDetail email = emails[i];
bool found = false;
for(int x=0; x < otherEmails.size(); x++) {
QtContacts::QContactDetail otherEmail = otherEmails[x];
if (email.value(QtContacts::QContactEmailAddress::FieldEmailAddress) ==
otherEmail.value(QtContacts::QContactEmailAddress::FieldEmailAddress)) {
found = true;
QCOMPARE(email.value(QtContacts::QContactEmailAddress::FieldContext),
otherEmail.value(QtContacts::QContactEmailAddress::FieldContext));
break;
}
}
QVERIFY2(found, "Email is not equal");
}
}
/*
* Use this function to compare vcards because the order of the attributes in the returned vcard
* can be different for each vcard. Example:
* "TEL;PID=1.1;TYPE=ISDN:33331410\r\n" or "TEL;TYPE=ISDN;PID=1.1:33331410\r\n"
*/
void compareVCards(const QString &vcard, const QString &other)
{
QStringList vcardLines = vcard.split("\n", QString::SkipEmptyParts);
QStringList otherLines = other.split("\n", QString::SkipEmptyParts);
QCOMPARE(vcardLines.size(), otherLines.size());
for(int i=0; i < vcardLines.size(); i++) {
QString value = vcardLines[i].split(":").last();
QString otherValue = otherLines.first().split(":").last();
// compare values. After ":"
QCOMPARE(value, otherValue);
QString attribute = vcardLines[i].split(":").first();
QString attributeOther = otherLines.first().split(":").first();
// compare attributes. Before ":"
QStringList attributeFields = attribute.split(";");
QStringList attributeOtherFields = attributeOther.split(";");
Q_FOREACH(const QString &attr, attributeFields) {
attributeOtherFields.removeOne(attr);
}
QVERIFY2(attributeOtherFields.size() == 0,
QString("Vcard attribute is not equal (%1) != (%2)").arg(vcardLines[i]).arg(otherLines.first()).toUtf8());
otherLines.removeFirst();
}
}
private Q_SLOTS:
void init()
{
m_vcards << QStringLiteral("BEGIN:VCARD\r\n"
"VERSION:3.0\r\n"
"N:Sauro;Dino;da Silva;;\r\n"
"EMAIL: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");
m_vcards << QStringLiteral("BEGIN:VCARD\r\n"
"VERSION:3.0\r\n"
"N:Sauro;Baby;da Silva;;\r\n"
"EMAIL:baby@familiadinosauro.com.br\r\n"
"TEL;PID=1.1;TYPE=ISDN:1111111\r\n"
"TEL;PID=1.2;TYPE=CELL:2222222\r\n"
"END:VCARD\r\n");
QContact contactDino;
QContactName name;
name.setFirstName("Dino");
name.setMiddleName("da Silva");
name.setLastName("Sauro");
contactDino.saveDetail(&name);
QContactEmailAddress email;
email.setEmailAddress("dino@familiadinosauro.com.br");
contactDino.saveDetail(&email);
QContactPhoneNumber phoneLandLine;
phoneLandLine.setSubTypes(QList() << QContactPhoneNumber::SubTypeLandline);
phoneLandLine.setNumber("33331410");
phoneLandLine.setDetailUri("1.1");
contactDino.saveDetail(&phoneLandLine);
QContactPhoneNumber phoneMobile;
phoneMobile.setSubTypes(QList() << QContactPhoneNumber::SubTypeMobile);
phoneMobile.setNumber("8888888");
phoneMobile.setDetailUri("1.2");
contactDino.saveDetail(&phoneMobile);
QContact contactBaby;
name.setFirstName("Baby");
name.setMiddleName("da Silva");
name.setLastName("Sauro");
contactBaby.saveDetail(&name);
email.setEmailAddress("baby@familiadinosauro.com.br");
contactBaby.saveDetail(&email);
phoneLandLine.setSubTypes(QList() << QContactPhoneNumber::SubTypeLandline);
phoneLandLine.setNumber("1111111");
phoneLandLine.setDetailUri("1.1");
contactBaby.saveDetail(&phoneLandLine);
phoneMobile.setSubTypes(QList() << QContactPhoneNumber::SubTypeMobile);
phoneMobile.setNumber("2222222");
phoneMobile.setDetailUri("1.2");
contactBaby.saveDetail(&phoneMobile);
m_contacts << contactDino << contactBaby;
}
void cleanup()
{
m_vcards.clear();
m_contacts.clear();
}
/*
* Test parse from vcard to contact using the async function
*/
void testVCardToContactAsync()
{
VCardParser parser;
qRegisterMetaType< QList >();
QSignalSpy vcardToContactSignal(&parser, SIGNAL(contactsParsed(QList)));
parser.vcardToContact(m_vcards);
QTRY_COMPARE(vcardToContactSignal.count(), 1);
QList arguments = vcardToContactSignal.takeFirst();
QCOMPARE(arguments.size(), 1);
QList contacts = qvariant_cast >(arguments.at(0));
QCOMPARE(contacts.size(), 2);
compareContact(contacts[0], m_contacts[0]);
compareContact(contacts[1], m_contacts[1]);
}
/*
* Test parse from vcard to contact using the sync function
*/
void testVCardToContactSync()
{
QList contacts = VCardParser::vcardToContactSync(m_vcards);
QCOMPARE(contacts.size(), 2);
compareContact(contacts[0], m_contacts[0]);
compareContact(contacts[1], m_contacts[1]);
}
/*
* Test parse a single vcard to contact using the sync function
*/
void testSingleVCardToContactSync()
{
QContact contact = VCardParser::vcardToContact(m_vcards[0]);
compareContact(contact, m_contacts[0]);
}
/*
* Test parse a invalid vcard
*/
void testInvalidVCard()
{
QString vcard("BEGIN:VCARD\r\nEND::VCARD\r\n");
QContact contact = VCardParser::vcardToContact(vcard);
QVERIFY(contact.isEmpty());
}
/*
* Test parse contacts to vcard using the async function
*/
void testContactToVCardAsync()
{
VCardParser parser;
QSignalSpy contactToVCardSignal(&parser, SIGNAL(vcardParsed(QStringList)));
parser.contactToVcard(m_contacts);
// Check if the vcardParsed signal was fired
QTRY_COMPARE(contactToVCardSignal.count(), 1);
// Check if the signal was fired with two vcards
QList arguments = contactToVCardSignal.takeFirst();
QCOMPARE(arguments.size(), 1);
QStringList vcardsResults = qvariant_cast(arguments.at(0));
QCOMPARE(vcardsResults.size(), 2);
// Check if the vcard in the signals was correct parsed
compareVCards(vcardsResults[0], m_vcards[0]);
compareVCards(vcardsResults[1], m_vcards[1]);
}
/*
* Test parse contacts to vcard using the sync function
*/
void testContactToVCardSync()
{
QStringList vcards = VCardParser::contactToVcardSync(m_contacts);
QCOMPARE(vcards.size(), 2);
// Check if the returned vcards are correct
compareVCards(vcards[0], m_vcards[0]);
compareVCards(vcards[1], m_vcards[1]);
}
/*
* Test parse a single contact to vcard using the sync function
*/
void testSingContactToVCardSync()
{
QString vcard = VCardParser::contactToVcard(m_contacts[0]);
// Check if the returned vcard is correct
compareVCards(vcard, m_vcards[0]);
}
/*
* 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)
#include "vcardparser-test.moc"
address-book-service-0.1.1+14.04.20140408.3/tests/unittest/contactmap-test.cpp 0000644 0000153 0177776 00000011021 12321057324 027112 0 ustar pbuser nogroup 0000000 0000000 /*
* 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 "config.h"
#include "dummy-backend.h"
#include "scoped-loop.h"
#include "lib/contacts-map.h"
#include "lib/qindividual.h"
#include
#include
#include
#include
#include
#include
class ContactMapTest : public QObject
{
Q_OBJECT
private:
DummyBackendProxy *m_dummy;
galera::ContactsMap m_map;
QList m_individuals;
int randomIndex() const
{
return qrand() % m_map.size();
}
FolksIndividual *randomIndividual() const
{
return m_individuals[randomIndex()];
}
void createContactWithSuffix(const QString &suffix)
{
QtContacts::QContact contact;
QtContacts::QContactName name;
name.setFirstName(QString("Fulano_%1").arg(suffix));
name.setMiddleName("de");
name.setLastName("Tal");
contact.saveDetail(&name);
QtContacts::QContactEmailAddress email;
email.setEmailAddress(QString("fulano_%1@ubuntu.com").arg(suffix));
contact.saveDetail(&email);
QtContacts::QContactPhoneNumber phone;
phone.setNumber("33331410");
contact.saveDetail(&phone);
m_dummy->createContact(contact);
}
private Q_SLOTS:
void initTestCase()
{
m_dummy = new DummyBackendProxy();
m_dummy->start();
QTRY_VERIFY(m_dummy->isReady());
createContactWithSuffix("1");
createContactWithSuffix("2");
createContactWithSuffix("3");
Q_FOREACH(galera::QIndividual *i, m_dummy->individuals()) {
m_map.insert(new galera::ContactEntry(new galera::QIndividual(i->individual(), m_dummy->aggregator())));
m_individuals << i->individual();
}
}
void cleanupTestCase()
{
m_dummy->shutdown();
delete m_dummy;
m_map.clear();
}
void testLookupByFolksIndividual()
{
QVERIFY(m_map.size() > 0);
FolksIndividual *fIndividual = randomIndividual();
QVERIFY(m_map.contains(fIndividual));
galera::ContactEntry *entry = m_map.value(fIndividual);
QVERIFY(entry->individual()->individual() == fIndividual);
}
void testLookupByFolksIndividualId()
{
FolksIndividual *fIndividual = randomIndividual();
QString id = QString::fromUtf8(folks_individual_get_id(fIndividual));
galera::ContactEntry *entry = m_map.value(id);
QVERIFY(entry->individual()->individual() == fIndividual);
}
void testValues()
{
QList