21 #include "calendarbase.h"
22 #include "calendarbase_p.h"
23 #include "incidencechanger.h"
26 #include <akonadi/item.h>
27 #include <akonadi/collection.h>
29 #include <KSystemTimeZones>
31 using namespace Akonadi;
32 using namespace KCalCore;
36 const KCalCore::Incidence::Ptr &incidence = CalendarUtils::incidence(item);
38 QTextStream stream(&str);
40 <<
"; summary=" << incidence->summary() <<
"; uid=" << incidence->uid() <<
"; type="
41 << incidence->type() <<
"; recurs=" << incidence->recurs() <<
"; recurrenceId="
42 << incidence->recurrenceId().toString() <<
"; dtStart=" << incidence->dtStart().toString()
43 <<
"; dtEnd=" << incidence->dateTime(Incidence::RoleEnd).toString()
49 CalendarBasePrivate::CalendarBasePrivate(
CalendarBase *qq) : QObject()
50 , mIncidenceChanger(new IncidenceChanger())
51 , mBatchInsertionCancelled(false)
52 , mListensForNewItems(false)
55 connect(mIncidenceChanger,
56 SIGNAL(createFinished(
int,
Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)),
57 SLOT(slotCreateFinished(
int,
Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)));
59 connect(mIncidenceChanger,
60 SIGNAL(deleteFinished(
int,QVector<Akonadi::Item::Id>,Akonadi::IncidenceChanger::ResultCode,QString)),
61 SLOT(slotDeleteFinished(
int,QVector<Akonadi::Item::Id>,Akonadi::IncidenceChanger::ResultCode,QString)));
63 connect(mIncidenceChanger,
64 SIGNAL(modifyFinished(
int,
Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)),
65 SLOT(slotModifyFinished(
int,
Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)));
67 mIncidenceChanger->setDestinationPolicy(IncidenceChanger::DestinationPolicyAsk);
68 mIncidenceChanger->setGroupwareCommunication(
false);
69 mIncidenceChanger->setHistoryEnabled(
false);
72 CalendarBasePrivate::~CalendarBasePrivate()
74 delete mIncidenceChanger;
75 mIncidenceChanger = 0;
78 void CalendarBasePrivate::internalInsert(
const Akonadi::Item &item)
81 Q_ASSERT(item.
hasPayload<KCalCore::Incidence::Ptr>());
82 KCalCore::Incidence::Ptr incidence = CalendarUtils::incidence(item);
85 kError() <<
"Incidence is null. id=" << item.
id()
87 <<
"; has incidence=" << item.
hasPayload<KCalCore::Incidence::Ptr>()
88 <<
"; mime type=" << item.
mimeType();
94 const QString uid = incidence->instanceIdentifier();
98 kError() <<
"Incidence has empty UID. id=" << item.
id()
99 <<
"; summary=" << incidence->summary()
100 <<
"Please fix it. Ignoring this incidence.";
104 if (mItemIdByUid.contains(uid) && mItemIdByUid[uid] != item.
id()) {
107 kWarning() <<
"Discarding duplicate incidence with instanceIdentifier=" << uid
108 <<
"and summary " << incidence->summary()
109 <<
"; recurrenceId() =" << incidence->recurrenceId()
110 <<
"; new id=" << item.
id()
111 <<
"; existing id=" << mItemIdByUid[uid];
115 if (incidence->type() == KCalCore::Incidence::TypeEvent && !incidence->dtStart().isValid()) {
117 kWarning() <<
"Discarding event with invalid DTSTART. identifier="
118 << incidence->instanceIdentifier() <<
"; summary=" << incidence->summary();
128 mItemById.insert(item.
id(), item);
129 mItemIdByUid.insert(uid, item.
id());
132 if (!incidence->hasRecurrenceId()) {
134 const QString parentUid = incidence->relatedTo();
135 if (!parentUid.isEmpty()) {
136 mParentUidToChildrenUid[parentUid].append(incidence->uid());
137 mUidToParent.insert(uid, parentUid);
141 incidence->setCustomProperty(
"VOLATILE",
"AKONADI-ID", QString::number(item.
id()));
143 const bool result = q->MemoryCalendar::addIncidence(incidence);
145 kError() <<
"Error adding incidence " << itemToString(item);
150 void CalendarBasePrivate::internalRemove(
const Akonadi::Item &item)
154 Incidence::Ptr tmp = CalendarUtils::incidence(item);
156 kError() <<
"CalendarBase::internalRemove1: incidence is null, item.id=" << item.
id();
161 Incidence::Ptr incidence = q->incidence(tmp->uid(), tmp->recurrenceId());
166 mItemById.remove(item.
id());
168 mItemIdByUid.remove(incidence->instanceIdentifier());
172 if (!incidence->hasRecurrenceId()) {
173 const QString uid = incidence->uid();
174 const QString parentUid = incidence->relatedTo();
175 mParentUidToChildrenUid.remove(uid);
176 if (!parentUid.isEmpty()) {
177 mParentUidToChildrenUid[parentUid].removeAll(uid);
178 mUidToParent.remove(uid);
182 const bool result = q->MemoryCalendar::deleteIncidence(incidence);
184 kError() <<
"Error removing incidence " << itemToString(item);
188 kWarning() <<
"CalendarBase::internalRemove2: incidence is null, item.id=" << itemToString(item);
192 void CalendarBasePrivate::deleteAllIncidencesOfType(
const QString &mimeType)
194 kWarning() <<
"Refusing to delete your Incidences.";
208 void CalendarBasePrivate::slotDeleteFinished(
int changeId,
209 const QVector<Akonadi::Item::Id> &itemIds,
210 IncidenceChanger::ResultCode resultCode,
211 const QString &errorMessage)
214 if (resultCode == IncidenceChanger::ResultCodeSuccess) {
216 if (mItemById.contains(
id))
217 internalRemove(mItemById.value(
id));
220 emit q->deleteFinished(resultCode == IncidenceChanger::ResultCodeSuccess, errorMessage);
223 void CalendarBasePrivate::slotCreateFinished(
int changeId,
225 IncidenceChanger::ResultCode resultCode,
226 const QString &errorMessage)
230 if (resultCode == IncidenceChanger::ResultCodeSuccess && !mListensForNewItems) {
232 Q_ASSERT(item.
hasPayload<KCalCore::Incidence::Ptr>());
233 internalInsert(item);
235 emit q->createFinished(resultCode == IncidenceChanger::ResultCodeSuccess, errorMessage);
238 void CalendarBasePrivate::slotModifyFinished(
int changeId,
240 IncidenceChanger::ResultCode resultCode,
241 const QString &errorMessage)
245 QString message = errorMessage;
246 if (resultCode == IncidenceChanger::ResultCodeSuccess) {
247 KCalCore::Incidence::Ptr incidence = CalendarUtils::incidence(item);
249 KCalCore::Incidence::Ptr localIncidence = q->incidence(incidence->instanceIdentifier());
251 if (localIncidence) {
253 *(
static_cast<KCalCore::IncidenceBase*
>(localIncidence.data())) = *(incidence.data());
256 kWarning() <<
"CalendarBasePrivate::slotModifyFinished() Incidence was deleted already probably? id=" << item.
id();
257 message = QLatin1String(
"Could not find incidence to update, probably was deleted recently.");
258 resultCode = IncidenceChanger::ResultCodeAlreadyDeleted;
261 emit q->modifyFinished(resultCode == IncidenceChanger::ResultCodeSuccess, message);
264 void CalendarBasePrivate::handleUidChange(
const Akonadi::Item &oldItem,
268 Incidence::Ptr newIncidence = CalendarUtils::incidence(newItem);
269 Q_ASSERT(newIncidence);
270 Incidence::Ptr oldIncidence = CalendarUtils::incidence(oldItem);
271 Q_ASSERT(oldIncidence);
273 const QString newUid = newIncidence->uid();
274 if (mItemIdByUid.contains(newIdentifier)) {
275 Incidence::Ptr oldIncidence = CalendarUtils::incidence(oldItem);
276 kWarning() <<
"New uid shouldn't be known: " << newIdentifier <<
"; id="
277 << newItem.
id() <<
"; oldItem.id=" << mItemIdByUid[newIdentifier]
278 <<
"; new summary= " << newIncidence->summary()
279 <<
"; new recurrenceId=" << newIncidence->recurrenceId()
280 <<
"; oldIncidence" << oldIncidence;
282 kWarning() <<
"; oldIncidence uid=" << oldIncidence->uid()
283 <<
"; oldIncidence recurrenceId = " << oldIncidence->recurrenceId()
284 <<
"; oldIncidence summary = " << oldIncidence->summary();
290 mItemIdByUid[newIdentifier] = newItem.
id();
293 oldIncidence = q->MemoryCalendar::incidence(oldIncidence->uid());
297 kWarning() <<
"Couldn't find old incidence";
302 if (newIncidence->instanceIdentifier() == oldIncidence->instanceIdentifier()) {
303 kWarning() <<
"New uid=" << newIncidence->uid() <<
"; old uid=" << oldIncidence->uid()
304 <<
"; new recurrenceId="
305 << newIncidence->recurrenceId()
306 <<
"; old recurrenceId=" << oldIncidence->recurrenceId()
307 <<
"; new summary = " << newIncidence->summary()
308 <<
"; old summary = " << oldIncidence->summary()
309 <<
"; id = " << newItem.
id();
314 mItemIdByUid.remove(oldIncidence->instanceIdentifier());
315 const QString oldUid = oldIncidence->uid();
317 if (mParentUidToChildrenUid.contains(oldUid)) {
318 Q_ASSERT(!mParentUidToChildrenUid.contains(newIdentifier));
319 QStringList children = mParentUidToChildrenUid.value(oldUid);
320 mParentUidToChildrenUid.insert(newIdentifier, children);
321 mParentUidToChildrenUid.remove(oldUid);
325 q->setObserversEnabled(
false);
326 q->MemoryCalendar::deleteIncidence(oldIncidence);
327 q->MemoryCalendar::addIncidence(newIncidence);
329 newIncidence->setUid(oldUid);
330 q->setObserversEnabled(
true);
331 newIncidence->setUid(newUid);
334 void CalendarBasePrivate::handleParentChanged(
const KCalCore::Incidence::Ptr &newIncidence)
336 Q_ASSERT(newIncidence);
338 if (newIncidence->hasRecurrenceId()) {
342 const QString originalParentUid = mUidToParent.value(newIncidence->uid());
343 const QString newParentUid = newIncidence->relatedTo();
345 if (originalParentUid == newParentUid) {
349 if (!originalParentUid.isEmpty()) {
351 Q_ASSERT(mParentUidToChildrenUid.contains(originalParentUid));
352 mParentUidToChildrenUid[originalParentUid].removeAll(newIncidence->uid());
355 mUidToParent.remove(newIncidence->uid());
357 if (!newParentUid.isEmpty()) {
359 Q_ASSERT(!mParentUidToChildrenUid[newParentUid].contains(newIncidence->uid()));
360 mParentUidToChildrenUid[newParentUid].append(newIncidence->uid());
361 mUidToParent.insert(newIncidence->uid(), newParentUid);
366 , d_ptr(new CalendarBasePrivate(this))
369 setDeletionTracking(
false);
373 QObject *parent) : MemoryCalendar(KSystemTimeZones::local())
377 setDeletionTracking(
false);
388 if (d->mItemById.contains(
id)) {
389 i = d->mItemById[id];
391 kDebug() <<
"Can't find any item with id " << id;
404 if (d->mItemIdByUid.contains(uid)) {
406 if (!d->mItemById.contains(
id)) {
407 kError() <<
"Item with id " <<
id <<
"(uid=" << uid <<
") not found, but in uid map";
408 Q_ASSERT_X(
false,
"CalendarBase::item",
"not in mItemById");
410 i = d->mItemById[id];
412 kDebug() <<
"Can't find any incidence with uid " << uid;
419 return incidence ?
item(incidence->instanceIdentifier()) :
Item();
425 return d->mItemById.values();
432 foreach(
const KCalCore::Incidence::Ptr &incidence, incidences) {
434 items <<
item(incidence->instanceIdentifier());
446 KCalCore::Incidence::List childs;
448 if (d->mItemById.contains(parentId)) {
451 KCalCore::Incidence::Ptr parent = CalendarUtils::incidence(item);
466 KCalCore::Incidence::List children;
467 const QStringList uids = d->mParentUidToChildrenUid.value(parentUid);
468 Q_FOREACH(
const QString &uid, uids) {
469 Incidence::Ptr child = incidence(uid);
471 children.append(child);
473 kWarning() <<
"Invalid child with uid " << uid;
483 if (d->mItemById.contains(parentId)) {
486 KCalCore::Incidence::Ptr parent = CalendarUtils::incidence(item);
502 const QStringList uids = d->mParentUidToChildrenUid.value(parentUid);
503 Q_FOREACH(
const QString &uid, uids) {
506 children.append(child);
508 kWarning() <<
"Invalid child with uid " << uid;
526 d->deleteAllIncidencesOfType(Event::eventMimeType());
542 d->deleteAllIncidencesOfType(Todo::todoMimeType());
558 d->deleteAllIncidencesOfType(Journal::journalMimeType());
567 if (batchAdding() && d->mBatchInsertionCancelled) {
573 if (batchAdding() && d->mCollectionForBatchInsertion.isValid()) {
574 collection = d->mCollectionForBatchInsertion;
577 if (incidence->hasRecurrenceId() && !collection.
isValid()) {
579 Item mainItem =
item(incidence->uid());
585 const int changeId = d->mIncidenceChanger->createIncidence(incidence, collection);
589 if (changeId != -1 && !lastCollection.
isValid()) {
590 d->mBatchInsertionCancelled =
true;
591 }
else if (lastCollection.
isValid() && !d->mCollectionForBatchInsertion.isValid()) {
592 d->mCollectionForBatchInsertion = d->mIncidenceChanger->lastCollectionUsed();
596 return changeId != -1;
604 return -1 != d->mIncidenceChanger->deleteIncidence(item_);
610 Q_ASSERT(newIncidence);
612 item_.
setPayload<KCalCore::Incidence::Ptr>(newIncidence);
613 return -1 != d->mIncidenceChanger->modifyIncidence(item_);
619 d->mWeakPointer = pointer;
625 return d->mWeakPointer;
631 return d->mIncidenceChanger;
636 KCalCore::MemoryCalendar::startBatchAdding();
643 d->mBatchInsertionCancelled =
false;
644 KCalCore::MemoryCalendar::endBatchAdding();
647 #include "calendarbase.moc"
648 #include "calendarbase_p.moc"