22 #include "alarmcalendar.moc"
27 #include "alarmresources.h"
39 #include <kcalcore/memorycalendar.h>
40 #include <kcalcore/icalformat.h>
42 #include <kcal/calendarlocal.h>
43 #include <kcal/icalformat.h>
48 #include <kstandarddirs.h>
52 #include <kaboutdata.h>
53 #include <kio/netaccess.h>
54 #include <kfileitem.h>
55 #include <ktemporaryfile.h>
59 using namespace Akonadi;
60 using namespace KCalCore;
64 using namespace KAlarmCal;
67 static KACalendar::Compat
fix(
const KCalCore::FileStorage::Ptr&);
72 static const Collection::Id DISPLAY_COL_ID = -1;
96 AlarmResources::setDebugArea(5951);
97 AlarmResources::setReservedFile(displayCal);
105 resources->showProgress(
true);
110 mDisplayCalendar =
new AlarmCalendar(displayCal, CalEvent::DISPLAYING);
112 CalFormat::setApplication(QLatin1String(
KALARM_NAME), QString::fromLatin1(KACalendar::icalProductId()));
121 delete mResourcesCalendar;
122 mResourcesCalendar = 0;
123 delete mDisplayCalendar;
124 mDisplayCalendar = 0;
132 if (mDisplayCalendar->open())
133 return mDisplayCalendar;
134 kError() <<
"Open error";
145 if (eventId.
eventId().isEmpty())
147 return mResourcesCalendar->event(eventId);
152 if (uniqueId.isEmpty())
154 KAEvent*
event = mResourcesCalendar->event(uniqueId);
156 event = mDisplayCalendar->event(uniqueId);
164 AlarmCalendar::AlarmCalendar()
170 mEventType(CalEvent::EMPTY),
174 mHaveDisabledAlarms(false)
181 connect(model, SIGNAL(collectionStatusChanged(Akonadi::Collection,
AkonadiModel::Change,QVariant,
bool)),
184 AlarmResources*
resources = AlarmResources::instance();
185 resources->setCalIDFunction(&KACalendar::setKAlarmVersion);
187 resources->setCustomEventFunction(&updateResourceKAEvents);
188 connect(resources, SIGNAL(resourceStatusChanged(AlarmResource*,AlarmResources::Change)), SLOT(slotResourceChange(AlarmResource*,AlarmResources::Change)));
189 connect(resources, SIGNAL(cacheDownloaded(AlarmResource*)), SLOT(slotCacheDownloaded(AlarmResource*)));
190 connect(resources, SIGNAL(resourceLoaded(AlarmResource*,
bool)), SLOT(slotResourceLoaded(AlarmResource*,
bool)));
198 AlarmCalendar::AlarmCalendar(
const QString& path, CalEvent::Type type)
207 mHaveDisabledAlarms(false)
211 case CalEvent::ACTIVE:
212 case CalEvent::ARCHIVED:
213 case CalEvent::TEMPLATE:
214 case CalEvent::DISPLAYING:
221 QString icalPath =
path;
222 icalPath.replace(QLatin1String(
"\\.vcs$"), QLatin1String(
".ics"));
223 mICalUrl.setPath(icalPath);
224 mCalType = (path == icalPath) ? LOCAL_ICAL : LOCAL_VCAL;
238 if (mOpen && mCalType == RESOURCES && !AlarmResources::instance())
254 if (mCalType == RESOURCES)
259 kDebug() <<
"RESOURCES";
260 mCalendar = AlarmResources::instance();
269 kDebug() << mUrl.prettyUrl();
271 if (!mCalendarStorage)
274 mCalendarStorage = FileStorage::Ptr(
new FileStorage(calendar));
287 bool created =
false;
288 if (mICalUrl.isLocalFile())
289 created = saveCal(mICalUrl.toLocalFile());
292 KTemporaryFile tmpFile;
293 tmpFile.setAutoRemove(
false);
295 created = saveCal(tmpFile.fileName());
304 mCalendarStorage->calendar().clear();
305 mCalendarStorage.clear();
323 if (mCalType == RESOURCES)
326 kDebug() <<
"RESOURCES";
327 static_cast<AlarmResources*
>(mCalendar)->
load();
333 if (!mCalendarStorage)
338 CalendarLocal* calendar =
static_cast<CalendarLocal*
>(mCalendar);
341 kDebug() << mUrl.prettyUrl();
345 kError() <<
"Download failure";
347 i18nc(
"@info",
"Cannot download calendar: <filename>%1</filename>", mUrl.prettyUrl()));
350 kDebug() <<
"--- Downloaded to" << tmpFile;
353 mCalendarStorage->setFileName(tmpFile);
354 if (!mCalendarStorage->load())
357 if (!calendar->load(tmpFile))
361 KIO::NetAccess::removeTempFile(tmpFile);
364 KFileItem fi(uds, mUrl);
367 kError() <<
"Error loading calendar file '" << tmpFile <<
"'";
369 i18nc(
"@info",
"<para>Error loading calendar:</para><para><filename>%1</filename></para><para>Please fix or delete the file.</para>", mUrl.prettyUrl()));
372 mCalendarStorage->calendar()->close();
373 mCalendarStorage->calendar().clear();
374 mCalendarStorage.clear();
383 if (!mLocalFile.isEmpty())
384 KIO::NetAccess::removeTempFile(mLocalFile);
385 mLocalFile = tmpFile;
387 fix(mCalendarStorage);
388 updateDisplayKAEvents();
391 updateKAEvents(0, calendar);
404 if (mCalType == RESOURCES)
406 if (!mCalendarStorage)
411 if (mCalType == RESOURCES)
413 kDebug() <<
"RESOURCES";
414 return mCalendar->reload();
419 kDebug() << mUrl.prettyUrl();
429 bool AlarmCalendar::saveCal(
const QString& newFile)
432 if (mCalType == RESOURCES)
434 if (!mCalendarStorage)
439 if (mCalType == RESOURCES)
441 kDebug() <<
"RESOURCES";
447 if (!mOpen && newFile.isNull())
450 kDebug() <<
"\"" << newFile <<
"\"," << mEventType;
451 QString saveFilename = newFile.isNull() ? mLocalFile : newFile;
452 if (mCalType == LOCAL_VCAL && newFile.isNull() && mUrl.isLocalFile())
453 saveFilename = mICalUrl.toLocalFile();
455 mCalendarStorage->setFileName(saveFilename);
456 mCalendarStorage->setSaveFormat(
new ICalFormat);
457 if (!mCalendarStorage->save())
459 if (!static_cast<CalendarLocal*>(mCalendar)->save(saveFilename,
new ICalFormat))
462 kError() <<
"Saving" << saveFilename <<
"failed.";
464 i18nc(
"@info",
"Failed to save calendar to <filename>%1</filename>", mICalUrl.prettyUrl()));
468 if (!mICalUrl.isLocalFile())
472 kError() << saveFilename <<
"upload failed.";
474 i18nc(
"@info",
"Cannot upload calendar to <filename>%1</filename>", mICalUrl.prettyUrl()));
479 if (mCalType == LOCAL_VCAL)
483 mCalType = LOCAL_ICAL;
497 if (mCalType != RESOURCES)
499 if (!mLocalFile.isEmpty())
501 KIO::NetAccess::removeTempFile(mLocalFile);
502 mLocalFile = QLatin1String(
"");
509 if (mCalendarStorage)
511 mCalendarStorage->calendar()->close();
512 mCalendarStorage->calendar().clear();
513 mCalendarStorage.clear();
524 while (!mResourceMap.isEmpty())
526 removeKAEvents(mResourceMap.begin().key(),
true, CalEvent::ACTIVE | CalEvent::ARCHIVED | CalEvent::TEMPLATE | CalEvent::DISPLAYING);
528 removeKAEvents(mResourceMap.begin().key(),
true);
538 if (!AlarmResources::instance()->
load(resource, ResourceCached::SyncCache))
539 slotResourceLoaded(resource,
false);
545 void AlarmCalendar::slotCacheDownloaded(AlarmResource* resource)
547 slotResourceLoaded(resource,
false);
554 void AlarmCalendar::setAskResource(
bool ask)
559 AlarmResources::instance()->setAskDestinationPolicy(ask);
569 void AlarmCalendar::updateResourceKAEvents(AlarmResource* resource, KCal::CalendarLocal* cal)
571 mResourcesCalendar->updateKAEvents(resource, cal);
576 void AlarmCalendar::updateDisplayKAEvents()
578 void AlarmCalendar::updateKAEvents(AlarmResource* resource, KCal::CalendarLocal* cal)
582 if (mCalType == RESOURCES)
585 const Collection::Id key = DISPLAY_COL_ID;
587 kDebug() << (resource ? resource->resourceName() :
"0");
588 AlarmResource* key = resource;
590 KAEvent::List& events = mResourceMap[key];
592 for (i = 0, end = events.count(); i < end; ++i)
594 KAEvent*
event = events[i];
596 mEventMap.remove(
EventId(key, event->id()));
598 mEventMap.remove(event->id());
603 mEarliestAlarm[key] = 0;
605 Calendar::Ptr cal = mCalendarStorage->calendar();
611 KConfigGroup config(KGlobal::config(), KAEvent::commandErrorConfigGroup());
613 Event::List kcalevents = cal->rawEvents();
614 for (i = 0, end = kcalevents.count(); i < end; ++i)
617 Event::Ptr kcalevent = kcalevents[i];
619 const Event* kcalevent = kcalevents[i];
621 if (kcalevent->alarms().isEmpty())
624 KAEvent*
event =
new KAEvent(kcalevent);
625 if (!event->isValid())
627 kWarning() <<
"Ignoring unusable event" << kcalevent->uid();
632 event->setCollectionId(key);
634 mEventMap[
EventId(key, kcalevent->uid())] = event;
636 event->setResource(resource);
638 mEventMap[kcalevent->uid()] = event;
643 QString cmdErr = config.readEntry(event->id());
644 if (!cmdErr.isEmpty())
645 event->setCommandError(cmdErr);
651 findEarliestAlarm(resource);
652 checkForDisabledAlarms();
663 void AlarmCalendar::removeKAEvents(Collection::Id key,
bool closing, CalEvent::Types types)
665 bool removed =
false;
666 ResourceMap::Iterator rit = mResourceMap.find(key);
667 if (rit != mResourceMap.end())
670 KAEvent::List& events = rit.value();
671 for (
int i = 0, end = events.count(); i < end; ++i)
673 KAEvent*
event = events[i];
674 bool remove = (
event->collectionId() != key);
677 if (key != DISPLAY_COL_ID)
678 kError() <<
"Event" <<
event->id() <<
", collection" <<
event->collectionId() <<
"Indexed under collection" << key;
681 remove =
event->category() & types;
692 mResourceMap.erase(rit);
696 mEarliestAlarm.remove(key);
698 if (!closing && mOpen)
701 if (mHaveDisabledAlarms)
702 checkForDisabledAlarms();
712 void AlarmCalendar::removeKAEvents(AlarmResource* key,
bool closing)
714 ResourceMap::Iterator rit = mResourceMap.find(key);
715 if (rit != mResourceMap.end())
717 KAEvent::List& events = rit.value();
718 for (
int i = 0, end = events.count(); i < end; ++i)
720 KAEvent*
event = events[i];
721 mEventMap.remove(
event->id());
724 mResourceMap.erase(rit);
726 mEarliestAlarm.remove(key);
728 if (!closing && mOpen)
731 if (mHaveDisabledAlarms)
732 checkForDisabledAlarms();
742 void AlarmCalendar::slotCollectionStatusChanged(
const Collection& collection,
AkonadiModel::Change change,
const QVariant& value,
bool inserted)
748 CalEvent::Types enabled =
static_cast<CalEvent::Types
>(value.toInt());
749 CalEvent::Types disabled = ~enabled & (CalEvent::ACTIVE | CalEvent::ARCHIVED | CalEvent::TEMPLATE);
750 removeKAEvents(collection.id(),
false, disabled);
760 for (
int i = 0, count = events.count(); i < count; ++i)
761 slotEventChanged(events[i]);
772 kError() <<
"Inconsistent AkonadiModel::Event: event:" <<
event.event.collectionId() <<
", collection" <<
event.collection.id();
777 bool updated =
false;
778 KAEventMap::Iterator it = mEventMap.find(event.
eventId());
779 if (it != mEventMap.end())
782 KAEvent* storedEvent = it.value();
783 if (event.
event.category() == storedEvent->category())
786 *storedEvent =
event.event;
787 addNewEvent(event.
collection, storedEvent,
true);
797 bool enabled =
event.event.enabled();
798 checkForDisabledAlarms(!enabled, enabled);
799 if (added && enabled && event.
event.category() == CalEvent::ACTIVE
800 &&
event.event.repeatAtLogin())
801 emit atLoginEventAdded(event.
event);
810 for (
int i = 0, count = events.count(); i < count; ++i)
812 if (!events[i].isConsistent())
813 kError() <<
"Inconsistent AkonadiModel::Event: event:" << events[i].event.collectionId() <<
", collection" << events[i].collection.id();
814 else if (mEventMap.contains(events[i].eventId()))
815 deleteEventInternal(events[i].event, events[i].collection,
false);
820 void AlarmCalendar::slotResourceChange(AlarmResource* resource, AlarmResources::Change change)
824 case AlarmResources::Enabled:
825 if (resource->isActive())
827 kDebug() <<
"Enabled (inactive)";
829 case AlarmResources::Invalidated:
830 kDebug() <<
"Invalidated";
832 case AlarmResources::Deleted:
833 kDebug() <<
"Deleted";
840 removeKAEvents(resource);
846 void AlarmCalendar::slotResourceLoaded(AlarmResource* resource,
bool success)
855 kDebug() << resourceID;
856 if (mCalendar && mCalType == RESOURCES)
858 AlarmResource* resource =
static_cast<AlarmResources*
>(mCalendar)->resourceWithId(resourceID);
860 resource->load(ResourceCached::NoSyncCache);
879 KUrl url = KFileDialog::getOpenUrl(KUrl(
"filedialog:///importalarms"),
880 QString::fromLatin1(
"*.vcs *.ics|%1").arg(i18nc(
"@info/plain",
"Calendar Files")), parent);
883 kError() <<
"Empty URL";
888 kDebug() <<
"Invalid URL";
891 kDebug() << url.prettyUrl();
895 bool local = url.isLocalFile();
898 filename = url.toLocalFile();
899 if (!KStandardDirs::exists(filename))
901 kDebug() <<
"File '" << url.prettyUrl() <<
"' not found";
902 KAMessageBox::error(parent, i18nc(
"@info",
"Could not load calendar <filename>%1</filename>.", url.prettyUrl()));
910 kError() <<
"Download failure";
911 KAMessageBox::error(parent, i18nc(
"@info",
"Cannot download calendar: <filename>%1</filename>", url.prettyUrl()));
914 kDebug() <<
"--- Downloaded to" << filename;
920 FileStorage::Ptr calStorage(
new FileStorage(cal, filename));
921 success = calStorage->load();
924 success = cal.load(filename);
928 kDebug() <<
"Error loading calendar '" << filename <<
"'";
929 KAMessageBox::error(parent, i18nc(
"@info",
"Could not load calendar <filename>%1</filename>.", url.prettyUrl()));
934 KACalendar::Compat caltype =
fix(calStorage);
935 CalEvent::Types wantedTypes = collection && collection->isValid() ? CalEvent::types(collection->contentMimeTypes()) : CalEvent::EMPTY;
936 Collection activeColl, archiveColl, templateColl;
939 CalEvent::Type wantedType = resource ? resource->alarmType() : CalEvent::EMPTY;
940 AlarmResources* resources = AlarmResources::instance();
941 AlarmResource* activeRes = 0;
942 AlarmResource* archivedRes = 0;
943 AlarmResource* templateRes = 0;
944 bool saveRes =
false;
947 KAEvent::List newEvents;
949 Event::List events = cal->rawEvents();
951 Event::List events = cal.rawEvents();
953 for (
int i = 0, end = events.count(); i < end; ++i)
956 Event::Ptr
event = events[i];
958 const Event*
event = events[i];
960 if (event->alarms().isEmpty() || !KAEvent(event).isValid())
962 CalEvent::Type type = CalEvent::status(event);
963 if (type == CalEvent::TEMPLATE)
966 if (caltype == KACalendar::Incompatible)
967 type = CalEvent::ACTIVE;
971 if (collection && collection->isValid())
973 if (!(type & wantedTypes))
981 case CalEvent::ACTIVE: coll = &activeColl;
break;
982 case CalEvent::ARCHIVED: coll = &archiveColl;
break;
983 case CalEvent::TEMPLATE: coll = &templateColl;
break;
986 if (!coll->isValid())
990 Event::Ptr newev(
new Event(*event));
995 if (type != wantedType)
1003 case CalEvent::ACTIVE: res = &activeRes;
break;
1004 case CalEvent::ARCHIVED: res = &archivedRes;
break;
1005 case CalEvent::TEMPLATE: res = &templateRes;
break;
1009 *res = resources->destination(type);
1012 Event* newev =
new Event(*event);
1017 if (type == CalEvent::ACTIVE && !newev->summary().isEmpty())
1019 const Alarm::List& alarms = newev->alarms();
1020 for (
int ai = 0, aend = alarms.count(); ai < aend; ++ai)
1023 Alarm::Ptr alarm = alarms[ai];
1025 Alarm* alarm = alarms[ai];
1027 if (alarm->type() == Alarm::Display && alarm->text().isEmpty())
1028 alarm->setText(newev->summary());
1030 newev->setSummary(QString());
1034 newev->setUid(CalEvent::uid(CalFormat::createUniqueId(), type));
1036 KAEvent* newEvent =
new KAEvent(newev);
1040 if (resources->addEvent(newev, *res))
1043 KAEvent* ev = mResourcesCalendar->addEvent(*res, newev);
1044 if (type != CalEvent::TEMPLATE)
1046 if (type == CalEvent::ACTIVE && !ev->enabled())
1061 mResourcesCalendar->checkForDisabledAlarms(
true, enabled);
1066 KIO::NetAccess::removeTempFile(filename);
1081 QString::fromLatin1(
"*.ics|%1").arg(i18nc(
"@info/plain",
"Calendar Files")),
1082 parent, i18nc(
"@title:window",
"Choose Export Calendar"),
1090 kDebug() <<
"Invalid URL";
1093 kDebug() << url.prettyUrl();
1097 FileStorage::Ptr calStorage(
new FileStorage(calendar, file));
1098 if (append && !calStorage->load())
1101 if (append && !calendar.load(file))
1105 KIO::NetAccess::stat(url, uds, parent);
1106 KFileItem fi(uds, url);
1109 kError() <<
"Error loading calendar file" << file <<
"for append";
1111 i18nc(
"@info",
"Error loading calendar to append to:<nl/><filename>%1</filename>", url.prettyUrl()));
1115 KACalendar::setKAlarmVersion(calendar);
1118 bool success =
true;
1119 bool exported =
false;
1120 for (
int i = 0, end = events.count(); i < end; ++i)
1122 const KAEvent*
event = events[i];
1126 Event* kcalEvent =
new Event;
1128 CalEvent::Type type =
event->category();
1129 QString
id = CalEvent::uid(kcalEvent->uid(),
type);
1130 kcalEvent->setUid(
id);
1131 event->updateKCalEvent(kcalEvent, KAEvent::UID_IGNORE);
1133 if (calendar->addEvent(kcalEvent))
1135 if (calendar.addEvent(kcalEvent))
1146 KTemporaryFile* tempFile = 0;
1147 bool local = url.isLocalFile();
1150 tempFile =
new KTemporaryFile;
1151 file = tempFile->fileName();
1154 calStorage->setFileName(file);
1155 calStorage->setSaveFormat(
new ICalFormat);
1156 if (!calStorage->save())
1158 if (!calendar.save(file,
new ICalFormat))
1161 kError() << file <<
": failed";
1163 i18nc(
"@info",
"Failed to save new calendar to:<nl/><filename>%1</filename>", url.prettyUrl()));
1166 else if (!local && !KIO::NetAccess::upload(file, url, parent))
1168 kError() << file <<
": upload failed";
1170 i18nc(
"@info",
"Cannot upload new calendar to:<nl/><filename>%1</filename>", url.prettyUrl()));
1198 if (mUpdateCount > 0)
1231 for (
int i = 0, end = events.count(); i < end; ++i)
1234 deleteEventInternal(*events[i]);
1236 deleteEventInternal(events[i]->
id());
1239 if (mHaveDisabledAlarms)
1240 checkForDisabledAlarms();
1270 kDebug() << evnt.id();
1271 CalEvent::Type type = evnt.category();
1273 kDebug() <<
event->id();
1274 CalEvent::Type type =
event->category();
1276 if (type != mEventType)
1280 case CalEvent::ACTIVE:
1281 case CalEvent::ARCHIVED:
1282 case CalEvent::TEMPLATE:
1283 if (mEventType == CalEvent::EMPTY)
1292 Collection::Id key = (collection && collection->isValid()) ? collection->id() : -1;
1293 Event::Ptr kcalEvent((mCalType == RESOURCES) ? (Event*)0 :
new Event);
1294 KAEvent*
event =
new KAEvent(evnt);
1296 AlarmResource* key = resource;
1297 Event* kcalEvent =
new Event;
1298 KAEvent oldEvent(*event);
1300 QString
id =
event->id();
1301 if (type == CalEvent::ACTIVE)
1305 else if (!useEventID)
1312 id = (mCalType == RESOURCES) ? CalFormat::createUniqueId() : kcalEvent->uid();
1314 id = kcalEvent->uid();
1318 id = CalEvent::uid(
id, type);
1322 kcalEvent->setUid(
id);
1324 event->setEventId(
id);
1326 event->updateKCalEvent(kcalEvent, KAEvent::UID_IGNORE);
1329 bool remove =
false;
1330 if (mCalType == RESOURCES)
1341 resource = AlarmResources::instance()->destination(type, promptParent, noPrompt, cancelled);
1342 if (resource && addEvent(resource, event))
1351 ok = AlarmResources::instance()->addEvent(kcalEvent, resource);
1355 if (ok && type == CalEvent::ACTIVE && !event->enabled())
1356 checkForDisabledAlarms(
true,
false);
1363 event->updateKCalEvent(kcalEvent, KAEvent::UID_IGNORE);
1364 key = DISPLAY_COL_ID;
1365 if (!mEventMap.contains(
EventId(key, event->id())))
1367 addNewEvent(Collection(), event);
1368 ok = mCalendarStorage->calendar()->addEvent(kcalEvent);
1373 if (addEvent(0, event))
1375 ok = mCalendar->addEvent(kcalEvent);
1386 mEventMap.remove(
EventId(key, event->id()));
1388 mEventMap.remove(event->id());
1390 KAEvent::List& events = mResourceMap[key];
1391 int i = events.indexOf(event);
1394 if (mEarliestAlarm[key] == event)
1395 findEarliestAlarm(key);
1422 kDebug() <<
"KAEvent:" <<
event->id();
1423 if (mEventMap.contains(event->id()))
1425 addNewEvent(resource, event);
1436 kDebug() <<
"Event:" << kcalEvent->uid();
1437 if (mEventMap.contains(kcalEvent->uid()))
1440 KAEvent* ev =
new KAEvent(kcalEvent);
1441 addNewEvent(resource, ev);
1453 void AlarmCalendar::addNewEvent(
const Collection& collection, KAEvent* event,
bool replace)
1455 void AlarmCalendar::addNewEvent(AlarmResource* resource, KAEvent* event)
1459 Collection::Id key = collection.isValid() ? collection.id() : -1;
1460 event->setCollectionId(key);
1463 mResourceMap[key] += event;
1464 mEventMap[
EventId(key, event->id())] = event;
1467 && event->category() == CalEvent::ACTIVE)
1469 AlarmResource* key = resource;
1470 mResourceMap[key] += event;
1471 mEventMap[
event->id()] = event;
1472 if (resource && resource->alarmType() == CalEvent::ACTIVE
1473 &&
event->category() == CalEvent::ACTIVE)
1477 KAEvent* earliest = mEarliestAlarm.value(key, (KAEvent*)0);
1479 if (replace && earliest == event)
1480 findEarliestAlarm(key);
1484 KDateTime dt =
event->nextTrigger(KAEvent::ALL_TRIGGER).effectiveKDateTime();
1486 && (!earliest || dt < earliest->nextTrigger(KAEvent::ALL_TRIGGER)))
1488 mEarliestAlarm[key] = event;
1489 emit earliestAlarmChanged();
1511 EventId newId(oldEventId.collectionId(), newEvent.id());
1513 QString newId = newEvent->id();
1515 kDebug() << oldEventId <<
"->" << newId;
1516 bool noNewId = newId.
isEmpty();
1517 if (!noNewId && oldEventId == newId)
1519 kError() <<
"Same IDs";
1524 if (mCalType == RESOURCES)
1529 KAEvent* storedEvent = event(oldEventId);
1532 kError() <<
"Old event not found";
1536 newEvent.setEventId(CalFormat::createUniqueId());
1545 deleteEventInternal(KAEvent(*storedEvent), c);
1546 if (mHaveDisabledAlarms)
1547 checkForDisabledAlarms();
1551 Event* kcalEvent = createKCalEvent(newEvent, oldEventId);
1553 kcalEvent->setUid(CalFormat::createUniqueId());
1554 AlarmResources* resources = AlarmResources::instance();
1555 AlarmResource* resource = resources->resourceForIncidence(oldEventId);
1556 if (!resources->addEvent(kcalEvent, resource))
1559 newEvent->setEventId(kcalEvent->uid());
1560 addEvent(resource, newEvent);
1561 deleteEvent(oldEventId);
1571 if (!addEvent(newEvent, 0,
true))
1573 deleteEvent(oldEventId);
1591 if (!mOpen || mCalType != RESOURCES)
1597 KAEvent newEvnt(*evnt);
1598 newEvnt.setItemId(evnt->itemId());
1606 QString
id = evnt->id();
1607 KAEvent* kaevnt =
event(
id);
1608 Event* kcalEvent = mCalendar ? mCalendar->event(
id) : 0;
1609 if (kaevnt && kcalEvent)
1611 evnt->updateKCalEvent(kcalEvent, KAEvent::UID_CHECK);
1612 bool oldEnabled = kaevnt->enabled();
1615 findEarliestAlarm(AlarmResources::instance()->resource(kcalEvent));
1616 if (mCalType == RESOURCES && evnt->category() == CalEvent::ACTIVE)
1617 checkForDisabledAlarms(oldEnabled, evnt->enabled());
1621 kDebug() <<
"error";
1633 if (mOpen && mCalType == RESOURCES)
1635 CalEvent::Type status = deleteEventInternal(event);
1636 if (mHaveDisabledAlarms)
1637 checkForDisabledAlarms();
1638 if (status != CalEvent::EMPTY)
1654 bool AlarmCalendar::deleteDisplayEvent(
const QString& eventID,
bool saveit)
1660 if (mOpen && mCalType != RESOURCES)
1665 CalEvent::Type status = deleteEventInternal(eventID);
1666 if (mHaveDisabledAlarms)
1667 checkForDisabledAlarms();
1668 if (status != CalEvent::EMPTY)
1685 CalEvent::Type AlarmCalendar::deleteEventInternal(
const KAEvent& event,
bool deleteFromAkonadi)
1688 if (!collection.isValid())
1689 return CalEvent::EMPTY;
1690 return deleteEventInternal(event.id(),
event, collection, deleteFromAkonadi);
1693 CalEvent::Type AlarmCalendar::deleteEventInternal(
const KAEvent& event,
const Collection& collection,
bool deleteFromAkonadi)
1695 if (!collection.isValid())
1696 return CalEvent::EMPTY;
1697 if (event.collectionId() != collection.id())
1699 kError() <<
"Event" <<
event.id() <<
": collection" <<
event.collectionId() <<
"differs from 'collection'" << collection.id();
1700 return CalEvent::EMPTY;
1702 return deleteEventInternal(event.id(),
event, collection, deleteFromAkonadi);
1705 CalEvent::Type AlarmCalendar::deleteEventInternal(
const QString& eventID,
const KAEvent& event,
const Collection& collection,
bool deleteFromAkonadi)
1707 CalEvent::Type AlarmCalendar::deleteEventInternal(
const QString& eventID)
1712 const QString
id = eventID;
1714 const KAEvent paramEvent = event;
1716 Event::Ptr kcalEvent;
1717 if (mCalendarStorage)
1718 kcalEvent = mCalendarStorage->calendar()->event(
id);
1719 Collection::Id key = collection.isValid() ? collection.id() : -1;
1720 KAEventMap::Iterator it = mEventMap.find(
EventId(key,
id));
1722 Event* kcalEvent = mCalendar ? mCalendar->event(
id) : 0;
1723 KAEventMap::Iterator it = mEventMap.find(
id);
1725 if (it != mEventMap.end())
1727 KAEvent* ev = it.value();
1728 mEventMap.erase(it);
1730 AlarmResource* key = AlarmResources::instance()->resource(kcalEvent);
1732 KAEvent::List& events = mResourceMap[key];
1733 int i = events.indexOf(ev);
1737 if (mEarliestAlarm[key] == ev)
1739 findEarliestAlarm(collection);
1741 findEarliestAlarm(key);
1746 for (EarliestMap::Iterator eit = mEarliestAlarm.begin(); eit != mEarliestAlarm.end(); ++eit)
1748 KAEvent* ev = eit.value();
1749 if (ev && ev->id() == id)
1751 findEarliestAlarm(eit.key());
1756 CalEvent::Type status = CalEvent::EMPTY;
1759 status = CalEvent::status(kcalEvent);
1761 mCalendarStorage->calendar()->deleteEvent(kcalEvent);
1763 mCalendar->deleteEvent(kcalEvent);
1767 else if (deleteFromAkonadi)
1770 CalEvent::Type s = paramEvent.category();
1777 KConfigGroup config(KGlobal::config(), KAEvent::commandErrorConfigGroup());
1778 if (config.hasKey(
id))
1780 config.deleteEntry(
id);
1800 if (mCalType != RESOURCES)
1801 kFatal() <<
"AlarmCalendar::createKCalEvent(KAEvent): invalid for display calendar";
1804 QString
id = baseID.isEmpty() ? ev->id() : baseID;
1805 Event* calEvent =
id.isEmpty() ? 0 : AlarmResources::instance()->event(
id);
1806 Event* newEvent = calEvent ?
new Event(*calEvent) : new Event;
1807 ev->updateKCalEvent(newEvent, KAEvent::UID_SET);
1826 const QString eventId = uniqueID.
eventId();
1827 if (uniqueID.collectionId() == -1 && checkDuplicates)
1831 KAEvent::List list = events(eventId);
1832 if (list.count() > 1)
1834 kWarning() <<
"Multiple events found with ID" << eventId;
1842 KAEventMap::ConstIterator it = mEventMap.constFind(uniqueID);
1843 if (it == mEventMap.constEnd())
1855 Q_ASSERT(mCalType != RESOURCES);
1856 if (!mCalendarStorage)
1857 return Event::Ptr();
1858 return mCalendarStorage->calendar()->event(uniqueID);
1863 return mCalendar ? mCalendar->event(uniqueID) : 0;
1873 if (templateName.isEmpty())
1875 KAEvent::List eventlist =
events(CalEvent::TEMPLATE);
1876 for (
int i = 0, end = eventlist.count(); i < end; ++i)
1878 if (eventlist[i]->templateName() == templateName)
1879 return eventlist[i];
1891 if (mCalType == RESOURCES && isValid())
1893 for (ResourceMap::ConstIterator rit = mResourceMap.constBegin(); rit != mResourceMap.constEnd(); ++rit)
1895 const Collection::Id
id = rit.key();
1896 KAEventMap::ConstIterator it = mEventMap.constFind(
EventId(
id, uniqueId));
1897 if (it != mEventMap.constEnd())
1917 if (mCalType != RESOURCES && (!mCalendarStorage || collection.isValid()))
1919 if (collection.isValid())
1921 if (!mCalendar || (resource && mCalType != RESOURCES))
1927 Collection::Id key = collection.isValid() ? collection.id() : -1;
1928 ResourceMap::ConstIterator rit = mResourceMap.constFind(key);
1930 ResourceMap::ConstIterator rit = mResourceMap.constFind(resource);
1932 if (rit == mResourceMap.constEnd())
1934 const KAEvent::List events = rit.value();
1935 if (type == CalEvent::EMPTY)
1937 for (
int i = 0, end = events.count(); i < end; ++i)
1938 if (type & events[i]->category())
1943 for (ResourceMap::ConstIterator rit = mResourceMap.constBegin(); rit != mResourceMap.constEnd(); ++rit)
1945 const KAEvent::List events = rit.value();
1946 if (type == CalEvent::EMPTY)
1950 for (
int i = 0, end = events.count(); i < end; ++i)
1951 if (type & events[i]->category())
1972 Q_ASSERT(mCalType != RESOURCES);
1973 if (!mCalendarStorage)
1975 list = mCalendarStorage->calendar()->rawEvents();
1977 if (!mCalendar || (resource && mCalType != RESOURCES))
1979 list = resource ? AlarmResources::instance()->rawEvents(resource) : mCalendar->rawEvents();
1981 for (
int i = 0; i < list.count(); )
1984 Event::Ptr
event = list[i];
1986 Event*
event = list[i];
1988 if (event->alarms().isEmpty()
1989 || (type != CalEvent::EMPTY && !(type & CalEvent::status(event)))
1990 || !KAEvent(event).isValid())
2009 kDebug() << from <<
"-" <<
to;
2010 KAEvent::List evnts;
2014 AlarmResources* resources = AlarmResources::instance();
2015 KAEvent::List allEvents =
events(type);
2016 for (
int i = 0, end = allEvents.count(); i < end; ++i)
2018 KAEvent*
event = allEvents[i];
2019 Event* e = resources->event(event->id());
2020 bool recurs = e->recurs();
2022 bool endOffsetValid =
false;
2023 const Alarm::List& alarms = e->alarms();
2024 for (
int ai = 0, aend = alarms.count(); ai < aend; ++ai)
2026 Alarm* alarm = alarms[ai];
2027 if (alarm->enabled())
2031 if (alarm->hasTime())
2039 if (alarm->hasStartOffset())
2040 offset = alarm->startOffset().asSeconds();
2041 else if (alarm->hasEndOffset())
2043 if (!endOffsetValid)
2045 endOffset = e->hasDuration() ? e->duration().asSeconds() : e->hasEndDate() ? e->dtStart().secsTo(e->dtEnd()) : 0;
2046 endOffsetValid =
true;
2048 offset = alarm->endOffset().asSeconds() + endOffset;
2051 KDateTime pre = from.addSecs(-offset - 1);
2053 pre = pre.addDays(-1);
2054 dt = e->recurrence()->getNextDateTime(pre);
2057 dt = dt.addSecs(offset);
2062 if (dt >= from && dt <= to)
2064 kDebug() <<
"'" << e->summary() <<
"':" << dt;
2065 evnts.append(event);
2082 if (mCalType != RESOURCES)
2086 KAEvent
event = model->
event(
id);
2089 return !
event.isValid() ||
event.isReadOnly();
2095 if (!mCalendar || mCalType != RESOURCES)
2097 AlarmResources* resources = AlarmResources::instance();
2098 const Event*
event = resources->event(uniqueID);
2099 AlarmResource* resource = resources->resource(event);
2102 return !resource->writable(event);
2110 Collection AlarmCalendar::collectionForEvent(Item::Id itemId)
const
2112 if (mCalType != RESOURCES)
2113 return Collection();
2122 if (!mCalendar || mCalType != RESOURCES)
2124 return AlarmResources::instance()->resourceForIncidence(eventID);
2133 if (event->category() == CalEvent::ACTIVE)
2135 bool status =
event->enabled();
2136 checkForDisabledAlarms(!status, status);
2144 void AlarmCalendar::checkForDisabledAlarms(
bool oldEnabled,
bool newEnabled)
2146 if (mCalType == RESOURCES && newEnabled != oldEnabled)
2148 if (newEnabled && mHaveDisabledAlarms)
2149 checkForDisabledAlarms();
2150 else if (!newEnabled && !mHaveDisabledAlarms)
2152 mHaveDisabledAlarms =
true;
2161 void AlarmCalendar::checkForDisabledAlarms()
2163 if (mCalType != RESOURCES)
2165 bool disabled =
false;
2166 KAEvent::List eventlist =
events(CalEvent::ACTIVE);
2167 for (
int i = 0, end = eventlist.count(); i < end; ++i)
2169 if (!eventlist[i]->enabled())
2175 if (disabled != mHaveDisabledAlarms)
2177 mHaveDisabledAlarms = disabled;
2187 KAEvent::List atlogins;
2189 if (mCalType != RESOURCES)
2192 if (!mCalendarStorage || mCalType != RESOURCES)
2195 if (!mCalendar || mCalType != RESOURCES)
2198 for (ResourceMap::ConstIterator rit = mResourceMap.constBegin(); rit != mResourceMap.constEnd(); ++rit)
2201 const Collection::Id
id = rit.key();
2206 const AlarmResource* resource = rit.key();
2207 if (!resource || resource->alarmType() != CalEvent::ACTIVE)
2210 const KAEvent::List& events = rit.value();
2211 for (
int i = 0, end = events.count(); i < end; ++i)
2213 KAEvent*
event = events[i];
2214 if (event->category() == CalEvent::ACTIVE &&
event->repeatAtLogin())
2225 void AlarmCalendar::findEarliestAlarm(
const Collection& collection)
2227 if (mCalType != RESOURCES)
2229 if (!collection.isValid()
2232 findEarliestAlarm(collection.id());
2235 void AlarmCalendar::findEarliestAlarm(Collection::Id key)
2237 void AlarmCalendar::findEarliestAlarm(AlarmResource* key)
2240 EarliestMap::Iterator eit = mEarliestAlarm.find(key);
2241 if (eit != mEarliestAlarm.end())
2244 if (mCalType != RESOURCES
2248 if (!mCalendar || mCalType != RESOURCES
2249 || !key || key->alarmType() != CalEvent::ACTIVE)
2252 ResourceMap::ConstIterator rit = mResourceMap.constFind(key);
2253 if (rit == mResourceMap.constEnd())
2255 const KAEvent::List& events = rit.value();
2256 KAEvent* earliest = 0;
2257 KDateTime earliestTime;
2258 for (
int i = 0, end = events.count(); i < end; ++i)
2260 KAEvent*
event = events[i];
2261 if (event->category() != CalEvent::ACTIVE
2262 || mPendingAlarms.contains(event->id()))
2264 KDateTime dt =
event->nextTrigger(KAEvent::ALL_TRIGGER).effectiveKDateTime();
2265 if (dt.isValid() && (!earliest || dt < earliestTime))
2271 mEarliestAlarm[key] = earliest;
2272 emit earliestAlarmChanged();
2281 KAEvent* earliest = 0;
2282 KDateTime earliestTime;
2283 for (EarliestMap::ConstIterator eit = mEarliestAlarm.constBegin(); eit != mEarliestAlarm.constEnd(); ++eit)
2285 KAEvent*
event = eit.value();
2288 KDateTime dt =
event->nextTrigger(KAEvent::ALL_TRIGGER).effectiveKDateTime();
2289 if (dt.isValid() && (!earliest || dt < earliestTime))
2304 QString
id =
event->id();
2305 bool wasPending = mPendingAlarms.contains(
id);
2306 kDebug() <<
id <<
"," << pending <<
"(was" << wasPending <<
")";
2311 mPendingAlarms.append(
id);
2317 mPendingAlarms.removeAll(
id);
2323 findEarliestAlarm(AlarmResources::instance()->resourceForIncidence(
id));
2335 for (ResourceMap::ConstIterator rit = mResourceMap.constBegin(); rit != mResourceMap.constEnd(); ++rit)
2336 KAEvent::adjustStartOfDay(rit.value());
2344 KACalendar::Compat
fix(
const FileStorage::Ptr& fileStorage)
2346 QString versionString;
2347 int version = KACalendar::updateVersion(fileStorage, versionString);
2348 if (version == KACalendar::IncompatibleFormat)
2349 return KACalendar::Incompatible;
2350 return KACalendar::Current;
static void resourceStatusChanged(AlarmResource *, AlarmResources::Change)
static void setAskDestinationPolicy(bool ask)
Set whether the user should be prompted for the destination collection to add alarms to...
bool deleteEvent(const QString &eventID, bool save=false)
static EventListModel * alarms()
void disabledChanged(const KAEvent *)
static bool importAlarms(QWidget *, AlarmResource *=0)
CalEvent::Type type() const
KAEvent::List atLoginAlarms() const
static int isWritableEnabled(const Akonadi::Collection &, CalEvent::Type)
Return whether a collection is both enabled and fully writable for a given alarm type, i.e.
bool updateEvent(KAEvent &event)
void reloadFromCache(const QString &resourceID)
bool eventReadOnly(const QString &uniqueID) const
KAEvent * updateEvent(const KAEvent &)
KCal::Event * kcalEvent(const QString &uniqueId)
void earliestAlarmChanged()
void loadResource(AlarmResource *, QWidget *parent)
static AlarmCalendar * resources()
static void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Options(Notify|WindowModal))
void calendarSaved(AlarmCalendar *)
bool addEvent(KAEvent *, QWidget *promptParent=0, bool useEventID=false, AlarmResource *=0, bool noPrompt=false, bool *cancelled=0)
static void terminateCalendars()
void addEvents(const KAEvent::List &)
static const QString displayCalendarName
AlarmResource * resourceForEvent(const QString &eventID) const
KAEvent * templateEvent(const QString &templateName)
KAEvent event(const Akonadi::Item &item) const
Return the alarm with the specified unique identifier.
Akonadi::Collection collectionById(Akonadi::Collection::Id) const
static bool isEnabled(const Akonadi::Collection &, CalEvent::Type)
Return whether a collection is enabled (and valid).
static QString getSaveFileName(const KUrl &dir=KUrl(), const QString &filter=QString(), QWidget *parent=0, const QString &caption=QString(), bool *append=0)
static KAEvent * getEvent(const QString &uniqueId)
the KAlarm application object
Struct containing a KAEvent and its parent Collection.
KAEvent * earliestAlarm() const
bool modifyEvent(const QString &oldEventId, KAEvent *newEvent)
static QTime startOfDay()
void purgeEvents(const KAEvent::List &)
static KTimeZone timeZone(bool reload=false)
static Akonadi::Collection destination(CalEvent::Type, QWidget *promptParent=0, bool noPrompt=false, bool *cancelled=0)
Find the collection to be used to store an event of a given type.
static AkonadiModel * instance()
Akonadi::Collection collection
KACalendar::Compat fix(KCal::CalendarLocal &calendar, const QString &localFile, AlarmResource *resource, AlarmResource::FixFunc conv, bool *wrongType)
static bool askResource()
Get Prompt for which calendar to store in.
static void setBackend(Backend v)
Set Data storage backend.
KCal::Event * createKCalEvent(const KAEvent *e) const
static void connect(const char *signal, const QObject *receiver, const char *member)
Unique event identifier for Akonadi.
static CalEvent::Types types(const Akonadi::Collection &)
KCal::Event::List kcalEvents(CalEvent::Type s=CalEvent::EMPTY)
bool isConsistent() const
void setAlarmPending(KAEvent *, bool pending=true)
static bool initialiseCalendars()
static Preferences * self()
Provides read and write access to calendar files and resources.
static AlarmCalendar * displayCalendarOpen()
KAEvent::List events(CalEvent::Types s=CalEvent::EMPTY) const
static bool exportAlarms(const KAEvent::List &, QWidget *parent)
KAEvent * event(const QString &uniqueId)
static MainWindow * mainMainWindow()
Akonadi::Collection collectionForItem(Akonadi::Item::Id) const
void haveDisabledAlarmsChanged(bool haveDisabled)
static void displayFatalError(const QString &message)
bool isEmpty() const
Return whether the instance contains any data.
bool addEvent(KAEvent &, Akonadi::Collection &)