Commit 5363ba63 authored by David Jarvie's avatar David Jarvie
Browse files

Fix handling of calendar update or save errors when making alarm changes

When calendar save fails, reload the calendar to revert unsaved
changes to alarms. Don't create Undo items for alarm changes which
fail.
parent e24ddf56
Pipeline #22882 passed with stage
in 10 minutes and 42 seconds
KAlarm Change Log
=== Version 3.0.0 --- 14 May 2020 ===
=== Version 3.0.0 --- 7 June 2020 ===
+ Provide option to use file system resources instead of Akonadi resources.
+ Enable selection of multiple calendar files in Import Alarms dialogue.
+ Show alarm calendars sorted by name in calendars list.
+ Return to last used tab in Configuration dialogue when it is reopened.
+ Fix handling of calendar update or save errors when making alarm changes.
+ Refactor AlarmCalendar to split out resources and display calendars.
=== Version 2.14.2 (KDE Applications 20.04.2) --- 23 May 2020 ===
......
......@@ -282,11 +282,21 @@ bool ResourcesCalendar::save()
bool ok = true;
// Get all enabled, writable resources.
QVector<Resource> resources = Resources::enabledResources(CalEvent::EMPTY, true);
for (Resource& resource : resources)
ok = ok && resource.save();
for (Resource& res : resources)
ok = ok && res.save();
return ok;
}
/******************************************************************************
* Save a resource in the calendar.
* If errorMessage is non-null, it will receive the error message in case of
* error, and the resource will not display the error message.
*/
bool ResourcesCalendar::save(Resource& resource, QString* errorMessage)
{
return resource.save(errorMessage);
}
/******************************************************************************
* Save the calendar.
*/
......@@ -574,7 +584,9 @@ void ResourcesCalendar::purgeEvents(const KAEvent::List& events)
{
for (const KAEvent* event : events)
{
deleteEventInternal(*event);
Resource resource = Resources::resource(event->resourceId());
if (resource.isValid())
deleteEventInternal(event->id(), *event, resource, true);
}
if (mHaveDisabledAlarms)
checkForDisabledAlarms();
......@@ -586,18 +598,17 @@ void ResourcesCalendar::purgeEvents(const KAEvent::List& events)
* created. In all other cases, the event ID is taken from 'evnt' (if non-null).
* 'evnt' is updated with the actual event ID.
* The event is added to 'resource' if specified; otherwise the default resource
* is used or the user is prompted, depending on policy. If 'noPrompt' is true,
* the user will not be prompted so that if no default resource is defined, the
* function will fail.
* is used or the user is prompted, depending on policy, and 'resource' is
* updated with the actual resource used. If 'noPrompt' is true, the user will
* not be prompted so that if no default resource is defined, the function will
* fail.
* Reply = true if 'evnt' was written to the calendar. 'evnt' is updated.
* = false if an error occurred, in which case 'evnt' is unchanged.
*/
bool ResourcesCalendar::addEvent(KAEvent& evnt, QWidget* promptParent, bool useEventID, Resource* resourceptr, bool noPrompt, bool* cancelled)
bool ResourcesCalendar::addEvent(KAEvent& evnt, Resource& resource, QWidget* promptParent, bool useEventID, bool noPrompt, bool* cancelled)
{
if (cancelled)
*cancelled = false;
Resource nullresource;
Resource& resource(resourceptr ? *resourceptr : nullresource);
qCDebug(KALARM_LOG) << "ResourcesCalendar::addEvent:" << evnt.id() << ", resource" << resource.displayId();
// Check that the event type is valid for the calendar
......@@ -632,25 +643,22 @@ bool ResourcesCalendar::addEvent(KAEvent& evnt, QWidget* promptParent, bool useE
bool ok = false;
bool remove = false;
Resource res;
if (resource.isEnabled(type))
res = resource;
else
if (!resource.isEnabled(type))
{
res = Resources::destination(type, promptParent, noPrompt, cancelled);
if (!res.isValid())
resource = Resources::destination(type, promptParent, noPrompt, cancelled);
if (!resource.isValid())
qCWarning(KALARM_LOG) << "ResourcesCalendar::addEvent: Error! Cannot create" << type << "(No default calendar is defined)";
}
if (res.isValid())
if (resource.isValid())
{
// Don't add event to mEventMap yet - its ID is not yet known.
// It will be added after it is inserted into the data model, when
// the resource signals eventsAdded().
ok = res.addEvent(*event);
ok = resource.addEvent(*event);
remove = ok; // if success, delete the local event instance on exit
if (ok && type == CalEvent::ACTIVE && !event->enabled())
checkForDisabledAlarms(true, false);
event->setResourceId(res.id());
event->setResourceId(resource.id());
}
if (!ok)
{
......@@ -820,7 +828,8 @@ bool ResourcesCalendar::modifyEvent(const EventId& oldEventId, KAEvent& newEvent
/******************************************************************************
* Update the specified event in the calendar with its new contents.
* The event retains the same ID. The event must be in the resource calendar.
* The event retains the same ID. The event must be in the resource calendar,
* and must have its resourceId() set correctly.
* Reply = event which has been updated
* = 0 if error.
*/
......@@ -829,7 +838,7 @@ KAEvent* ResourcesCalendar::updateEvent(const KAEvent& evnt)
KAEvent* kaevnt = event(EventId(evnt));
if (kaevnt)
{
Resource resource = Resources::resourceForEvent(evnt.id());
Resource resource = Resources::resource(evnt.resourceId());
if (resource.updateEvent(evnt))
{
*kaevnt = evnt;
......@@ -845,11 +854,26 @@ KAEvent* ResourcesCalendar::updateEvent(const KAEvent& evnt)
* Delete the specified event from the resource calendar, if it exists.
* The calendar is then optionally saved.
*/
bool ResourcesCalendar::deleteEvent(const KAEvent& event, bool saveit)
bool ResourcesCalendar::deleteEvent(const KAEvent& event, Resource& resource, bool saveit)
{
Q_UNUSED(saveit);
const CalEvent::Type status = deleteEventInternal(event);
if (!resource.isValid())
{
resource = Resources::resource(event.resourceId());
if (!resource.isValid())
{
qCDebug(KALARM_LOG) << "ResourcesCalendar::deleteEvent: Resource not found for" << event.id();
return false;
}
}
else if (!resource.containsEvent(event.id()))
{
qCDebug(KALARM_LOG) << "ResourcesCalendar::deleteEvent: Event" << event.id() << "not in resource" << resource.displayId();
return false;
}
qCDebug(KALARM_LOG) << "ResourcesCalendar::deleteEvent:" << event.id();
const CalEvent::Type status = deleteEventInternal(event.id(), event, resource, true);
if (mHaveDisabledAlarms)
checkForDisabledAlarms();
return status != CalEvent::EMPTY;
......@@ -893,14 +917,6 @@ bool DisplayCalendar::deleteEvent(const QString& eventID, bool saveit)
* resource or local calendar
* = CalEvent::EMPTY otherwise.
*/
CalEvent::Type ResourcesCalendar::deleteEventInternal(const KAEvent& event, bool deleteFromResources)
{
Resource resource = Resources::resource(event.resourceId());
if (!resource.isValid())
return CalEvent::EMPTY;
return deleteEventInternal(event.id(), event, resource, deleteFromResources);
}
CalEvent::Type ResourcesCalendar::deleteEventInternal(const KAEvent& event, Resource& resource, bool deleteFromResources)
{
if (!resource.isValid())
......
......@@ -75,6 +75,7 @@ public:
~ResourcesCalendar() override;
bool reload();
bool save();
bool save(Resource&, QString* errorMessage = nullptr);
void close();
KAEvent* earliestAlarm() const;
void setAlarmPending(KAEvent*, bool pending = true);
......@@ -87,10 +88,10 @@ public:
KAEvent::List events(const Resource&, CalEvent::Types = CalEvent::EMPTY) const;
KAEvent::List events(CalEvent::Types s = CalEvent::EMPTY) const;
bool eventReadOnly(const QString& eventId) const;
bool addEvent(KAEvent&, QWidget* promptparent = nullptr, bool useEventID = false, Resource* = nullptr, bool noPrompt = false, bool* cancelled = nullptr);
bool addEvent(KAEvent&, Resource&, QWidget* promptparent = nullptr, bool useEventID = false, bool noPrompt = false, bool* cancelled = nullptr);
bool modifyEvent(const EventId& oldEventId, KAEvent& newEvent);
KAEvent* updateEvent(const KAEvent&);
bool deleteEvent(const KAEvent&, bool save = false);
bool deleteEvent(const KAEvent&, Resource&, bool save = false);
void purgeEvents(const KAEvent::List&);
static void initialise();
......@@ -116,7 +117,6 @@ private:
ResourcesCalendar();
bool isValid() const override { return true; }
void addNewEvent(const Resource&, KAEvent*, bool replace = false) override;
CalEvent::Type deleteEventInternal(const KAEvent&, bool deleteFromResources = true);
CalEvent::Type deleteEventInternal(const KAEvent&, Resource&, bool deleteFromResources = true);
CalEvent::Type deleteEventInternal(const QString& eventID, const KAEvent&, Resource&,
bool deleteFromResources = true);
......
This diff is collapsed.
......@@ -66,6 +66,8 @@ struct UpdateResult
{
UpdateStatus status; // status code
QString message; // error message if any
QVector<int> failed; // indexes to events whose update failed
UpdateResult() : status(UPDATE_OK) {}
explicit UpdateResult(UpdateStatus s, const QString& m = QString()) : status(s), message(m) {}
UpdateResult& operator=(UpdateStatus s) { status = s; message.clear(); return *this; }
......@@ -115,22 +117,159 @@ enum // 'options' parameter values for addEvent(). May be OR'ed together
NO_RESOURCE_PROMPT = 0x02, // don't prompt for resource
ALLOW_KORG_UPDATE = 0x04 // allow change to be sent to KOrganizer
};
UpdateResult addEvent(KAEvent&, Resource* = nullptr, QWidget* msgParent = nullptr, int options = ALLOW_KORG_UPDATE, bool showKOrgErr = true);
UpdateResult addEvents(QVector<KAEvent>&, QWidget* msgParent = nullptr, bool allowKOrgUpdate = true, bool showKOrgErr = true);
bool addArchivedEvent(KAEvent&, Resource* = nullptr);
UpdateResult addTemplate(KAEvent&, Resource* = nullptr, QWidget* msgParent = nullptr);
UpdateResult modifyEvent(KAEvent& oldEvent, KAEvent& newEvent, QWidget* msgParent = nullptr, bool showKOrgErr = true);
UpdateResult updateEvent(KAEvent&, QWidget* msgParent = nullptr, bool archiveOnDelete = true);
UpdateResult updateTemplate(KAEvent&, QWidget* msgParent = nullptr);
UpdateResult deleteEvent(KAEvent&, bool archive = true, QWidget* msgParent = nullptr, bool showKOrgErr = true);
UpdateResult deleteEvents(QVector<KAEvent>&, bool archive = true, QWidget* msgParent = nullptr, bool showKOrgErr = true);
UpdateResult deleteTemplates(const KAEvent::List& events, QWidget* msgParent = nullptr);
/** Add a new active (non-archived) alarm to a resource.
* @param event Updated with the actual event ID.
* @param resource Resource to add event to. If invalid, the default resource
* is used or the user is prompted, depending on policy, and
* 'resource' is updated with the actual resource used.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, the new alarm has been discarded.
*/
UpdateResult addEvent(KAEvent& event, Resource& resource, QWidget* msgParent = nullptr, int options = ALLOW_KORG_UPDATE, bool showKOrgErr = true);
/** Add new active (non-archived) alarms to a resource.
* @param events Updated with the actual event IDs.
* @param resource Resource to add event to. If invalid, the default resource
* is used or the user is prompted, depending on policy, and
* 'resource' is updated with the actual resource used.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, all new alarms have been discarded.
*/
UpdateResult addEvents(QVector<KAEvent>& events, Resource& resource, QWidget* msgParent = nullptr, bool allowKOrgUpdate = true, bool showKOrgErr = true);
/** Save the event in the archived calendar.
* The event's ID is changed to an archived ID if necessary.
* @param event Updated with the archived event ID.
* @param resource Resource to add event to. If invalid, the default resource
* is used or the user is prompted, depending on policy, and
* 'resource' is updated with the actual resource used.
*/
bool addArchivedEvent(KAEvent& event, Resource& resource);
/** Add a new template to a resource.
* @param event Updated with the actual event ID.
* @param resource Resource to add event to. If invalid, the default resource
* is used or the user is prompted, depending on policy, and
* 'resource' is updated with the actual resource used.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, the new template has been discarded.
*/
UpdateResult addTemplate(KAEvent& event, Resource& resource, QWidget* msgParent = nullptr);
/** Modify an active (non-archived) alarm in a resource.
* The new event must have a different event ID from the old one.
* @param oldEvent Event to be replaced. Its resourceId() must give the ID of
* the resource which contains it.
* @param newEvent Modified version of the event. Updated with its new ID if
* it was not supplied with one.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, the modification has been discarded.
*/
UpdateResult modifyEvent(KAEvent& oldEvent, KAEvent& newEvent, QWidget* msgParent = nullptr, bool showKOrgErr = true);
/** Update an active (non-archived) alarm.
* The new event will have the same event ID as the old one.
* The event is not updated in KOrganizer, since this function is called when an
* existing alarm is rescheduled (due to recurrence or deferral).
* @param event Event to be replaced. Its resourceId() must give the ID of
* the resource which contains it.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, the update has been discarded.
*/
UpdateResult updateEvent(KAEvent& event, QWidget* msgParent = nullptr, bool archiveOnDelete = true);
/** Update an alarm template.
* The new event will have the same event ID as the old one.
* @param event Event to be replaced. Its resourceId() must give the ID of
* the resource which contains it.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, the update has been discarded.
*/
UpdateResult updateTemplate(KAEvent& event, QWidget* msgParent = nullptr);
/** Delete an alarm from a resource.
* If the event is archived, the event's ID is changed to an archived ID if necessary.
* @param event Event to delete.
* @param resource Resource to delete event from. If invalid, this is
* updated to the resource which contained the event.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, the deletion has been discarded.
*/
UpdateResult deleteEvent(KAEvent& event, Resource& resource, bool archive = true, QWidget* msgParent = nullptr, bool showKOrgErr = true);
/** Delete alarms from the resources.
* If the events are archived, the events' IDs are changed to archived IDs if necessary.
* @param event Event to delete.
* @param resource Resource to delete event from. If invalid, and all events
* are found in the same resource, this is updated to the
* resource which contained the events.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, all deletions have been discarded.
*/
UpdateResult deleteEvents(QVector<KAEvent>&, Resource& resource, bool archive = true, QWidget* msgParent = nullptr, bool showKOrgErr = true);
/** Delete templates from the resources.
* @param event Event to delete.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, all deletions have been discarded.
*/
UpdateResult deleteTemplates(const KAEvent::List& events, QWidget* msgParent = nullptr);
inline UpdateResult deleteTemplate(KAEvent& event, QWidget* msgParent = nullptr)
{ KAEvent::List e; e += &event; return deleteTemplates(e, msgParent); }
void deleteDisplayEvent(const QString& eventID);
UpdateResult reactivateEvent(KAEvent&, Resource* = nullptr, QWidget* msgParent = nullptr, bool showKOrgErr = true);
UpdateResult reactivateEvents(QVector<KAEvent>&, QVector<EventId>& ineligibleIDs, Resource* = nullptr, QWidget* msgParent = nullptr, bool showKOrgErr = true);
UpdateResult enableEvents(QVector<KAEvent>&, bool enable, QWidget* msgParent = nullptr);
/** Undelete an archived alarm.
* The archive bit is set to ensure that it gets re-archived if deleted again.
* @param event Updated with the restored event.
* @param resource Active alarms resource to restore the event to. If
* invalid, the default resource is used or the user is
* prompted, depending on policy, and 'resource' is updated
* with the actual resource used.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, the reactivated event has been discarded.
*/
UpdateResult reactivateEvent(KAEvent& event, Resource& resource, QWidget* msgParent = nullptr, bool showKOrgErr = true);
/** Undelete archived alarms.
* The archive bit is set to ensure that they get re-archived if deleted again.
* @param events Updated to contain the restored events.
* @param ineligibleIndexes Receives the indexes to any ineligible events.
* @param resource Active alarms resource to restore the events to. If
* invalid, the default resource is used or the user is
* prompted, depending on policy, and 'resource' is updated
* with the actual resource used.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if >= UPDATE_FAILED, all reactivated events have been discarded.
*/
UpdateResult reactivateEvents(QVector<KAEvent>& events, QVector<int>& ineligibleIndexes, Resource& resource, QWidget* msgParent = nullptr, bool showKOrgErr = true);
/** Enable or disable alarms.
* The new events will have the same event IDs as the old ones.
* @param events Events to be enabled. Each one's resourceId() must give
* the ID of the resource which contains it.
* @param enable Whether to enable or disable the events.
* @param msgParent Parent widget for any calendar selection prompt or error
* message.
* @return Success status; if == UPDATE_FAILED, the enabled status of all
* events is unchanged; if == SAVE_FAILED, the enabled status of at
* least one event has been successfully changed, but will be lost
* when its resource is reloaded.
*/
UpdateResult enableEvents(QVector<KAEvent>& events, bool enable, QWidget* msgParent = nullptr);
QVector<KAEvent> getSortedActiveEvents(QObject* parent, AlarmListModel** model = nullptr);
void purgeArchive(int purgeDays); // must only be called from KAlarmApp::processQueue()
......
......@@ -986,8 +986,11 @@ void KAlarmApp::processQueue()
execAlarm(entry.event, entry.event.firstAlarm(), false);
break;
case QueuedAction::Handle:
KAlarm::addEvent(entry.event, nullptr, nullptr, KAlarm::ALLOW_KORG_UPDATE | KAlarm::NO_RESOURCE_PROMPT);
{
Resource resource;
KAlarm::addEvent(entry.event, resource, nullptr, KAlarm::ALLOW_KORG_UPDATE | KAlarm::NO_RESOURCE_PROMPT);
break;
}
case QueuedAction::List:
{
const QStringList alarms = scheduledAlarmList();
......@@ -1695,10 +1698,12 @@ bool KAlarmApp::handleEvent(const EventId& id, QueuedAction action, bool findUni
switch (action)
{
case QueuedAction::Cancel:
{
qCDebug(KALARM_LOG) << "KAlarmApp::handleEvent:" << eventID << ", CANCEL";
KAlarm::deleteEvent(*event, true);
Resource resource = Resources::resource(event->resourceId());
KAlarm::deleteEvent(*event, resource, true);
break;
}
case QueuedAction::Trigger: // handle it if it's due, else execute it regardless
case QueuedAction::Handle: // handle it if it's due
{
......@@ -2045,9 +2050,10 @@ bool KAlarmApp::cancelAlarm(KAEvent& event, KAAlarm::Type alarmType, bool update
qCDebug(KALARM_LOG) << "KAlarmApp::cancelAlarm";
if (alarmType == KAAlarm::MAIN_ALARM && !event.displaying() && event.toBeArchived())
{
// The event is being deleted. Save it in the archived resources first.
// The event is being deleted. Save it in the archived resource first.
Resource resource;
KAEvent ev(event);
KAlarm::addArchivedEvent(ev);
KAlarm::addArchivedEvent(ev, resource);
}
event.removeExpiredAlarm(alarmType);
if (!event.alarmCount())
......@@ -2058,7 +2064,8 @@ bool KAlarmApp::cancelAlarm(KAEvent& event, KAAlarm::Type alarmType, bool update
pd->eventDeleted = true;
// Delete it
KAlarm::deleteEvent(event, false);
Resource resource;
KAlarm::deleteEvent(event, resource, false);
return true;
}
if (updateCalAndDisplay)
......
......@@ -753,8 +753,15 @@ void MainWindow::slotDelete(bool force)
else
{
// Delete the events from the calendar and displays
KAlarm::deleteEvents(events, true, this);
Undo::saveDeletes(undos);
Resource resource;
const KAlarm::UpdateResult status = KAlarm::deleteEvents(events, resource, true, this);
if (status.status < KAlarm::UPDATE_FAILED)
{
// Create the undo list
for (int i = status.failed.count(); --i >= 0; )
undos.removeAt(status.failed.at(i));
Undo::saveDeletes(undos);
}
}
}
......@@ -768,17 +775,20 @@ void MainWindow::slotReactivate()
mListView->clearSelection();
// Add the alarms to the displayed lists and to the calendar file
Undo::EventList undos;
QVector<EventId> ineligibleIDs;
KAlarm::reactivateEvents(events, ineligibleIDs, nullptr, this);
// Create the undo list, excluding ineligible events
for (int i = 0, end = events.count(); i < end; ++i)
Resource resource; // active alarms resource which alarms are restored to
QVector<int> ineligibleIndexes;
const KAlarm::UpdateResult status = KAlarm::reactivateEvents(events, ineligibleIndexes, resource, this);
if (status.status < KAlarm::UPDATE_FAILED)
{
if (!ineligibleIDs.contains(EventId(events[i])))
undos.append(events[i], Resources::resourceForEvent(events[i].id()));
// Create the undo list, excluding ineligible events
Undo::EventList undos;
for (int i = 0, end = events.count(); i < end; ++i)
{
if (!ineligibleIndexes.contains(i) && !status.failed.contains(i))
undos.append(events[i], resource);
}
Undo::saveReactivates(undos);
}
Undo::saveReactivates(undos);
}
/******************************************************************************
......@@ -880,15 +890,19 @@ void MainWindow::slotBirthdays()
{
mListView->clearSelection();
// Add alarm to the displayed lists and to the calendar file
KAlarm::UpdateResult status = KAlarm::addEvents(events, dlg, true, true);
Undo::EventList undos;
for (int i = 0, end = events.count(); i < end; ++i)
undos.append(events[i], Resources::resourceForEvent(events[i].id()));
Undo::saveAdds(undos, i18nc("@info", "Import birthdays"));
Resource resource;
const KAlarm::UpdateResult status = KAlarm::addEvents(events, resource, dlg, true, true);
if (status.status < KAlarm::UPDATE_FAILED)
{
// Create the undo list
Undo::EventList undos;
for (int i = 0, end = events.count(); i < end; ++i)
if (!status.failed.contains(i))
undos.append(events[i], resource);
Undo::saveAdds(undos, i18nc("@info", "Import birthdays"));
if (status != KAlarm::UPDATE_FAILED)
KAlarm::outputAlarmWarnings(dlg);
}
}
}
}
......
......@@ -1140,7 +1140,8 @@ void MessageWin::redisplayAlarms()
/******************************************************************************
* Retrieves the event with the current ID from the displaying calendar file,
* or if not found there, from the archive calendar.
* or if not found there, from the archive calendar. 'resource' is set to the
* resource which originally contained the event, or invalid if not known.
*/
bool MessageWin::retrieveEvent(KAEvent& event, Resource& resource, bool& showEdit, bool& showDefer)
{
......@@ -1171,7 +1172,8 @@ bool MessageWin::retrieveEvent(KAEvent& event, Resource& resource, bool& showEdi
/******************************************************************************
* Retrieves the displayed event from the calendar file, or if not found there,
* from the displaying calendar.
* from the displaying calendar. 'resource' is set to the resource which
* originally contained the event.
*/
bool MessageWin::reinstateFromDisplaying(const Event::Ptr& kcalEvent, KAEvent& event, Resource& resource, bool& showEdit, bool& showDefer)
{
......@@ -1179,7 +1181,7 @@ bool MessageWin::reinstateFromDisplaying(const Event::Ptr& kcalEvent, KAEvent& e
return false;
ResourceId resourceId;
event.reinstateFromDisplaying(kcalEvent, resourceId, showEdit, showDefer);
event.setCollectionId(resourceId);
event.setResourceId(resourceId);
resource = Resources::resource(resourceId);
qCDebug(KALARM_LOG) << "MessageWin::reinstateFromDisplaying:" << EventId(event) << ": success";
return true;
......@@ -2163,7 +2165,7 @@ void MessageWin::slotDefer()
else
{
// Try to retrieve the event from the displaying or archive calendars
Resource resource;
Resource resource; // receives the event's original resource, if known
KAEvent event;
bool showEdit, showDefer;
if (!retrieveEvent(event, resource, showEdit, showDefer))
......@@ -2184,13 +2186,14 @@ void MessageWin::slotDefer()
event.setCommandError(mCommandError);
// Add the event back into the calendar file, retaining its ID
// and not updating KOrganizer.
KAlarm::addEvent(event, &resource, mDeferDlg, KAlarm::USE_EVENT_ID);
KAlarm::addEvent(event, resource, mDeferDlg, KAlarm::USE_EVENT_ID);
if (event.deferred())
mNoPostAction = true;
// Finally delete it from the archived calendar now that it has
// been reactivated.
event.setCategory(CalEvent::ARCHIVED);
KAlarm::deleteEvent(event, false);
Resource res;
KAlarm::deleteEvent(event, res, false);
}
if (theApp()->wantShowInSystemTray())
{
......
......@@ -414,16 +414,19 @@ bool AkonadiResource::isPopulated() const
return true;
}
bool AkonadiResource::save(bool writeThroughCache, bool force)
bool AkonadiResource::save(QString* errorMessage, bool writeThroughCache, bool force)
{
Q_UNUSED(errorMessage);
Q_UNUSED(writeThroughCache);
Q_UNUSED(force);
AgentManager::self()->instance(mCollection.resource()).synchronize();
return true;
}
bool AkonadiResource::reload()
bool AkonadiResource::reload(bool discardMods)
{
Q_UNUSED(discardMods);
// Akonadi provides no means to reload from the backend.
return false;
}
......
......@@ -234,8 +234,12 @@ public:
*/
bool load(bool readThroughCache = true) override;
/** Reload the resource. Any cached data is first discarded. */
bool reload() override;
/** Reload the resource. Any cached data is first discarded.
* Not applicable to AkonadiResource, since Akonadi provides no means to
* reload from the backend.
* @return false
*/
bool reload(bool discardMods = false) override;
/** Return whether the resource has fully loaded. */
bool isPopulated() const override;
......@@ -245,7 +249,7 @@ public:
* automatically.
* @return true.
*/
bool save(bool writeThroughCache = true, bool force = false) override;
bool save(QString* errorMessage = nullptr, bool writeThroughCache = true, bool force = false) override;
/** Add an event to the resource, and add it to Akonadi. */
bool addEvent(const KAEvent&) override;
......
......@@ -390,14 +390,14 @@ void FileResource::loaded(bool success, QHash<QString, KAEvent>& newEvents, cons