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

KDE's Doxygen guidelines are available online.