1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the QtContacts module of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
42
#include "qcontactmanager.h"
44
#include <QContactManagerEngine>
45
#include <QContactAbstractRequest>
46
#include <QContactChangeSet>
47
#include <QContactTimestamp>
48
#include <QContactIdFilter>
49
#include <qcontactrequests.h>
50
#include "qcontactmemorybackend_p.h"
52
#include <QtCore/qdebug.h>
53
#include <QtCore/qstringbuilder.h>
54
#include <QtCore/quuid.h>
56
QT_BEGIN_NAMESPACE_CONTACTS
58
QContactManagerEngine* QContactMemoryEngineFactory::engine(const QMap<QString, QString> ¶meters, QContactManager::Error *error)
62
QContactMemoryEngine *ret = QContactMemoryEngine::createMemoryEngine(parameters);
67
QContactEngineId* QContactMemoryEngineFactory::createContactEngineId(const QMap<QString, QString> ¶meters, const QString &engineIdString) const
70
QContactMemoryEngineId *retn = new QContactMemoryEngineId(parameters, engineIdString);
74
QString QContactMemoryEngineFactory::managerName() const
76
return QString::fromLatin1("memory");
80
\class QContactMemoryEngine
84
\brief The QContactMemoryEngine class provides an in-memory implementation
85
of a contacts backend.
89
It may be used as a reference implementation, or when persistent storage is not required.
91
During construction, it will load the in-memory data associated with the memory store
92
identified by the "id" parameter from the given parameters if it exists, or a new,
93
anonymous store if it does not.
95
Data stored in this engine is only available in the current process.
97
This engine supports sharing, so an internal reference count is increased
98
whenever a manager uses this backend, and is decreased when the manager
99
no longer requires this engine.
102
/* static data for manager class */
103
QMap<QString, QContactMemoryEngineData*> QContactMemoryEngine::engineDatas;
106
* Factory function for creating a new in-memory backend, based
107
* on the given \a parameters.
109
* The same engine will be returned for multiple calls with the
110
* same value for the "id" parameter, while one of them is in scope.
112
QContactMemoryEngine* QContactMemoryEngine::createMemoryEngine(const QMap<QString, QString> ¶meters)
114
bool anonymous = false;
115
QString idValue = parameters.value(QStringLiteral("id"));
116
if (idValue.isNull() || idValue.isEmpty()) {
117
// no store given? new, anonymous store.
118
idValue = QUuid::createUuid().toString();
122
QContactMemoryEngineData *data = engineDatas.value(idValue);
124
data->m_refCount.ref();
126
data = new QContactMemoryEngineData();
127
data->m_id = idValue;
128
data->m_anonymous = anonymous;
129
engineDatas.insert(idValue, data);
131
return new QContactMemoryEngine(data);
135
* Constructs a new in-memory backend which shares the given \a data with
136
* other shared memory engines.
138
QContactMemoryEngine::QContactMemoryEngine(QContactMemoryEngineData *data)
141
qRegisterMetaType<QContactAbstractRequest::State>("QContactAbstractRequest::State");
142
qRegisterMetaType<QList<QContactId> >("QList<QContactId>");
143
qRegisterMetaType<QContactId>("QContactId");
144
d->m_managerUri = managerUri();
145
d->m_sharedEngines.append(this);
148
/*! Frees any memory used by this engine */
149
QContactMemoryEngine::~QContactMemoryEngine()
151
d->m_sharedEngines.removeAll(this);
152
if (!d->m_refCount.deref()) {
153
engineDatas.remove(d->m_id);
159
QString QContactMemoryEngine::managerName() const
161
return QStringLiteral("memory");
165
QMap<QString, QString> QContactMemoryEngine::managerParameters() const
167
QMap<QString, QString> params;
168
params.insert(QStringLiteral("id"), d->m_id);
173
bool QContactMemoryEngine::setSelfContactId(const QContactId &contactId, QContactManager::Error *error)
175
if (contactId.isNull() || d->m_contactIds.contains(contactId)) {
176
*error = QContactManager::NoError;
177
QContactId oldId = d->m_selfContactId;
178
d->m_selfContactId = contactId;
180
QContactChangeSet changeSet;
181
changeSet.setOldAndNewSelfContactId(QPair<QContactId, QContactId>(oldId, contactId));
182
d->emitSharedSignals(&changeSet);
186
*error = QContactManager::DoesNotExistError;
191
QContactId QContactMemoryEngine::selfContactId(QContactManager::Error *error) const
193
*error = QContactManager::DoesNotExistError;
194
if (!d->m_selfContactId.isNull())
195
*error = QContactManager::NoError;
196
return d->m_selfContactId;
200
QContact QContactMemoryEngine::contact(const QContactId &contactId, const QContactFetchHint &fetchHint, QContactManager::Error *error) const
202
Q_UNUSED(fetchHint); // no optimizations are possible in the memory backend; ignore the fetch hint.
203
int index = d->m_contactIds.indexOf(contactId);
205
// found the contact successfully.
206
*error = QContactManager::NoError;
207
return d->m_contacts.at(index);
210
*error = QContactManager::DoesNotExistError;
215
QList<QContactId> QContactMemoryEngine::contactIds(const QContactFilter &filter, const QList<QContactSortOrder> &sortOrders, QContactManager::Error *error) const
217
/* Special case the fast case */
218
if (filter.type() == QContactFilter::DefaultFilter && sortOrders.count() == 0) {
219
return d->m_contactIds;
221
QList<QContact> clist = contacts(filter, sortOrders, QContactFetchHint(), error);
223
/* Extract the ids */
224
QList<QContactId> ids;
225
foreach (const QContact &c, clist)
233
QList<QContact> QContactMemoryEngine::contacts(const QContactFilter &filter, const QList<QContactSortOrder> &sortOrders, const QContactFetchHint &fetchHint, QContactManager::Error *error) const
235
Q_UNUSED(fetchHint); // no optimizations are possible in the memory backend; ignore the fetch hint.
238
QList<QContact> sorted;
240
/* First filter out contacts - check for default filter first */
241
if (filter.type() == QContactFilter::DefaultFilter) {
242
foreach(const QContact&c, d->m_contacts) {
243
QContactManagerEngine::addSorted(&sorted,c, sortOrders);
246
foreach(const QContact&c, d->m_contacts) {
247
if (QContactManagerEngine::testFilter(filter, c))
248
QContactManagerEngine::addSorted(&sorted,c, sortOrders);
255
/*! Saves the given contact \a theContact, storing any error to \a error and
256
filling the \a changeSet with ids of changed contacts as required
257
Returns true if the operation was successful otherwise false.
259
bool QContactMemoryEngine::saveContact(QContact *theContact, QContactChangeSet &changeSet, QContactManager::Error *error)
261
return saveContact(theContact, changeSet, error, QList<QContactDetail::DetailType>());
265
bool QContactMemoryEngine::saveContacts(QList<QContact> *contacts, QMap<int, QContactManager::Error> *errorMap, QContactManager::Error *error)
267
return saveContacts(contacts, errorMap, error, QList<QContactDetail::DetailType>());
270
/*! Removes the contact identified by the given \a contactId, storing any error to \a error and
271
filling the \a changeSet with ids of changed contacts and relationships as required.
272
Returns true if the operation was successful otherwise false.
274
bool QContactMemoryEngine::removeContact(const QContactId &contactId, QContactChangeSet &changeSet, QContactManager::Error *error)
276
int index = d->m_contactIds.indexOf(contactId);
279
*error = QContactManager::DoesNotExistError;
283
// remove the contact from any relationships it was in.
284
QContact thisContact = d->m_contacts.at(index);
285
QList<QContactRelationship> allRelationships = relationships(QString(), thisContact, QContactRelationship::Either, error);
286
if (*error != QContactManager::NoError && *error != QContactManager::DoesNotExistError) {
287
*error = QContactManager::UnspecifiedError; // failed to clean up relationships
291
// this is meant to be a transaction, so if any of these fail, we're in BIG TROUBLE.
292
// a real backend will use DBMS transactions to ensure database integrity.
293
removeRelationships(allRelationships, 0, error);
295
// having cleaned up the relationships, remove the contact from the lists.
296
d->m_contacts.removeAt(index);
297
d->m_contactIds.removeAt(index);
298
*error = QContactManager::NoError;
300
// and if it was the self contact, reset the self contact id
301
if (contactId == d->m_selfContactId) {
302
d->m_selfContactId = QContactId();
303
changeSet.setOldAndNewSelfContactId(QPair<QContactId, QContactId>(contactId, QContactId()));
306
changeSet.insertRemovedContact(contactId);
311
bool QContactMemoryEngine::removeContacts(const QList<QContactId> &contactIds, QMap<int, QContactManager::Error> *errorMap, QContactManager::Error *error)
313
if (contactIds.count() == 0) {
314
*error = QContactManager::BadArgumentError;
318
QContactChangeSet changeSet;
320
QContactManager::Error operationError = QContactManager::NoError;
321
for (int i = 0; i < contactIds.count(); i++) {
322
current = contactIds.at(i);
323
if (!removeContact(current, changeSet, error)) {
324
operationError = *error;
326
errorMap->insert(i, operationError);
330
*error = operationError;
331
d->emitSharedSignals(&changeSet);
332
// return false if some errors occurred
333
return (*error == QContactManager::NoError);
337
QList<QContactRelationship> QContactMemoryEngine::relationships(const QString &relationshipType, const QContact &participant, QContactRelationship::Role role, QContactManager::Error *error) const
339
QContact defaultContact;
340
QList<QContactRelationship> retn;
341
for (int i = 0; i < d->m_relationships.size(); i++) {
342
QContactRelationship curr = d->m_relationships.at(i);
344
// check that the relationship type matches
345
if (curr.relationshipType() != relationshipType && !relationshipType.isEmpty())
348
// if the participantId argument is default constructed, then the relationship matches.
349
if (participant == defaultContact) {
354
// otherwise, check that the participant exists and plays the required role in the relationship.
355
if (role == QContactRelationship::First && curr.first() == participant) {
357
} else if (role == QContactRelationship::Second && curr.second() == participant) {
359
} else if (role == QContactRelationship::Either && (curr.first() == participant || curr.second() == participant)) {
364
*error = QContactManager::NoError;
366
*error = QContactManager::DoesNotExistError;
370
/*! Saves the given relationship \a relationship, storing any error to \a error and
371
filling the \a changeSet with ids of changed contacts and relationships as required
372
Returns true if the operation was successful otherwise false.
374
bool QContactMemoryEngine::saveRelationship(QContactRelationship *relationship, QContactChangeSet &changeSet, QContactManager::Error *error)
376
// Attempt to validate the relationship.
377
// first, check that the source contact exists and is in this manager.
378
QString myUri = managerUri();
379
int firstContactIndex = d->m_contactIds.indexOf(relationship->first().id());
380
if ((!relationship->first().id().managerUri().isEmpty() && relationship->first().id().managerUri() != myUri)
381
||firstContactIndex == -1) {
382
*error = QContactManager::InvalidRelationshipError;
386
// second, check that the second contact exists (if it's local); we cannot check other managers' contacts.
387
QContact dest = relationship->second();
388
int secondContactIndex = d->m_contactIds.indexOf(dest.id());
390
if (dest.id().managerUri().isEmpty() || dest.id().managerUri() == myUri) {
391
// this entry in the destination list is supposedly stored in this manager.
392
// check that it exists, and that it isn't the source contact (circular)
393
if (secondContactIndex == -1 || dest.id() == relationship->first().id()) {
394
*error = QContactManager::InvalidRelationshipError;
399
// the relationship is valid. We need to update the manager URIs in the second contact if it is empty to our URI.
400
if (dest.id().managerUri().isEmpty()) {
401
// need to update the URI
402
relationship->setSecond(dest);
405
// check to see if the relationship already exists in the database. If so, replace.
406
// We do this because we don't want duplicates in our lists / maps of relationships.
407
*error = QContactManager::NoError;
408
QList<QContactRelationship> allRelationships = d->m_relationships;
409
for (int i = 0; i < allRelationships.size(); i++) {
410
QContactRelationship curr = allRelationships.at(i);
411
if (curr == *relationship) {
413
// TODO: set error to AlreadyExistsError and return false?
417
// no matching relationship; must be new. append it to lists in our map of relationships where required.
418
QList<QContactRelationship> firstRelationships = d->m_orderedRelationships.value(relationship->first().id());
419
QList<QContactRelationship> secondRelationships = d->m_orderedRelationships.value(relationship->second().id());
420
firstRelationships.append(*relationship);
421
secondRelationships.append(*relationship);
422
d->m_orderedRelationships.insert(relationship->first().id(), firstRelationships);
423
d->m_orderedRelationships.insert(relationship->second().id(), secondRelationships);
424
changeSet.insertAddedRelationshipsContact(relationship->first().id());
425
changeSet.insertAddedRelationshipsContact(relationship->second().id());
427
// update the contacts involved
428
QContactManagerEngine::setContactRelationships(&d->m_contacts[firstContactIndex], firstRelationships);
429
QContactManagerEngine::setContactRelationships(&d->m_contacts[secondContactIndex], secondRelationships);
431
// finally, insert into our list of all relationships, and return.
432
d->m_relationships.append(*relationship);
437
bool QContactMemoryEngine::saveRelationships(QList<QContactRelationship> *relationships, QMap<int, QContactManager::Error> *errorMap, QContactManager::Error *error)
439
*error = QContactManager::NoError;
440
QContactManager::Error functionError;
441
QContactChangeSet changeSet;
443
for (int i = 0; i < relationships->size(); i++) {
444
QContactRelationship curr = relationships->at(i);
445
saveRelationship(&curr, changeSet, &functionError);
446
if (functionError != QContactManager::NoError && errorMap)
447
errorMap->insert(i, functionError);
449
// and replace the current relationship with the updated version.
450
relationships->replace(i, curr);
452
// also, update the total error if it did not succeed.
453
if (functionError != QContactManager::NoError)
454
*error = functionError;
457
d->emitSharedSignals(&changeSet);
458
return (*error == QContactManager::NoError);
461
/*! Removes the given relationship \a relationship, storing any error to \a error and
462
filling the \a changeSet with ids of changed contacts and relationships as required
463
Returns true if the operation was successful otherwise false.
465
bool QContactMemoryEngine::removeRelationship(const QContactRelationship &relationship, QContactChangeSet &changeSet, QContactManager::Error *error)
467
// attempt to remove it from our list of relationships.
468
if (!d->m_relationships.removeOne(relationship)) {
469
*error = QContactManager::DoesNotExistError;
473
// if that worked, then we need to remove it from the two locations in our map, also.
474
QList<QContactRelationship> firstRelationships = d->m_orderedRelationships.value(relationship.first().id());
475
QList<QContactRelationship> secondRelationships = d->m_orderedRelationships.value(relationship.second().id());
476
firstRelationships.removeOne(relationship);
477
secondRelationships.removeOne(relationship);
478
d->m_orderedRelationships.insert(relationship.first().id(), firstRelationships);
479
d->m_orderedRelationships.insert(relationship.second().id(), secondRelationships);
481
// Update the contacts as well
482
int firstContactIndex = d->m_contactIds.indexOf(relationship.first().id());
483
int secondContactIndex = relationship.second().id().managerUri() == managerUri() ? d->m_contactIds.indexOf(relationship.second().id()) : -1;
484
if (firstContactIndex != -1)
485
QContactMemoryEngine::setContactRelationships(&d->m_contacts[firstContactIndex], firstRelationships);
486
if (secondContactIndex != -1)
487
QContactMemoryEngine::setContactRelationships(&d->m_contacts[secondContactIndex], secondRelationships);
489
// set our changes, and return.
490
changeSet.insertRemovedRelationshipsContact(relationship.first().id());
491
changeSet.insertRemovedRelationshipsContact(relationship.second().id());
492
*error = QContactManager::NoError;
497
bool QContactMemoryEngine::removeRelationships(const QList<QContactRelationship> &relationships, QMap<int, QContactManager::Error> *errorMap, QContactManager::Error *error)
499
QContactManager::Error functionError;
500
QContactChangeSet cs;
501
for (int i = 0; i < relationships.size(); i++) {
502
removeRelationship(relationships.at(i), cs, &functionError);
504
// update the total error if it did not succeed.
505
if (functionError != QContactManager::NoError) {
507
errorMap->insert(i, functionError);
508
*error = functionError;
512
d->emitSharedSignals(&cs);
513
return (*error == QContactManager::NoError);
517
void QContactMemoryEngine::requestDestroyed(QContactAbstractRequest *req)
523
bool QContactMemoryEngine::startRequest(QContactAbstractRequest *req)
528
QPointer<QContactAbstractRequest> checkDeletion(req);
529
updateRequestState(req, QContactAbstractRequest::ActiveState);
530
if (!checkDeletion.isNull())
531
performAsynchronousOperation(req);
536
bool QContactMemoryEngine::cancelRequest(QContactAbstractRequest *req)
538
Q_UNUSED(req); // we can't cancel since we complete immediately
543
bool QContactMemoryEngine::waitForRequestFinished(QContactAbstractRequest *req, int msecs)
545
// in our implementation, we always complete any operation we start.
553
* This slot is called some time after an asynchronous request is started.
554
* It performs the required operation, sets the result and returns.
556
void QContactMemoryEngine::performAsynchronousOperation(QContactAbstractRequest *currentRequest)
558
// store up changes, and emit signals once at the end of the (possibly batch) operation.
559
QContactChangeSet changeSet;
561
// Now perform the active request and emit required signals.
562
Q_ASSERT(currentRequest->state() == QContactAbstractRequest::ActiveState);
563
switch (currentRequest->type()) {
564
case QContactAbstractRequest::ContactFetchRequest:
566
QContactFetchRequest *r = static_cast<QContactFetchRequest*>(currentRequest);
567
QContactFilter filter = r->filter();
568
QList<QContactSortOrder> sorting = r->sorting();
569
QContactFetchHint fetchHint = r->fetchHint();
571
QContactManager::Error operationError = QContactManager::NoError;
572
QList<QContact> requestedContacts = contacts(filter, sorting, fetchHint, &operationError);
574
// update the request with the results.
575
if (!requestedContacts.isEmpty() || operationError != QContactManager::NoError)
576
updateContactFetchRequest(r, requestedContacts, operationError, QContactAbstractRequest::FinishedState);
578
updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
582
case QContactAbstractRequest::ContactFetchByIdRequest:
584
QContactFetchByIdRequest *r = static_cast<QContactFetchByIdRequest*>(currentRequest);
585
QContactIdFilter idFilter;
586
idFilter.setIds(r->contactIds());
587
QList<QContactSortOrder> sorting;
588
QContactFetchHint fetchHint = r->fetchHint();
589
QContactManager::Error error = QContactManager::NoError;
590
QList<QContact> requestedContacts = contacts(idFilter, sorting, fetchHint, &error);
591
// Build an index into the results
592
QHash<QContactId, int> idMap; // value is index into unsorted
593
if (error == QContactManager::NoError) {
594
for (int i = 0; i < requestedContacts.size(); i++) {
595
idMap.insert(requestedContacts[i].id(), i);
598
// Find the order in which the results should be presented
599
// Build up the results and errors
600
QList<QContact> results;
601
QMap<int, QContactManager::Error> errorMap;
603
foreach (const QContactId &id, r->contactIds()) {
604
if (!idMap.contains(id)) {
605
errorMap.insert(index, QContactManager::DoesNotExistError);
606
error = QContactManager::DoesNotExistError;
607
results.append(QContact());
609
results.append(requestedContacts[idMap[id]]);
614
// update the request with the results.
615
if (!requestedContacts.isEmpty() || error != QContactManager::NoError)
616
QContactManagerEngine::updateContactFetchByIdRequest(r, results, error, errorMap, QContactAbstractRequest::FinishedState);
618
updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
622
case QContactAbstractRequest::ContactIdFetchRequest:
624
QContactIdFetchRequest *r = static_cast<QContactIdFetchRequest*>(currentRequest);
625
QContactFilter filter = r->filter();
626
QList<QContactSortOrder> sorting = r->sorting();
628
QContactManager::Error operationError = QContactManager::NoError;
629
QList<QContactId> requestedContactIds = contactIds(filter, sorting, &operationError);
631
if (!requestedContactIds.isEmpty() || operationError != QContactManager::NoError)
632
updateContactIdFetchRequest(r, requestedContactIds, operationError, QContactAbstractRequest::FinishedState);
634
updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
638
case QContactAbstractRequest::ContactSaveRequest:
640
QContactSaveRequest *r = static_cast<QContactSaveRequest*>(currentRequest);
641
QList<QContact> contacts = r->contacts();
643
QContactManager::Error operationError = QContactManager::NoError;
644
QMap<int, QContactManager::Error> errorMap;
645
saveContacts(&contacts, &errorMap, &operationError, r->typeMask());
647
updateContactSaveRequest(r, contacts, operationError, errorMap, QContactAbstractRequest::FinishedState);
651
case QContactAbstractRequest::ContactRemoveRequest:
653
// this implementation provides scant information to the user
654
// the operation either succeeds (all contacts matching the filter were removed)
655
// or it fails (one or more contacts matching the filter could not be removed)
656
// if a failure occurred, the request error will be set to the most recent
657
// error that occurred during the remove operation.
658
QContactRemoveRequest *r = static_cast<QContactRemoveRequest*>(currentRequest);
659
QContactManager::Error operationError = QContactManager::NoError;
660
QList<QContactId> contactsToRemove = r->contactIds();
661
QMap<int, QContactManager::Error> errorMap;
663
for (int i = 0; i < contactsToRemove.size(); i++) {
664
QContactManager::Error tempError;
665
removeContact(contactsToRemove.at(i), changeSet, &tempError);
667
if (tempError != QContactManager::NoError) {
668
errorMap.insert(i, tempError);
669
operationError = tempError;
673
if (!errorMap.isEmpty() || operationError != QContactManager::NoError)
674
updateContactRemoveRequest(r, operationError, errorMap, QContactAbstractRequest::FinishedState);
676
updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
680
case QContactAbstractRequest::RelationshipFetchRequest:
682
QContactRelationshipFetchRequest *r = static_cast<QContactRelationshipFetchRequest*>(currentRequest);
683
QContactManager::Error operationError = QContactManager::NoError;
684
QList<QContactManager::Error> operationErrors;
685
QList<QContactRelationship> allRelationships = relationships(QString(), QContact(), QContactRelationship::Either, &operationError);
686
QList<QContactRelationship> requestedRelationships;
688
// select the requested relationships.
689
for (int i = 0; i < allRelationships.size(); i++) {
690
QContactRelationship currRel = allRelationships.at(i);
691
if (r->first() != QContact() && r->first() != currRel.first())
693
if (r->second() != QContact() && r->second() != currRel.second())
695
if (!r->relationshipType().isEmpty() && r->relationshipType() != currRel.relationshipType())
697
requestedRelationships.append(currRel);
700
// update the request with the results.
701
if (!requestedRelationships.isEmpty() || operationError != QContactManager::NoError)
702
updateRelationshipFetchRequest(r, requestedRelationships, operationError, QContactAbstractRequest::FinishedState);
704
updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
708
case QContactAbstractRequest::RelationshipRemoveRequest:
710
QContactRelationshipRemoveRequest *r = static_cast<QContactRelationshipRemoveRequest*>(currentRequest);
711
QContactManager::Error operationError = QContactManager::NoError;
712
QList<QContactRelationship> relationshipsToRemove = r->relationships();
713
QMap<int, QContactManager::Error> errorMap;
715
removeRelationships(r->relationships(), &errorMap, &operationError);
717
if (!errorMap.isEmpty() || operationError != QContactManager::NoError)
718
updateRelationshipRemoveRequest(r, operationError, errorMap, QContactAbstractRequest::FinishedState);
720
updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
724
case QContactAbstractRequest::RelationshipSaveRequest:
726
QContactRelationshipSaveRequest *r = static_cast<QContactRelationshipSaveRequest*>(currentRequest);
727
QContactManager::Error operationError = QContactManager::NoError;
728
QMap<int, QContactManager::Error> errorMap;
729
QList<QContactRelationship> requestRelationships = r->relationships();
731
saveRelationships(&requestRelationships, &errorMap, &operationError);
733
// update the request with the results.
734
updateRelationshipSaveRequest(r, requestRelationships, operationError, errorMap, QContactAbstractRequest::FinishedState);
738
default: // unknown request type.
742
// now emit any signals we have to emit
743
d->emitSharedSignals(&changeSet);
746
void QContactMemoryEngine::partiallySyncDetails(QContact *to, const QContact &from, const QList<QContactDetail::DetailType> &mask)
748
// these details in old contact
749
QList<QContactDetail> fromDetails;
750
// these details in new contact
751
QList<QContactDetail> toDetails;
752
// Collect details that match mask
753
foreach (QContactDetail::DetailType type, mask) {
754
fromDetails.append(from.details(type));
755
toDetails.append(to->details(type));
757
// check details to remove
758
foreach (QContactDetail detail, toDetails) {
759
if (!fromDetails.contains(detail))
760
to->removeDetail(&detail);
762
// check details to save
763
foreach (QContactDetail detail, fromDetails) {
764
if (!toDetails.contains(detail))
765
to->saveDetail(&detail);
772
bool QContactMemoryEngine::isRelationshipTypeSupported(const QString& relationshipType, QContactType::TypeValues contactType) const
774
// the memory backend supports arbitrary relationship types
775
// but some relationship types don't make sense for groups.
776
if (contactType == QContactType::TypeGroup) {
777
if (relationshipType == QContactRelationship::HasSpouse() || relationshipType == QContactRelationship::HasAssistant()) {
782
// all other relationship types for all contact types are supported.
789
QList<QVariant::Type> QContactMemoryEngine::supportedDataTypes() const
791
QList<QVariant::Type> st;
792
st.append(QVariant::String);
793
st.append(QVariant::Date);
794
st.append(QVariant::DateTime);
795
st.append(QVariant::Time);
796
st.append(QVariant::Bool);
797
st.append(QVariant::Char);
798
st.append(QVariant::Int);
799
st.append(QVariant::UInt);
800
st.append(QVariant::LongLong);
801
st.append(QVariant::ULongLong);
802
st.append(QVariant::Double);
808
* The function returns true if the backend natively supports the given filter \a filter, otherwise false.
810
bool QContactMemoryEngine::isFilterSupported(const QContactFilter &filter) const
813
// Until we add hashes for common stuff, fall back to slow code
817
bool QContactMemoryEngine::saveContacts(QList<QContact> *contacts, QMap<int, QContactManager::Error> *errorMap,
818
QContactManager::Error *error, const QList<QContactDetail::DetailType> &mask)
821
*error = QContactManager::BadArgumentError;
825
QContactChangeSet changeSet;
827
QContactManager::Error operationError = QContactManager::NoError;
828
for (int i = 0; i < contacts->count(); i++) {
829
current = contacts->at(i);
830
if (!saveContact(¤t, changeSet, error, mask)) {
831
operationError = *error;
833
errorMap->insert(i, operationError);
835
(*contacts)[i] = current;
839
*error = operationError;
840
d->emitSharedSignals(&changeSet);
841
// return false if some error occurred
842
return (*error == QContactManager::NoError);
845
bool QContactMemoryEngine::saveContact(QContact *theContact, QContactChangeSet &changeSet,
846
QContactManager::Error *error, const QList<QContactDetail::DetailType> &mask)
848
// ensure that the contact's details conform to their definitions
849
if (!validateContact(*theContact, error)) {
853
QContactId id(theContact->id());
854
if (!id.managerUri().isEmpty() && id.managerUri() != managerUri()) {
855
// the contact doesn't belong to this manager
856
*error = QContactManager::DoesNotExistError;
860
// check to see if this contact already exists
861
int index = d->m_contactIds.indexOf(id);
863
/* We also need to check that there are no modified create only details */
864
QContact oldContact = d->m_contacts.at(index);
866
if (oldContact.type() != theContact->type()) {
867
*error = QContactManager::AlreadyExistsError;
871
// check if this is partial save
872
if (!mask.isEmpty()) {
873
QContact tempContact = oldContact;
874
partiallySyncDetails(&tempContact, *theContact, mask);
875
*theContact = tempContact;
878
QContactTimestamp ts = theContact->detail(QContactTimestamp::Type);
879
ts.setLastModified(QDateTime::currentDateTime());
880
QContactManagerEngine::setDetailAccessConstraints(&ts, QContactDetail::ReadOnly | QContactDetail::Irremovable);
881
theContact->saveDetail(&ts);
883
// Looks ok, so continue
884
d->m_contacts.replace(index, *theContact);
885
changeSet.insertChangedContact(theContact->id());
887
// id does not exist; if not zero, fail.
889
if (theContact->id() != QContactId() && theContact->id() != newId) {
890
// the ID is not empty, and it doesn't identify an existing contact in our database either.
891
*error = QContactManager::DoesNotExistError;
895
// check if this is partial save
896
if (!mask.isEmpty()) {
897
QContact tempContact;
898
partiallySyncDetails(&tempContact, *theContact, mask);
899
*theContact = tempContact;
903
QContactTimestamp ts = theContact->detail(QContactTimestamp::Type);
904
ts.setLastModified(QDateTime::currentDateTime());
905
ts.setCreated(ts.lastModified());
906
setDetailAccessConstraints(&ts, QContactDetail::ReadOnly | QContactDetail::Irremovable);
907
theContact->saveDetail(&ts);
909
// update the contact item - set its ID
910
quint32 nextContactId = d->m_nextContactId; // don't increment the persistent version until we're successful or we know it collides.
911
nextContactId += 1; // but do increment the temporary version to check for collision
912
QContactMemoryEngineId *newMemoryEngineId = new QContactMemoryEngineId;
913
newMemoryEngineId->m_contactId = nextContactId;
914
newMemoryEngineId->m_managerUri = d->m_managerUri;
915
QContactId newContactId = QContactId(newMemoryEngineId);
916
theContact->setId(newContactId);
918
// note: do NOT delete the QContactMemoryEngineId -- the QContactId ctor takes ownership of it.
921
// finally, add the contact to our internal lists and return
922
d->m_contacts.append(*theContact); // add contact to list
923
d->m_contactIds.append(theContact->id()); // track the contact id.
925
changeSet.insertAddedContact(theContact->id());
926
// successful, now increment the persistent version of the next item id.
927
d->m_nextContactId += 1;
930
*error = QContactManager::NoError; // successful.
935
\class QContactMemoryEngineId
936
\brief The QContactMemoryEngineId class provides an id which uniquely identifies
937
a QContact stored within a QContactMemoryEngine.
940
It may be used as a reference implementation, although since different platforms
941
have different semantics for ids
942
the precise implementation required may differ.
944
QContactMemoryEngineId::QContactMemoryEngineId()
945
: QContactEngineId(), m_contactId(0)
949
QContactMemoryEngineId::QContactMemoryEngineId(quint32 contactId, const QString &managerUri)
950
: QContactEngineId(), m_contactId(contactId), m_managerUri(managerUri)
954
QContactMemoryEngineId::~QContactMemoryEngineId()
958
QContactMemoryEngineId::QContactMemoryEngineId(const QContactMemoryEngineId &other)
959
: QContactEngineId(), m_contactId(other.m_contactId), m_managerUri(other.m_managerUri)
963
QContactMemoryEngineId::QContactMemoryEngineId(const QMap<QString, QString> ¶meters, const QString &engineIdString)
966
m_contactId = engineIdString.toInt();
967
m_managerUri = QContactManager::buildUri("memory", parameters);
970
bool QContactMemoryEngineId::isEqualTo(const QContactEngineId *other) const
972
if (m_contactId != static_cast<const QContactMemoryEngineId*>(other)->m_contactId)
977
bool QContactMemoryEngineId::isLessThan(const QContactEngineId *other) const
979
const QContactMemoryEngineId *otherPtr = static_cast<const QContactMemoryEngineId*>(other);
980
if (m_managerUri < otherPtr->m_managerUri)
982
if (m_contactId < otherPtr->m_contactId)
987
QString QContactMemoryEngineId::managerUri() const
992
QString QContactMemoryEngineId::toString() const
994
return QString::number(m_contactId);
997
QContactEngineId* QContactMemoryEngineId::clone() const
999
return new QContactMemoryEngineId(m_contactId, m_managerUri);
1002
#ifndef QT_NO_DEBUG_STREAM
1003
QDebug& QContactMemoryEngineId::debugStreamOut(QDebug &dbg) const
1005
dbg.nospace() << "QContactMemoryEngineId(" << m_managerUri << "," << m_contactId << ")";
1006
return dbg.maybeSpace();
1010
uint QContactMemoryEngineId::hash() const
1016
#include "moc_qcontactmemorybackend_p.cpp"
1018
QT_END_NAMESPACE_CONTACTS