1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtContacts module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
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 The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
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 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#include "qcontactchangeset.h"
35#include "qcontactchangeset_p.h"
36
37#include "qcontactmanagerengine.h"
38
39#include <algorithm>
40
41QT_BEGIN_NAMESPACE_CONTACTS
42
43/*!
44 \class QContactChangeSet
45
46 \inmodule QtContacts
47
48 \brief The QContactChangeSet class provides a simple API to
49 simplify the emission of state-change signals from
50 QContactManagerEngine implementations.
51
52 This class can be utilised by backend implementations to ensure
53 correct emission of the \l QContactManagerEngine::dataChanged(), \l
54 QContactManagerEngine::contactsAdded(), \l
55 QContactManagerEngine::contactsChanged() and \l
56 QContactManagerEngine::contactsRemoved().
57
58 \sa QContactManagerEngine
59 */
60
61/*!
62 \typedef QContactChangeSet::ContactChangeList
63
64 This type describes a set of contact changes, where each contact whose
65 ID is listed in \c second is subject to a change that affects some or
66 all of the property types listed in \c first.
67
68 Note that change grouping is of contacts affected by equivalent changes,
69 rather than of multiple changes affecting the same contact.
70
71 \code
72 foreach (QContactChangeSet::ContactChangeList changeList, set.changedContacts()) {
73 if (changeList.first.contains(QContactAvatar::Type)) {
74 qDebug() << "Contact IDs with avatar changes:" << changeList.second;
75 }
76 }
77 \endcode
78
79 \sa QContactChangeSet::changedContacts()
80 */
81
82/*!
83 Constructs a new change set
84 */
85QContactChangeSet::QContactChangeSet()
86 : d(new QContactChangeSetData)
87{
88}
89
90/*!
91 Constructs a copy of the \a other change set
92 */
93QContactChangeSet::QContactChangeSet(const QContactChangeSet& other)
94 : d(other.d)
95{
96}
97
98/*!
99 Frees the memory used by this change set
100 */
101QContactChangeSet::~QContactChangeSet()
102{
103}
104
105/*!
106 Assigns this change set to be equal to \a other
107 */
108QContactChangeSet& QContactChangeSet::operator=(const QContactChangeSet& other)
109{
110 d = other.d;
111 return *this;
112}
113
114/*!
115 Sets the data changed flag to \a dataChanged. If this is set to true prior to calling \l emitSignals(),
116 only the \l QContactManagerEngine::dataChanged() signal will be emitted; otherwise, the appropriate
117 finer-grained signals will be emitted.
118 */
119void QContactChangeSet::setDataChanged(bool dataChanged)
120{
121 d->m_dataChanged = dataChanged;
122}
123
124/*!
125 Returns the value of the data changed flag
126 */
127bool QContactChangeSet::dataChanged() const
128{
129 return d->m_dataChanged;
130}
131
132/*!
133 Returns the set of ids of contacts which have been added to
134 the database.
135 */
136QSet<QContactId> QContactChangeSet::addedContacts() const
137{
138 return d->m_addedContacts;
139}
140
141/*!
142 Inserts the given contact id \a addedContactId into the set of ids of contacts
143 which have been added to the database.
144 */
145void QContactChangeSet::insertAddedContact(QContactId addedContactId)
146{
147 d->m_addedContacts.insert(value: addedContactId);
148}
149
150/*!
151 Inserts each of the given contact ids \a addedContactIds into the set of ids of contacts
152 which have been added to the database.
153 */
154void QContactChangeSet::insertAddedContacts(const QList<QContactId>& addedContactIds)
155{
156 foreach (const QContactId& id, addedContactIds)
157 d->m_addedContacts.insert(value: id);
158}
159
160/*!
161 Clears the set of ids of contacts which have been added to the database
162 */
163void QContactChangeSet::clearAddedContacts()
164{
165 d->m_addedContacts.clear();
166}
167
168/*!
169 Returns a list of ContactChangeLists describing which contacts have been
170 changed in the database, and what properties of those contacts have changed.
171 */
172QList<QContactChangeSet::ContactChangeList> QContactChangeSet::changedContacts() const
173{
174 return d->m_changedContacts;
175}
176
177/*!
178 Inserts the given contact ID \a changedContactId into the set of IDs of contacts
179 which have been changed in the database, with the changes described by \a typesChanged.
180 */
181void QContactChangeSet::insertChangedContact(QContactId changedContactId, const QList<QContactDetail::DetailType> &typesChanged)
182{
183 insertChangedContacts(addedContactIds: QList<QContactId>() << changedContactId, typesChanged);
184}
185
186/*!
187 Inserts each of the contact IDs listed in \a changedContactIds into the set of IDs of contacts
188 which have been changed in the database, with the changes described by \a typesChanged.
189 */
190void QContactChangeSet::insertChangedContacts(const QList<QContactId>& changedContactIds, const QList<QContactDetail::DetailType> &typesChanged)
191{
192 // Sort and de-duplicate the IDs and change types
193 QList<QContactId> contactIds(changedContactIds);
194 std::sort(first: contactIds.begin(), last: contactIds.end());
195 {
196 QList<QContactId>::iterator iit = std::unique(first: contactIds.begin(), last: contactIds.end());
197 while (iit != contactIds.end()) {
198 iit = contactIds.erase(it: iit);
199 }
200 }
201
202 QList<QContactDetail::DetailType> changeSet(typesChanged);
203 std::sort(first: changeSet.begin(), last: changeSet.end());
204 {
205 QList<QContactDetail::DetailType>::iterator cit = std::unique(first: changeSet.begin(), last: changeSet.end());
206 while (cit != changeSet.end()) {
207 cit = changeSet.erase(it: cit);
208 }
209 }
210
211 // Add these contacts to the list of contacts that match this change set
212 QList<ContactChangeList>::iterator it = d->m_changedContacts.begin(), end = d->m_changedContacts.end();
213 for ( ; it != end; ++it) {
214 if ((*it).first == changeSet) {
215 break;
216 }
217 }
218 if (it == end) {
219 // Add a list for this set of changes
220 d->m_changedContacts.append(t: qMakePair(x: changeSet, y: contactIds));
221 } else {
222 QList<QContactId> &changedIds((*it).second);
223 QList<QContactId>::iterator iit = changedIds.begin();
224
225 foreach (const QContactId &contactId, contactIds) {
226 // Add this ID if not yet present
227 iit = std::lower_bound(first: iit, last: changedIds.end(), val: contactId);
228 if (iit == changedIds.end() || *iit != contactId) {
229 iit = changedIds.insert(before: iit, t: contactId);
230 }
231 }
232 }
233}
234
235/*!
236 Clears the set of ids of contacts which have been changed to the database
237 */
238void QContactChangeSet::clearChangedContacts()
239{
240 d->m_changedContacts.clear();
241}
242
243/*!
244 Returns the set of ids of contacts which have been removed from
245 the database.
246 */
247QSet<QContactId> QContactChangeSet::removedContacts() const
248{
249 return d->m_removedContacts;
250}
251
252/*!
253 Inserts the given contact id \a removedContactId into the set of ids of contacts
254 which have been removed to the database.
255 */
256void QContactChangeSet::insertRemovedContact(QContactId removedContactId)
257{
258 d->m_removedContacts.insert(value: removedContactId);
259}
260
261/*!
262 Inserts each of the given contact ids \a removedContactIds into the set of ids of contacts
263 which have been removed to the database.
264 */
265void QContactChangeSet::insertRemovedContacts(const QList<QContactId>& removedContactIds)
266{
267 foreach (const QContactId& id, removedContactIds)
268 d->m_removedContacts.insert(value: id);
269}
270
271/*!
272 Clears the set of ids of contacts which have been removed to the database
273 */
274void QContactChangeSet::clearRemovedContacts()
275{
276 d->m_removedContacts.clear();
277}
278
279/*!
280 Returns the set of ids of contacts which have been affected
281 by the addition of relationships to the database.
282 */
283QSet<QContactId> QContactChangeSet::addedRelationshipsContacts() const
284{
285 return d->m_addedRelationships;
286}
287
288/*!
289 Inserts the given contact id \a affectedContactId into the set of ids of contacts
290 which have been affected by the addition of a relationship to the database.
291 */
292void QContactChangeSet::insertAddedRelationshipsContact(QContactId affectedContactId)
293{
294 d->m_addedRelationships.insert(value: affectedContactId);
295}
296
297/*!
298 Inserts each of the given contact ids \a affectedContactIds into the set of ids of contacts
299 which have been affected by the addition of a relationship to the database.
300 */
301void QContactChangeSet::insertAddedRelationshipsContacts(const QList<QContactId>& affectedContactIds)
302{
303 foreach (const QContactId& id, affectedContactIds)
304 d->m_addedRelationships.insert(value: id);
305}
306
307/*!
308 Clears the set of ids of contacts which have been affected by the addition of a relationship to the database.
309 */
310void QContactChangeSet::clearAddedRelationshipsContacts()
311{
312 d->m_addedRelationships.clear();
313}
314
315/*!
316 Returns the set of ids of contacts which have been affected
317 by the removal of relationships from the database.
318 */
319QSet<QContactId> QContactChangeSet::removedRelationshipsContacts() const
320{
321 return d->m_removedRelationships;
322}
323
324/*!
325 Inserts the given contact id \a affectedContactId into the set of ids of contacts
326 which have been affected by the removal of a relationship to the database.
327 */
328void QContactChangeSet::insertRemovedRelationshipsContact(QContactId affectedContactId)
329{
330 d->m_removedRelationships.insert(value: affectedContactId);
331}
332
333/*!
334 Inserts each of the given contact ids \a affectedContactIds into the set of ids of contacts
335 which have been affected by the removal of a relationship to the database.
336 */
337void QContactChangeSet::insertRemovedRelationshipsContacts(const QList<QContactId>& affectedContactIds)
338{
339 foreach (const QContactId& id, affectedContactIds)
340 d->m_removedRelationships.insert(value: id);
341}
342
343/*!
344 Clears the set of ids of contacts which have been affected by the removal of a relationship to the database.
345 */
346void QContactChangeSet::clearRemovedRelationshipsContacts()
347{
348 d->m_removedRelationships.clear();
349}
350
351/*!
352 Sets the pair of ids which represent the old and new self contact ids
353 to the given pair of ids \a oldAndNewContactId.
354 The first id in the pair is the old self contact id, while the second
355 id in the pair is the new self contact id. If the new id is different
356 to the old id at the point in time when emitSignals() is called,
357 the QContactManagerEngine::selfContactIdChanged signal will be emitted.
358 */
359void QContactChangeSet::setOldAndNewSelfContactId(const QPair<QContactId, QContactId> &oldAndNewContactId)
360{
361 d->m_oldAndNewSelfContactId = oldAndNewContactId;
362}
363
364/*!
365 Returns the pair of ids which represents the
366 old and new self contact ids. The first id in the pair is the
367 old self contact id, while the second id in the pair is the
368 new self contact id. If the new id is different to the old id
369 at the point in time when emitSignals() is called,
370 the QContactManagerEngine::selfContactIdChanged() signal will be emitted.
371 */
372QPair<QContactId, QContactId> QContactChangeSet::oldAndNewSelfContactId() const
373{
374 return d->m_oldAndNewSelfContactId;
375}
376
377/*!
378 Clears all flags and sets of ids in this change set
379 */
380void QContactChangeSet::clearAll()
381{
382 d->m_dataChanged = false;
383 d->m_addedContacts.clear();
384 d->m_changedContacts.clear();
385 d->m_removedContacts.clear();
386 d->m_addedRelationships.clear();
387 d->m_removedRelationships.clear();
388 d->m_oldAndNewSelfContactId = QPair<QContactId, QContactId>();
389}
390
391/*!
392 Emits the appropriate signals from the given \a engine given the state of the change set
393 */
394void QContactChangeSet::emitSignals(QContactManagerEngine *engine) const
395{
396 if (!engine)
397 return;
398
399 if (d->m_dataChanged) {
400 emit engine->dataChanged();
401 } else {
402 if (!d->m_addedContacts.isEmpty())
403 emit engine->contactsAdded(contactIds: d->m_addedContacts.toList());
404 if (!d->m_changedContacts.isEmpty()) {
405 QList<ContactChangeList>::const_iterator it = d->m_changedContacts.constBegin(), end = d->m_changedContacts.constEnd();
406 for ( ; it != end; ++it)
407 emit engine->contactsChanged(contactIds: (*it).second, typesChanged: (*it).first);
408 }
409 if (!d->m_removedContacts.isEmpty())
410 emit engine->contactsRemoved(contactIds: d->m_removedContacts.toList());
411 if (!d->m_addedRelationships.isEmpty())
412 emit engine->relationshipsAdded(affectedContactIds: d->m_addedRelationships.toList());
413 if (!d->m_removedRelationships.isEmpty())
414 emit engine->relationshipsRemoved(affectedContactIds: d->m_removedRelationships.toList());
415 if (d->m_oldAndNewSelfContactId.first != d->m_oldAndNewSelfContactId.second)
416 emit engine->selfContactIdChanged(oldId: d->m_oldAndNewSelfContactId.first, newId: d->m_oldAndNewSelfContactId.second);
417 }
418}
419
420QT_END_NAMESPACE_CONTACTS
421

source code of qtpim/src/contacts/qcontactchangeset.cpp