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 QtOrganizer 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 "qorganizeritemchangeset.h"
35#include "qorganizeritemchangeset_p.h"
36
37#include "qorganizermanagerengine.h"
38
39QT_BEGIN_NAMESPACE_ORGANIZER
40
41/*!
42 \class QOrganizerItemChangeSet
43 \brief The QOrganizerItemChangeSet class provides a simple API to simplify the emission of
44 state-change signals for items from QOrganizerManagerEngine implementations.
45 \inmodule QtOrganizer
46 \ingroup organizer-backends
47
48 This class should only be used by backend developers.
49 */
50
51/*!
52 \typedef QOrganizerItemChangeSet::ItemChangeList
53
54 This type describes a set of item changes, where each item whose
55 ID is listed in \c second is subject to a change that affects some or
56 all of the detail types listed in \c first.
57
58 Note that change grouping is of items affected by equivalent changes,
59 rather than of multiple changes affecting the same item.
60
61 \code
62 foreach (QOrganizerItemChangeSet::ItemChangeList changeList, set.changedItems()) {
63 if (changeList.first.contains(QOrganizerItemDetail::TypeDescription)) {
64 qDebug() << "Item IDs with description changes:" << changeList.second;
65 }
66 }
67 \endcode
68
69 \sa QOrganizerItemChangeSet::changedItems()
70 */
71
72/*!
73 Constructs a new change set.
74 */
75QOrganizerItemChangeSet::QOrganizerItemChangeSet()
76 : d(new QOrganizerItemChangeSetData)
77{
78}
79
80/*!
81 Constructs a copy of the \a other change set.
82 */
83QOrganizerItemChangeSet::QOrganizerItemChangeSet(const QOrganizerItemChangeSet &other)
84 : d(other.d)
85{
86}
87
88/*!
89 Frees the memory used by this change set.
90 */
91QOrganizerItemChangeSet::~QOrganizerItemChangeSet()
92{
93}
94
95/*!
96 Assigns this change set to be equal to \a other.
97 */
98QOrganizerItemChangeSet &QOrganizerItemChangeSet::operator=(const QOrganizerItemChangeSet &other)
99{
100 d = other.d;
101 return *this;
102}
103
104/*!
105 Sets the data changed flag to \a dataChanged.
106
107 If this is set to true prior to calling emitSignals(), only the QOrganizerManagerEngine::dataChanged()
108 signal will be emitted; otherwise, the appropriate finer-grained signals will be emitted.
109 */
110void QOrganizerItemChangeSet::setDataChanged(bool dataChanged)
111{
112 d->m_dataChanged = dataChanged;
113}
114
115/*!
116 Returns the value of the data changed flag.
117 */
118bool QOrganizerItemChangeSet::dataChanged() const
119{
120 return d->m_dataChanged;
121}
122
123/*!
124 Returns the set of IDs of organizer items which have been added to the database.
125 */
126QSet<QOrganizerItemId> QOrganizerItemChangeSet::addedItems() const
127{
128 return d->m_addedItems;
129}
130
131/*!
132 Inserts the given \a itemId into the set of ids of organizer items which have been added to the
133 database.
134 */
135void QOrganizerItemChangeSet::insertAddedItem(const QOrganizerItemId &itemId)
136{
137 d->m_addedItems.insert(value: itemId);
138 d->m_modifiedItems.append(t: QPair<QOrganizerItemId, QOrganizerManager::Operation>(itemId, QOrganizerManager::Add));
139}
140
141/*!
142 Inserts each of the given \a itemIds into the set of IDs of organizer items which have been added
143 to the database.
144 */
145void QOrganizerItemChangeSet::insertAddedItems(const QList<QOrganizerItemId> &itemIds)
146{
147 foreach (const QOrganizerItemId &id, itemIds) {
148 d->m_addedItems.insert(value: id);
149 d->m_modifiedItems.append(t: QPair<QOrganizerItemId, QOrganizerManager::Operation>(id, QOrganizerManager::Add));
150 }
151}
152
153/*!
154 Clears the set of IDs of organizer items which have been added to the database.
155 */
156void QOrganizerItemChangeSet::clearAddedItems()
157{
158 d->m_addedItems.clear();
159}
160
161/*!
162 Returns a list of ItemChangeLists describing which items have been
163 changed in the database, and what details of those items have changed.
164
165 */
166QList<QOrganizerItemChangeSet::ItemChangeList> QOrganizerItemChangeSet::changedItems() const
167{
168 return d->m_changedItems;
169}
170
171/*!
172 Inserts the given item ID \a itemId into the set of IDs of organizer items which have been changed in
173 the database, with the changes described by \a typesChanged.
174 */
175void QOrganizerItemChangeSet::insertChangedItem(const QOrganizerItemId &itemId, const QList<QOrganizerItemDetail::DetailType> &typesChanged)
176{
177 insertChangedItems(itemIds: QList<QOrganizerItemId>() << itemId, typesChanged);
178}
179
180/*!
181 Inserts each of the itemIDs listed in \a itemIds into the set of IDs of organizer items which have been
182 changed in the database, with the changes described by \a typesChanged.
183 */
184void QOrganizerItemChangeSet::insertChangedItems(const QList<QOrganizerItemId> &changedItemIds, const QList<QOrganizerItemDetail::DetailType> &typesChanged)
185{
186 // Sort and de-duplicate the IDs and change types
187 QList<QOrganizerItemId> itemIds(changedItemIds);
188 std::sort(first: itemIds.begin(), last: itemIds.end());
189 {
190 QList<QOrganizerItemId>::iterator iit = std::unique(first: itemIds.begin(), last: itemIds.end());
191 while (iit != itemIds.end()) {
192 iit = itemIds.erase(it: iit);
193 }
194 }
195
196 QList<QOrganizerItemDetail::DetailType> changeSet(typesChanged);
197 std::sort(first: changeSet.begin(), last: changeSet.end());
198 {
199 QList<QOrganizerItemDetail::DetailType>::iterator cit = std::unique(first: changeSet.begin(), last: changeSet.end());
200 while (cit != changeSet.end()) {
201 cit = changeSet.erase(it: cit);
202 }
203 }
204
205 // Add these items to the list of items that match this change set
206 QList<ItemChangeList>::iterator it = d->m_changedItems.begin(), end = d->m_changedItems.end();
207 for ( ; it != end; ++it) {
208 if ((*it).first == changeSet) {
209 break;
210 }
211 }
212 if (it == end) {
213 // Add a list for this set of changes
214 d->m_changedItems.append(t: qMakePair(x: changeSet, y: itemIds));
215 } else {
216 QList<QOrganizerItemId> &changedIds((*it).second);
217 QList<QOrganizerItemId>::iterator iit = changedIds.begin();
218
219 foreach (const QOrganizerItemId &itemId, itemIds) {
220 // Add this ID if not yet present
221 iit = std::lower_bound(first: iit, last: changedIds.end(), val: itemId);
222 if (iit == changedIds.end() || *iit != itemId) {
223 iit = changedIds.insert(before: iit, t: itemId);
224 }
225 }
226 }
227
228 // These items are all now modified
229 foreach (const QOrganizerItemId &id, itemIds)
230 d->m_modifiedItems.append(t: QPair<QOrganizerItemId, QOrganizerManager::Operation>(id, QOrganizerManager::Change));
231}
232
233/*!
234 Clears the set of IDs of organizer items which have been changed in the database.
235 */
236void QOrganizerItemChangeSet::clearChangedItems()
237{
238 d->m_changedItems.clear();
239}
240
241/*!
242 Returns the set of IDs of organizer items which have been removed from the database.
243 */
244QSet<QOrganizerItemId> QOrganizerItemChangeSet::removedItems() const
245{
246 return d->m_removedItems;
247}
248
249/*!
250 Inserts the given \a itemId into the set of IDs of organizer items which have been removed from
251 the database.
252 */
253void QOrganizerItemChangeSet::insertRemovedItem(const QOrganizerItemId &itemId)
254{
255 d->m_removedItems.insert(value: itemId);
256 d->m_modifiedItems.append(t: QPair<QOrganizerItemId, QOrganizerManager::Operation>(itemId, QOrganizerManager::Remove));
257}
258
259/*!
260 Inserts each of the given \a itemIds into the set of IDs of organizer items which have been
261 removed from the database.
262 */
263void QOrganizerItemChangeSet::insertRemovedItems(const QList<QOrganizerItemId> &itemIds)
264{
265 foreach (const QOrganizerItemId &id, itemIds) {
266 d->m_removedItems.insert(value: id);
267 d->m_modifiedItems.append(t: QPair<QOrganizerItemId, QOrganizerManager::Operation>(id, QOrganizerManager::Remove));
268 }
269}
270
271/*!
272 Clears the set of IDs of organizer items which have been removed from the database.
273 */
274void QOrganizerItemChangeSet::clearRemovedItems()
275{
276 d->m_removedItems.clear();
277}
278
279/*!
280 Returns the list of ids of organizer items which have been added, changed or removed from
281 the database. The list includes information about which database operation was done. The ids and
282 operations are ordered so that the first operation is first in the list.
283 */
284QList<QPair<QOrganizerItemId, QOrganizerManager::Operation> > QOrganizerItemChangeSet::modifiedItems() const
285{
286 return d->m_modifiedItems;
287}
288
289/*!
290 Clears the list of ids of organizer items which have been added, changed or removed from the database
291 */
292void QOrganizerItemChangeSet::clearModifiedItems()
293{
294 d->m_modifiedItems.clear();
295}
296
297/*!
298 Clears all flags and sets of IDs in this change set.
299 */
300void QOrganizerItemChangeSet::clearAll()
301{
302 d->m_dataChanged = false;
303 d->m_addedItems.clear();
304 d->m_changedItems.clear();
305 d->m_removedItems.clear();
306 d->m_modifiedItems.clear();
307}
308
309/*!
310 Emits the appropriate signals from the given \a engine given the state of the change set. Note
311 that the flags and sets of IDs are not cleared after signals are emitted.
312 */
313void QOrganizerItemChangeSet::emitSignals(QOrganizerManagerEngine *engine) const
314{
315 if (!engine)
316 return;
317
318 if (d->m_dataChanged) {
319 emit engine->dataChanged();
320 } else {
321 if (!d->m_addedItems.isEmpty())
322 emit engine->itemsAdded(itemIds: d->m_addedItems.toList());
323 if (!d->m_changedItems.isEmpty()) {
324 QList<ItemChangeList>::const_iterator it = d->m_changedItems.constBegin(), end = d->m_changedItems.constEnd();
325 for ( ; it != end; ++it)
326 emit engine->itemsChanged(itemIds: (*it).second, typesChanged: (*it).first);
327 }
328 if (!d->m_removedItems.isEmpty())
329 emit engine->itemsRemoved(itemIds: d->m_removedItems.toList());
330 if (!d->m_modifiedItems.isEmpty())
331 emit engine->itemsModified(itemIds: d->m_modifiedItems);
332 }
333}
334
335QT_END_NAMESPACE_ORGANIZER
336

source code of qtpim/src/organizer/qorganizeritemchangeset.cpp