Akonadi

notificationcollector.cpp
1 /*
2  Copyright (c) 2006 - 2007 Volker Krause <[email protected]>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "notificationcollector.h"
21 #include "storage/datastore.h"
22 #include "storage/entity.h"
23 #include "storage/collectionstatistics.h"
24 #include "handlerhelper.h"
25 #include "cachecleaner.h"
26 #include "intervalcheck.h"
27 #include "search/searchmanager.h"
28 #include "akonadi.h"
29 #include "notificationmanager.h"
30 #include "aggregatedfetchscope.h"
31 #include "selectquerybuilder.h"
32 #include "handler/itemfetchhelper.h"
33 #include "connection.h"
34 #include "shared/akranges.h"
35 
36 #include "akonadiserver_debug.h"
37 
38 #include <QScopedValueRollback>
39 
40 using namespace Akonadi;
41 using namespace Akonadi::Server;
42 
44  : mDb(db)
45  , mAkonadi(akonadi)
46 {
48  [this]() {
49  if (!mIgnoreTransactions) {
51  }
52  });
54  [this]() {
55  if (!mIgnoreTransactions) {
56  clear();
57  }
58  });
59 }
60 
62  bool seen,
63  const Collection &collection,
64  const QByteArray &resource)
65 {
66  mAkonadi.searchManager().scheduleSearchUpdate();
67  mAkonadi.collectionStatistics().itemAdded(collection, item.size(), seen);
68  itemNotification(Protocol::ItemChangeNotification::Add, item, collection, Collection(), resource);
69 }
70 
72  const QSet<QByteArray> &changedParts,
73  const Collection &collection,
74  const QByteArray &resource)
75 {
76  mAkonadi.searchManager().scheduleSearchUpdate();
77  itemNotification(Protocol::ItemChangeNotification::Modify, item, collection, Collection(), resource, changedParts);
78 }
79 
81  const QSet<QByteArray> &addedFlags,
82  const QSet<QByteArray> &removedFlags,
83  const Collection &collection,
84  const QByteArray &resource)
85 {
86  int seenCount = (addedFlags.contains(AKONADI_FLAG_SEEN) || addedFlags.contains(AKONADI_FLAG_IGNORED) ? items.count() : 0);
87  seenCount -= (removedFlags.contains(AKONADI_FLAG_SEEN) || removedFlags.contains(AKONADI_FLAG_IGNORED) ? items.count() : 0);
88 
89  mAkonadi.collectionStatistics().itemsSeenChanged(collection, seenCount);
90  itemNotification(Protocol::ItemChangeNotification::ModifyFlags, items, collection, Collection(), resource, QSet<QByteArray>(), addedFlags, removedFlags);
91 }
92 
94  const QSet<qint64> &addedTags,
95  const QSet<qint64> &removedTags,
96  const Collection &collection,
97  const QByteArray &resource)
98 {
99  itemNotification(Protocol::ItemChangeNotification::ModifyTags, items, collection, Collection(), resource, QSet<QByteArray>(), QSet<QByteArray>(), QSet<QByteArray>(), addedTags, removedTags);
100 }
101 
103  const Relation::List &addedRelations,
104  const Relation::List &removedRelations,
105  const Collection &collection,
106  const QByteArray &resource)
107 {
108  itemNotification(Protocol::ItemChangeNotification::ModifyRelations, items, collection, Collection(), resource, QSet<QByteArray>(), QSet<QByteArray>(), QSet<QByteArray>(), QSet<qint64>(), QSet<qint64>(), addedRelations, removedRelations);
109 }
110 
112  const Collection &collectionSrc,
113  const Collection &collectionDest,
114  const QByteArray &sourceResource)
115 {
116  mAkonadi.searchManager().scheduleSearchUpdate();
117  itemNotification(Protocol::ItemChangeNotification::Move, items, collectionSrc, collectionDest, sourceResource);
118 }
119 
121  const Collection &collection,
122  const QByteArray &resource)
123 {
124  itemNotification(Protocol::ItemChangeNotification::Remove, items, collection, Collection(), resource);
125 }
126 
127 void NotificationCollector::itemsLinked(const PimItem::List &items, const Collection &collection)
128 {
129  itemNotification(Protocol::ItemChangeNotification::Link, items, collection, Collection(), QByteArray());
130 }
131 
132 void NotificationCollector::itemsUnlinked(const PimItem::List &items, const Collection &collection)
133 {
134  itemNotification(Protocol::ItemChangeNotification::Unlink, items, collection, Collection(), QByteArray());
135 }
136 
138  const QByteArray &resource)
139 {
140  if (auto cleaner = mAkonadi.cacheCleaner()) {
141  cleaner->collectionAdded(collection.id());
142  }
143  mAkonadi.intervalChecker().collectionAdded(collection.id());
144  collectionNotification(Protocol::CollectionChangeNotification::Add, collection, collection.parentId(), -1, resource);
145 }
146 
148  const QList<QByteArray> &changes,
149  const QByteArray &resource)
150 {
151  if (auto cleaner = mAkonadi.cacheCleaner()) {
152  cleaner->collectionChanged(collection.id());
153  }
154  mAkonadi.intervalChecker().collectionChanged(collection.id());
155  if (changes.contains(AKONADI_PARAM_ENABLED)) {
156  mAkonadi.collectionStatistics().invalidateCollection(collection);
157  }
158  collectionNotification(Protocol::CollectionChangeNotification::Modify, collection, collection.parentId(),
159  -1, resource, changes | AkRanges::Actions::toQSet);
160 }
161 
163  const Collection &source,
164  const QByteArray &resource,
165  const QByteArray &destResource)
166 {
167  if (auto cleaner = mAkonadi.cacheCleaner()) {
168  cleaner->collectionChanged(collection.id());
169  }
170  mAkonadi.intervalChecker().collectionChanged(collection.id());
171  collectionNotification(Protocol::CollectionChangeNotification::Move, collection, source.id(), collection.parentId(), resource, QSet<QByteArray>(), destResource);
172 }
173 
175  const QByteArray &resource)
176 {
177  if (auto cleaner = mAkonadi.cacheCleaner()) {
178  cleaner->collectionRemoved(collection.id());
179  }
180  mAkonadi.intervalChecker().collectionRemoved(collection.id());
181  mAkonadi.collectionStatistics().invalidateCollection(collection);
182  collectionNotification(Protocol::CollectionChangeNotification::Remove, collection, collection.parentId(), -1, resource);
183 }
184 
186  const QByteArray &resource)
187 {
188  if (auto cleaner = mAkonadi.cacheCleaner()) {
189  cleaner->collectionAdded(collection.id());
190  }
191  mAkonadi.intervalChecker().collectionAdded(collection.id());
192  collectionNotification(Protocol::CollectionChangeNotification::Subscribe, collection, collection.parentId(), -1, resource, QSet<QByteArray>());
193 }
194 
196  const QByteArray &resource)
197 {
198  if (auto cleaner = mAkonadi.cacheCleaner()) {
199  cleaner->collectionRemoved(collection.id());
200  }
201  mAkonadi.intervalChecker().collectionRemoved(collection.id());
202  mAkonadi.collectionStatistics().invalidateCollection(collection);
203  collectionNotification(Protocol::CollectionChangeNotification::Unsubscribe, collection, collection.parentId(), -1, resource, QSet<QByteArray>());
204 }
205 
207 {
208  tagNotification(Protocol::TagChangeNotification::Add, tag);
209 }
210 
212 {
213  tagNotification(Protocol::TagChangeNotification::Modify, tag);
214 }
215 
216 void NotificationCollector::tagRemoved(const Tag &tag, const QByteArray &resource, const QString &remoteId)
217 {
218  tagNotification(Protocol::TagChangeNotification::Remove, tag, resource, remoteId);
219 }
220 
222 {
223  relationNotification(Protocol::RelationChangeNotification::Add, relation);
224 }
225 
227 {
228  relationNotification(Protocol::RelationChangeNotification::Remove, relation);
229 }
230 
231 void NotificationCollector::clear()
232 {
233  mNotifications.clear();
234 }
235 
237 {
238  mConnection = connection;
239 }
240 
241 void NotificationCollector::itemNotification(Protocol::ItemChangeNotification::Operation op,
242  const PimItem &item,
243  const Collection &collection,
244  const Collection &collectionDest,
245  const QByteArray &resource,
246  const QSet<QByteArray> &parts)
247 {
248  PimItem::List items;
249  items << item;
250  itemNotification(op, items, collection, collectionDest, resource, parts);
251 }
252 
253 void NotificationCollector::itemNotification(Protocol::ItemChangeNotification::Operation op,
254  const PimItem::List &items,
255  const Collection &collection,
256  const Collection &collectionDest,
257  const QByteArray &resource,
258  const QSet<QByteArray> &parts,
259  const QSet<QByteArray> &addedFlags,
260  const QSet<QByteArray> &removedFlags,
261  const QSet<qint64> &addedTags,
262  const QSet<qint64> &removedTags,
263  const Relation::List &addedRelations,
264  const Relation::List &removedRelations)
265 {
266  QMap<Entity::Id, QList<PimItem> > vCollections;
267 
268  if ((op == Protocol::ItemChangeNotification::Modify) ||
269  (op == Protocol::ItemChangeNotification::ModifyFlags) ||
270  (op == Protocol::ItemChangeNotification::ModifyTags) ||
271  (op == Protocol::ItemChangeNotification::ModifyRelations)) {
272  vCollections = DataStore::self()->virtualCollections(items);
273  }
274 
275  auto msg = Protocol::ItemChangeNotificationPtr::create();
276  if (mConnection) {
277  msg->setSessionId(mConnection->sessionId());
278  }
279  msg->setOperation(op);
280 
281  msg->setItemParts(parts);
282  msg->setAddedFlags(addedFlags);
283  msg->setRemovedFlags(removedFlags);
284  msg->setAddedTags(addedTags);
285  msg->setRemovedTags(removedTags);
286  if (!addedRelations.isEmpty()) {
288  Q_FOREACH (const Relation &rel, addedRelations) {
289  rels.insert(Protocol::ItemChangeNotification::Relation(rel.leftId(), rel.rightId(), rel.relationType().name()));
290  }
291  msg->setAddedRelations(rels);
292  }
293  if (!removedRelations.isEmpty()) {
295  Q_FOREACH (const Relation &rel, removedRelations) {
296  rels.insert(Protocol::ItemChangeNotification::Relation(rel.leftId(), rel.rightId(), rel.relationType().name()));
297  }
298  msg->setRemovedRelations(rels);
299  }
300 
301  if (collectionDest.isValid()) {
302  QByteArray destResourceName;
303  destResourceName = collectionDest.resource().name().toLatin1();
304  msg->setDestinationResource(destResourceName);
305  }
306 
307  msg->setParentDestCollection(collectionDest.id());
308 
310  Q_FOREACH (const PimItem &item, items) {
311  Protocol::FetchItemsResponse i;
312  i.setId(item.id());
313  i.setRemoteId(item.remoteId());
314  i.setRemoteRevision(item.remoteRevision());
315  i.setMimeType(item.mimeType().name());
316  ntfItems.push_back(std::move(i));
317  }
318 
319  /* Notify all virtual collections the items are linked to. */
321  for (const auto &ntfItem : ntfItems) {
322  virtItems.insert(ntfItem.id(), std::move(ntfItem));
323  }
324  auto iter = vCollections.constBegin(), endIter = vCollections.constEnd();
325  for (; iter != endIter; ++iter) {
326  auto copy = Protocol::ItemChangeNotificationPtr::create(*msg);
328  items.reserve(iter->size());
329  for (const auto &item : qAsConst(*iter)) {
330  items.append(virtItems.value(item.id()));
331  }
332  copy->setItems(items);
333  copy->setParentCollection(iter.key());
334  copy->setResource(resource);
335 
336  mAkonadi.collectionStatistics().invalidateCollection(Collection::retrieveById(iter.key()));
337  dispatchNotification(copy);
338  }
339 
340  msg->setItems(ntfItems);
341 
342  Collection col;
343  if (!collection.isValid()) {
344  msg->setParentCollection(items.first().collection().id());
345  col = items.first().collection();
346  } else {
347  msg->setParentCollection(collection.id());
348  col = collection;
349  }
350 
351  QByteArray res = resource;
352  if (res.isEmpty()) {
353  if (col.resourceId() <= 0) {
354  col = Collection::retrieveById(col.id());
355  }
356  res = col.resource().name().toLatin1();
357  }
358  msg->setResource(res);
359 
360  // Add and ModifyFlags are handled incrementally
361  // (see itemAdded() and itemsFlagsChanged())
362  if (msg->operation() != Protocol::ItemChangeNotification::Add
363  && msg->operation() != Protocol::ItemChangeNotification::ModifyFlags) {
364  mAkonadi.collectionStatistics().invalidateCollection(col);
365  }
366  dispatchNotification(msg);
367 }
368 
369 void NotificationCollector::collectionNotification(Protocol::CollectionChangeNotification::Operation op,
370  const Collection &collection,
371  Collection::Id source,
372  Collection::Id destination,
373  const QByteArray &resource,
374  const QSet<QByteArray> &changes,
375  const QByteArray &destResource)
376 {
377  auto msg = Protocol::CollectionChangeNotificationPtr::create();
378  msg->setOperation(op);
379  if (mConnection) {
380  msg->setSessionId(mConnection->sessionId());
381  }
382  msg->setParentCollection(source);
383  msg->setParentDestCollection(destination);
384  msg->setDestinationResource(destResource);
385  msg->setChangedParts(changes);
386 
387  auto msgCollection = HandlerHelper::fetchCollectionsResponse(mAkonadi, collection);
388  if (auto mgr = mAkonadi.notificationManager()) {
389  auto fetchScope = mgr->collectionFetchScope();
390  // Make sure we have all the data
391  if (!fetchScope->fetchIdOnly() && msgCollection.name().isEmpty()) {
392  const auto col = Collection::retrieveById(msgCollection.id());
393  const auto mts = col.mimeTypes();
394  QStringList mimeTypes;
395  mimeTypes.reserve(mts.size());
396  for (const auto &mt : mts) {
397  mimeTypes.push_back(mt.name());
398  }
399  msgCollection = HandlerHelper::fetchCollectionsResponse(mAkonadi, col, {}, false, 0, {}, {}, mimeTypes);
400  }
401  // Get up-to-date statistics
402  if (fetchScope->fetchStatistics()) {
403  Collection col;
404  col.setId(msgCollection.id());
405  const auto stats = mAkonadi.collectionStatistics().statistics(col);
406  msgCollection.setStatistics(Protocol::FetchCollectionStatsResponse(stats.count, stats.count - stats.read, stats.size));
407  }
408  // Get attributes
409  const auto requestedAttrs = fetchScope->attributes();
410  auto msgColAttrs = msgCollection.attributes();
411  // TODO: This assumes that we have either none or all attributes in msgCollection
412  if (msgColAttrs.isEmpty() && !requestedAttrs.isEmpty()) {
414  qb.addColumn(CollectionAttribute::typeFullColumnName());
415  qb.addColumn(CollectionAttribute::valueFullColumnName());
416  qb.addValueCondition(CollectionAttribute::collectionIdFullColumnName(),
417  Query::Equals, msgCollection.id());
418  Query::Condition cond(Query::Or);
419  for (const auto &attr : requestedAttrs) {
420  cond.addValueCondition(CollectionAttribute::typeFullColumnName(), Query::Equals, attr);
421  }
422  qb.addCondition(cond);
423  if (!qb.exec()) {
424  qCWarning(AKONADISERVER_LOG) << "NotificationCollector failed to query attributes for Collection"
425  << collection.name() << "(ID" << collection.id() << ")";
426  }
427  const auto attrs = qb.result();
428  for (const auto &attr : attrs) {
429  msgColAttrs.insert(attr.type(), attr.value());
430  }
431  msgCollection.setAttributes(msgColAttrs);
432  }
433  }
434  msg->setCollection(std::move(msgCollection));
435 
436  if (!collection.enabled()) {
437  msg->addMetadata("DISABLED");
438  }
439 
440  QByteArray res = resource;
441  if (res.isEmpty()) {
442  res = collection.resource().name().toLatin1();
443  }
444  msg->setResource(res);
445 
446  dispatchNotification(msg);
447 }
448 
449 void NotificationCollector::tagNotification(Protocol::TagChangeNotification::Operation op,
450  const Tag &tag,
451  const QByteArray &resource,
452  const QString &remoteId)
453 {
454  auto msg = Protocol::TagChangeNotificationPtr::create();
455  msg->setOperation(op);
456  if (mConnection) {
457  msg->setSessionId(mConnection->sessionId());
458  }
459  msg->setResource(resource);
460  Protocol::FetchTagsResponse msgTag;
461  msgTag.setId(tag.id());
462  msgTag.setRemoteId(remoteId.toUtf8());
463  msgTag.setParentId(tag.parentId());
464  if (auto mgr = mAkonadi.notificationManager()) {
465  auto fetchScope = mgr->tagFetchScope();
466  if (!fetchScope->fetchIdOnly() && msgTag.gid().isEmpty()) {
467  msgTag = HandlerHelper::fetchTagsResponse(Tag::retrieveById(msgTag.id()), fetchScope->toFetchScope(), mConnection);
468  }
469 
470  const auto requestedAttrs = fetchScope->attributes();
471  auto msgTagAttrs = msgTag.attributes();
472  if (msgTagAttrs.isEmpty() && !requestedAttrs.isEmpty()) {
474  qb.addColumn(TagAttribute::typeFullColumnName());
475  qb.addColumn(TagAttribute::valueFullColumnName());
476  qb.addValueCondition(TagAttribute::tagIdFullColumnName(), Query::Equals, msgTag.id());
477  Query::Condition cond(Query::Or);
478  for (const auto &attr : requestedAttrs) {
479  cond.addValueCondition(TagAttribute::typeFullColumnName(), Query::Equals, attr);
480  }
481  qb.addCondition(cond);
482  if (!qb.exec()) {
483  qCWarning(AKONADISERVER_LOG) << "NotificationCollection failed to query attributes for Tag" << tag.id();
484  }
485  const auto attrs = qb.result();
486  for (const auto &attr : attrs) {
487  msgTagAttrs.insert(attr.type(), attr.value());
488  }
489  msgTag.setAttributes(msgTagAttrs);
490  }
491  }
492  msg->setTag(std::move(msgTag));
493 
494  dispatchNotification(msg);
495 }
496 
497 void NotificationCollector::relationNotification(Protocol::RelationChangeNotification::Operation op,
498  const Relation &relation)
499 {
500  auto msg = Protocol::RelationChangeNotificationPtr::create();
501  msg->setOperation(op);
502  if (mConnection) {
503  msg->setSessionId(mConnection->sessionId());
504  }
505  msg->setRelation(HandlerHelper::fetchRelationsResponse(relation));
506 
507  dispatchNotification(msg);
508 }
509 
510 void NotificationCollector::completeNotification(const Protocol::ChangeNotificationPtr &changeMsg)
511 {
512  if (changeMsg->type() == Protocol::Command::ItemChangeNotification) {
513  const auto msg = changeMsg.staticCast<Protocol::ItemChangeNotification>();
514  const auto mgr = mAkonadi.notificationManager();
515  if (mgr && msg->operation() != Protocol::ItemChangeNotification::Remove) {
516  if (mDb->inTransaction()) {
517  qCWarning(AKONADISERVER_LOG) << "NotificationCollector requested FetchHelper from within a transaction."
518  << "Aborting since this would deadlock!";
519  return;
520  }
521  auto fetchScope = mgr->itemFetchScope();
522  // NOTE: Checking and retrieving missing elements for each Item manually
523  // here would require a complex code (and I'm too lazy), so instead we simply
524  // feed the Items to FetchHelper and retrieve them all with the setup from
525  // the aggregated fetch scope. The worst case is that we re-fetch everything
526  // we already have, but that's stil better than the pre-ntf-payload situation
527  QVector<qint64> ids;
528  const auto items = msg->items();
529  ids.reserve(items.size());
530  bool allHaveRID = true;
531  for (const auto &item : items) {
532  ids.push_back(item.id());
533  allHaveRID &= !item.remoteId().isEmpty();
534  }
535 
536  // FetchHelper may trigger ItemRetriever, which needs RemoteID. If we
537  // don't have one (maybe because the Resource has not stored it yet,
538  // we emit a notification without it and leave it up to the Monitor
539  // to retrieve the Item on demand - we should have a RID stored in
540  // Akonadi by then.
541  if (mConnection && (allHaveRID || msg->operation() != Protocol::ItemChangeNotification::Add)) {
542 
543  // Prevent transactions inside FetchHelper to recursively call our slot
544  QScopedValueRollback<bool> ignoreTransactions(mIgnoreTransactions);
545  mIgnoreTransactions = true;
546  CommandContext context;
547  auto itemFetchScope = fetchScope->toFetchScope();
548  auto tagFetchScope = mgr->tagFetchScope()->toFetchScope();
549  itemFetchScope.setFetch(Protocol::ItemFetchScope::CacheOnly);
550  ItemFetchHelper helper(mConnection, context, Scope(ids), itemFetchScope, tagFetchScope, mAkonadi);
551  // The Item was just changed, which means the atime was
552  // updated, no need to do it again a couple milliseconds later.
553  helper.disableATimeUpdates();
555  auto callback = [&fetchedItems](Protocol::FetchItemsResponse &&cmd) {
556  fetchedItems.push_back(std::move(cmd));
557  };
558  if (helper.fetchItems(std::move(callback))) {
559  msg->setItems(fetchedItems);
560  } else {
561  qCWarning(AKONADISERVER_LOG) << "NotificationCollector railed to retrieve Items for notification!";
562  }
563  } else {
565  for (const auto &item : items) {
566  Protocol::FetchItemsResponse resp;
567  resp.setId(item.id());
568  resp.setRevision(item.revision());
569  resp.setMimeType(item.mimeType());
570  resp.setParentId(item.parentId());
571  resp.setGid(item.gid());
572  resp.setSize(item.size());
573  resp.setMTime(item.mTime());
574  resp.setFlags(item.flags());
575  fetchedItems.push_back(std::move(resp));
576  }
577  msg->setItems(fetchedItems);
578  msg->setMustRetrieve(true);
579  }
580  }
581  }
582 }
583 
584 void NotificationCollector::dispatchNotification(const Protocol::ChangeNotificationPtr &msg)
585 {
586  if (!mDb || mDb->inTransaction()) {
587  if (msg->type() == Protocol::Command::CollectionChangeNotification) {
588  Protocol::CollectionChangeNotification::appendAndCompress(mNotifications, msg);
589  } else {
590  mNotifications.append(msg);
591  }
592  } else {
593  completeNotification(msg);
594  notify({msg});
595  }
596 }
597 
599 {
600  if (!mNotifications.isEmpty()) {
601  for (auto &ntf : mNotifications) {
602  completeNotification(ntf);
603  }
604  notify(std::move(mNotifications));
605  clear();
606  return true;
607  }
608 
609  return false;
610 }
611 
612 void NotificationCollector::notify(Protocol::ChangeNotificationList msgs)
613 {
614  if (auto mgr = mAkonadi.notificationManager()) {
615  QMetaObject::invokeMethod(mgr, "slotNotify", Qt::QueuedConnection,
616  Q_ARG(Akonadi::Protocol::ChangeNotificationList, msgs));
617  }
618 }
void addValueCondition(const QString &column, Query::CompareOperator op, const QVariant &value, ConditionType type=WhereCondition)
Add a WHERE or HAVING condition which compares a column with a given value.
void itemsRelationsChanged(const PimItem::List &items, const Relation::List &addedRelations, const Relation::List &removedRelations, const Collection &collection=Collection(), const QByteArray &resource=QByteArray())
Notify about changed items relations.
QHash::iterator insert(const Key &key, const T &value)
bool dispatchNotifications()
Trigger sending of collected notifications.
void collectionAdded(const Collection &collection, const QByteArray &resource=QByteArray())
Notify about a added collection.
void append(const T &value)
void push_back(const T &value)
void collectionChanged(const Collection &collection, const QList< QByteArray > &changes, const QByteArray &resource=QByteArray())
Notify about a changed collection.
void reserve(int alloc)
Resource resource() const
Retrieve the Resource record referred to by the resourceId column of this record. ...
void itemsFlagsChanged(const PimItem::List &items, const QSet< QByteArray > &addedFlags, const QSet< QByteArray > &removedFlags, const Collection &collection=Collection(), const QByteArray &resource=QByteArray())
Notify about changed items flags Provide as many parameters as you have at hand currently, everything that is missing will be looked up in the database later.
void itemsUnlinked(const PimItem::List &items, const Collection &collection)
Notify about unlinked items.
qint64 Id
Describes the unique id type.
Definition: collection.h:82
QMap::const_iterator constBegin() const const
void itemsLinked(const PimItem::List &items, const Collection &collection)
Notify about linked items.
void tagChanged(const Tag &tag)
Notify about a changed tag.
bool isEmpty() const const
qint64 rightId() const
Returns the value of the rightId column of this record.
Definition: entities.cpp:10637
void collectionMoved(const Collection &collection, const Collection &source, const QByteArray &resource=QByteArray(), const QByteArray &destResource=QByteArray())
Notify about a moved collection.
QVector< Collection > virtualCollections(const PimItem &item)
Returns all virtual collections the item is linked to.
Definition: datastore.cpp:1059
qint64 resourceId() const
Returns the value of the resourceId column of this record.
Definition: entities.cpp:1455
T & first()
QSet::iterator insert(const T &value)
qint64 parentId() const
Returns the value of the parentId column of this record.
Definition: entities.cpp:1442
void itemAdded(const PimItem &item, bool seen, const Collection &collection=Collection(), const QByteArray &resource=QByteArray())
Notify about an added item.
QString name() const
Returns the value of the name column of this record.
Definition: entities.cpp:3309
void itemsMoved(const PimItem::List &items, const Collection &collectionSrc=Collection(), const Collection &collectionDest=Collection(), const QByteArray &sourceResource=QByteArray())
Notify about moved items Provide as many parameters as you have at hand currently, everything that is missing will be looked up in the database later.
void transactionCommitted()
Emitted if a transaction has been successfully committed.
void addColumn(const QString &col)
Adds the given column to a select query.
void itemChanged(const PimItem &item, const QSet< QByteArray > &changedParts, const Collection &collection=Collection(), const QByteArray &resource=QByteArray())
Notify about a changed item.
void collectionUnsubscribed(const Collection &collection, const QByteArray &resource=QByteArray())
Notify about a collection unsubscription.
bool inTransaction() const
Returns true if there is a transaction in progress.
Definition: datastore.cpp:1498
qint64 leftId() const
Returns the value of the leftId column of this record.
Definition: entities.cpp:10624
RelationType relationType() const
Retrieve the RelationType record referred to by the typeId column of this record. ...
Definition: entities.cpp:10865
bool isEmpty() const const
QMap::const_iterator constEnd() const const
QVector< T > result()
Returns the result of this SELECT query.
QString gid() const
Returns the value of the gid column of this record.
Definition: entities.cpp:4022
static Protocol::FetchCollectionsResponse fetchCollectionsResponse(AkonadiServer &akonadi, const Collection &col)
Returns the protocol representation of the given collection.
QString remoteRevision() const
Returns the value of the remoteRevision column of this record.
Definition: entities.cpp:4009
void itemsTagsChanged(const PimItem::List &items, const QSet< qint64 > &addedTags, const QSet< qint64 > &removedTags, const Collection &collection=Collection(), const QByteArray &resource=QByteArray())
Notify about changed items tags.
void relationAdded(const Relation &relation)
Notify about an added relation.
void tagAdded(const Tag &tag)
Notify about an added tag.
const T value(const Key &key) const const
void reserve(int size)
void collectionRemoved(const Collection &collection, const QByteArray &resource=QByteArray())
Notify about a removed collection.
bool contains(const T &value) const const
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
bool contains(const T &value) const const
void relationRemoved(const Relation &relation)
Notify about a removed relation.
static DataStore * self()
Per thread singleton.
Definition: datastore.cpp:235
qint64 parentId() const
Returns the value of the parentId column of this record.
Definition: entities.cpp:8375
NotificationCollector(AkonadiServer &akonadi, DataStore *db)
Create a new notification collector for the given DataStore db.
Helper class for creating and executing database SELECT queries.
static Tag retrieveById(qint64 id)
Returns the record with id id.
Definition: entities.cpp:8535
void itemsRemoved(const PimItem::List &items, const Collection &collection=Collection(), const QByteArray &resource=QByteArray())
Notify about removed items.
QByteArray toLatin1() const const
Definition: item.h:44
void collectionSubscribed(const Collection &collection, const QByteArray &resource=QByteArray())
Notify about a collection subscription.
QString name() const
Returns the value of the name column of this record.
bool isEmpty() const const
Helper integration between Akonadi and Qt.
Representation of a record in the Tag table.
Definition: entities.h:2653
static Collection retrieveById(qint64 id)
Returns the record with id id.
Definition: entities.cpp:2037
int count(const T &value) const const
Representation of a record in the Relation table.
Definition: entities.h:3492
void setConnection(Connection *connection)
Sets the connection that is causing the changes.
QString name() const
Returns the value of the name column of this record.
Definition: entities.cpp:10064
bool enabled() const
Returns the value of the enabled column of this record.
void transactionRolledBack()
Emitted if a transaction has been aborted.
void push_back(const T &value)
void tagRemoved(const Tag &tag, const QByteArray &resource, const QString &remoteId)
Notify about a removed tag.
Represents a WHERE condition tree.
Definition: query.h:77
QString remoteId() const
Returns the value of the remoteId column of this record.
Definition: entities.cpp:3996
This class handles all the database access.
Definition: datastore.h:102
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int size() const const
QSharedPointer< X > staticCast() const const
QString name() const
Returns the value of the name column of this record.
Definition: entities.cpp:545
MimeType mimeType() const
Retrieve the MimeType record referred to by the mimeTypeId column of this record. ...
Definition: entities.cpp:4567
void addCondition(const Query::Condition &condition, ConditionType type=WhereCondition)
Add a WHERE condition.
Representation of a record in the PimItem table.
Definition: entities.h:1194
bool exec()
Executes the query, returns true on success.
An Connection represents one connection of a client to the server.
Definition: connection.h:53
void addValueCondition(const QString &column, CompareOperator op, const QVariant &value)
Add a WHERE condition which compares a column with a given value.
Definition: query.cpp:25
Representation of a record in the Collection table.
Definition: entities.h:451
qint64 size() const
Returns the value of the size column of this record.
Definition: entities.cpp:4100
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Tue May 26 2020 22:46:20 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.