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 | |
41 | QT_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 | */ |
85 | QContactChangeSet::QContactChangeSet() |
86 | : d(new QContactChangeSetData) |
87 | { |
88 | } |
89 | |
90 | /*! |
91 | Constructs a copy of the \a other change set |
92 | */ |
93 | QContactChangeSet::QContactChangeSet(const QContactChangeSet& other) |
94 | : d(other.d) |
95 | { |
96 | } |
97 | |
98 | /*! |
99 | Frees the memory used by this change set |
100 | */ |
101 | QContactChangeSet::~QContactChangeSet() |
102 | { |
103 | } |
104 | |
105 | /*! |
106 | Assigns this change set to be equal to \a other |
107 | */ |
108 | QContactChangeSet& 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 | */ |
119 | void QContactChangeSet::setDataChanged(bool dataChanged) |
120 | { |
121 | d->m_dataChanged = dataChanged; |
122 | } |
123 | |
124 | /*! |
125 | Returns the value of the data changed flag |
126 | */ |
127 | bool 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 | */ |
136 | QSet<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 | */ |
145 | void 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 | */ |
154 | void 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 | */ |
163 | void 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 | */ |
172 | QList<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 | */ |
181 | void 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 | */ |
190 | void 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 | */ |
238 | void 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 | */ |
247 | QSet<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 | */ |
256 | void 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 | */ |
265 | void 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 | */ |
274 | void 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 | */ |
283 | QSet<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 | */ |
292 | void 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 | */ |
301 | void 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 | */ |
310 | void 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 | */ |
319 | QSet<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 | */ |
328 | void 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 | */ |
337 | void 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 | */ |
346 | void 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 | */ |
359 | void 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 | */ |
372 | QPair<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 | */ |
380 | void 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 | */ |
394 | void 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 | |
420 | QT_END_NAMESPACE_CONTACTS |
421 | |