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;
94 Preferences::setBackend(Preferences::Akonadi);
96 AlarmResources::setDebugArea(5951);
97 AlarmResources::setReservedFile(displayCal);
104 resources->setAskDestinationPolicy(Preferences::askResource());
105 resources->showProgress(
true);
106 Preferences::setBackend(Preferences::Kresources);
110 mDisplayCalendar =
new AlarmCalendar(displayCal, CalEvent::DISPLAYING);
121 delete mResourcesCalendar;
122 mResourcesCalendar = 0;
123 delete mDisplayCalendar;
124 mDisplayCalendar = 0;
132 if (mDisplayCalendar->open())
133 return mDisplayCalendar;
134 kError() <<
"Open error";
147 return mResourcesCalendar->event(eventId);
154 KAEvent*
event = mResourcesCalendar->event(uniqueId);
156 event = mDisplayCalendar->event(uniqueId);
164 AlarmCalendar::AlarmCalendar()
170 mEventType(CalEvent::EMPTY),
174 mHaveDisabledAlarms(false)
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:
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();
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)
501 KIO::NetAccess::removeTempFile(mLocalFile);
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());
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;
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)
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];
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;
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;
937 Event::List events = cal->rawEvents();
940 CalEvent::Type wantedType = resource ? resource->alarmType() : CalEvent::EMPTY;
941 AlarmResources* resources = AlarmResources::instance();
942 AlarmResource* activeRes = 0;
943 AlarmResource* archivedRes = 0;
944 AlarmResource* templateRes = 0;
945 bool saveRes =
false;
947 KAEvent::List newEvents;
948 Event::List events = cal.rawEvents();
950 for (
int i = 0, end = events.count(); i < end; ++i)
953 Event::Ptr
event = events[i];
955 const Event*
event = events[i];
957 if (event->alarms().isEmpty() || !KAEvent(event).isValid())
959 CalEvent::Type type = CalEvent::status(event);
960 if (type == CalEvent::TEMPLATE)
963 if (caltype == KACalendar::Incompatible)
964 type = CalEvent::ACTIVE;
968 if (collection && collection->isValid())
970 if (!(type & wantedTypes))
978 case CalEvent::ACTIVE: coll = &activeColl;
break;
979 case CalEvent::ARCHIVED: coll = &archiveColl;
break;
980 case CalEvent::TEMPLATE: coll = &templateColl;
break;
983 if (!coll->isValid())
987 Event::Ptr newev(
new Event(*event));
992 if (type != wantedType)
1000 case CalEvent::ACTIVE: res = &activeRes;
break;
1001 case CalEvent::ARCHIVED: res = &archivedRes;
break;
1002 case CalEvent::TEMPLATE: res = &templateRes;
break;
1006 *res = resources->destination(type);
1009 Event* newev =
new Event(*event);
1014 if (type == CalEvent::ACTIVE && !newev->summary().isEmpty())
1016 const Alarm::List& alarms = newev->alarms();
1017 for (
int ai = 0, aend = alarms.count(); ai < aend; ++ai)
1020 Alarm::Ptr alarm = alarms[ai];
1022 Alarm* alarm = alarms[ai];
1024 if (alarm->type() == Alarm::Display && alarm->text().isEmpty())
1025 alarm->setText(newev->summary());
1031 newev->setUid(CalEvent::uid(CalFormat::createUniqueId(), type));
1033 KAEvent* newEvent =
new KAEvent(newev);
1037 if (resources->addEvent(newev, *res))
1040 KAEvent* ev = mResourcesCalendar->addEvent(*res, newev);
1041 if (type != CalEvent::TEMPLATE)
1043 if (type == CalEvent::ACTIVE && !ev->enabled())
1058 mResourcesCalendar->checkForDisabledAlarms(
true, enabled);
1063 KIO::NetAccess::removeTempFile(filename);
1079 parent, i18nc(
"@title:window",
"Choose Export Calendar"),
1087 kDebug() <<
"Invalid URL";
1090 kDebug() << url.prettyUrl();
1094 FileStorage::Ptr calStorage(
new FileStorage(calendar, file));
1095 if (append && !calStorage->load())
1098 if (append && !calendar.load(file))
1102 KIO::NetAccess::stat(url, uds, parent);
1103 KFileItem fi(uds, url);
1106 kError() <<
"Error loading calendar file" << file <<
"for append";
1108 i18nc(
"@info",
"Error loading calendar to append to:<nl/><filename>%1</filename>", url.prettyUrl()));
1112 KACalendar::setKAlarmVersion(calendar);
1115 bool success =
true;
1116 bool exported =
false;
1117 for (
int i = 0, end = events.count(); i < end; ++i)
1119 const KAEvent*
event = events[i];
1123 Event* kcalEvent =
new Event;
1125 CalEvent::Type type =
event->category();
1126 QString id = CalEvent::uid(kcalEvent->uid(),
type);
1127 kcalEvent->setUid(
id);
1128 event->updateKCalEvent(kcalEvent, KAEvent::UID_IGNORE);
1130 if (calendar->addEvent(kcalEvent))
1132 if (calendar.addEvent(kcalEvent))
1143 KTemporaryFile* tempFile = 0;
1144 bool local = url.isLocalFile();
1147 tempFile =
new KTemporaryFile;
1148 file = tempFile->fileName();
1151 calStorage->setFileName(file);
1152 calStorage->setSaveFormat(
new ICalFormat);
1153 if (!calStorage->save())
1155 if (!calendar.save(file,
new ICalFormat))
1158 kError() << file <<
": failed";
1160 i18nc(
"@info",
"Failed to save new calendar to:<nl/><filename>%1</filename>", url.prettyUrl()));
1163 else if (!local && !KIO::NetAccess::upload(file, url, parent))
1165 kError() << file <<
": upload failed";
1167 i18nc(
"@info",
"Cannot upload new calendar to:<nl/><filename>%1</filename>", url.prettyUrl()));
1195 if (mUpdateCount > 0)
1228 for (
int i = 0, end = events.count(); i < end; ++i)
1231 deleteEventInternal(*events[i]);
1233 deleteEventInternal(events[i]->
id());
1236 if (mHaveDisabledAlarms)
1237 checkForDisabledAlarms();
1267 kDebug() << evnt.id();
1268 CalEvent::Type type = evnt.category();
1270 kDebug() <<
event->id();
1271 CalEvent::Type type =
event->category();
1273 if (type != mEventType)
1277 case CalEvent::ACTIVE:
1278 case CalEvent::ARCHIVED:
1279 case CalEvent::TEMPLATE:
1280 if (mEventType == CalEvent::EMPTY)
1289 Collection::Id key = (collection && collection->isValid()) ? collection->id() : -1;
1290 Event::Ptr kcalEvent((mCalType == RESOURCES) ? (Event*)0 :
new Event);
1291 KAEvent*
event =
new KAEvent(evnt);
1293 AlarmResource* key = resource;
1294 Event* kcalEvent =
new Event;
1295 KAEvent oldEvent(*event);
1298 if (type == CalEvent::ACTIVE)
1302 else if (!useEventID)
1309 id = (mCalType == RESOURCES) ? CalFormat::createUniqueId() : kcalEvent->uid();
1311 id = kcalEvent->uid();
1315 id = CalEvent::uid(
id, type);
1319 kcalEvent->setUid(
id);
1321 event->setEventId(
id);
1323 event->updateKCalEvent(kcalEvent, KAEvent::UID_IGNORE);
1326 bool remove =
false;
1327 if (mCalType == RESOURCES)
1338 resource = AlarmResources::instance()->destination(type, promptParent, noPrompt, cancelled);
1339 if (resource && addEvent(resource, event))
1348 ok = AlarmResources::instance()->addEvent(kcalEvent, resource);
1352 if (ok && type == CalEvent::ACTIVE && !event->enabled())
1353 checkForDisabledAlarms(
true,
false);
1360 event->updateKCalEvent(kcalEvent, KAEvent::UID_IGNORE);
1361 key = DISPLAY_COL_ID;
1362 if (!mEventMap.contains(
EventId(key, event->id())))
1364 addNewEvent(Collection(), event);
1365 ok = mCalendarStorage->calendar()->addEvent(kcalEvent);
1370 if (addEvent(0, event))
1372 ok = mCalendar->addEvent(kcalEvent);
1383 mEventMap.remove(
EventId(key, event->id()));
1385 mEventMap.remove(event->id());
1387 KAEvent::List& events = mResourceMap[key];
1388 int i = events.
indexOf(event);
1391 if (mEarliestAlarm[key] == event)
1392 findEarliestAlarm(key);
1419 kDebug() <<
"KAEvent:" <<
event->id();
1420 if (mEventMap.
contains(event->id()))
1422 addNewEvent(resource, event);
1433 kDebug() <<
"Event:" << kcalEvent->uid();
1434 if (mEventMap.
contains(kcalEvent->uid()))
1437 KAEvent* ev =
new KAEvent(kcalEvent);
1438 addNewEvent(resource, ev);
1450 void AlarmCalendar::addNewEvent(
const Collection& collection, KAEvent* event,
bool replace)
1452 void AlarmCalendar::addNewEvent(AlarmResource* resource, KAEvent* event)
1456 Collection::Id key = collection.isValid() ? collection.id() : -1;
1457 event->setCollectionId(key);
1460 mResourceMap[key] += event;
1461 mEventMap[
EventId(key, event->id())] = event;
1464 && event->category() == CalEvent::ACTIVE)
1466 AlarmResource* key = resource;
1467 mResourceMap[key] += event;
1468 mEventMap[
event->id()] = event;
1469 if (resource && resource->alarmType() == CalEvent::ACTIVE
1470 &&
event->category() == CalEvent::ACTIVE)
1474 KAEvent* earliest = mEarliestAlarm.value(key, (KAEvent*)0);
1476 if (replace && earliest == event)
1477 findEarliestAlarm(key);
1481 KDateTime dt =
event->nextTrigger(KAEvent::ALL_TRIGGER).effectiveKDateTime();
1483 && (!earliest || dt < earliest->nextTrigger(KAEvent::ALL_TRIGGER)))
1485 mEarliestAlarm[key] = event;
1486 emit earliestAlarmChanged();
1508 EventId newId(oldEventId.collectionId(), newEvent.id());
1510 QString newId = newEvent->id();
1512 kDebug() << oldEventId <<
"->" << newId;
1513 bool noNewId = newId.
isEmpty();
1514 if (!noNewId && oldEventId == newId)
1516 kError() <<
"Same IDs";
1521 if (mCalType == RESOURCES)
1526 KAEvent* storedEvent = event(oldEventId);
1529 kError() <<
"Old event not found";
1533 newEvent.setEventId(CalFormat::createUniqueId());
1542 deleteEventInternal(KAEvent(*storedEvent), c);
1543 if (mHaveDisabledAlarms)
1544 checkForDisabledAlarms();
1548 Event* kcalEvent = createKCalEvent(newEvent, oldEventId);
1550 kcalEvent->setUid(CalFormat::createUniqueId());
1551 AlarmResources* resources = AlarmResources::instance();
1552 AlarmResource* resource = resources->resourceForIncidence(oldEventId);
1553 if (!resources->addEvent(kcalEvent, resource))
1556 newEvent->setEventId(kcalEvent->uid());
1557 addEvent(resource, newEvent);
1558 deleteEvent(oldEventId);
1568 if (!addEvent(newEvent, 0,
true))
1570 deleteEvent(oldEventId);
1588 if (!mOpen || mCalType != RESOURCES)
1594 KAEvent newEvnt(*evnt);
1595 newEvnt.setItemId(evnt->itemId());
1604 KAEvent* kaevnt =
event(
id);
1605 Event* kcalEvent = mCalendar ? mCalendar->event(
id) : 0;
1606 if (kaevnt && kcalEvent)
1608 evnt->updateKCalEvent(kcalEvent, KAEvent::UID_CHECK);
1609 bool oldEnabled = kaevnt->enabled();
1612 findEarliestAlarm(AlarmResources::instance()->resource(kcalEvent));
1613 if (mCalType == RESOURCES && evnt->category() == CalEvent::ACTIVE)
1614 checkForDisabledAlarms(oldEnabled, evnt->enabled());
1618 kDebug() <<
"error";
1630 if (mOpen && mCalType == RESOURCES)
1632 CalEvent::Type status = deleteEventInternal(event);
1633 if (mHaveDisabledAlarms)
1634 checkForDisabledAlarms();
1635 if (status != CalEvent::EMPTY)
1651 bool AlarmCalendar::deleteDisplayEvent(
const QString& eventID,
bool saveit)
1657 if (mOpen && mCalType != RESOURCES)
1662 CalEvent::Type status = deleteEventInternal(eventID);
1663 if (mHaveDisabledAlarms)
1664 checkForDisabledAlarms();
1665 if (status != CalEvent::EMPTY)
1682 CalEvent::Type AlarmCalendar::deleteEventInternal(
const KAEvent& event,
bool deleteFromAkonadi)
1685 if (!collection.isValid())
1686 return CalEvent::EMPTY;
1687 return deleteEventInternal(event.id(),
event, collection, deleteFromAkonadi);
1690 CalEvent::Type AlarmCalendar::deleteEventInternal(
const KAEvent& event,
const Collection& collection,
bool deleteFromAkonadi)
1692 if (!collection.isValid())
1693 return CalEvent::EMPTY;
1694 if (event.collectionId() != collection.id())
1696 kError() <<
"Event" <<
event.id() <<
": collection" <<
event.collectionId() <<
"differs from 'collection'" << collection.id();
1697 return CalEvent::EMPTY;
1699 return deleteEventInternal(event.id(),
event, collection, deleteFromAkonadi);
1702 CalEvent::Type AlarmCalendar::deleteEventInternal(
const QString& eventID,
const KAEvent& event,
const Collection& collection,
bool deleteFromAkonadi)
1704 CalEvent::Type AlarmCalendar::deleteEventInternal(
const QString& eventID)
1711 const KAEvent paramEvent = event;
1713 Event::Ptr kcalEvent;
1714 if (mCalendarStorage)
1715 kcalEvent = mCalendarStorage->calendar()->event(
id);
1716 Collection::Id key = collection.isValid() ? collection.id() : -1;
1717 KAEventMap::Iterator it = mEventMap.
find(
EventId(key,
id));
1719 Event* kcalEvent = mCalendar ? mCalendar->event(
id) : 0;
1720 KAEventMap::Iterator it = mEventMap.find(
id);
1722 if (it != mEventMap.end())
1724 KAEvent* ev = it.value();
1725 mEventMap.erase(it);
1727 AlarmResource* key = AlarmResources::instance()->resource(kcalEvent);
1729 KAEvent::List& events = mResourceMap[key];
1734 if (mEarliestAlarm[key] == ev)
1736 findEarliestAlarm(collection);
1738 findEarliestAlarm(key);
1743 for (EarliestMap::Iterator eit = mEarliestAlarm.begin(); eit != mEarliestAlarm.end(); ++eit)
1745 KAEvent* ev = eit.value();
1746 if (ev && ev->id() == id)
1748 findEarliestAlarm(eit.key());
1753 CalEvent::Type status = CalEvent::EMPTY;
1756 status = CalEvent::status(kcalEvent);
1758 mCalendarStorage->calendar()->deleteEvent(kcalEvent);
1760 mCalendar->deleteEvent(kcalEvent);
1764 else if (deleteFromAkonadi)
1767 CalEvent::Type s = paramEvent.category();
1774 KConfigGroup config(KGlobal::config(), KAEvent::commandErrorConfigGroup());
1775 if (config.hasKey(
id))
1777 config.deleteEntry(
id);
1797 if (mCalType != RESOURCES)
1798 kFatal() <<
"AlarmCalendar::createKCalEvent(KAEvent): invalid for display calendar";
1802 Event* calEvent =
id.
isEmpty() ? 0 : AlarmResources::instance()->event(
id);
1803 Event* newEvent = calEvent ?
new Event(*calEvent) : new Event;
1804 ev->updateKCalEvent(newEvent, KAEvent::UID_SET);
1823 const QString eventId = uniqueID.eventId();
1824 if (uniqueID.collectionId() == -1 && checkDuplicates)
1828 KAEvent::List list = events(eventId);
1829 if (list.count() > 1)
1831 kWarning() <<
"Multiple events found with ID" << eventId;
1839 KAEventMap::ConstIterator it = mEventMap.constFind(uniqueID);
1840 if (it == mEventMap.constEnd())
1852 Q_ASSERT(mCalType != RESOURCES);
1853 if (!mCalendarStorage)
1854 return Event::Ptr();
1855 return mCalendarStorage->calendar()->event(uniqueID);
1860 return mCalendar ? mCalendar->event(uniqueID) : 0;
1872 KAEvent::List eventlist =
events(CalEvent::TEMPLATE);
1873 for (
int i = 0, end = eventlist.count(); i < end; ++i)
1875 if (eventlist[i]->templateName() == templateName)
1876 return eventlist[i];
1888 if (mCalType == RESOURCES && isValid())
1892 const Collection::Id
id = rit.key();
1914 if (mCalType != RESOURCES && (!mCalendarStorage || collection.isValid()))
1916 if (collection.isValid())
1918 if (!mCalendar || (resource && mCalType != RESOURCES))
1924 Collection::Id key = collection.isValid() ? collection.id() : -1;
1925 ResourceMap::ConstIterator rit = mResourceMap.constFind(key);
1927 ResourceMap::ConstIterator rit = mResourceMap.constFind(resource);
1929 if (rit == mResourceMap.constEnd())
1931 const KAEvent::List events = rit.value();
1932 if (type == CalEvent::EMPTY)
1934 for (
int i = 0, end = events.count(); i < end; ++i)
1935 if (type & events[i]->category())
1940 for (ResourceMap::ConstIterator rit = mResourceMap.constBegin(); rit != mResourceMap.constEnd(); ++rit)
1942 const KAEvent::List events = rit.value();
1943 if (type == CalEvent::EMPTY)
1947 for (
int i = 0, end = events.count(); i < end; ++i)
1948 if (type & events[i]->category())
1969 Q_ASSERT(mCalType != RESOURCES);
1970 if (!mCalendarStorage)
1972 list = mCalendarStorage->calendar()->rawEvents();
1974 if (!mCalendar || (resource && mCalType != RESOURCES))
1976 list = resource ? AlarmResources::instance()->rawEvents(resource) : mCalendar->rawEvents();
1978 for (
int i = 0; i < list.count(); )
1981 Event::Ptr
event = list[i];
1983 Event*
event = list[i];
1985 if (event->alarms().isEmpty()
1986 || (type != CalEvent::EMPTY && !(type & CalEvent::status(event)))
1987 || !KAEvent(event).isValid())
2006 kDebug() << from <<
"-" <<
to;
2007 KAEvent::List evnts;
2011 AlarmResources* resources = AlarmResources::instance();
2012 KAEvent::List allEvents =
events(type);
2013 for (
int i = 0, end = allEvents.count(); i < end; ++i)
2015 KAEvent*
event = allEvents[i];
2016 Event* e = resources->event(event->id());
2017 bool recurs = e->recurs();
2019 bool endOffsetValid =
false;
2020 const Alarm::List& alarms = e->alarms();
2021 for (
int ai = 0, aend = alarms.count(); ai < aend; ++ai)
2023 Alarm* alarm = alarms[ai];
2024 if (alarm->enabled())
2028 if (alarm->hasTime())
2036 if (alarm->hasStartOffset())
2037 offset = alarm->startOffset().asSeconds();
2038 else if (alarm->hasEndOffset())
2040 if (!endOffsetValid)
2042 endOffset = e->hasDuration() ? e->duration().asSeconds() : e->hasEndDate() ? e->dtStart().secsTo(e->dtEnd()) : 0;
2043 endOffsetValid =
true;
2045 offset = alarm->endOffset().asSeconds() + endOffset;
2048 KDateTime pre = from.addSecs(-offset - 1);
2050 pre = pre.addDays(-1);
2051 dt = e->recurrence()->getNextDateTime(pre);
2054 dt = dt.addSecs(offset);
2059 if (dt >= from && dt <= to)
2061 kDebug() <<
"'" << e->summary() <<
"':" << dt;
2062 evnts.append(event);
2079 if (mCalType != RESOURCES)
2083 KAEvent
event = model->
event(
id);
2086 return !
event.isValid() ||
event.isReadOnly();
2092 if (!mCalendar || mCalType != RESOURCES)
2094 AlarmResources* resources = AlarmResources::instance();
2095 const Event*
event = resources->event(uniqueID);
2096 AlarmResource* resource = resources->resource(event);
2099 return !resource->writable(event);
2107 Collection AlarmCalendar::collectionForEvent(Item::Id itemId)
const
2109 if (mCalType != RESOURCES)
2110 return Collection();
2119 if (!mCalendar || mCalType != RESOURCES)
2121 return AlarmResources::instance()->resourceForIncidence(eventID);
2130 if (event->category() == CalEvent::ACTIVE)
2132 bool status =
event->enabled();
2133 checkForDisabledAlarms(!status, status);
2141 void AlarmCalendar::checkForDisabledAlarms(
bool oldEnabled,
bool newEnabled)
2143 if (mCalType == RESOURCES && newEnabled != oldEnabled)
2145 if (newEnabled && mHaveDisabledAlarms)
2146 checkForDisabledAlarms();
2147 else if (!newEnabled && !mHaveDisabledAlarms)
2149 mHaveDisabledAlarms =
true;
2158 void AlarmCalendar::checkForDisabledAlarms()
2160 if (mCalType != RESOURCES)
2162 bool disabled =
false;
2163 KAEvent::List eventlist =
events(CalEvent::ACTIVE);
2164 for (
int i = 0, end = eventlist.count(); i < end; ++i)
2166 if (!eventlist[i]->enabled())
2172 if (disabled != mHaveDisabledAlarms)
2174 mHaveDisabledAlarms = disabled;
2184 KAEvent::List atlogins;
2186 if (mCalType != RESOURCES)
2189 if (!mCalendarStorage || mCalType != RESOURCES)
2192 if (!mCalendar || mCalType != RESOURCES)
2198 const Collection::Id
id = rit.key();
2203 const AlarmResource* resource = rit.key();
2204 if (!resource || resource->alarmType() != CalEvent::ACTIVE)
2207 const KAEvent::List& events = rit.value();
2208 for (
int i = 0, end = events.count(); i < end; ++i)
2210 KAEvent*
event = events[i];
2211 if (event->category() == CalEvent::ACTIVE &&
event->repeatAtLogin())
2222 void AlarmCalendar::findEarliestAlarm(
const Collection& collection)
2224 if (mCalType != RESOURCES)
2226 if (!collection.isValid()
2229 findEarliestAlarm(collection.id());
2232 void AlarmCalendar::findEarliestAlarm(Collection::Id key)
2234 void AlarmCalendar::findEarliestAlarm(AlarmResource* key)
2237 EarliestMap::Iterator eit = mEarliestAlarm.find(key);
2238 if (eit != mEarliestAlarm.end())
2241 if (mCalType != RESOURCES
2245 if (!mCalendar || mCalType != RESOURCES
2246 || !key || key->alarmType() != CalEvent::ACTIVE)
2249 ResourceMap::ConstIterator rit = mResourceMap.constFind(key);
2250 if (rit == mResourceMap.constEnd())
2252 const KAEvent::List& events = rit.value();
2253 KAEvent* earliest = 0;
2254 KDateTime earliestTime;
2255 for (
int i = 0, end = events.count(); i < end; ++i)
2257 KAEvent*
event = events[i];
2258 if (event->category() != CalEvent::ACTIVE
2259 || mPendingAlarms.contains(event->id()))
2261 KDateTime dt =
event->nextTrigger(KAEvent::ALL_TRIGGER).effectiveKDateTime();
2262 if (dt.isValid() && (!earliest || dt < earliestTime))
2268 mEarliestAlarm[key] = earliest;
2269 emit earliestAlarmChanged();
2278 KAEvent* earliest = 0;
2279 KDateTime earliestTime;
2282 KAEvent*
event = eit.value();
2285 KDateTime dt =
event->nextTrigger(KAEvent::ALL_TRIGGER).effectiveKDateTime();
2286 if (dt.isValid() && (!earliest || dt < earliestTime))
2302 bool wasPending = mPendingAlarms.
contains(
id);
2303 kDebug() <<
id <<
"," << pending <<
"(was" << wasPending <<
")";
2308 mPendingAlarms.
append(
id);
2320 findEarliestAlarm(AlarmResources::instance()->resourceForIncidence(
id));
2333 KAEvent::adjustStartOfDay(rit.value());
2341 KACalendar::Compat
fix(
const FileStorage::Ptr& fileStorage)
2344 int version = KACalendar::updateVersion(fileStorage, versionString);
2345 if (version == KACalendar::IncompatibleFormat)
2346 return KACalendar::Incompatible;
2347 return KACalendar::Current;
2350 #include "moc_alarmcalendar.cpp"
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)
iterator erase(iterator pos)
bool contains(const Key &key) const
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)
const_iterator constBegin() const
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 &)
const_iterator constFind(const Key &key) const
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)
int indexOf(const T &value, int from) const
static KAEvent * getEvent(const QString &uniqueId)
the KAlarm application object
Struct containing a KAEvent and its parent Collection.
KAEvent * earliestAlarm() const
int count(const T &value) const
void append(const T &value)
bool modifyEvent(const QString &oldEventId, KAEvent *newEvent)
static QTime startOfDay()
int toInt(bool *ok) const
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)
int removeAll(const T &value)
const_iterator constEnd() const
KCal::Event * createKCalEvent(const KAEvent *e) const
static void connect(const char *signal, const QObject *receiver, const char *member)
bool contains(const T &value) const
QString & replace(int position, int n, QChar after)
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()
QString fromLatin1(const char *str, int size)
Provides read and write access to calendar files and resources.
static AlarmCalendar * displayCalendarOpen()
KAEvent::List events(CalEvent::Types s=CalEvent::EMPTY) const
int find(QChar c, int i, bool cs) const
static bool exportAlarms(const KAEvent::List &, QWidget *parent)
KAEvent * event(const QString &uniqueId)
static MainWindow * mainMainWindow()
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Akonadi::Collection collectionForItem(Akonadi::Item::Id) const
void haveDisabledAlarmsChanged(bool haveDisabled)
static void displayFatalError(const QString &message)
iterator find(const Key &key)
bool addEvent(KAEvent &, Akonadi::Collection &)
int remove(const Key &key)