Akonadi Calendar

calendarbase.cpp
1 /*
2  SPDX-FileCopyrightText: 2011 Sérgio Martins <[email protected]>
3  SPDX-FileCopyrightText: 2012 Sérgio Martins <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "calendarbase.h"
9 #include "calendarbase_p.h"
10 #include "incidencechanger.h"
11 #include "utils_p.h"
12 #include "akonadicalendar_debug.h"
13 #include <item.h>
14 #include <collectionfetchjob.h>
15 #include <collection.h>
16 
17 #include <KLocalizedString>
18 #include <QTimeZone>
19 
20 using namespace Akonadi;
21 using namespace KCalendarCore;
22 
23 static QString itemToString(const Akonadi::Item &item)
24 {
25  const KCalendarCore::Incidence::Ptr &incidence = CalendarUtils::incidence(item);
26  QString str;
27  QTextStream stream(&str);
28  stream << item.id()
29  << "; summary=" << incidence->summary() << "; uid=" << incidence->uid() << "; type="
30  << incidence->type() << "; recurs=" << incidence->recurs() << "; recurrenceId="
31  << incidence->recurrenceId().toString() << "; dtStart=" << incidence->dtStart().toString()
32  << "; dtEnd=" << incidence->dateTime(Incidence::RoleEnd).toString()
33  << "; parentCollection=" << item.storageCollectionId() << item.parentCollection().displayName();
34 
35  return str;
36 }
37 
38 CalendarBasePrivate::CalendarBasePrivate(CalendarBase *qq)
39  : QObject()
40  , mIncidenceChanger(new IncidenceChanger())
41  , mBatchInsertionCancelled(false)
42  , mListensForNewItems(false)
43  , mLastCreationCancelled(false)
44  , q(qq)
45 {
46  connect(mIncidenceChanger, &IncidenceChanger::createFinished,
47  this, &CalendarBasePrivate::slotCreateFinished);
48 
49  connect(mIncidenceChanger, &IncidenceChanger::deleteFinished,
50  this, &CalendarBasePrivate::slotDeleteFinished);
51 
52  connect(mIncidenceChanger, &IncidenceChanger::modifyFinished,
53  this, &CalendarBasePrivate::slotModifyFinished);
54 
55  mIncidenceChanger->setDestinationPolicy(IncidenceChanger::DestinationPolicyAsk);
56  mIncidenceChanger->setGroupwareCommunication(false);
57  mIncidenceChanger->setHistoryEnabled(false);
58 }
59 
60 CalendarBasePrivate::~CalendarBasePrivate()
61 {
62  delete mIncidenceChanger;
63  mIncidenceChanger = nullptr;
64 }
65 
66 void CalendarBasePrivate::internalInsert(const Akonadi::Item &item)
67 {
68  Q_ASSERT(item.isValid());
69  Q_ASSERT(item.hasPayload<KCalendarCore::Incidence::Ptr>());
70  KCalendarCore::Incidence::Ptr incidence = CalendarUtils::incidence(item);
71 
72  if (!incidence) {
73  qCritical() << "Incidence is null. id=" << item.id()
74  << "; hasPayload()=" << item.hasPayload()
75  << "; has incidence=" << item.hasPayload<KCalendarCore::Incidence::Ptr>()
76  << "; mime type=" << item.mimeType();
77  Q_ASSERT(false);
78  return;
79  }
80 
81  //qCDebug(AKONADICALENDAR_LOG) << "Inserting incidence in calendar. id=" << item.id() << "uid=" << incidence->uid();
82  const QString uid = incidence->instanceIdentifier();
83 
84  if (uid.isEmpty()) {
85  // This code path should never happen
86  qCritical() << "Incidence has empty UID. id=" << item.id()
87  << "; summary=" << incidence->summary()
88  << "Please fix it. Ignoring this incidence.";
89  return;
90  }
91 
92  if (mItemIdByUid.contains(uid) && mItemIdByUid[uid] != item.id()) {
93  // We only allow duplicate UIDs if they have the same item id, for example
94  // when using virtual folders.
95 #if 0
96  qCWarning(AKONADICALENDAR_LOG) << "Discarding duplicate incidence with instanceIdentifier=" << uid
97  << "and summary " << incidence->summary()
98  << "; recurrenceId() =" << incidence->recurrenceId()
99  << "; new id=" << item.id()
100  << "; existing id=" << mItemIdByUid[uid];
101 #endif
102  return;
103  }
104 
105  if (incidence->type() == KCalendarCore::Incidence::TypeEvent && !incidence->dtStart().isValid()) {
106  // TODO: make the parser discard them would also be a good idea
107  qCWarning(AKONADICALENDAR_LOG) << "Discarding event with invalid DTSTART. identifier="
108  << incidence->instanceIdentifier() << "; summary=" << incidence->summary();
109  return;
110  }
111 
112  Akonadi::Collection collection = item.parentCollection();
113  if (collection.isValid()) {
114  // Some items don't have collection set
115  if (item.storageCollectionId() != collection.id() && item.storageCollectionId() > -1) {
116  if (mCollections.contains(item.storageCollectionId())) {
117  collection = mCollections.value(item.storageCollectionId());
118  incidence->setReadOnly(!(collection.rights() & Akonadi::Collection::CanChangeItem));
119  } else if (!mCollectionJobs.key(item.storageCollectionId())) {
120  collection = Akonadi::Collection(item.storageCollectionId());
122  QObject::connect(job, &KJob::result, this, &CalendarBasePrivate::collectionFetchResult);
123  mCollectionJobs.insert(job, collection.id());
124  }
125  } else {
126  mCollections.insert(collection.id(), collection);
127  incidence->setReadOnly(!(collection.rights() & Akonadi::Collection::CanChangeItem));
128  }
129  }
130 
131  mItemById.insert(item.id(), item);
132  mItemIdByUid.insert(uid, item.id());
133  mItemsByCollection.insert(item.storageCollectionId(), item);
134 
135  if (!incidence->hasRecurrenceId()) {
136  // Insert parent relationships
137  const QString parentUid = incidence->relatedTo();
138  if (!parentUid.isEmpty()) {
139  mParentUidToChildrenUid[parentUid].append(incidence->uid());
140  mUidToParent.insert(uid, parentUid);
141  }
142  }
143 
144  incidence->setCustomProperty("VOLATILE", "AKONADI-ID", QString::number(item.id()));
145  // Must be the last one due to re-entrancy
146  const bool result = q->MemoryCalendar::addIncidence(incidence);
147  if (!result) {
148  qCritical() << "Error adding incidence " << itemToString(item);
149  Q_ASSERT(false);
150  }
151 }
152 
153 void CalendarBasePrivate::collectionFetchResult(KJob *job)
154 {
155  Akonadi::Collection::Id colid = mCollectionJobs.take(job);
156 
157  if (job->error()) {
158  qWarning() << "Error occurred: " << job->errorString();
159  return;
160  }
161 
162  Akonadi::CollectionFetchJob *fetchJob = qobject_cast<Akonadi::CollectionFetchJob *>(job);
163 
164  const Akonadi::Collection collection = fetchJob->collections().at(0);
165  if (collection.id() != colid) {
166  qCritical() << "Fetched the wrong collection, should fetch: " << colid << "fetched: " << collection.id();
167  }
168 
169  bool isReadOnly = !(collection.rights() & Akonadi::Collection::CanChangeItem);
170  const auto lst = mItemsByCollection.values(collection.id());
171  for (const Akonadi::Item &item : lst) {
172  KCalendarCore::Incidence::Ptr incidence = CalendarUtils::incidence(item);
173  incidence->setReadOnly(isReadOnly);
174  }
175 
176  mCollections.insert(collection.id(), collection);
177 
178  if (mCollectionJobs.isEmpty()) {
179  Q_EMIT fetchFinished();
180  }
181 }
182 
183 void CalendarBasePrivate::internalRemove(const Akonadi::Item &item)
184 {
185  Q_ASSERT(item.isValid());
186 
187  Incidence::Ptr tmp = CalendarUtils::incidence(item);
188  if (!tmp) {
189  qCritical() << "CalendarBase::internalRemove1: incidence is null, item.id=" << item.id();
190  return;
191  }
192 
193  // We want the one stored in the calendar
194  Incidence::Ptr incidence = q->incidence(tmp->uid(), tmp->recurrenceId());
195 
196  // Null incidence means it was deleted via CalendarBase::deleteIncidence(), but then
197  // the ETMCalendar received the monitor notification and tried to delete it again.
198  if (incidence) {
199  q->Calendar::notifyIncidenceAboutToBeDeleted(incidence);
200 
201  mItemById.remove(item.id());
202  // qCDebug(AKONADICALENDAR_LOG) << "Deleting incidence from calendar .id=" << item.id() << "uid=" << incidence->uid();
203  mItemIdByUid.remove(incidence->instanceIdentifier());
204 
205  mItemsByCollection.remove(item.storageCollectionId(), item);
206 
207  if (!incidence->hasRecurrenceId()) {
208  const QString uid = incidence->uid();
209  const QString parentUid = incidence->relatedTo();
210  mParentUidToChildrenUid.remove(uid);
211  if (!parentUid.isEmpty()) {
212  mParentUidToChildrenUid[parentUid].removeAll(uid);
213  mUidToParent.remove(uid);
214  }
215  }
216 
217  q->Calendar::setObserversEnabled(false);
218  // Must be the last one due to re-entrancy
219  const bool result = q->MemoryCalendar::deleteIncidence(incidence);
220  q->Calendar::setObserversEnabled(true);
221  q->Calendar::notifyIncidenceDeleted(incidence);
222  if (!result) {
223  qCritical() << "Error removing incidence " << itemToString(item);
224  Q_ASSERT(false);
225  }
226  } else {
227  qCWarning(AKONADICALENDAR_LOG) << "CalendarBase::internalRemove2: incidence is null, item.id=" << itemToString(item);
228  }
229 }
230 
231 void CalendarBasePrivate::slotDeleteFinished(int changeId, const QVector<Akonadi::Item::Id> &itemIds, IncidenceChanger::ResultCode resultCode, const QString &errorMessage)
232 {
233  Q_UNUSED(changeId);
234  if (resultCode == IncidenceChanger::ResultCodeSuccess) {
235  for (const Akonadi::Item::Id &id : itemIds) {
236  if (mItemById.contains(id)) {
237  internalRemove(mItemById.value(id));
238  }
239  }
240  }
241 
242  Q_EMIT q->deleteFinished(resultCode == IncidenceChanger::ResultCodeSuccess, errorMessage);
243 }
244 
245 void CalendarBasePrivate::slotCreateFinished(int changeId, const Akonadi::Item &item, IncidenceChanger::ResultCode resultCode, const QString &errorMessage)
246 {
247  Q_UNUSED(changeId);
248  Q_UNUSED(item);
249  if (resultCode == IncidenceChanger::ResultCodeSuccess && !mListensForNewItems) {
250  Q_ASSERT(item.isValid());
251  Q_ASSERT(item.hasPayload<KCalendarCore::Incidence::Ptr>());
252  internalInsert(item);
253  }
254 
255  mLastCreationCancelled = (resultCode == IncidenceChanger::ResultCodeUserCanceled);
256 
257  Q_EMIT q->createFinished(resultCode == IncidenceChanger::ResultCodeSuccess, errorMessage);
258 }
259 
260 void CalendarBasePrivate::slotModifyFinished(int changeId, const Akonadi::Item &item, IncidenceChanger::ResultCode resultCode, const QString &errorMessage)
261 {
262  Q_UNUSED(changeId);
263  Q_UNUSED(item);
264  QString message = errorMessage;
265  if (resultCode == IncidenceChanger::ResultCodeSuccess) {
266  KCalendarCore::Incidence::Ptr incidence = CalendarUtils::incidence(item);
267  Q_ASSERT(incidence);
268  KCalendarCore::Incidence::Ptr localIncidence = q->incidence(incidence->instanceIdentifier());
269 
270  if (localIncidence) {
271  //update our local one
272  *(static_cast<KCalendarCore::IncidenceBase *>(localIncidence.data())) = *(incidence.data());
273  } else {
274  // This shouldn't happen, unless the incidence gets deleted between event loops
275  qCWarning(AKONADICALENDAR_LOG) << "CalendarBasePrivate::slotModifyFinished() Incidence was deleted already probably? id=" << item.id();
276  message = i18n("Could not find incidence to update, it probably was deleted recently.");
277  resultCode = IncidenceChanger::ResultCodeAlreadyDeleted;
278  }
279  }
280  Q_EMIT q->modifyFinished(resultCode == IncidenceChanger::ResultCodeSuccess, message);
281 }
282 
283 void CalendarBasePrivate::handleUidChange(const Akonadi::Item &oldItem, const Akonadi::Item &newItem, const QString &newIdentifier)
284 {
285  Q_ASSERT(oldItem.isValid());
286  Incidence::Ptr newIncidence = CalendarUtils::incidence(newItem);
287  Q_ASSERT(newIncidence);
288  Incidence::Ptr oldIncidence = CalendarUtils::incidence(oldItem);
289  Q_ASSERT(oldIncidence);
290 
291  const QString newUid = newIncidence->uid();
292  if (mItemIdByUid.contains(newIdentifier)) {
293  Incidence::Ptr oldIncidence = CalendarUtils::incidence(oldItem);
294 #if 0
295  qCWarning(AKONADICALENDAR_LOG) << "New uid shouldn't be known: " << newIdentifier << "; id="
296  << newItem.id() << "; oldItem.id=" << mItemIdByUid[newIdentifier]
297  << "; new summary= " << newIncidence->summary()
298  << "; new recurrenceId=" << newIncidence->recurrenceId()
299  << "; oldIncidence" << oldIncidence;
300 #endif
301  if (oldIncidence) {
302 #if 0
303  qCWarning(AKONADICALENDAR_LOG) << "; oldIncidence uid=" << oldIncidence->uid()
304  << "; oldIncidence recurrenceId = " << oldIncidence->recurrenceId()
305  << "; oldIncidence summary = " << oldIncidence->summary();
306 #endif
307  }
308  Q_ASSERT(false);
309  return;
310  }
311 
312  mItemIdByUid[newIdentifier] = newItem.id();
313 
314  // Get the real pointer
315  oldIncidence = q->MemoryCalendar::incidence(oldIncidence->uid());
316 
317  if (!oldIncidence) {
318  // How can this happen ?
319  qCWarning(AKONADICALENDAR_LOG) << "Couldn't find old incidence";
320  Q_ASSERT(false);
321  return;
322  }
323 
324  if (newIncidence->instanceIdentifier() == oldIncidence->instanceIdentifier()) {
325 #if 0
326  qCWarning(AKONADICALENDAR_LOG) << "New uid=" << newIncidence->uid() << "; old uid=" << oldIncidence->uid()
327  << "; new recurrenceId="
328  << newIncidence->recurrenceId()
329  << "; old recurrenceId=" << oldIncidence->recurrenceId()
330  << "; new summary = " << newIncidence->summary()
331  << "; old summary = " << oldIncidence->summary()
332  << "; id = " << newItem.id();
333 #endif
334  Q_ASSERT(false); // The reason we're here in the first place
335  return;
336  }
337 
338  mItemIdByUid.remove(oldIncidence->instanceIdentifier());
339  const QString oldUid = oldIncidence->uid();
340 
341  if (mParentUidToChildrenUid.contains(oldUid)) {
342  Q_ASSERT(!mParentUidToChildrenUid.contains(newIdentifier));
343  QStringList children = mParentUidToChildrenUid.value(oldUid);
344  mParentUidToChildrenUid.insert(newIdentifier, children);
345  mParentUidToChildrenUid.remove(oldUid);
346  }
347 
348  // Update internal maps of the base class, MemoryCalendar
349  q->setObserversEnabled(false);
350  q->MemoryCalendar::deleteIncidence(oldIncidence);
351  q->MemoryCalendar::addIncidence(newIncidence);
352 
353  newIncidence->setUid(oldUid); // We set and unset just to notify observers of a change.
354  q->setObserversEnabled(true);
355  newIncidence->setUid(newUid);
356 }
357 
358 void CalendarBasePrivate::handleParentChanged(const KCalendarCore::Incidence::Ptr &newIncidence)
359 {
360  Q_ASSERT(newIncidence);
361 
362  if (newIncidence->hasRecurrenceId()) { // These ones don't/shouldn't have a parent
363  return;
364  }
365 
366  const QString originalParentUid = mUidToParent.value(newIncidence->uid());
367  const QString newParentUid = newIncidence->relatedTo();
368 
369  if (originalParentUid == newParentUid) {
370  return; // nothing changed
371  }
372 
373  if (!originalParentUid.isEmpty()) {
374  // Remove this child from it's old parent:
375  Q_ASSERT(mParentUidToChildrenUid.contains(originalParentUid));
376  mParentUidToChildrenUid[originalParentUid].removeAll(newIncidence->uid());
377  }
378 
379  mUidToParent.remove(newIncidence->uid());
380 
381  if (!newParentUid.isEmpty()) {
382  // Deliver this child to it's new parent:
383  Q_ASSERT(!mParentUidToChildrenUid[newParentUid].contains(newIncidence->uid()));
384  mParentUidToChildrenUid[newParentUid].append(newIncidence->uid());
385  mUidToParent.insert(newIncidence->uid(), newParentUid);
386  }
387 }
388 
390  : MemoryCalendar(QTimeZone::systemTimeZone())
391  , d_ptr(new CalendarBasePrivate(this))
392 {
393  setParent(parent);
394  setDeletionTracking(false);
395 }
396 
397 CalendarBase::CalendarBase(CalendarBasePrivate *const dd, QObject *parent)
399  , d_ptr(dd)
400 {
401  setParent(parent);
402  setDeletionTracking(false);
403 }
404 
406 {
407 }
408 
409 Akonadi::Item CalendarBase::item(Akonadi::Item::Id id) const
410 {
411  Q_D(const CalendarBase);
412  Akonadi::Item i;
413  auto it = d->mItemById.constFind(id);
414  if (it != d->mItemById.cend()) {
415  i = *it;
416  } else {
417  qCDebug(AKONADICALENDAR_LOG) << "Can't find any item with id " << id;
418  }
419  return i;
420 }
421 
422 Akonadi::Item CalendarBase::item(const QString &uid) const
423 {
424  Q_D(const CalendarBase);
425  Akonadi::Item i;
426 
427  if (uid.isEmpty()) {
428  return i;
429  }
430 
431  auto it = d->mItemIdByUid.constFind(uid);
432  if (it != d->mItemIdByUid.cend()) {
433  const Akonadi::Item::Id id = *it;
434  auto it2 = d->mItemById.constFind(id);
435  if (it2 == d->mItemById.cend()) {
436  qCritical() << "Item with id " << id << "(uid=" << uid << ") not found, but in uid map";
437  Q_ASSERT_X(false, "CalendarBase::item", "not in mItemById");
438  } else {
439  i = *it2;
440  }
441  } else {
442  qCDebug(AKONADICALENDAR_LOG) << "Can't find any incidence with uid " << uid;
443  }
444  return i;
445 }
446 
447 Item CalendarBase::item(const Incidence::Ptr &incidence) const
448 {
449  return incidence ? item(incidence->instanceIdentifier()) : Item();
450 }
451 
452 Akonadi::Item::List CalendarBase::items(Akonadi::Collection::Id id) const
453 {
454  Q_D(const CalendarBase);
455 
456  Akonadi::Item::List result;
457  if (id == -1) {
458  result.reserve(d->mItemsByCollection.size());
459  }
460 
461  auto it = id == -1 ? d->mItemsByCollection.cbegin() : d->mItemsByCollection.constFind(id);
462  while (it != d->mItemsByCollection.cend() && (id == -1 || it.key() == id)) {
463  result.push_back(*it);
464  ++it;
465  }
466 
467  return result;
468 }
469 
471 {
472  Akonadi::Item::List items;
473  items.reserve(incidences.size());
474 
475  for (const KCalendarCore::Incidence::Ptr &incidence : incidences) {
476  if (incidence) {
477  items << item(incidence->instanceIdentifier());
478  } else {
479  items << Akonadi::Item();
480  }
481  }
482 
483  return items;
484 }
485 
486 KCalendarCore::Incidence::List CalendarBase::childIncidences(Akonadi::Item::Id parentId) const
487 {
488  Q_D(const CalendarBase);
490 
491  if (d->mItemById.contains(parentId)) {
492  const Akonadi::Item item = d->mItemById.value(parentId);
493  Q_ASSERT(item.isValid());
494  KCalendarCore::Incidence::Ptr parent = CalendarUtils::incidence(item);
495 
496  if (parent) {
497  childs = childIncidences(parent->uid());
498  } else {
499  Q_ASSERT(false);
500  }
501  }
502 
503  return childs;
504 }
505 
507 {
508  Q_D(const CalendarBase);
510  const QStringList uids = d->mParentUidToChildrenUid.value(parentUid);
511  for (const QString &uid : uids) {
512  Incidence::Ptr child = incidence(uid);
513  if (child) {
514  children.append(child);
515  } else {
516  qCWarning(AKONADICALENDAR_LOG) << "Invalid child with uid " << uid;
517  }
518  }
519  return children;
520 }
521 
522 Akonadi::Item::List CalendarBase::childItems(Akonadi::Item::Id parentId) const
523 {
524  Q_D(const CalendarBase);
525  Akonadi::Item::List childs;
526 
527  if (d->mItemById.contains(parentId)) {
528  const Akonadi::Item item = d->mItemById.value(parentId);
529  Q_ASSERT(item.isValid());
530  KCalendarCore::Incidence::Ptr parent = CalendarUtils::incidence(item);
531 
532  if (parent) {
533  childs = childItems(parent->uid());
534  } else {
535  Q_ASSERT(false);
536  }
537  }
538 
539  return childs;
540 }
541 
542 Akonadi::Item::List CalendarBase::childItems(const QString &parentUid) const
543 {
544  Q_D(const CalendarBase);
545  Akonadi::Item::List children;
546  const QStringList uids = d->mParentUidToChildrenUid.value(parentUid);
547  for (const QString &uid : uids) {
548  Akonadi::Item child = item(uid);
549  if (child.isValid() && child.hasPayload<KCalendarCore::Incidence::Ptr>()) {
550  children.append(child);
551  } else {
552  qCWarning(AKONADICALENDAR_LOG) << "Invalid child with uid " << uid;
553  }
554  }
555  return children;
556 }
557 
559 {
560  return addIncidence(event);
561 }
562 
564 {
565  return deleteIncidence(event);
566 }
567 
569 {
570  return addIncidence(todo);
571 }
572 
574 {
575  return deleteIncidence(todo);
576 }
577 
579 {
580  return addIncidence(journal);
581 }
582 
584 {
585  return deleteIncidence(journal);
586 }
587 
589 {
590  //TODO: Parent for dialogs
591  Q_D(CalendarBase);
592 
593  // User canceled on the collection selection dialog
594  if (batchAdding() && d->mBatchInsertionCancelled) {
595  return false;
596  }
597 
598  d->mLastCreationCancelled = false;
599 
600  Akonadi::Collection collection;
601 
602  if (batchAdding() && d->mCollectionForBatchInsertion.isValid()) {
603  collection = d->mCollectionForBatchInsertion;
604  }
605 
606  if (incidence->hasRecurrenceId() && !collection.isValid()) {
607  // We are creating an exception, reuse the same collection that the main incidence uses
608  Item mainItem = item(incidence->uid());
609  if (mainItem.isValid()) {
610  collection = Collection(mainItem.storageCollectionId());
611  }
612  }
613 
614  const int changeId = d->mIncidenceChanger->createIncidence(incidence, collection);
615 
616  if (batchAdding()) {
617  const Akonadi::Collection lastCollection = d->mIncidenceChanger->lastCollectionUsed();
618  if (changeId != -1 && !lastCollection.isValid()) {
619  d->mBatchInsertionCancelled = true;
620  } else if (lastCollection.isValid() && !d->mCollectionForBatchInsertion.isValid()) {
621  d->mCollectionForBatchInsertion = d->mIncidenceChanger->lastCollectionUsed();
622  }
623  }
624 
625  return changeId != -1;
626 }
627 
629 {
630  Q_D(CalendarBase);
631  Q_ASSERT(incidence);
632  Akonadi::Item item_ = item(incidence->instanceIdentifier());
633  return -1 != d->mIncidenceChanger->deleteIncidence(item_);
634 }
635 
637 {
638  Q_D(CalendarBase);
639  Q_ASSERT(newIncidence);
640  Akonadi::Item item_ = item(newIncidence->instanceIdentifier());
641  item_.setPayload<KCalendarCore::Incidence::Ptr>(newIncidence);
642  return -1 != d->mIncidenceChanger->modifyIncidence(item_);
643 }
644 
645 IncidenceChanger *CalendarBase::incidenceChanger() const
646 {
647  Q_D(const CalendarBase);
648  return d->mIncidenceChanger;
649 }
650 
652 {
654 }
655 
657 {
658  Q_D(CalendarBase);
659  d->mCollectionForBatchInsertion = Akonadi::Collection();
660  d->mBatchInsertionCancelled = false;
662 }
663 
665 {
666  return true;
667 }
668 
669 #include "moc_calendarbase.cpp"
670 #include "moc_calendarbase_p.cpp"
KCOREADDONS_EXPORT void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
Collection::List collections() const
bool isValid() const
void append(const T &value)
Akonadi::Item::List itemList(const KCalendarCore::Incidence::List &incidenceList) const
Returns the item list that corresponds to the incidenceList.
virtual QString errorString() const
virtual bool isLoaded() const
Returns if the calendar already finished loading.
const QObjectList & children() const const
Akonadi::Item item(const QString &uid) const
Returns the Item containing the incidence with uid uid or an invalid Item if the incidence isn&#39;t foun...
bool addEvent(const KCalendarCore::Event::Ptr &event) override
Adds an Event to the calendar.
Akonadi::Item::List items(Akonadi::Collection::Id=-1) const
Returns the list of items contained in this calendar that belong to the specified collection...
bool deleteTodo(const KCalendarCore::Todo::Ptr &todo) override
Deletes a Todo from the calendar.
bool deleteEvent(const KCalendarCore::Event::Ptr &event) override
Deletes an Event from the calendar.
T * data() const const
Todo::Ptr todo(const QString &uid, const QDateTime &recurrenceId={}) const override
bool addIncidence(const KCalendarCore::Incidence::Ptr &incidence) override
Adds an incidence to the calendar.
bool modifyIncidence(const KCalendarCore::Incidence::Ptr &newIncidence)
Modifies an incidence.
T value(int i) const const
T value(int i) const const
QString number(int n, int base)
void setDeletionTracking(bool enable)
MemoryCalendar(const QTimeZone &timeZone)
bool isEmpty() const const
Journal::Ptr journal(const QString &uid, const QDateTime &recurrenceId={}) const override
QTimeZone systemTimeZone()
Event::Ptr event(const QString &uid, const QDateTime &recurrenceId={}) const override
Collection parentCollection() const
KCalendarCore::Incidence::List childIncidences(const QString &parentUid) const
Returns the child incidences of the parent identified by parentUid.
Rights rights() const
virtual void endBatchAdding()
void setParent(QObject *parent)
bool addJournal(const KCalendarCore::Journal::Ptr &journal) override
Adds a Journal to the calendar.
~CalendarBase() override
Destroys the calendar.
Akonadi::Item::List childItems(const QString &parentUid) const
Returns the child items of the parent identified by parentUid.
QString i18n(const char *text, const TYPE &arg...)
virtual void startBatchAdding()
const T & at(int i) const const
bool batchAdding() const
bool addTodo(const KCalendarCore::Todo::Ptr &todo) override
Adds a Todo to the calendar.
FreeBusyManager::Singleton.
Akonadi::IncidenceChanger * incidenceChanger() const
Returns the IncidenceChanger used by this calendar to make changes in akonadi.
Incidence::Ptr incidence(const QString &uid, const QDateTime &recurrenceId={}) const
void endBatchAdding() override
Tells the Calendar that you stoped adding a batch of incidences.
void startBatchAdding() override
Call this to tell the calendar that you&#39;re adding a batch of incidences.
bool deleteJournal(const KCalendarCore::Journal::Ptr &journal) override
Deletes a Journal from the calendar.
void result(KJob *job)
The base class for all akonadi aware calendars.
Definition: calendarbase.h:35
bool deleteIncidence(const KCalendarCore::Incidence::Ptr &incidence) override
Deletes an incidence from the calendar.
CalendarBase(QObject *parent=nullptr)
Constructs a CalendarBase object.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
int size() const const
virtual Incidence::List incidences() const
int error() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Jul 1 2020 23:08:51 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.