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

KDE's Doxygen guidelines are available online.