Akonadi

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

KDE's Doxygen guidelines are available online.