summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Jarvie <djarvie@kde.org>2012-02-19 00:41:04 (GMT)
committerDavid Jarvie <djarvie@kde.org>2012-02-19 00:41:04 (GMT)
commitc55b943be61cded1cedd05e9e6b04612b2d6058c (patch)
tree3f994bff12209660e92b3168cc0b863d809bff89
parent818b77885418ddd9e109584a59b9369a3ceea43a (diff)
Handle duplicate event UIDs in different calendars
Event cache is now indexed by calendar ID and event UID, which should reduce the possibility of crashes due to the wrong event being deleted if any duplicate UIDs exist. This should fix crashes (bugs 293193, 293290, 293360, and possibly 293346). Backport of 036983b5f47fec7da5778f68f0fe655b82e3a634 and f8969a48da10f0c87d4d024bc67c710bf5020638 (master)
-rw-r--r--kalarm/akonadimodel.cpp38
-rw-r--r--kalarm/akonadimodel.h9
-rw-r--r--kalarm/alarmcalendar.cpp245
-rw-r--r--kalarm/alarmcalendar.h33
-rw-r--r--kalarm/dbushandler.cpp4
-rw-r--r--kalarm/deferdlg.cpp21
-rw-r--r--kalarm/deferdlg.h14
-rw-r--r--kalarm/eventid.h57
-rw-r--r--kalarm/functions.cpp116
-rw-r--r--kalarm/functions.h16
-rw-r--r--kalarm/kalarmapp.cpp34
-rw-r--r--kalarm/mainwindow.cpp14
-rw-r--r--kalarm/messagewin.cpp132
-rw-r--r--kalarm/messagewin.h17
-rw-r--r--kalarm/undo.cpp64
-rw-r--r--kalarm/undo.h8
-rw-r--r--kalarm/wakedlg.cpp6
17 files changed, 589 insertions, 239 deletions
diff --git a/kalarm/akonadimodel.cpp b/kalarm/akonadimodel.cpp
index 9c9afff..66c470d 100644
--- a/kalarm/akonadimodel.cpp
+++ b/kalarm/akonadimodel.cpp
@@ -1260,24 +1260,37 @@ void AkonadiModel::getChildEvents(const QModelIndex& parent, CalEvent::Type type
}
#endif
-KAEvent AkonadiModel::event(const QModelIndex& index) const
-{
- return event(index.data(ItemRole).value<Item>());
-}
-
KAEvent AkonadiModel::event(Item::Id itemId) const
{
QModelIndex ix = itemIndex(itemId);
if (!ix.isValid())
return KAEvent();
- return event(ix);
+ return event(ix.data(ItemRole).value<Item>(), ix, 0);
}
-KAEvent AkonadiModel::event(const Item& item) const
+KAEvent AkonadiModel::event(const QModelIndex& index) const
+{
+ return event(index.data(ItemRole).value<Item>(), index, 0);
+}
+
+KAEvent AkonadiModel::event(const Item& item, const QModelIndex& index, Collection* collection) const
{
if (!item.isValid() || !item.hasPayload<KAEvent>())
return KAEvent();
- return item.payload<KAEvent>();
+ const QModelIndex ix = index.isValid() ? index : itemIndex(item.id());
+ if (!ix.isValid())
+ return KAEvent();
+ KAEvent e = item.payload<KAEvent>();
+ if (e.isValid())
+ {
+
+ Collection c = data(index, ParentCollectionRole).value<Collection>();
+ // Set collection ID using a const method, to avoid unnecessary copying of KAEvent
+ e.setCollectionId_const(c.id());
+ if (collection)
+ *collection = c;
+ }
+ return e;
}
#if 0
@@ -1629,10 +1642,11 @@ AkonadiModel::EventList AkonadiModel::eventList(const QModelIndex& parent, int s
EventList events;
for (int row = start; row <= end; ++row)
{
+ Collection c;
QModelIndex ix = index(row, 0, parent);
- KAEvent evnt = event(ix.data(ItemRole).value<Item>());
+ KAEvent evnt = event(ix.data(ItemRole).value<Item>(), ix, &c);
if (evnt.isValid())
- events += Event(evnt, data(ix, ParentCollectionRole).value<Collection>());
+ events += Event(evnt, c);
}
return events;
}
@@ -1734,7 +1748,9 @@ void AkonadiModel::slotMonitoredItemChanged(const Akonadi::Item& item, const QSe
{
// Wait to ensure that the base EntityTreeModel has processed the
// itemChanged() signal first, before we emit eventChanged().
- mPendingEventChanges.enqueue(Event(evnt, data(index, ParentCollectionRole).value<Collection>()));
+ Collection c = data(index, ParentCollectionRole).value<Collection>();
+ evnt.setCollectionId(c.id());
+ mPendingEventChanges.enqueue(Event(evnt, c));
QTimer::singleShot(0, this, SLOT(slotEmitEventChanged()));
break;
}
diff --git a/kalarm/akonadimodel.h b/kalarm/akonadimodel.h
index 8517a27..0b4fcad 100644
--- a/kalarm/akonadimodel.h
+++ b/kalarm/akonadimodel.h
@@ -1,7 +1,7 @@
/*
* akonadimodel.h - KAlarm calendar file access using Akonadi
* Program: kalarm
- * Copyright © 2010-2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2010-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,6 +21,8 @@
#ifndef AKONADIMODEL_H
#define AKONADIMODEL_H
+#include "eventid.h"
+
#include <kalarmcal/kacalendar.h>
#include <kalarmcal/kaevent.h>
@@ -75,6 +77,8 @@ class AkonadiModel : public Akonadi::EntityTreeModel
struct Event
{
Event(const KAEvent& e, const Akonadi::Collection& c) : event(e), collection(c) {}
+ EventId eventId() const { return EventId(collection.id(), event.id()); }
+ bool isConsistent() const { return event.collectionId() == collection.id(); }
KAEvent event;
Akonadi::Collection collection;
};
@@ -140,7 +144,7 @@ class AkonadiModel : public Akonadi::EntityTreeModel
/** Return the alarm with the specified unique identifier.
* @return the event, or invalid event if no such event exists.
*/
- KAEvent event(const Akonadi::Item&) const;
+ KAEvent event(const Akonadi::Item& item) const { return event(item, QModelIndex(), 0); }
KAEvent event(Akonadi::Item::Id) const;
KAEvent event(const QModelIndex&) const;
using QObject::event; // prevent warning about hidden virtual method
@@ -275,6 +279,7 @@ class AkonadiModel : public Akonadi::EntityTreeModel
};
AkonadiModel(Akonadi::ChangeRecorder*, QObject* parent);
+ KAEvent event(const Akonadi::Item&, const QModelIndex&, Akonadi::Collection*) const;
QString alarmTimeText(const DateTime&) const;
QString timeToAlarmText(const DateTime&) const;
void signalDataChanged(bool (*checkFunc)(const Akonadi::Item&), int startColumn, int endColumn, const QModelIndex& parent);
diff --git a/kalarm/alarmcalendar.cpp b/kalarm/alarmcalendar.cpp
index 7db96e4..dba225b 100644
--- a/kalarm/alarmcalendar.cpp
+++ b/kalarm/alarmcalendar.cpp
@@ -133,15 +133,24 @@ AlarmCalendar* AlarmCalendar::displayCalendarOpen()
* Find and return the event with the specified ID.
* The calendar searched is determined by the calendar identifier in the ID.
*/
-KAEvent* AlarmCalendar::getEvent(const QString& uniqueID)
+#ifdef USE_AKONADI
+KAEvent* AlarmCalendar::getEvent(const EventId& eventId)
{
- if (uniqueID.isEmpty())
+ if (eventId.eventId().isEmpty())
return 0;
- KAEvent* event = mResourcesCalendar->event(uniqueID);
+ return mResourcesCalendar->event(eventId);
+}
+#else
+KAEvent* AlarmCalendar::getEvent(const QString& uniqueId)
+{
+ if (uniqueId.isEmpty())
+ return 0;
+ KAEvent* event = mResourcesCalendar->event(uniqueId);
if (!event)
- event = mDisplayCalendar->event(uniqueID);
+ event = mDisplayCalendar->event(uniqueId);
return event;
}
+#endif
/******************************************************************************
* Constructor for the resources calendar.
@@ -355,7 +364,7 @@ int AlarmCalendar::load()
mLocalFile = tmpFile;
#ifdef USE_AKONADI
fix(mCalendarStorage); // convert events to current KAlarm format for when calendar is saved
- updateKAEvents(Collection());
+ updateDisplayKAEvents();
#else
CalendarCompat::fix(*calendar, mLocalFile); // convert events to current KAlarm format for when calendar is saved
updateKAEvents(0, calendar);
@@ -539,16 +548,18 @@ void AlarmCalendar::updateResourceKAEvents(AlarmResource* resource, KCal::Calend
#endif
#ifdef USE_AKONADI
-void AlarmCalendar::updateKAEvents(const Collection& collection)
+void AlarmCalendar::updateDisplayKAEvents()
#else
void AlarmCalendar::updateKAEvents(AlarmResource* resource, KCal::CalendarLocal* cal)
#endif
{
#ifdef USE_AKONADI
- kDebug() << "AlarmCalendar::updateKAEvents(" << (collection.isValid() ? collection.name() : "0") << ")";
- Collection::Id key = collection.isValid() ? collection.id() : -1;
+ if (mCalType == RESOURCES)
+ return;
+ kDebug();
+ Collection::Id key = -1;
#else
- kDebug() << "AlarmCalendar::updateKAEvents(" << (resource ? resource->resourceName() : "0") << ")";
+ kDebug() << (resource ? resource->resourceName() : "0");
AlarmResource* key = resource;
#endif
KAEvent::List& events = mResourceMap[key];
@@ -556,7 +567,11 @@ void AlarmCalendar::updateKAEvents(AlarmResource* resource, KCal::CalendarLocal*
for (i = 0, end = events.count(); i < end; ++i)
{
KAEvent* event = events[i];
+#ifdef USE_AKONADI
+ mEventMap.remove(EventId(key, event->id()));
+#else
mEventMap.remove(event->id());
+#endif
delete event;
}
events.clear();
@@ -588,13 +603,15 @@ void AlarmCalendar::updateKAEvents(AlarmResource* resource, KCal::CalendarLocal*
delete event;
continue; // ignore events without usable alarms
}
-#ifndef USE_AKONADI
+#ifdef USE_AKONADI
+ event->setCollectionId(key);
+ events += event;
+ mEventMap[EventId(key, kcalevent->uid())] = event;
+#else
event->setResource(resource);
-#endif
events += event;
mEventMap[kcalevent->uid()] = event;
-#ifndef USE_AKONADI
// Set any command execution error flags for the alarm.
// These are stored in the KAlarm config file, not the alarm
// calendar, since they are specific to the user's local system.
@@ -604,13 +621,11 @@ void AlarmCalendar::updateKAEvents(AlarmResource* resource, KCal::CalendarLocal*
#endif
}
+#ifndef USE_AKONADI
// Now scan the list of alarms to find the earliest one to trigger
-#ifdef USE_AKONADI
- findEarliestAlarm(collection);
-#else
findEarliestAlarm(resource);
-#endif
checkForDisabledAlarms();
+#endif
}
#ifdef USE_AKONADI
@@ -631,9 +646,14 @@ void AlarmCalendar::removeKAEvents(Collection::Id key, bool closing, CalEvent::T
for (int i = 0, end = events.count(); i < end; ++i)
{
KAEvent* event = events[i];
- if (event->category() & types)
+ bool remove = (event->collectionId() != key);
+ if (remove)
+ kError() << "Event" << event->id() << ", collection" << event->collectionId() << "Indexed under collection" << key;
+ else
+ remove = event->category() & types;
+ if (remove)
{
- mEventMap.remove(event->id());
+ mEventMap.remove(EventId(key, event->id()));
delete event;
removed = true;
}
@@ -719,11 +739,32 @@ void AlarmCalendar::slotEventsAdded(const AkonadiModel::EventList& events)
*/
void AlarmCalendar::slotEventChanged(const AkonadiModel::Event& event)
{
- bool added = !mEventMap.contains(event.event.id());
- if (added)
+ if (!event.isConsistent())
+ {
+ kError() << "Inconsistent AkonadiModel::Event: event:" << event.event.collectionId() << ", collection" << event.collection.id();
+ return;
+ }
+
+ bool added = true;
+ bool updated = false;
+ KAEventMap::Iterator it = mEventMap.find(event.eventId());
+ if (it != mEventMap.end())
+ {
+ // The event ID already exists - remove the existing event first
+ KAEvent* storedEvent = it.value();
+ if (event.event.category() == storedEvent->category())
+ {
+ // The existing event is the same type - update it in place
+ *storedEvent = event.event;
+ addNewEvent(event.collection, storedEvent, true);
+ updated = true;
+ }
+ else
+ delete storedEvent;
+ added = false;
+ }
+ if (!updated)
addNewEvent(event.collection, new KAEvent(event.event));
- else
- updateEventInternal(event.event, event.collection);
bool enabled = event.event.enabled();
checkForDisabledAlarms(!enabled, enabled);
@@ -740,48 +781,12 @@ void AlarmCalendar::slotEventsToBeRemoved(const AkonadiModel::EventList& events)
{
for (int i = 0, count = events.count(); i < count; ++i)
{
- if (mEventMap.contains(events[i].event.id()))
+ if (!events[i].isConsistent())
+ kError() << "Inconsistent AkonadiModel::Event: event:" << events[i].event.collectionId() << ", collection" << events[i].collection.id();
+ else if (mEventMap.contains(events[i].eventId()))
deleteEventInternal(events[i].event, events[i].collection, false);
}
}
-
-/******************************************************************************
-* Update an event already held by AlarmCalendar.
-*/
-void AlarmCalendar::updateEventInternal(const KAEvent& event, const Collection& collection)
-{
- KAEventMap::Iterator it = mEventMap.find(event.id());
- if (it != mEventMap.end())
- {
- // The event ID already exists - remove the existing event first
- // from all resources.
- KAEvent* storedEvent = it.value();
-#ifdef __GNUC__
-#warning This assumes the uniqueness of event IDs across all resources
-#endif
- if (mResourceMap[collection.id()].contains(storedEvent)
- && event.category() == storedEvent->category())
- {
- // The existing event is in the correct collection - update it in place
- *storedEvent = event;
- addNewEvent(collection, storedEvent, true);
- return;
- }
- // First remove the event from other collections
- mEventMap.erase(it);
- for (ResourceMap::Iterator rit = mResourceMap.begin(); rit != mResourceMap.end(); ++rit)
- {
- KAEvent::List& events = rit.value();
- int i = events.indexOf(storedEvent);
- if (i >= 0)
- events.remove(i);
- if (mEarliestAlarm[rit.key()] == storedEvent)
- findEarliestAlarm(Collection(rit.key()));
- }
- delete storedEvent;
- }
- addNewEvent(collection, new KAEvent(event));
-}
#else
void AlarmCalendar::slotResourceChange(AlarmResource* resource, AlarmResources::Change change)
@@ -1193,11 +1198,13 @@ bool AlarmCalendar::save()
void AlarmCalendar::purgeEvents(const KAEvent::List& events)
{
for (int i = 0, end = events.count(); i < end; ++i)
+ {
#ifdef USE_AKONADI
deleteEventInternal(*events[i]);
#else
deleteEventInternal(events[i]->id());
#endif
+ }
if (mHaveDisabledAlarms)
checkForDisabledAlarms();
saveCal();
@@ -1305,7 +1312,8 @@ bool AlarmCalendar::addEvent(KAEvent* event, QWidget* promptParent, bool useEven
#endif
{
#ifdef USE_AKONADI
- // Don't add event to mEventMap yet - its Akonadi item id is not yet known
+ // Don't add event to mEventMap yet - its Akonadi item id is not yet known.
+ // It will be added once it is inserted into AkonadiModel.
ok = AkonadiModel::instance()->addEvent(*event, col);
remove = ok; // if success, delete the local event instance on exit
#else
@@ -1319,29 +1327,35 @@ bool AlarmCalendar::addEvent(KAEvent* event, QWidget* promptParent, bool useEven
}
else
{
+ // It's the display calendar
#ifdef USE_AKONADI
event->updateKCalEvent(kcalEvent, KAEvent::UID_IGNORE);
key = -1;
- if (addEvent(Collection(), event))
+ if (!mEventMap.contains(EventId(key, event->id())))
+ {
+ addNewEvent(Collection(), event);
+ ok = mCalendarStorage->calendar()->addEvent(kcalEvent);
+ remove = !ok;
+ }
#else
key = 0;
if (addEvent(0, event))
-#endif
{
-#ifdef USE_AKONADI
- ok = mCalendarStorage->calendar()->addEvent(kcalEvent);
-#else
ok = mCalendar->addEvent(kcalEvent);
-#endif
remove = !ok;
}
+#endif
}
if (!ok)
{
if (remove)
{
// Adding to mCalendar failed, so undo AlarmCalendar::addEvent()
+#ifdef USE_AKONADI
+ mEventMap.remove(EventId(key, event->id()));
+#else
mEventMap.remove(event->id());
+#endif
KAEvent::List& events = mResourceMap[key];
int i = events.indexOf(event);
if (i >= 0)
@@ -1365,17 +1379,14 @@ bool AlarmCalendar::addEvent(KAEvent* event, QWidget* promptParent, bool useEven
return true;
}
+#ifndef USE_AKONADI
/******************************************************************************
* Internal method to add an event to the calendar.
* The calendar takes ownership of 'event'.
* Reply = true if success
* = false if error because the event ID already exists.
*/
-#ifdef USE_AKONADI
-bool AlarmCalendar::addEvent(const Collection& resource, KAEvent* event)
-#else
bool AlarmCalendar::addEvent(AlarmResource* resource, KAEvent* event)
-#endif
{
kDebug() << "KAEvent:" << event->id();
if (mEventMap.contains(event->id()))
@@ -1384,7 +1395,6 @@ bool AlarmCalendar::addEvent(AlarmResource* resource, KAEvent* event)
return true;
}
-#ifndef USE_AKONADI
/******************************************************************************
* Internal method to add an event to the calendar.
* Reply = event as stored in calendar
@@ -1416,18 +1426,18 @@ void AlarmCalendar::addNewEvent(AlarmResource* resource, KAEvent* event)
{
#ifdef USE_AKONADI
Collection::Id key = collection.isValid() ? collection.id() : -1;
+ event->setCollectionId(key);
if (!replace)
{
-#else
- AlarmResource* key = resource;
-#endif
mResourceMap[key] += event;
- mEventMap[event->id()] = event;
-#ifdef USE_AKONADI
+ mEventMap[EventId(key, event->id())] = event;
}
if (collection.isValid() && (AkonadiModel::types(collection) & CalEvent::ACTIVE)
&& event->category() == CalEvent::ACTIVE)
#else
+ AlarmResource* key = resource;
+ mResourceMap[key] += event;
+ mEventMap[event->id()] = event;
if (resource && resource->alarmType() == CalEvent::ACTIVE
&& event->category() == CalEvent::ACTIVE)
#endif
@@ -1461,13 +1471,13 @@ void AlarmCalendar::addNewEvent(AlarmResource* resource, KAEvent* event)
* = false if an error occurred, in which case 'newEvent' is unchanged.
*/
#ifdef USE_AKONADI
-bool AlarmCalendar::modifyEvent(const QString& oldEventId, KAEvent& newEvent)
+bool AlarmCalendar::modifyEvent(const EventId& oldEventId, KAEvent& newEvent)
#else
bool AlarmCalendar::modifyEvent(const QString& oldEventId, KAEvent* newEvent)
#endif
{
#ifdef USE_AKONADI
- QString newId = newEvent.id();
+ EventId newId(oldEventId.collectionId(), newEvent.id());
#else
QString newId = newEvent->id();
#endif
@@ -1485,23 +1495,23 @@ bool AlarmCalendar::modifyEvent(const QString& oldEventId, KAEvent* newEvent)
#ifdef USE_AKONADI
// Set the event's ID and Akonadi ID, and update the old
// event in Akonadi.
- KAEvent* oldEvent = event(oldEventId);
- if (!oldEvent)
+ KAEvent* storedEvent = event(oldEventId);
+ if (!storedEvent)
{
kError() << "Old event not found";
return false;
}
if (noNewId)
newEvent.setEventId(CalFormat::createUniqueId());
- Entity::Id oldItemId = oldEvent->itemId();
- Collection c = AkonadiModel::instance()->collectionForItem(oldItemId);
+ Collection c = AkonadiModel::instance()->collectionById(oldEventId.collectionId());
if (!c.isValid())
return false;
// Don't add new event to mEventMap yet - its Akonadi item id is not yet known
if (!AkonadiModel::instance()->addEvent(newEvent, c))
return false;
- KAEvent ev(*oldEvent); // deleteEventInternal() will delete oldEvent before using event parameter
- deleteEventInternal(KAEvent(*oldEvent), c);
+ // Note: deleteEventInternal() will delete storedEvent before using the
+ // event parameter, so need to pass a copy as the parameter.
+ deleteEventInternal(KAEvent(*storedEvent), c);
if (mHaveDisabledAlarms)
checkForDisabledAlarms();
#else
@@ -1550,7 +1560,7 @@ KAEvent* AlarmCalendar::updateEvent(const KAEvent* evnt)
if (!mOpen || mCalType != RESOURCES)
return 0;
#ifdef USE_AKONADI
- KAEvent* kaevnt = event(evnt->id());
+ KAEvent* kaevnt = event(EventId(*evnt));
if (kaevnt)
{
KAEvent newEvnt(*evnt);
@@ -1641,10 +1651,24 @@ bool AlarmCalendar::deleteEvent(const QString& eventID, bool saveit)
* = CalEvent::EMPTY otherwise.
*/
#ifdef USE_AKONADI
+CalEvent::Type AlarmCalendar::deleteEventInternal(const KAEvent& event, bool deleteFromAkonadi)
+{
+ Collection collection = AkonadiModel::instance()->collectionById(event.collectionId());
+ if (!collection.isValid())
+ return CalEvent::EMPTY;
+ return deleteEventInternal(event.id(), event, collection, deleteFromAkonadi);
+}
+
CalEvent::Type AlarmCalendar::deleteEventInternal(const KAEvent& event, const Collection& collection, bool deleteFromAkonadi)
{
- Collection col = collection.isValid() ? collection : AkonadiModel::instance()->collection(event);
- return deleteEventInternal(event.id(), event, col, deleteFromAkonadi);
+ if (!collection.isValid())
+ return CalEvent::EMPTY;
+ if (event.collectionId() != collection.id())
+ {
+ kError() << "Event" << event.id() << ": collection" << event.collectionId() << "differs from 'collection'" << collection.id();
+ return CalEvent::EMPTY;
+ }
+ return deleteEventInternal(event.id(), event, collection, deleteFromAkonadi);
}
CalEvent::Type AlarmCalendar::deleteEventInternal(const QString& eventID, const KAEvent& event, const Collection& collection, bool deleteFromAkonadi)
@@ -1661,17 +1685,17 @@ CalEvent::Type AlarmCalendar::deleteEventInternal(const QString& eventID)
Event::Ptr kcalEvent;
if (mCalendarStorage)
kcalEvent = mCalendarStorage->calendar()->event(id);
+ Collection::Id key = collection.isValid() ? collection.id() : -1;
+ KAEventMap::Iterator it = mEventMap.find(EventId(key, id));
#else
Event* kcalEvent = mCalendar ? mCalendar->event(id) : 0;
-#endif
KAEventMap::Iterator it = mEventMap.find(id);
+#endif
if (it != mEventMap.end())
{
KAEvent* ev = it.value();
mEventMap.erase(it);
-#ifdef USE_AKONADI
- Collection::Id key = collection.isValid() ? collection.id() : -1;
-#else
+#ifndef USE_AKONADI
AlarmResource* key = AlarmResources::instance()->resource(kcalEvent);
#endif
KAEvent::List& events = mResourceMap[key];
@@ -1757,7 +1781,11 @@ Event* AlarmCalendar::createKCalEvent(const KAEvent* ev, const QString& baseID)
/******************************************************************************
* Return the event with the specified ID.
*/
+#ifdef USE_AKONADI
+KAEvent* AlarmCalendar::event(const EventId& uniqueID)
+#else
KAEvent* AlarmCalendar::event(const QString& uniqueID)
+#endif
{
if (!isValid())
return 0;
@@ -1776,7 +1804,7 @@ Event::Ptr AlarmCalendar::kcalEvent(const QString& uniqueID)
{
Q_ASSERT(mCalType != RESOURCES); // only allowed for display calendar
if (!mCalendarStorage)
- return Event::Ptr();
+ return Event::Ptr();
return mCalendarStorage->calendar()->event(uniqueID);
}
#else
@@ -1803,14 +1831,35 @@ KAEvent* AlarmCalendar::templateEvent(const QString& templateName)
return 0;
}
+#ifdef USE_AKONADI
+/******************************************************************************
+* Return all events with the specified ID, from all calendars.
+*/
+KAEvent::List AlarmCalendar::events(const QString& uniqueId) const
+{
+ KAEvent::List list;
+ if (mCalType == RESOURCES && isValid())
+ {
+ for (ResourceMap::ConstIterator rit = mResourceMap.constBegin(); rit != mResourceMap.constEnd(); ++rit)
+ {
+ const Collection::Id id = rit.key();
+ KAEventMap::ConstIterator it = mEventMap.constFind(EventId(id, uniqueId));
+ if (it != mEventMap.constEnd())
+ list += it.value();
+ }
+ }
+ return list;
+}
+#endif
+
/******************************************************************************
* Return all events in the calendar which contain alarms.
* Optionally the event type can be filtered, using an OR of event types.
*/
#ifdef USE_AKONADI
-KAEvent::List AlarmCalendar::events(const Collection& collection, CalEvent::Types type)
+KAEvent::List AlarmCalendar::events(const Collection& collection, CalEvent::Types type) const
#else
-KAEvent::List AlarmCalendar::events(AlarmResource* resource, CalEvent::Types type)
+KAEvent::List AlarmCalendar::events(AlarmResource* resource, CalEvent::Types type) const
#endif
{
KAEvent::List list;
@@ -2099,12 +2148,12 @@ KAEvent::List AlarmCalendar::atLoginAlarms() const
for (ResourceMap::ConstIterator rit = mResourceMap.constBegin(); rit != mResourceMap.constEnd(); ++rit)
{
#ifdef USE_AKONADI
- Collection::Id id = rit.key();
+ const Collection::Id id = rit.key();
if (id < 0
|| !(AkonadiModel::types(model->collectionById(id)) & CalEvent::ACTIVE))
continue;
#else
- AlarmResource* resource = rit.key();
+ const AlarmResource* resource = rit.key();
if (!resource || resource->alarmType() != CalEvent::ACTIVE)
continue;
#endif
diff --git a/kalarm/alarmcalendar.h b/kalarm/alarmcalendar.h
index 0ab08f7..4274fb4 100644
--- a/kalarm/alarmcalendar.h
+++ b/kalarm/alarmcalendar.h
@@ -1,7 +1,7 @@
/*
* alarmcalendar.h - KAlarm calendar file access
* Program: kalarm
- * Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2001-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,6 +23,7 @@
#ifdef USE_AKONADI
#include "akonadimodel.h"
+#include "eventid.h"
#else
#include "alarmresources.h"
#endif
@@ -33,6 +34,7 @@
#include <akonadi/collection.h>
#include <kcalcore/filestorage.h>
#include <kcalcore/event.h>
+#include <QHash>
#endif
#include <kurl.h>
#include <QObject>
@@ -78,19 +80,21 @@ class AlarmCalendar : public QObject
KAEvent::List atLoginAlarms() const;
#ifdef USE_AKONADI
KCalCore::Event::Ptr kcalEvent(const QString& uniqueID); // if Akonadi, display calendar only
+ KAEvent* event(const EventId& uniqueId);
#else
KCal::Event* createKCalEvent(const KAEvent* e) const
{ return createKCalEvent(e, QString()); }
- KCal::Event* kcalEvent(const QString& uniqueID); // if Akonadi, display calendar only
+ KCal::Event* kcalEvent(const QString& uniqueId); // if Akonadi, display calendar only
+ KAEvent* event(const QString& uniqueId);
#endif
- KAEvent* event(const QString& uniqueID);
KAEvent* templateEvent(const QString& templateName);
#ifdef USE_AKONADI
- KAEvent::List events(CalEvent::Types s = CalEvent::EMPTY) { return events(Akonadi::Collection(), s); }
- KAEvent::List events(const Akonadi::Collection&, CalEvent::Types = CalEvent::EMPTY);
+ KAEvent::List events(const QString& uniqueId) const;
+ KAEvent::List events(CalEvent::Types s = CalEvent::EMPTY) const { return events(Akonadi::Collection(), s); }
+ KAEvent::List events(const Akonadi::Collection&, CalEvent::Types = CalEvent::EMPTY) const;
#else
- KAEvent::List events(CalEvent::Types s = CalEvent::EMPTY) { return events(0, s); }
- KAEvent::List events(AlarmResource*, CalEvent::Types = CalEvent::EMPTY);
+ KAEvent::List events(CalEvent::Types s = CalEvent::EMPTY) const { return events(0, s); }
+ KAEvent::List events(AlarmResource*, CalEvent::Types = CalEvent::EMPTY) const;
KAEvent::List events(const KDateTime& from, const KDateTime& to, CalEvent::Types);
#endif
#ifdef USE_AKONADI
@@ -98,7 +102,7 @@ class AlarmCalendar : public QObject
bool eventReadOnly(Akonadi::Item::Id) const;
Akonadi::Collection collectionForEvent(Akonadi::Item::Id) const;
bool addEvent(KAEvent&, QWidget* promptParent = 0, bool useEventID = false, Akonadi::Collection* = 0, bool noPrompt = false, bool* cancelled = 0);
- bool modifyEvent(const QString& oldEventId, KAEvent& newEvent);
+ bool modifyEvent(const EventId& oldEventId, KAEvent& newEvent);
#else
KCal::Event::List kcalEvents(CalEvent::Type s = CalEvent::EMPTY) { return kcalEvents(0, s); }
KCal::Event::List kcalEvents(AlarmResource*, CalEvent::Type = CalEvent::EMPTY);
@@ -127,12 +131,13 @@ class AlarmCalendar : public QObject
static AlarmCalendar* displayCalendar() { return mDisplayCalendar; }
static AlarmCalendar* displayCalendarOpen();
#ifdef USE_AKONADI
+ static KAEvent* getEvent(const EventId&);
static bool importAlarms(QWidget*, Akonadi::Collection* = 0);
#else
+ static KAEvent* getEvent(const QString& uniqueId);
static bool importAlarms(QWidget*, AlarmResource* = 0);
#endif
static bool exportAlarms(const KAEvent::List&, QWidget* parent);
- static KAEvent* getEvent(const QString& uniqueID);
signals:
void earliestAlarmChanged();
@@ -161,25 +166,25 @@ class AlarmCalendar : public QObject
#ifdef USE_AKONADI
typedef QMap<Akonadi::Collection::Id, KAEvent::List> ResourceMap; // id = invalid for display calendar
typedef QMap<Akonadi::Collection::Id, KAEvent*> EarliestMap;
+ typedef QHash<EventId, KAEvent*> KAEventMap; // indexed by collection and event UID
#else
typedef QMap<AlarmResource*, KAEvent::List> ResourceMap; // resource = null for display calendar
typedef QMap<AlarmResource*, KAEvent*> EarliestMap;
-#endif
typedef QMap<QString, KAEvent*> KAEventMap; // indexed by event UID
+#endif
AlarmCalendar();
AlarmCalendar(const QString& file, CalEvent::Type);
bool saveCal(const QString& newFile = QString());
#ifdef USE_AKONADI
bool isValid() const { return mCalType == RESOURCES || mCalendarStorage; }
- bool addEvent(const Akonadi::Collection&, KAEvent*);
void addNewEvent(const Akonadi::Collection&, KAEvent*, bool replace = false);
- void updateEventInternal(const KAEvent&, const Akonadi::Collection&);
- CalEvent::Type deleteEventInternal(const KAEvent&, const Akonadi::Collection& = Akonadi::Collection(),
+ CalEvent::Type deleteEventInternal(const KAEvent&, bool deleteFromAkonadi = true);
+ CalEvent::Type deleteEventInternal(const KAEvent&, const Akonadi::Collection&,
bool deleteFromAkonadi = true);
CalEvent::Type deleteEventInternal(const QString& eventID, const KAEvent& = KAEvent(),
const Akonadi::Collection& = Akonadi::Collection(), bool deleteFromAkonadi = true);
- void updateKAEvents(const Akonadi::Collection&);
+ void updateDisplayKAEvents();
void removeKAEvents(Akonadi::Collection::Id, bool closing = false, CalEvent::Types = CalEvent::ACTIVE | CalEvent::ARCHIVED | CalEvent::TEMPLATE);
void findEarliestAlarm(const Akonadi::Collection&);
void findEarliestAlarm(Akonadi::Collection::Id); //deprecated
diff --git a/kalarm/dbushandler.cpp b/kalarm/dbushandler.cpp
index 83d754e..ffac899 100644
--- a/kalarm/dbushandler.cpp
+++ b/kalarm/dbushandler.cpp
@@ -1,7 +1,7 @@
/*
* dbushandler.cpp - handler for D-Bus calls by other applications
* Program: kalarm
- * Copyright © 2002-2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2002-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -242,7 +242,7 @@ bool DBusHandler::scheduleAudio(const QString& audioUrl, int volumePercent, cons
bool DBusHandler::edit(const QString& eventID)
{
- return KAlarm::editAlarm(eventID);
+ return KAlarm::editAlarmById(eventID);
}
bool DBusHandler::editNew(int type)
diff --git a/kalarm/deferdlg.cpp b/kalarm/deferdlg.cpp
index 306729c..0d676b1 100644
--- a/kalarm/deferdlg.cpp
+++ b/kalarm/deferdlg.cpp
@@ -1,7 +1,7 @@
/*
* deferdlg.cpp - dialog to defer an alarm
* Program: kalarm
- * Copyright © 2002-2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2002-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -77,10 +77,10 @@ void DeferAlarmDlg::slotOk()
return;
KAEvent::DeferLimitType limitType;
DateTime endTime;
- if (!mLimitEventID.isEmpty())
+ if (!mLimitEventId.isEmpty())
{
// Get the event being deferred
- const KAEvent* event = AlarmCalendar::getEvent(mLimitEventID);
+ const KAEvent* event = AlarmCalendar::getEvent(mLimitEventId);
if (event)
endTime = event->deferralLimit(&limitType);
}
@@ -141,7 +141,7 @@ void DeferAlarmDlg::slotPastLimit()
*/
void DeferAlarmDlg::setLimit(const DateTime& limit)
{
- mLimitEventID .clear();
+ mLimitEventId.clear();
mLimitDateTime = limit;
mTimeWidget->setMaxDateTime(mLimitDateTime);
}
@@ -150,11 +150,16 @@ void DeferAlarmDlg::setLimit(const DateTime& limit)
* Set the time limit for deferral based on the next occurrence of the alarm
* with the specified ID.
*/
-DateTime DeferAlarmDlg::setLimit(const QString& eventID)
+DateTime DeferAlarmDlg::setLimit(const KAEvent& event)
{
- mLimitEventID = eventID;
- const KAEvent* event = AlarmCalendar::getEvent(mLimitEventID);
- mLimitDateTime = event ? event->deferralLimit() : DateTime();
+#ifdef USE_AKONADI
+ Q_ASSERT(event.collectionId() >= 0);
+ mLimitEventId = EventId(event);
+#else
+ mLimitEventId = event.id();
+#endif
+ const KAEvent* evnt = AlarmCalendar::getEvent(mLimitEventId);
+ mLimitDateTime = evnt ? evnt->deferralLimit() : DateTime();
mTimeWidget->setMaxDateTime(mLimitDateTime);
return mLimitDateTime;
}
diff --git a/kalarm/deferdlg.h b/kalarm/deferdlg.h
index 8bff6c1..ec8d12f 100644
--- a/kalarm/deferdlg.h
+++ b/kalarm/deferdlg.h
@@ -1,7 +1,7 @@
/*
* deferdlg.h - dialog to defer an alarm
* Program: kalarm
- * Copyright © 2002-2004,2006,2007-2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2002-2004,2006,2007-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,10 +21,14 @@
#ifndef DEFERDLG_H
#define DEFERDLG_H
+#include "eventid.h"
+
#include <kalarmcal/datetime.h>
+#include <akonadi/collection.h>
#include <kdialog.h>
class AlarmTimeWidget;
+namespace KAlarmCal { class KAEvent; }
using namespace KAlarmCal;
@@ -35,7 +39,7 @@ class DeferAlarmDlg : public KDialog
public:
DeferAlarmDlg(const DateTime& initialDT, bool anyTimeOption, bool cancelButton, QWidget* parent = 0);
void setLimit(const DateTime&);
- DateTime setLimit(const QString& eventID);
+ DateTime setLimit(const KAEvent& event);
const DateTime& getDateTime() const { return mAlarmDateTime; }
void setDeferMinutes(int mins);
int deferMinutes() const { return mDeferMinutes; }
@@ -51,7 +55,11 @@ class DeferAlarmDlg : public KDialog
AlarmTimeWidget* mTimeWidget;
DateTime mAlarmDateTime;
DateTime mLimitDateTime; // latest date/time allowed for deferral
- QString mLimitEventID; // event from whose recurrences to derive the limit date/time for deferral
+#ifdef USE_AKONADI
+ EventId mLimitEventId; // event IDs from whose recurrences to derive the limit date/time for deferral
+#else
+ QString mLimitEventId; // event from whose recurrences to derive the limit date/time for deferral
+#endif
int mDeferMinutes; // number of minutes deferral selected, or 0 if date/time entered
};
diff --git a/kalarm/eventid.h b/kalarm/eventid.h
new file mode 100644
index 0000000..03c07d5
--- /dev/null
+++ b/kalarm/eventid.h
@@ -0,0 +1,57 @@
+/*
+ * eventid.h - KAlarm unique event identifier for Akonadi
+ * Program: kalarm
+ * Copyright © 2012 by David Jarvie <djarvie@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef EVENTID_H
+#define EVENTID_H
+
+#include <kalarmcal/kaevent.h>
+#include <QPair>
+#include <QDebug>
+
+using namespace KAlarmCal;
+
+/**
+ * Unique event identifier for Akonadi.
+ * This consists of the event UID within the individual calendar,
+ * plus the collection ID.
+ *
+ * Note that the collection ID of the display calendar is -1, since
+ * it is not an Akonadi calendar.
+ */
+struct EventId : public QPair<Akonadi::Collection::Id, QString>
+{
+ EventId() {}
+ EventId(Akonadi::Collection::Id c, const QString& e)
+ : QPair<Akonadi::Collection::Id, QString>(c, e) {}
+ explicit EventId(const KAEvent& event)
+ : QPair<Akonadi::Collection::Id, QString>(event.collectionId(), event.id()) {}
+ void clear() { first = -1; second.clear(); }
+ /** Return whether the instance contains any data. */
+ bool isEmpty() const { return second.isEmpty(); }
+
+ Akonadi::Collection::Id collectionId() const { return first; }
+ QString eventId() const { return second; }
+};
+
+inline QDebug operator<<(QDebug s, const EventId& id) { return s << id.eventId(); }
+
+#endif // EVENTID_H
+
+// vim: et sw=4:
diff --git a/kalarm/functions.cpp b/kalarm/functions.cpp
index 0ee2e13..33e27fb 100644
--- a/kalarm/functions.cpp
+++ b/kalarm/functions.cpp
@@ -1,7 +1,7 @@
/*
* functions.cpp - miscellaneous functions
* Program: kalarm
- * Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2001-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -482,13 +482,21 @@ UpdateStatus modifyEvent(KAEvent& oldEvent, KAEvent& newEvent, QWidget* msgParen
}
else
{
+#ifdef USE_AKONADI
+ EventId oldId(oldEvent);
+#else
QString oldId = oldEvent.id();
+#endif
if (oldEvent.copyToKOrganizer())
{
// Tell KOrganizer to delete its old event.
// But ignore errors, because the user could have manually
// deleted it since KAlarm asked KOrganizer to set it up.
+#ifdef USE_AKONADI
+ deleteFromKOrganizer(oldId.eventId());
+#else
deleteFromKOrganizer(oldId);
+#endif
}
#ifdef USE_AKONADI
// Update the event in the calendar file, and get the new event ID
@@ -687,7 +695,11 @@ UpdateStatus deleteEvents(KAEvent::List& events, bool archive, QWidget* msgParen
deleteWakeFromSuspendAlarm = true;
// Remove "Don't show error messages again" for this alarm
+#ifdef USE_AKONADI
+ setDontShowErrors(EventId(*event));
+#else
setDontShowErrors(id);
+#endif
}
if (warnErr == events.count())
@@ -786,10 +798,11 @@ UpdateStatus reactivateEvent(KAEvent& event, Collection* calendar, QWidget* msgP
UpdateStatus reactivateEvent(KAEvent& event, AlarmResource* calendar, QWidget* msgParent, bool showKOrgErr)
#endif
{
- QStringList ids;
#ifdef USE_AKONADI
+ QVector<EventId> ids;
QVector<KAEvent> events(1, event);
#else
+ QStringList ids;
KAEvent::List events;
events += &event;
#endif
@@ -797,7 +810,7 @@ UpdateStatus reactivateEvent(KAEvent& event, AlarmResource* calendar, QWidget* m
}
#ifdef USE_AKONADI
-UpdateStatus reactivateEvents(QVector<KAEvent>& events, QStringList& ineligibleIDs, Collection* col, QWidget* msgParent, bool showKOrgErr)
+UpdateStatus reactivateEvents(QVector<KAEvent>& events, QVector<EventId>& ineligibleIDs, Collection* col, QWidget* msgParent, bool showKOrgErr)
#else
UpdateStatus reactivateEvents(KAEvent::List& events, QStringList& ineligibleIDs, AlarmResource* resource, QWidget* msgParent, bool showKOrgErr)
#endif
@@ -843,7 +856,11 @@ UpdateStatus reactivateEvents(KAEvent::List& events, QStringList& ineligibleIDs,
if (event->category() != CalEvent::ARCHIVED
|| !event->occursAfter(now, true))
{
+#ifdef USE_AKONADI
+ ineligibleIDs += EventId(*event);
+#else
ineligibleIDs += event->id();
+#endif
continue;
}
++count;
@@ -893,7 +910,7 @@ UpdateStatus reactivateEvents(KAEvent::List& events, QStringList& ineligibleIDs,
#endif
#ifdef USE_AKONADI
- if (cal->event(event->id()) // no error if event doesn't exist in archived resource
+ if (cal->event(EventId(*event)) // no error if event doesn't exist in archived resource
&& !cal->deleteEvent(*event, false)) // don't save calendar after deleting
#else
if (cal->event(oldid) // no error if event doesn't exist in archived resource
@@ -967,7 +984,11 @@ UpdateStatus enableEvents(KAEvent::List& events, bool enable, QWidget* msgParent
// If we're disabling a display alarm, close any message window
if (!enable && (event->actionTypes() & KAEvent::ACT_DISPLAY))
{
+#ifdef USE_AKONADI
+ MessageWin* win = MessageWin::findEvent(EventId(*event));
+#else
MessageWin* win = MessageWin::findEvent(event->id());
+#endif
delete win;
}
@@ -1255,16 +1276,26 @@ void editNewTemplate(const KAEvent* preset, QWidget* parent)
* if so, delete it from the config if it has expired.
* If 'checkExists' is true, the config entry will only be returned if the
* event exists.
-* Reply = config entry: [0] = event ID, [1] = trigger time (time_t).
+* Reply = config entry: [0] = event's collection ID (Akonadi only),
+* [1] = event ID,
+* [2] = trigger time (time_t).
* = empty list if none or expired.
*/
QStringList checkRtcWakeConfig(bool checkEventExists)
{
KConfigGroup config(KGlobal::config(), "General");
QStringList params = config.readEntry("RtcWake", QStringList());
+#ifdef USE_AKONADI
+ if (params.count() == 3 && params[2].toUInt() > KDateTime::currentUtcDateTime().toTime_t())
+#else
if (params.count() == 2 && params[1].toUInt() > KDateTime::currentUtcDateTime().toTime_t())
+#endif
{
+#ifdef USE_AKONADI
+ if (checkEventExists && !AlarmCalendar::getEvent(EventId(params[0].toLongLong(), params[1])))
+#else
if (checkEventExists && !AlarmCalendar::getEvent(params[0]))
+#endif
return QStringList();
return params; // config entry is valid
}
@@ -1426,7 +1457,11 @@ void editAlarm(KAEvent* event, QWidget* parent)
viewAlarm(event, parent);
return;
}
+#ifdef USE_AKONADI
+ EventId id(*event);
+#else
QString id = event->id();
+#endif
// Use AutoQPointer to guard against crash on application exit while
// the dialogue is still open. It prevents double deletion (both on
// deletion of parent, and on return from this function).
@@ -1469,18 +1504,30 @@ void editAlarm(KAEvent* event, QWidget* parent)
}
/******************************************************************************
-* Display the alarm edit dialog to edit a specified alarm.
-* An error occurs if the alarm is read-only or expired.
+* Display the alarm edit dialog to edit the alarm with the specified ID.
+* An error occurs if the alarm is not found, if there is more than one alarm
+* with the same ID, or if it is read-only or expired.
*/
-bool editAlarm(const QString& eventID, QWidget* parent)
+bool editAlarmById(const QString& eventID, QWidget* parent)
{
+#ifdef USE_AKONADI
+ KAEvent::List events = AlarmCalendar::resources()->events(eventID);
+ if (events.count() > 1)
+ {
+ kWarning() << eventID << ": multiple events found";
+ return false;
+ }
+ if (events.isEmpty())
+#else
KAEvent* event = AlarmCalendar::resources()->event(eventID);
if (!event)
+#endif
{
kError() << eventID << ": event ID not found";
return false;
}
#ifdef USE_AKONADI
+ KAEvent* event = events[0];
if (AlarmCalendar::resources()->eventReadOnly(event->itemId()))
#else
if (AlarmCalendar::resources()->eventReadOnly(eventID))
@@ -1579,7 +1626,11 @@ void updateEditedAlarm(EditAlarmDlg* editDlg, KAEvent& event, AlarmResource* cal
// Update the displayed lists and the calendar file
UpdateStatus status;
+#ifdef USE_AKONADI
+ if (AlarmCalendar::resources()->event(EventId(event)))
+#else
if (AlarmCalendar::resources()->event(event.id()))
+#endif
{
// The old alarm hasn't expired yet, so replace it
Undo::Event undo(event, calendar);
@@ -1677,7 +1728,11 @@ void refreshAlarmsIfQueued()
KAEvent* event = events[i];
if (!event->enabled() && (event->actionTypes() & KAEvent::ACT_DISPLAY))
{
+#ifdef USE_AKONADI
+ MessageWin* win = MessageWin::findEvent(EventId(*event));
+#else
MessageWin* win = MessageWin::findEvent(event->id());
+#endif
delete win;
}
}
@@ -1805,22 +1860,35 @@ void Private::windowAdded(WId w)
/******************************************************************************
* Return the Don't-show-again error message tags set for a specified alarm ID.
*/
+#ifdef USE_AKONADI
+QStringList dontShowErrors(const EventId& eventId)
+#else
QStringList dontShowErrors(const QString& eventId)
+#endif
{
if (eventId.isEmpty())
return QStringList();
KConfig config(KStandardDirs::locateLocal("appdata", ALARM_OPTS_FILE));
KConfigGroup group(&config, DONT_SHOW_ERRORS_GROUP);
- return group.readEntry(eventId, QStringList());
+#ifdef USE_AKONADI
+ const QString id = QString("%1:%2").arg(eventId.collectionId()).arg(eventId.eventId());
+#else
+ const QString id(eventId);
+#endif
+ return group.readEntry(id, QStringList());
}
/******************************************************************************
* Check whether the specified Don't-show-again error message tag is set for an
* alarm ID.
*/
+#ifdef USE_AKONADI
+bool dontShowErrors(const EventId& eventId, const QString& tag)
+#else
bool dontShowErrors(const QString& eventId, const QString& tag)
+#endif
{
- if (tag.isEmpty() || eventId.isEmpty())
+ if (tag.isEmpty())
return false;
QStringList tags = dontShowErrors(eventId);
return tags.indexOf(tag) >= 0;
@@ -1830,16 +1898,25 @@ bool dontShowErrors(const QString& eventId, const QString& tag)
* Reset the Don't-show-again error message tags for an alarm ID.
* If 'tags' is empty, the config entry is deleted.
*/
+#ifdef USE_AKONADI
+void setDontShowErrors(const EventId& eventId, const QStringList& tags)
+#else
void setDontShowErrors(const QString& eventId, const QStringList& tags)
+#endif
{
if (eventId.isEmpty())
return;
KConfig config(KStandardDirs::locateLocal("appdata", ALARM_OPTS_FILE));
KConfigGroup group(&config, DONT_SHOW_ERRORS_GROUP);
+#ifdef USE_AKONADI
+ const QString id = QString("%1:%2").arg(eventId.collectionId()).arg(eventId.eventId());
+#else
+ const QString id(eventId);
+#endif
if (tags.isEmpty())
- group.deleteEntry(eventId);
+ group.deleteEntry(id);
else
- group.writeEntry(eventId, tags);
+ group.writeEntry(id, tags);
group.sync();
}
@@ -1847,17 +1924,26 @@ void setDontShowErrors(const QString& eventId, const QStringList& tags)
* Set the specified Don't-show-again error message tag for an alarm ID.
* Existing tags are unaffected.
*/
+#ifdef USE_AKONADI
+void setDontShowErrors(const EventId& eventId, const QString& tag)
+#else
void setDontShowErrors(const QString& eventId, const QString& tag)
+#endif
{
- if (tag.isEmpty() || eventId.isEmpty())
+ if (eventId.isEmpty() || tag.isEmpty())
return;
KConfig config(KStandardDirs::locateLocal("appdata", ALARM_OPTS_FILE));
KConfigGroup group(&config, DONT_SHOW_ERRORS_GROUP);
- QStringList tags = group.readEntry(eventId, QStringList());
+#ifdef USE_AKONADI
+ const QString id = QString("%1:%2").arg(eventId.collectionId()).arg(eventId.eventId());
+#else
+ const QString id(eventId);
+#endif
+ QStringList tags = group.readEntry(id, QStringList());
if (tags.indexOf(tag) < 0)
{
tags += tag;
- group.writeEntry(eventId, tags);
+ group.writeEntry(id, tags);
group.sync();
}
}
diff --git a/kalarm/functions.h b/kalarm/functions.h
index 2b984b2..75d892b 100644
--- a/kalarm/functions.h
+++ b/kalarm/functions.h
@@ -1,7 +1,7 @@
/*
* functions.h - miscellaneous functions
* Program: kalarm
- * Copyright © 2004-2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2004-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,6 +24,9 @@
/** @file functions.h - miscellaneous functions */
#include "editdlg.h"
+#ifdef USE_AKONADI
+#include "eventid.h"
+#endif
#include <kalarmcal/kaevent.h>
#ifdef USE_AKONADI
@@ -105,7 +108,7 @@ bool editNewAlarm(const QString& templateName, QWidget* parent =
void editNewAlarm(EditAlarmDlg::Type, QWidget* parent = 0);
void editNewAlarm(KAEvent::SubAction, QWidget* parent = 0, const AlarmText* = 0);
void editNewAlarm(const KAEvent* preset, QWidget* parent = 0);
-bool editAlarm(const QString& eventID, QWidget* parent = 0);
+bool editAlarmById(const QString& eventID, QWidget* parent = 0);
void editAlarm(KAEvent*, QWidget* parent = 0);
#ifdef USE_AKONADI
void updateEditedAlarm(EditAlarmDlg*, KAEvent&, Akonadi::Collection&);
@@ -130,9 +133,16 @@ void refreshAlarms();
void refreshAlarmsIfQueued(); // must only be called from KAlarmApp::processQueue()
QString runKMail(bool minimise);
+#ifdef USE_AKONADI
+QStringList dontShowErrors(const EventId&);
+bool dontShowErrors(const EventId&, const QString& tag);
+void setDontShowErrors(const EventId&, const QStringList& tags = QStringList());
+void setDontShowErrors(const EventId&, const QString& tag);
+#else
QStringList dontShowErrors(const QString& eventId);
bool dontShowErrors(const QString& eventId, const QString& tag);
void setDontShowErrors(const QString& eventId, const QStringList& tags = QStringList());
+#endif
void setDontShowErrors(const QString& eventId, const QString& tag);
enum // 'options' parameter values for addEvent(). May be OR'ed together.
@@ -172,7 +182,7 @@ inline UpdateStatus deleteTemplate(const QString& eventID, QWidget* msgParent =
void deleteDisplayEvent(const QString& eventID);
#ifdef USE_AKONADI
UpdateStatus reactivateEvent(KAEvent&, Akonadi::Collection* = 0, QWidget* msgParent = 0, bool showKOrgErr = true);
-UpdateStatus reactivateEvents(QVector<KAEvent>&, QStringList& ineligibleIDs, Akonadi::Collection* = 0, QWidget* msgParent = 0, bool showKOrgErr = true);
+UpdateStatus reactivateEvents(QVector<KAEvent>&, QVector<EventId>& ineligibleIDs, Akonadi::Collection* = 0, QWidget* msgParent = 0, bool showKOrgErr = true);
UpdateStatus enableEvents(QVector<KAEvent>&, bool enable, QWidget* msgParent = 0);
#else
UpdateStatus reactivateEvent(KAEvent&, AlarmResource* = 0, QWidget* msgParent = 0, bool showKOrgErr = true);
diff --git a/kalarm/kalarmapp.cpp b/kalarm/kalarmapp.cpp
index f590b3b..c9b0e5d 100644
--- a/kalarm/kalarmapp.cpp
+++ b/kalarm/kalarmapp.cpp
@@ -340,7 +340,7 @@ int KAlarmApp::newInstance()
// Edit a specified existing alarm
if (!initCheck())
exitCode = 1;
- else if (!KAlarm::editAlarm(options.eventId()))
+ else if (!KAlarm::editAlarmById(options.eventId()))
{
CommandOptions::printError(i18nc("@info:shell", "<icode>%1</icode>: Event <resource>%2</resource> not found, or not editable", QString::fromLatin1("--edit"), options.eventId()));
exitCode = 1;
@@ -1243,19 +1243,33 @@ bool KAlarmApp::dbusHandleEvent(const QString& eventID, EventFunc function)
* c) Reschedule the event for its next repetition. If none remain, delete it.
* If the event is deleted, it is removed from the calendar file and from every
* main window instance.
-* Reply = false if event ID not found.
+* Reply = false if event ID not found, or if more than one event with the same
+* ID is found.
*/
bool KAlarmApp::handleEvent(const QString& eventID, EventFunc function)
{
// Delete any expired wake-on-suspend config data
KAlarm::checkRtcWakeConfig();
+#ifdef USE_AKONADI
+ KAEvent::List events = AlarmCalendar::resources()->events(eventID);
+ if (events.count() > 1)
+ {
+ kWarning() << "Multiple events found with ID" << eventID;
+ return false;
+ }
+ if (events.isEmpty())
+#else
KAEvent* event = AlarmCalendar::resources()->event(eventID);
if (!event)
+#endif
{
kWarning() << "Event ID not found:" << eventID;
return false;
}
+#ifdef USE_AKONADI
+ KAEvent* event = events[0];
+#endif
switch (function)
{
case EVENT_CANCEL:
@@ -1673,7 +1687,11 @@ void* KAlarmApp::execAlarm(KAEvent& event, const KAAlarm& alarm, bool reschedule
{
// Display a message, file or command output, provided that the same event
// isn't already being displayed
+#ifdef USE_AKONADI
+ MessageWin* win = MessageWin::findEvent(EventId(event));
+#else
MessageWin* win = MessageWin::findEvent(event.id());
+#endif
// Find if we're changing a reminder message to the real message
bool reminder = (alarm.type() & KAAlarm::REMINDER_ALARM);
bool replaceReminder = !reminder && win && (win->alarmType() & KAAlarm::REMINDER_ALARM);
@@ -1777,7 +1795,11 @@ void* KAlarmApp::execAlarm(KAEvent& event, const KAAlarm& alarm, bool reschedule
{
// Play the sound, provided that the same event
// isn't already playing
+#ifdef USE_AKONADI
+ MessageWin* win = MessageWin::findEvent(EventId(event));
+#else
MessageWin* win = MessageWin::findEvent(event.id());
+#endif
if (!win)
{
// There isn't already a message for this event.
@@ -2238,7 +2260,11 @@ void setEventCommandError(const KAEvent& event, KAEvent::CmdErrType err)
if (err == KAEvent::CMD_ERROR_POST && event.commandError() == KAEvent::CMD_ERROR_PRE)
err = KAEvent::CMD_ERROR_PRE_POST;
event.setCommandError(err);
+#ifdef USE_AKONADI
+ KAEvent* ev = AlarmCalendar::resources()->event(EventId(event));
+#else
KAEvent* ev = AlarmCalendar::resources()->event(event.id());
+#endif
if (ev && ev->commandError() != err)
ev->setCommandError(err);
#ifdef USE_AKONADI
@@ -2252,7 +2278,11 @@ void clearEventCommandError(const KAEvent& event, KAEvent::CmdErrType err)
{
KAEvent::CmdErrType newerr = static_cast<KAEvent::CmdErrType>(event.commandError() & ~err);
event.setCommandError(newerr);
+#ifdef USE_AKONADI
+ KAEvent* ev = AlarmCalendar::resources()->event(EventId(event));
+#else
KAEvent* ev = AlarmCalendar::resources()->event(event.id());
+#endif
if (ev)
{
newerr = static_cast<KAEvent::CmdErrType>(ev->commandError() & ~err);
diff --git a/kalarm/mainwindow.cpp b/kalarm/mainwindow.cpp
index faa5e56..db7d11e 100644
--- a/kalarm/mainwindow.cpp
+++ b/kalarm/mainwindow.cpp
@@ -1,7 +1,7 @@
/*
* mainwindow.cpp - main application window
* Program: kalarm
- * Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2001-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -882,18 +882,22 @@ void MainWindow::slotReactivate()
// Add the alarms to the displayed lists and to the calendar file
Undo::EventList undos;
+#ifdef USE_AKONADI
+ QVector<EventId> ineligibleIDs;
+ KAlarm::reactivateEvents(events, ineligibleIDs, 0, this);
+#else
QStringList ineligibleIDs;
KAlarm::reactivateEvents(events, ineligibleIDs, 0, this);
+#endif
// Create the undo list, excluding ineligible events
AlarmCalendar* resources = AlarmCalendar::resources();
for (int i = 0, end = events.count(); i < end; ++i)
{
#ifdef USE_AKONADI
- if (!ineligibleIDs.contains(events[i].id()))
+ if (!ineligibleIDs.contains(EventId(events[i])))
{
- Akonadi::Collection c = resources->collectionForEvent(events[i].itemId());
- undos.append(events[i], c);
+ undos.append(events[i], resources->collectionForEvent(events[i].itemId()));
}
#else
QString id = events[i]->id();
@@ -1590,7 +1594,7 @@ void MainWindow::slotSelection()
for (int i = 0; i < count; ++i)
{
#ifdef USE_AKONADI
- KAEvent* ev = resources->event(events[i].id()); // get up-to-date status
+ KAEvent* ev = resources->event(EventId(events[i])); // get up-to-date status
KAEvent* event = ev ? ev : &events[i];
#else
KAEvent* event = events[i];
diff --git a/kalarm/messagewin.cpp b/kalarm/messagewin.cpp
index aa48ce7..0d0263e 100644
--- a/kalarm/messagewin.cpp
+++ b/kalarm/messagewin.cpp
@@ -161,7 +161,11 @@ enum {
QList<MessageWin*> MessageWin::mWindowList;
+#ifdef USE_AKONADI
+QMap<EventId, unsigned> MessageWin::mErrorMessages;
+#else
QMap<QString, unsigned> MessageWin::mErrorMessages;
+#endif
// There can only be one audio thread at a time: trying to play multiple
// sound files simultaneously would result in a cacophony, and besides
// that, Phonon currently crashes...
@@ -182,8 +186,10 @@ MessageWin::MessageWin(const KAEvent* event, const KAAlarm& alarm, int flags)
mFgColour(event->fgColour()),
#ifdef USE_AKONADI
mEventItemId(event->itemId()),
+ mEventId(*event),
+#else
+ mEventId(event->id()),
#endif
- mEventID(event->id()),
mAudioFile(event->audioFile()),
mVolume(event->soundVolume()),
mFadeVolume(event->fadeVolume()),
@@ -207,7 +213,7 @@ MessageWin::MessageWin(const KAEvent* event, const KAAlarm& alarm, int flags)
#ifdef USE_AKONADI
mCollection(AlarmCalendar::resources()->collectionForEvent(mEventItemId)),
#else
- mResource(AlarmCalendar::resources()->resourceForEvent(mEventID)),
+ mResource(AlarmCalendar::resources()->resourceForEvent(mEventId)),
#endif
mTimeLabel(0),
mRemainingText(0),
@@ -254,9 +260,9 @@ MessageWin::MessageWin(const KAEvent* event, const KAAlarm& alarm, int flags)
#ifdef USE_AKONADI
bool readonly = AlarmCalendar::resources()->eventReadOnly(mEventItemId);
#else
- bool readonly = AlarmCalendar::resources()->eventReadOnly(mEventID);
+ bool readonly = AlarmCalendar::resources()->eventReadOnly(mEventId);
#endif
- mShowEdit = !mEventID.isEmpty() && !readonly;
+ mShowEdit = !mEventId.isEmpty() && !readonly;
mNoDefer = readonly || (flags & NO_DEFER) || alarm.repeatAtLogin();
initView();
}
@@ -281,16 +287,26 @@ MessageWin::MessageWin(const KAEvent* event, const KAAlarm& alarm, int flags)
void MessageWin::showError(const KAEvent& event, const DateTime& alarmDateTime,
const QStringList& errmsgs, const QString& dontShowAgain)
{
+#ifdef USE_AKONADI
+ if (!dontShowAgain.isEmpty()
+ && KAlarm::dontShowErrors(EventId(event), dontShowAgain))
+#else
if (!dontShowAgain.isEmpty()
&& KAlarm::dontShowErrors(event.id(), dontShowAgain))
+#endif
return;
// Don't pile up duplicate error messages for the same alarm
for (int i = 0, end = mWindowList.count(); i < end; ++i)
{
MessageWin* w = mWindowList[i];
- if (w->mErrorWindow && w->mEventID == event.id()
+#ifdef USE_AKONADI
+ if (w->mErrorWindow && w->mEventId == EventId(event)
+ && w->mErrorMsgs == errmsgs && w->mDontShowAgain == dontShowAgain)
+#else
+ if (w->mErrorWindow && w->mEventId == event.id()
&& w->mErrorMsgs == errmsgs && w->mDontShowAgain == dontShowAgain)
+#endif
return;
}
@@ -309,8 +325,10 @@ MessageWin::MessageWin(const KAEvent* event, const DateTime& alarmDateTime,
mDateTime(alarmDateTime),
#ifdef USE_AKONADI
mEventItemId(event->itemId()),
+ mEventId(*event),
+#else
+ mEventId(event->id()),
#endif
- mEventID(event->id()),
mAlarmType(KAAlarm::MAIN_ALARM),
mAction(event->actionSubType()),
mKMailSerialNumber(0),
@@ -396,10 +414,10 @@ MessageWin::MessageWin()
*/
MessageWin::~MessageWin()
{
- kDebug() << mEventID;
+ kDebug() << mEventId;
if (mAudioOwner == this && mAudioThread)
mAudioThread->quit();
- mErrorMessages.remove(mEventID);
+ mErrorMessages.remove(mEventId);
mWindowList.removeAll(this);
if (!mRecreating)
{
@@ -974,13 +992,15 @@ void MessageWin::saveProperties(KConfigGroup& config)
{
if (mShown && !mErrorWindow && !mAlwaysHide)
{
- config.writeEntry("EventID", mEventID);
#ifdef USE_AKONADI
+ config.writeEntry("EventID", mEventId.eventId());
config.writeEntry("EventItemID", mEventItemId);
+#else
+ config.writeEntry("EventID", mEventId);
#endif
config.writeEntry("AlarmType", static_cast<int>(mAlarmType));
if (mAlarmType == KAAlarm::INVALID_ALARM)
- kError() << "Invalid alarm: id=" << mEventID << ", alarm count=" << mEvent.alarmCount();
+ kError() << "Invalid alarm: id=" << mEventId << ", alarm count=" << mEvent.alarmCount();
config.writeEntry("Message", mMessage);
config.writeEntry("Type", static_cast<int>(mAction));
config.writeEntry("Font", mFont);
@@ -1033,15 +1053,18 @@ void MessageWin::saveProperties(KConfigGroup& config)
void MessageWin::readProperties(const KConfigGroup& config)
{
mInvalid = config.readEntry("Invalid", false);
- mEventID = config.readEntry("EventID");
#ifdef USE_AKONADI
mEventItemId = config.readEntry("EventItemID", Akonadi::Item::Id(-1));
+ mCollection = AkonadiModel::instance()->collectionForItem(mEventItemId);
+ mEventId = EventId(mCollection.id(), config.readEntry("EventID"));
+#else
+ mEventId = config.readEntry("EventID");
#endif
mAlarmType = static_cast<KAAlarm::Type>(config.readEntry("AlarmType", 0));
if (mAlarmType == KAAlarm::INVALID_ALARM)
{
mInvalid = true;
- kError() << "Invalid alarm: id=" << mEventID;
+ kError() << "Invalid alarm: id=" << mEventId;
}
mMessage = config.readEntry("Message");
mAction = static_cast<KAEvent::SubAction>(config.readEntry("Type", 0));
@@ -1088,20 +1111,18 @@ void MessageWin::readProperties(const KConfigGroup& config)
#else
mResource = 0;
#endif
- kDebug() << mEventID;
+ kDebug() << mEventId;
if (mAlarmType != KAAlarm::INVALID_ALARM)
{
// Recreate the event from the calendar file (if possible)
- if (!mEventID.isEmpty())
+ if (!mEventId.isEmpty())
{
- KAEvent* event = AlarmCalendar::resources()->event(mEventID);
+ KAEvent* event = AlarmCalendar::resources()->event(mEventId);
if (event)
{
mEvent = *event;
-#ifdef USE_AKONADI
- mCollection = AkonadiModel::instance()->collectionForItem(mEventItemId);
-#else
- mResource = AlarmCalendar::resources()->resourceForEvent(mEventID);
+#ifndef USE_AKONADI
+ mResource = AlarmCalendar::resources()->resourceForEvent(mEventId);
#endif
mShowEdit = true;
}
@@ -1143,10 +1164,11 @@ void MessageWin::redisplayAlarms()
bool showDefer, showEdit;
#ifdef USE_AKONADI
reinstateFromDisplaying(events[i], event, collection, showEdit, showDefer);
+ if (!findEvent(EventId(event)))
#else
reinstateFromDisplaying(events[i], event, resource, showEdit, showDefer);
-#endif
if (!findEvent(event.id()))
+#endif
{
// This event should be displayed, but currently isn't being
KAAlarm alarm = event.convertDisplayingAlarm();
@@ -1186,26 +1208,36 @@ bool MessageWin::retrieveEvent(KAEvent& event, AlarmResource*& resource, bool& s
#endif
{
#ifdef USE_AKONADI
- Event::Ptr kcalEvent = AlarmCalendar::displayCalendar()->kcalEvent(CalEvent::uid(mEventID, CalEvent::DISPLAYING));
+ Event::Ptr kcalEvent = AlarmCalendar::displayCalendar()->kcalEvent(CalEvent::uid(mEventId.eventId(), CalEvent::DISPLAYING));
#else
- const Event* kcalEvent = AlarmCalendar::displayCalendar()->kcalEvent(CalEvent::uid(mEventID, CalEvent::DISPLAYING));
+ const Event* kcalEvent = AlarmCalendar::displayCalendar()->kcalEvent(CalEvent::uid(mEventId, CalEvent::DISPLAYING));
#endif
if (!reinstateFromDisplaying(kcalEvent, event, resource, showEdit, showDefer))
{
// The event isn't in the displaying calendar.
// Try to retrieve it from the archive calendar.
- KAEvent* ev = AlarmCalendar::resources()->event(CalEvent::uid(mEventID, CalEvent::ARCHIVED));
+#ifdef USE_AKONADI
+ KAEvent* ev = 0;
+ Akonadi::Collection archiveCol = CollectionControlModel::getStandard(CalEvent::ARCHIVED);
+ if (archiveCol.isValid())
+ ev = AlarmCalendar::resources()->event(EventId(archiveCol.id(), CalEvent::uid(mEventId.eventId(), CalEvent::ARCHIVED)));
+#else
+ KAEvent* ev = AlarmCalendar::resources()->event(CalEvent::uid(mEventId, CalEvent::ARCHIVED));
+#endif
if (!ev)
return false;
event = *ev;
event.setArchive(); // ensure that it gets re-archived if it's saved
event.setCategory(CalEvent::ACTIVE);
- if (mEventID != event.id())
- kError() << "Wrong event ID";
- event.setEventId(mEventID);
#ifdef USE_AKONADI
+ if (mEventId.eventId() != event.id())
+ kError() << "Wrong event ID";
+ event.setEventId(mEventId.eventId());
resource = Akonadi::Collection();
#else
+ if (mEventId != event.id())
+ kError() << "Wrong event ID";
+ event.setEventId(mEventId);
resource = 0;
#endif
showEdit = true;
@@ -1374,14 +1406,18 @@ bool MessageWin::isSpread(const QPoint& topLeft)
* Returns the existing message window (if any) which is displaying the event
* with the specified ID.
*/
-MessageWin* MessageWin::findEvent(const QString& eventID)
+#ifdef USE_AKONADI
+MessageWin* MessageWin::findEvent(const EventId& eventId)
+#else
+MessageWin* MessageWin::findEvent(const QString& eventId)
+#endif
{
- if (!eventID.isEmpty())
+ if (!eventId.isEmpty())
{
for (int i = 0, end = mWindowList.count(); i < end; ++i)
{
MessageWin* w = mWindowList[i];
- if (w->mEventID == eventID && !w->mErrorWindow)
+ if (w->mEventId == eventId && !w->mErrorWindow)
return w;
}
}
@@ -1725,7 +1761,7 @@ void MessageWin::repeat(const KAAlarm& alarm)
delete mDeferDlg;
mDeferDlg = 0;
}
- KAEvent* event = mEventID.isNull() ? 0 : AlarmCalendar::resources()->event(mEventID);
+ KAEvent* event = mEventId.isEmpty() ? 0 : AlarmCalendar::resources()->event(mEventId);
if (event)
{
mAlarmType = alarm.type(); // store new alarm type for use if it is later deferred
@@ -2012,10 +2048,14 @@ void MessageWin::closeEvent(QCloseEvent* ce)
return;
}
}
- if (!mEventID.isNull())
+ if (!mEventId.isEmpty())
{
// Delete from the display calendar
- KAlarm::deleteDisplayEvent(CalEvent::uid(mEventID, CalEvent::DISPLAYING));
+#ifdef USE_AKONADI
+ KAlarm::deleteDisplayEvent(CalEvent::uid(mEventId.eventId(), CalEvent::DISPLAYING));
+#else
+ KAlarm::deleteDisplayEvent(CalEvent::uid(mEventId, CalEvent::DISPLAYING));
+#endif
}
}
MainWindowBase::closeEvent(ce);
@@ -2027,7 +2067,7 @@ void MessageWin::closeEvent(QCloseEvent* ce)
void MessageWin::slotOk()
{
if (mDontShowAgainCheck && mDontShowAgainCheck->isChecked())
- KAlarm::setDontShowErrors(mEventID, mDontShowAgain);
+ KAlarm::setDontShowErrors(mEventId, mDontShowAgain);
close();
}
@@ -2183,7 +2223,7 @@ void MessageWin::slotDefer()
mDeferDlg = new DeferAlarmDlg(KDateTime::currentDateTime(Preferences::timeZone()).addSecs(60), mDateTime.isDateOnly(), false, this);
mDeferDlg->setObjectName("DeferDlg"); // used by LikeBack
mDeferDlg->setDeferMinutes(mDefaultDeferMinutes > 0 ? mDefaultDeferMinutes : Preferences::defaultDeferTime());
- mDeferDlg->setLimit(mEventID);
+ mDeferDlg->setLimit(mEvent);
if (!Preferences::modalMessages())
lower();
if (mDeferDlg->exec() == QDialog::Accepted)
@@ -2192,11 +2232,11 @@ void MessageWin::slotDefer()
int delayMins = mDeferDlg->deferMinutes();
// Fetch the up-to-date alarm from the calendar. Note that it could have
// changed since it was displayed.
- const KAEvent* event = mEventID.isNull() ? 0 : AlarmCalendar::resources()->event(mEventID);
+ const KAEvent* event = mEventId.isEmpty() ? 0 : AlarmCalendar::resources()->event(mEventId);
if (event)
{
// The event still exists in the active calendar
- kDebug() << "Deferring event" << mEventID;
+ kDebug() << "Deferring event" << mEventId;
KAEvent newev(*event);
newev.defer(dateTime, (mAlarmType & KAAlarm::REMINDER_ALARM), true);
newev.setDeferDefaultMinutes(delayMins);
@@ -2230,7 +2270,7 @@ void MessageWin::slotDefer()
mEditButton->setEnabled(false);
return;
}
- kDebug() << "Deferring retrieved event" << mEventID;
+ kDebug() << "Deferring retrieved event" << mEventId;
event.defer(dateTime, (mAlarmType & KAAlarm::REMINDER_ALARM), true);
event.setDeferDefaultMinutes(delayMins);
event.setCommandError(mCommandError);
@@ -2272,7 +2312,7 @@ void MessageWin::displayMainWindow()
#ifdef USE_AKONADI
KAlarm::displayMainWindowSelected(mEventItemId);
#else
- KAlarm::displayMainWindowSelected(mEventID);
+ KAlarm::displayMainWindowSelected(mEventId);
#endif
}
@@ -2283,21 +2323,21 @@ void MessageWin::displayMainWindow()
*/
bool MessageWin::haveErrorMessage(unsigned msg) const
{
- if (!mErrorMessages.contains(mEventID))
- mErrorMessages.insert(mEventID, 0);
- bool result = (mErrorMessages[mEventID] & msg);
- mErrorMessages[mEventID] |= msg;
+ if (!mErrorMessages.contains(mEventId))
+ mErrorMessages.insert(mEventId, 0);
+ bool result = (mErrorMessages[mEventId] & msg);
+ mErrorMessages[mEventId] |= msg;
return result;
}
void MessageWin::clearErrorMessage(unsigned msg) const
{
- if (mErrorMessages.contains(mEventID))
+ if (mErrorMessages.contains(mEventId))
{
- if (mErrorMessages[mEventID] == msg)
- mErrorMessages.remove(mEventID);
+ if (mErrorMessages[mEventId] == msg)
+ mErrorMessages.remove(mEventId);
else
- mErrorMessages[mEventID] &= ~msg;
+ mErrorMessages[mEventId] &= ~msg;
}
}
diff --git a/kalarm/messagewin.h b/kalarm/messagewin.h
index d09ec52..b5fb709 100644
--- a/kalarm/messagewin.h
+++ b/kalarm/messagewin.h
@@ -1,7 +1,7 @@
/*
* messagewin.h - displays an alarm message
* Program: kalarm
- * Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2001-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
/** @file messagewin.h - displays an alarm message */
#include "autoqpointer.h"
+#include "eventid.h"
#include "mainwindowbase.h"
#include <kalarmcal/kaevent.h>
@@ -80,7 +81,11 @@ class MessageWin : public MainWindowBase
virtual void show();
virtual QSize sizeHint() const;
static int instanceCount(bool excludeAlwaysHidden = false);
- static MessageWin* findEvent(const QString& eventID);
+#ifdef USE_AKONADI
+ static MessageWin* findEvent(const EventId& eventId);
+#else
+ static MessageWin* findEvent(const QString& eventId);
+#endif
static void redisplayAlarms();
static void stopAudio(bool wait = false);
static bool isAudioPlaying();
@@ -145,7 +150,11 @@ class MessageWin : public MainWindowBase
static bool isSpread(const QPoint& topLeft);
static QList<MessageWin*> mWindowList; // list of existing message windows
+#ifdef USE_AKONADI
+ static QMap<EventId, unsigned> mErrorMessages; // error messages currently displayed, by event ID
+#else
static QMap<QString, unsigned> mErrorMessages; // error messages currently displayed, by event ID
+#endif
// Sound file playing
static QPointer<AudioThread> mAudioThread; // thread to play audio file
static MessageWin* mAudioOwner; // window which owns mAudioThread
@@ -157,8 +166,10 @@ class MessageWin : public MainWindowBase
QDateTime mCloseTime; // local time at which window should be auto-closed
#ifdef USE_AKONADI
Akonadi::Item::Id mEventItemId;
+ EventId mEventId;
+#else
+ QString mEventId;
#endif
- QString mEventID;
QString mAudioFile;
float mVolume;
float mFadeVolume;
diff --git a/kalarm/undo.cpp b/kalarm/undo.cpp
index 65712aa..b80f866 100644
--- a/kalarm/undo.cpp
+++ b/kalarm/undo.cpp
@@ -1,7 +1,7 @@
/*
* undo.cpp - undo/redo facility
* Program: kalarm
- * Copyright © 2005-2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2005-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,7 +42,7 @@ static int maxCount = 12;
// Simplify access to Undo::Event struct
#ifdef USE_AKONADI
-#define RESOURCE_PARAM_TYPE Collection&
+#define RESOURCE_PARAM_TYPE const Collection&
#define EVENT_RESOURCE collection
#else
#define RESOURCE_PARAM_TYPE AlarmResource*
@@ -137,19 +137,19 @@ class UndoAdd : public UndoItem
#else
virtual AlarmResource* resource() const { return mResource; }
#endif
- virtual QString eventID() const { return mEventID; }
- virtual QString newEventID() const { return mEventID; }
+ virtual QString eventID() const { return mEventId; }
+ virtual QString newEventID() const { return mEventId; }
virtual UndoItem* restore() { return doRestore(); }
protected:
UndoItem* doRestore(bool setArchive = false);
virtual UndoItem* createRedo(const KAEvent&, RESOURCE_PARAM_TYPE);
private:
#ifdef USE_AKONADI
- Collection mResource; // collection containing the event
+ Collection mResource; // collection containing the event
#else
AlarmResource* mResource; // resource calendar containing the event
#endif
- QString mEventID;
+ QString mEventId;
QString mDescription;
};
@@ -167,18 +167,18 @@ class UndoEdit : public UndoItem
#else
virtual AlarmResource* resource() const { return mResource; }
#endif
- virtual QString eventID() const { return mNewEventID; }
+ virtual QString eventID() const { return mNewEventId; }
virtual QString oldEventID() const { return mOldEvent->id(); }
- virtual QString newEventID() const { return mNewEventID; }
+ virtual QString newEventID() const { return mNewEventId; }
virtual UndoItem* restore();
private:
#ifdef USE_AKONADI
- Collection mResource; // collection containing the event
+ Collection mResource; // collection containing the event
#else
AlarmResource* mResource; // resource calendar containing the event
#endif
KAEvent* mOldEvent;
- QString mNewEventID;
+ QString mNewEventId;
QString mDescription;
QStringList mDontShowErrors;
};
@@ -205,7 +205,7 @@ class UndoDelete : public UndoItem
virtual UndoItem* createRedo(const KAEvent&, RESOURCE_PARAM_TYPE);
private:
#ifdef USE_AKONADI
- Collection mResource; // collection containing the event
+ Collection mResource; // collection containing the event
#else
AlarmResource* mResource; // resource calendar containing the event
#endif
@@ -780,7 +780,7 @@ bool UndoMulti<T>::deleteID(const QString& id)
UndoAdd::UndoAdd(Undo::Type type, const Undo::Event& undo, const QString& name)
: UndoItem(type, name),
mResource(undo.EVENT_RESOURCE),
- mEventID(undo.event.id())
+ mEventId(undo.event.id())
{
setCalendar(undo.event.category());
mDescription = UndoItem::description(undo.event); // calendar must be set before calling this
@@ -789,7 +789,7 @@ UndoAdd::UndoAdd(Undo::Type type, const Undo::Event& undo, const QString& name)
UndoAdd::UndoAdd(Undo::Type type, const KAEvent& event, RESOURCE_PARAM_TYPE resource, const QString& name)
: UndoItem(type, name),
mResource(resource),
- mEventID(event.id())
+ mEventId(event.id())
{
setCalendar(event.category());
mDescription = UndoItem::description(event); // calendar must be set before calling this
@@ -798,7 +798,7 @@ UndoAdd::UndoAdd(Undo::Type type, const KAEvent& event, RESOURCE_PARAM_TYPE reso
UndoAdd::UndoAdd(Undo::Type type, const KAEvent& event, RESOURCE_PARAM_TYPE resource, const QString& name, CalEvent::Type cal)
: UndoItem(type, name),
mResource(resource),
- mEventID(CalEvent::uid(event.id(), cal)) // convert if old-style event ID
+ mEventId(CalEvent::uid(event.id(), cal)) // convert if old-style event ID
{
setCalendar(cal);
mDescription = UndoItem::description(event); // calendar must be set before calling this
@@ -812,8 +812,12 @@ UndoAdd::UndoAdd(Undo::Type type, const KAEvent& event, RESOURCE_PARAM_TYPE reso
UndoItem* UndoAdd::doRestore(bool setArchive)
{
// Retrieve the current state of the alarm
- kDebug() << mEventID;
- const KAEvent* ev = AlarmCalendar::getEvent(mEventID);
+ kDebug() << mEventId;
+#ifdef USE_AKONADI
+ const KAEvent* ev = AlarmCalendar::getEvent(EventId(mResource.id(), mEventId));
+#else
+ const KAEvent* ev = AlarmCalendar::getEvent(mEventId);
+#endif
if (!ev)
{
mRestoreError = ERR_NOT_FOUND; // alarm is no longer in calendar
@@ -923,7 +927,7 @@ UndoEdit::UndoEdit(Undo::Type type, const KAEvent& oldEvent, const QString& newE
: UndoItem(type),
mResource(resource),
mOldEvent(new KAEvent(oldEvent)),
- mNewEventID(newEventID),
+ mNewEventId(newEventID),
mDescription(description),
mDontShowErrors(dontShowErrors)
{
@@ -942,9 +946,13 @@ UndoEdit::~UndoEdit()
*/
UndoItem* UndoEdit::restore()
{
- kDebug() << mNewEventID;
+ kDebug() << mNewEventId;
// Retrieve the current state of the alarm
- const KAEvent* event = AlarmCalendar::getEvent(mNewEventID);
+#ifdef USE_AKONADI
+ const KAEvent* event = AlarmCalendar::getEvent(EventId(mResource.id(), mNewEventId));
+#else
+ const KAEvent* event = AlarmCalendar::getEvent(mNewEventId);
+#endif
if (!event)
{
mRestoreError = ERR_NOT_FOUND; // alarm is no longer in calendar
@@ -954,7 +962,11 @@ UndoItem* UndoEdit::restore()
// Create a redo item to restore the edit
Undo::Type t = (type() == Undo::UNDO) ? Undo::REDO : (type() == Undo::REDO) ? Undo::UNDO : Undo::NONE;
- UndoItem* undo = new UndoEdit(t, newEvent, mOldEvent->id(), mResource, KAlarm::dontShowErrors(mNewEventID), mDescription);
+#ifdef USE_AKONADI
+ UndoItem* undo = new UndoEdit(t, newEvent, mOldEvent->id(), mResource, KAlarm::dontShowErrors(EventId(newEvent)), mDescription);
+#else
+ UndoItem* undo = new UndoEdit(t, newEvent, mOldEvent->id(), mResource, KAlarm::dontShowErrors(mNewEventId), mDescription);
+#endif
switch (calendar())
{
@@ -977,7 +989,11 @@ UndoItem* UndoEdit::restore()
mRestoreWarningKorg = status;
// fall through to default
default:
+#ifdef USE_AKONADI
+ KAlarm::setDontShowErrors(EventId(*mOldEvent), mDontShowErrors);
+#else
KAlarm::setDontShowErrors(mOldEvent->id(), mDontShowErrors);
+#endif
break;
}
break;
@@ -1107,7 +1123,11 @@ UndoItem* UndoDelete::restore()
break;
}
}
+#ifdef USE_AKONADI
+ KAlarm::setDontShowErrors(EventId(*mEvent), mDontShowErrors);
+#else
KAlarm::setDontShowErrors(mEvent->id(), mDontShowErrors);
+#endif
break;
case CalEvent::TEMPLATE:
#ifdef USE_AKONADI
@@ -1316,7 +1336,11 @@ Undo::Event::Event(const KAEvent& e, RESOURCE_PARAM_TYPE r)
EVENT_RESOURCE(r)
{
if (e.category() == CalEvent::ACTIVE)
+#ifdef USE_AKONADI
+ dontShowErrors = KAlarm::dontShowErrors(EventId(e));
+#else
dontShowErrors = KAlarm::dontShowErrors(e.id());
+#endif
}
// vim: et sw=4:
diff --git a/kalarm/undo.h b/kalarm/undo.h
index 652cd56..352da15 100644
--- a/kalarm/undo.h
+++ b/kalarm/undo.h
@@ -52,7 +52,7 @@ class Undo : public QObject
{
Event() {}
#ifdef USE_AKONADI
- Event(const KAEvent&, Akonadi::Collection&);
+ Event(const KAEvent&, const Akonadi::Collection&);
#else
Event(const KAEvent&, AlarmResource*);
#endif
@@ -68,7 +68,7 @@ class Undo : public QObject
{
public:
#ifdef USE_AKONADI
- void append(const KAEvent& e, Akonadi::Collection& c) { QList<Event>::append(Event(e, c)); }
+ void append(const KAEvent& e, const Akonadi::Collection& c) { QList<Event>::append(Event(e, c)); }
#else
void append(const KAEvent& e, AlarmResource* r) { QList<Event>::append(Event(e, r)); }
#endif
@@ -76,7 +76,7 @@ class Undo : public QObject
static Undo* instance();
#ifdef USE_AKONADI
- static void saveAdd(const KAEvent&, Akonadi::Collection&, const QString& name = QString());
+ static void saveAdd(const KAEvent&, const Akonadi::Collection&, const QString& name = QString());
#else
static void saveAdd(const KAEvent&, AlarmResource*, const QString& name = QString());
#endif
@@ -85,7 +85,7 @@ class Undo : public QObject
static void saveDelete(const Event&, const QString& name = QString());
static void saveDeletes(const EventList&, const QString& name = QString());
#ifdef USE_AKONADI
- static void saveReactivate(const KAEvent&, Akonadi::Collection&, const QString& name = QString());
+ static void saveReactivate(const KAEvent&, const Akonadi::Collection&, const QString& name = QString());
#else
static void saveReactivate(const KAEvent&, AlarmResource*, const QString& name = QString());
#endif
diff --git a/kalarm/wakedlg.cpp b/kalarm/wakedlg.cpp
index 5dd07ba..50d1a4b 100644
--- a/kalarm/wakedlg.cpp
+++ b/kalarm/wakedlg.cpp
@@ -1,7 +1,7 @@
/*
* wakedlg.cpp - dialog to configure wake-from-suspend alarms
* Program: kalarm
- * Copyright © 2011 by David Jarvie <djarvie@kde.org>
+ * Copyright © 2011-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -144,7 +144,7 @@ void WakeFromSuspendDlg::showWakeClicked()
if (!params.isEmpty())
{
#ifdef USE_AKONADI
- KAEvent* event = AlarmCalendar::resources()->event(params[0]);
+ KAEvent* event = AlarmCalendar::resources()->event(EventId(params[0].toLongLong(), params[1]));
if (event)
{
mMainWindow->selectEvent(event->itemId());
@@ -196,7 +196,7 @@ void WakeFromSuspendDlg::useWakeClicked()
{
QStringList param;
#ifdef USE_AKONADI
- param << event.id() << QString::number(triggerTime);
+ param << QString::number(event.collectionId()) << event.id() << QString::number(triggerTime);
#else
param << event->id() << QString::number(triggerTime);
#endif