Akonadi Calendar

calendarbase.cpp
1/*
2 SPDX-FileCopyrightText: 2011 Sérgio Martins <sergio.martins@kdab.com>
3 SPDX-FileCopyrightText: 2012 Sérgio Martins <iamsergio@gmail.com>
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 "calendarutils.h"
12#include "incidencechanger.h"
13#include <Akonadi/CollectionFetchJob>
14
15#include <KLocalizedString>
16#include <QTimeZone>
17
18using namespace Akonadi;
19using namespace KCalendarCore;
20
21static QString itemToString(const Akonadi::Item &item)
22{
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
34CalendarBasePrivate::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
50CalendarBasePrivate::~CalendarBasePrivate()
51{
52 delete mIncidenceChanger;
53}
54
55void CalendarBasePrivate::internalInsert(const Akonadi::Item &item)
56{
57 Q_ASSERT(item.isValid());
60
61 if (!incidence) {
62 qCritical() << "Incidence is null. id=" << item.id() << "; hasPayload()=" << item.hasPayload()
63 << "; has incidence=" << item.hasPayload<KCalendarCore::Incidence::Ptr>() << "; mime type=" << item.mimeType();
64 Q_ASSERT(false);
65 return;
66 }
67
68 // qCDebug(AKONADICALENDAR_LOG) << "Inserting incidence in calendar. id=" << item.id() << "uid=" << incidence->uid();
69 const QString uid = incidence->instanceIdentifier();
70
71 if (uid.isEmpty()) {
72 // This code path should never happen
73 qCritical() << "Incidence has empty UID. id=" << item.id() << "; summary=" << incidence->summary() << "Please fix it. Ignoring this incidence.";
74 return;
75 }
76
77 if (mItemIdByUid.contains(uid) && mItemIdByUid[uid] != item.id()) {
78 // We only allow duplicate UIDs if they have the same item id, for example
79 // when using virtual folders.
80#if 0
81 qCWarning(AKONADICALENDAR_LOG) << "Discarding duplicate incidence with instanceIdentifier=" << uid
82 << "and summary " << incidence->summary()
83 << "; recurrenceId() =" << incidence->recurrenceId()
84 << "; new id=" << item.id()
85 << "; existing id=" << mItemIdByUid[uid];
86#endif
87 return;
88 }
89
90 if (incidence->type() == KCalendarCore::Incidence::TypeEvent && !incidence->dtStart().isValid()) {
91 // TODO: make the parser discard them would also be a good idea
92 qCWarning(AKONADICALENDAR_LOG) << "Discarding event with invalid DTSTART. identifier=" << incidence->instanceIdentifier()
93 << "; summary=" << incidence->summary();
94 return;
95 }
96
97 Akonadi::Collection collection = item.parentCollection();
98 if (collection.isValid()) {
99 // Some items don't have collection set
100 if (item.storageCollectionId() != collection.id() && item.storageCollectionId() > -1) {
101 if (mCollections.contains(item.storageCollectionId())) {
102 collection = mCollections.value(item.storageCollectionId());
103 incidence->setReadOnly(!(collection.rights() & Akonadi::Collection::CanChangeItem));
104 } else if (!mCollectionJobs.key(item.storageCollectionId())) {
105 collection = Akonadi::Collection(item.storageCollectionId());
106 auto job = new Akonadi::CollectionFetchJob(collection, Akonadi::CollectionFetchJob::Base, this);
107 QObject::connect(job, &KJob::result, this, &CalendarBasePrivate::collectionFetchResult);
108 mCollectionJobs.insert(job, collection.id());
109 }
110 } else {
111 mCollections.insert(collection.id(), collection);
112 incidence->setReadOnly(!(collection.rights() & Akonadi::Collection::CanChangeItem));
113 }
114 }
115
116 mItemById.insert(item.id(), item);
117 mItemIdByUid.insert(uid, item.id());
118 mItemsByCollection.insert(item.storageCollectionId(), item);
119
120 if (!incidence->hasRecurrenceId()) {
121 // Insert parent relationships
122 const QString parentUid = incidence->relatedTo();
123 if (!parentUid.isEmpty()) {
124 mParentUidToChildrenUid[parentUid].append(incidence->uid());
125 mUidToParent.insert(uid, parentUid);
126 }
127 }
128
129 incidence->setCustomProperty("VOLATILE", "AKONADI-ID", QString::number(item.id()));
130 incidence->setCustomProperty("VOLATILE", "COLLECTION-ID", QString::number(item.storageCollectionId()));
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
139void 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) {
159 incidence->setReadOnly(isReadOnly);
160 }
161
162 mCollections.insert(collection.id(), collection);
163
164 if (mCollectionJobs.isEmpty()) {
165 Q_EMIT fetchFinished();
166 }
167}
168
169void CalendarBasePrivate::internalRemove(const Akonadi::Item &item)
170{
171 Q_ASSERT(item.isValid());
172
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
217void CalendarBasePrivate::slotDeleteFinished(int changeId,
218 const QList<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
234void 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());
241 internalInsert(item);
242 }
243
244 mLastCreationCancelled = (resultCode == IncidenceChanger::ResultCodeUserCanceled);
245
246 Q_EMIT q->createFinished(resultCode == IncidenceChanger::ResultCodeSuccess, errorMessage);
247}
248
249void 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) {
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
272void 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 Incidence::Ptr oldIncidence = CalendarUtils::incidence(oldItem);
283#if 0
284 qCWarning(AKONADICALENDAR_LOG) << "New uid shouldn't be known: " << newIdentifier << "; id="
285 << newItem.id() << "; oldItem.id=" << mItemIdByUid[newIdentifier]
286 << "; new summary= " << newIncidence->summary()
287 << "; new recurrenceId=" << newIncidence->recurrenceId()
288 << "; oldIncidence" << oldIncidence;
289#endif
290 if (oldIncidence) {
291#if 0
292 qCWarning(AKONADICALENDAR_LOG) << "; oldIncidence uid=" << oldIncidence->uid()
293 << "; oldIncidence recurrenceId = " << oldIncidence->recurrenceId()
294 << "; oldIncidence summary = " << oldIncidence->summary();
295#endif
296 }
297 Q_ASSERT(false);
298 return;
299 }
300
301 mItemIdByUid[newIdentifier] = newItem.id();
302
303 // Get the real pointer
304 oldIncidence = q->MemoryCalendar::incidence(oldIncidence->uid());
305
306 if (!oldIncidence) {
307 // How can this happen ?
308 qCWarning(AKONADICALENDAR_LOG) << "Couldn't find old incidence";
309 Q_ASSERT(false);
310 return;
311 }
312
313 if (newIncidence->instanceIdentifier() == oldIncidence->instanceIdentifier()) {
314#if 0
315 qCWarning(AKONADICALENDAR_LOG) << "New uid=" << newIncidence->uid() << "; old uid=" << oldIncidence->uid()
316 << "; new recurrenceId="
317 << newIncidence->recurrenceId()
318 << "; old recurrenceId=" << oldIncidence->recurrenceId()
319 << "; new summary = " << newIncidence->summary()
320 << "; old summary = " << oldIncidence->summary()
321 << "; id = " << newItem.id();
322#endif
323 Q_ASSERT(false); // The reason we're here in the first place
324 return;
325 }
326
327 mItemIdByUid.remove(oldIncidence->instanceIdentifier());
328 const QString oldUid = oldIncidence->uid();
329
330 if (mParentUidToChildrenUid.contains(oldUid)) {
331 Q_ASSERT(!mParentUidToChildrenUid.contains(newIdentifier));
332 QStringList children = mParentUidToChildrenUid.value(oldUid);
333 mParentUidToChildrenUid.insert(newIdentifier, children);
334 mParentUidToChildrenUid.remove(oldUid);
335 }
336
337 // Update internal maps of the base class, MemoryCalendar
338 q->setObserversEnabled(false);
339 q->MemoryCalendar::deleteIncidence(oldIncidence);
340 q->MemoryCalendar::addIncidence(newIncidence);
341
342 newIncidence->setUid(oldUid); // We set and unset just to notify observers of a change.
343 q->setObserversEnabled(true);
344 newIncidence->setUid(newUid);
345}
346
347void CalendarBasePrivate::handleParentChanged(const KCalendarCore::Incidence::Ptr &newIncidence)
348{
349 Q_ASSERT(newIncidence);
350
351 if (newIncidence->hasRecurrenceId()) { // These ones don't/shouldn't have a parent
352 return;
353 }
354
355 const QString originalParentUid = mUidToParent.value(newIncidence->uid());
356 const QString newParentUid = newIncidence->relatedTo();
357
358 if (originalParentUid == newParentUid) {
359 return; // nothing changed
360 }
361
362 if (!originalParentUid.isEmpty()) {
363 // Remove this child from it's old parent:
364 Q_ASSERT(mParentUidToChildrenUid.contains(originalParentUid));
365 mParentUidToChildrenUid[originalParentUid].removeAll(newIncidence->uid());
366 }
367
368 mUidToParent.remove(newIncidence->uid());
369
370 if (!newParentUid.isEmpty()) {
371 // Deliver this child to it's new parent:
372 Q_ASSERT(!mParentUidToChildrenUid[newParentUid].contains(newIncidence->uid()));
373 mParentUidToChildrenUid[newParentUid].append(newIncidence->uid());
374 mUidToParent.insert(newIncidence->uid(), newParentUid);
375 }
376}
377
379 : MemoryCalendar(QTimeZone::systemTimeZone())
380 , d_ptr(new CalendarBasePrivate(this))
381{
383}
384
385CalendarBase::CalendarBase(CalendarBasePrivate *const dd, QObject *parent)
386 : MemoryCalendar(QTimeZone::systemTimeZone())
387 , d_ptr(dd)
388{
390}
391
393
395{
396 Q_D(const CalendarBase);
398 auto it = d->mItemById.constFind(id);
399 if (it != d->mItemById.cend()) {
400 i = *it;
401 } else {
402 qCDebug(AKONADICALENDAR_LOG) << "Can't find any item with id " << id;
403 }
404 return i;
405}
406
408{
409 Q_D(const CalendarBase);
411
412 if (uid.isEmpty()) {
413 return i;
414 }
415
416 auto it = d->mItemIdByUid.constFind(uid);
417 if (it != d->mItemIdByUid.cend()) {
418 const Akonadi::Item::Id id = *it;
419 auto it2 = d->mItemById.constFind(id);
420 if (it2 == d->mItemById.cend()) {
421 qCritical() << "Item with id " << id << "(uid=" << uid << ") not found, but in uid map";
422 Q_ASSERT_X(false, "CalendarBase::item", "not in mItemById");
423 } else {
424 i = *it2;
425 }
426 } else {
427 qCDebug(AKONADICALENDAR_LOG) << "Can't find any incidence with uid " << uid;
428 }
429 return i;
430}
431
433{
434 return incidence ? item(incidence->instanceIdentifier()) : Item();
435}
436
438{
439 Q_D(const CalendarBase);
440
441 Akonadi::Item::List result;
442 if (id == -1) {
443 result.reserve(d->mItemsByCollection.size());
444 }
445
446 auto it = id == -1 ? d->mItemsByCollection.cbegin() : d->mItemsByCollection.constFind(id);
447 while (it != d->mItemsByCollection.cend() && (id == -1 || it.key() == id)) {
448 result.push_back(*it);
449 ++it;
450 }
451
452 return result;
453}
454
456{
459
461 if (incidence) {
462 items << item(incidence->instanceIdentifier());
463 } else {
464 items << Akonadi::Item();
465 }
466 }
467
468 return items;
469}
470
472{
473 Q_D(const CalendarBase);
475
476 if (d->mItemById.contains(parentId)) {
477 const Akonadi::Item item = d->mItemById.value(parentId);
478 Q_ASSERT(item.isValid());
480
481 if (parent) {
483 } else {
484 Q_ASSERT(false);
485 }
486 }
487
488 return children;
489}
490
492{
493 Q_D(const CalendarBase);
495 const QStringList uids = d->mParentUidToChildrenUid.value(parentUid);
496 for (const QString &uid : uids) {
497 Incidence::Ptr child = incidence(uid);
498 if (child) {
499 children.append(child);
500 } else {
501 qCWarning(AKONADICALENDAR_LOG) << "Invalid child with uid " << uid;
502 }
503 }
504 return children;
505}
506
508{
509 Q_D(const CalendarBase);
511
512 if (d->mItemById.contains(parentId)) {
513 const Akonadi::Item item = d->mItemById.value(parentId);
514 Q_ASSERT(item.isValid());
516
517 if (parent) {
518 children = childItems(parent->uid());
519 } else {
520 Q_ASSERT(false);
521 }
522 }
523
524 return children;
525}
526
528{
529 Q_D(const CalendarBase);
531 const QStringList uids = d->mParentUidToChildrenUid.value(parentUid);
532 for (const QString &uid : uids) {
533 Akonadi::Item child = item(uid);
534 if (child.isValid() && child.hasPayload<KCalendarCore::Incidence::Ptr>()) {
535 children.append(child);
536 } else {
537 qCWarning(AKONADICALENDAR_LOG) << "Invalid child with uid " << uid;
538 }
539 }
540 return children;
541}
542
544{
545 return addIncidence(event);
546}
547
552
554{
555 return addIncidence(todo);
556}
557
562
567
572
574{
575 // TODO: Parent for dialogs
577
578 // User canceled on the collection selection dialog
579 if (batchAdding() && d->mBatchInsertionCancelled) {
580 return false;
581 }
582
583 d->mLastCreationCancelled = false;
584
585 Akonadi::Collection collection;
586
587 if (batchAdding() && d->mCollectionForBatchInsertion.isValid()) {
588 collection = d->mCollectionForBatchInsertion;
589 }
590
591 if (incidence->hasRecurrenceId() && !collection.isValid()) {
592 // We are creating an exception, reuse the same collection that the main incidence uses
593 Item mainItem = item(incidence->uid());
594 if (mainItem.isValid()) {
595 collection = Collection(mainItem.storageCollectionId());
596 }
597 }
598
599 const int changeId = d->mIncidenceChanger->createIncidence(incidence, collection);
600
601 if (batchAdding()) {
602 const Akonadi::Collection lastCollection = d->mIncidenceChanger->lastCollectionUsed();
603 if (changeId != -1 && !lastCollection.isValid()) {
604 d->mBatchInsertionCancelled = true;
605 } else if (lastCollection.isValid() && !d->mCollectionForBatchInsertion.isValid()) {
606 d->mCollectionForBatchInsertion = d->mIncidenceChanger->lastCollectionUsed();
607 }
608 }
609
610 return changeId != -1;
611}
612
614{
616 Q_ASSERT(incidence);
617 if (!incidence->hasRecurrenceId() && incidence->recurs()) {
619 }
620 Akonadi::Item item_ = item(incidence->instanceIdentifier());
621 return -1 != d->mIncidenceChanger->deleteIncidence(item_);
622}
623
625{
627 Q_ASSERT(newIncidence);
628 Akonadi::Item item_ = item(newIncidence->instanceIdentifier());
629 item_.setPayload<KCalendarCore::Incidence::Ptr>(newIncidence);
630 return -1 != d->mIncidenceChanger->modifyIncidence(item_);
631}
632
633IncidenceChanger *CalendarBase::incidenceChanger() const
634{
635 Q_D(const CalendarBase);
636 return d->mIncidenceChanger;
637}
638
643
645{
647 d->mCollectionForBatchInsertion = Akonadi::Collection();
648 d->mBatchInsertionCancelled = false;
650}
651
652#include "moc_calendarbase.cpp"
653#include "moc_calendarbase_p.cpp"
The base class for all akonadi aware calendars.
bool addEvent(const KCalendarCore::Event::Ptr &event) override
Adds an Event to the calendar.
bool deleteEvent(const KCalendarCore::Event::Ptr &event) override
Deletes an Event from the calendar.
~CalendarBase() override
Destroys the calendar.
Akonadi::IncidenceChanger * incidenceChanger() const
Returns the IncidenceChanger used by this calendar to make changes in akonadi.
bool addTodo(const KCalendarCore::Todo::Ptr &todo) override
Adds a Todo to the calendar.
CalendarBase(QObject *parent=nullptr)
Constructs a CalendarBase object.
bool addJournal(const KCalendarCore::Journal::Ptr &journal) override
Adds a Journal to the calendar.
void endBatchAdding() override
Tells the Calendar that you stopped adding a batch of incidences.
KCalendarCore::Incidence::List childIncidences(const QString &parentUid) const
Returns the child incidences of the parent identified by parentUid.
bool addIncidence(const KCalendarCore::Incidence::Ptr &incidence) override
Adds an incidence to the calendar.
bool deleteIncidence(const KCalendarCore::Incidence::Ptr &incidence) override
Deletes an incidence from the calendar.
bool modifyIncidence(const KCalendarCore::Incidence::Ptr &newIncidence)
Modifies an incidence.
bool deleteTodo(const KCalendarCore::Todo::Ptr &todo) override
Deletes a Todo from the calendar.
Akonadi::Item::List childItems(const QString &parentUid) const
Returns the child items of the parent identified by parentUid.
Akonadi::Item::List itemList(const KCalendarCore::Incidence::List &incidenceList) const
Returns the item list that corresponds to the incidenceList.
Akonadi::Item::List items(Akonadi::Collection::Id=-1) const
Returns the list of items contained in this calendar that belong to the specified collection.
Akonadi::Item item(const QString &uid) const
Returns the Item containing the incidence with uid uid or an invalid Item if the incidence isn't foun...
bool deleteJournal(const KCalendarCore::Journal::Ptr &journal) override
Deletes a Journal from the calendar.
void startBatchAdding() override
Call this to tell the calendar that you're adding a batch of incidences.
bool isValid() const
QString displayName() const
Rights rights() const
void setPayload(const T &p)
QString mimeType() const
Collection & parentCollection()
bool hasPayload() const
Id id() const
Collection::Id storageCollectionId() const
bool isValid() const
Incidence::Ptr incidence(const QString &uid, const QDateTime &recurrenceId={}) const
virtual Incidence::List incidences() const
virtual void startBatchAdding()
bool batchAdding() const
QString id() const
virtual void endBatchAdding()
bool deleteIncidenceInstances(const Incidence::Ptr &incidence) override
Todo::Ptr todo(const QString &uid, const QDateTime &recurrenceId={}) const override
Event::Ptr event(const QString &uid, const QDateTime &recurrenceId={}) const override
Journal::Ptr journal(const QString &uid, const QDateTime &recurrenceId={}) const override
virtual QString errorString() const
int error() const
void result(KJob *job)
QString i18n(const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Incidence::Ptr incidence(const Akonadi::Item &item)
Returns the incidence from an Akonadi item, or a null pointer if the item has no such payload.
FreeBusyManager::Singleton.
KCALUTILS_EXPORT QString errorMessage(const KCalendarCore::Exception &exception)
void push_back(parameter_type value)
void reserve(qsizetype size)
qsizetype size() const const
T value(qsizetype i) const const
const QObjectList & children() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
void setParent(QObject *parent)
T * data() const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 22 2024 12:10:03 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.