Commit 9777fa45 authored by David Jarvie's avatar David Jarvie
Browse files

Improve handling of adding and removal of resources

parent 00554291
......@@ -123,11 +123,17 @@ AlarmCalendar::AlarmCalendar()
, mEventType(CalEvent::EMPTY)
{
Resources* resources = Resources::instance();
connect(resources, &Resources::resourceAdded, this, &AlarmCalendar::slotResourceAdded);
connect(resources, &Resources::eventsAdded, this, &AlarmCalendar::slotEventsAdded);
connect(resources, &Resources::eventsToBeRemoved, this, &AlarmCalendar::slotEventsToBeRemoved);
connect(resources, &Resources::eventUpdated, this, &AlarmCalendar::slotEventUpdated);
connect(resources, &Resources::resourcesPopulated, this, &AlarmCalendar::slotResourcesPopulated);
connect(resources, &Resources::settingsChanged, this, &AlarmCalendar::slotResourceSettingsChanged);
// Fetch events from all resources which already exist.
QVector<Resource> allResources = Resources::enabledResources();
for (Resource& resource : allResources)
slotResourceAdded(resource);
}
/******************************************************************************
......@@ -525,6 +531,16 @@ void AlarmCalendar::slotResourcesPopulated()
mIgnoreAtLogin = true;
}
/******************************************************************************
* Called when a resource has been added.
* Add its KAEvent instances to those held by AlarmCalendar.
* All events must have their resource ID set.
*/
void AlarmCalendar::slotResourceAdded(Resource& resource)
{
slotEventsAdded(resource, resource.events());
}
/******************************************************************************
* Called when events have been added to a resource.
* Add corresponding KAEvent instances to those held by AlarmCalendar.
......@@ -846,7 +862,7 @@ bool AlarmCalendar::endUpdate()
/******************************************************************************
* Save the calendar, or flag it for saving if in a group of calendar update calls.
* Note that this method has no effect for Akonadi calendars.
* Note that this method has no effect for resources calendars.
*/
bool AlarmCalendar::save()
{
......@@ -1046,7 +1062,7 @@ void AlarmCalendar::addNewEvent(const Resource& resource, KAEvent* event, bool r
*/
bool AlarmCalendar::modifyEvent(const EventId& oldEventId, KAEvent& newEvent)
{
const EventId newId(oldEventId.collectionId(), newEvent.id());
const EventId newId(oldEventId.resourceId(), newEvent.id());
qCDebug(KALARM_LOG) << "AlarmCalendar::modifyEvent:" << oldEventId << "->" << newId;
bool noNewId = newId.isEmpty();
if (!noNewId && oldEventId == newId)
......@@ -1058,8 +1074,7 @@ bool AlarmCalendar::modifyEvent(const EventId& oldEventId, KAEvent& newEvent)
return false;
if (mCalType == RESOURCES)
{
// Set the event's ID and Akonadi ID, and update the old
// event in Akonadi.
// Set the event's ID, and update the old event in the resources calendar.
const KAEvent* storedEvent = event(oldEventId);
if (!storedEvent)
{
......@@ -1068,7 +1083,7 @@ bool AlarmCalendar::modifyEvent(const EventId& oldEventId, KAEvent& newEvent)
}
if (noNewId)
newEvent.setEventId(CalFormat::createUniqueId());
Resource resource = Resources::resource(oldEventId.collectionId());
Resource resource = Resources::resource(oldEventId.resourceId());
if (!resource.isValid())
return false;
// Don't add new event to mEventMap yet - its Akonadi item id is not yet known
......@@ -1167,15 +1182,15 @@ bool AlarmCalendar::deleteDisplayEvent(const QString& eventID, bool saveit)
* resource or local calendar
* = CalEvent::EMPTY otherwise.
*/
CalEvent::Type AlarmCalendar::deleteEventInternal(const KAEvent& event, bool deleteFromAkonadi)
CalEvent::Type AlarmCalendar::deleteEventInternal(const KAEvent& event, bool deleteFromResources)
{
Resource resource = Resources::resource(event.resourceId());
if (!resource.isValid())
return CalEvent::EMPTY;
return deleteEventInternal(event.id(), event, resource, deleteFromAkonadi);
return deleteEventInternal(event.id(), event, resource, deleteFromResources);
}
CalEvent::Type AlarmCalendar::deleteEventInternal(const KAEvent& event, Resource& resource, bool deleteFromAkonadi)
CalEvent::Type AlarmCalendar::deleteEventInternal(const KAEvent& event, Resource& resource, bool deleteFromResources)
{
if (!resource.isValid())
return CalEvent::EMPTY;
......@@ -1184,10 +1199,10 @@ CalEvent::Type AlarmCalendar::deleteEventInternal(const KAEvent& event, Resource
qCCritical(KALARM_LOG) << "AlarmCalendar::deleteEventInternal: Event" << event.id() << ": resource" << event.resourceId() << "differs from 'resource'" << resource.id();
return CalEvent::EMPTY;
}
return deleteEventInternal(event.id(), event, resource, deleteFromAkonadi);
return deleteEventInternal(event.id(), event, resource, deleteFromResources);
}
CalEvent::Type AlarmCalendar::deleteEventInternal(const QString& eventID, const KAEvent& event, Resource& resource, bool deleteFromAkonadi)
CalEvent::Type AlarmCalendar::deleteEventInternal(const QString& eventID, const KAEvent& event, Resource& resource, bool deleteFromResources)
{
// Make a copy of the KAEvent and the ID QString, since the supplied
// references might be destructed when the event is deleted below.
......@@ -1196,7 +1211,7 @@ CalEvent::Type AlarmCalendar::deleteEventInternal(const QString& eventID, const
Event::Ptr kcalEvent;
if (mCalendarStorage)
kcalEvent = mCalendarStorage->calendar()->event(id);
kcalEvent = mCalendarStorage->calendar()->event(id); // display calendar
const ResourceId key = resource.id();
KAEventMap::Iterator it = mEventMap.find(EventId(key, id));
if (it != mEventMap.end())
......@@ -1226,12 +1241,13 @@ CalEvent::Type AlarmCalendar::deleteEventInternal(const QString& eventID, const
CalEvent::Type status = CalEvent::EMPTY;
if (kcalEvent)
{
// It's a display calendar event
status = CalEvent::status(kcalEvent);
mCalendarStorage->calendar()->deleteEvent(kcalEvent);
}
else if (deleteFromAkonadi)
else if (deleteFromResources)
{
// It's an Akonadi event
// Delete from the resources calendar
CalEvent::Type s = paramEvent.category();
if (resource.deleteEvent(paramEvent))
status = s;
......@@ -1250,7 +1266,7 @@ KAEvent* AlarmCalendar::event(const EventId& uniqueID, bool checkDuplicates)
if (!isValid())
return nullptr;
const QString eventId = uniqueID.eventId();
if (uniqueID.collectionId() == -1 && checkDuplicates)
if (uniqueID.resourceId() == -1 && checkDuplicates)
{
// The resource isn't known, but use the event ID if it is unique among
// all resources.
......@@ -1272,7 +1288,7 @@ KAEvent* AlarmCalendar::event(const EventId& uniqueID, bool checkDuplicates)
/******************************************************************************
* Return the event with the specified ID.
* For the Akonadi version, this method is for the display calendar only.
* This method is for the display calendar only.
*/
Event::Ptr AlarmCalendar::kcalEvent(const QString& uniqueID)
{
......@@ -1360,7 +1376,7 @@ KAEvent::List AlarmCalendar::events(const Resource& resource, CalEvent::Types ty
/******************************************************************************
* Return all events in the calendar which contain usable alarms.
* For the Akonadi version, this method is for the display calendar only.
* This method is for the display calendar only.
* Optionally the event type can be filtered, using an OR of event types.
*/
Event::List AlarmCalendar::kcalEvents(CalEvent::Type type)
......
/*
* alarmcalendar.h - KAlarm calendar file access
* Program: kalarm
* Copyright © 2001-2019 David Jarvie <djarvie@kde.org>
* Copyright © 2001-2020 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
......@@ -96,6 +96,7 @@ class AlarmCalendar : public QObject
private Q_SLOTS:
void slotResourceSettingsChanged(Resource&, ResourceType::Changes);
void slotResourcesPopulated();
void slotResourceAdded(Resource&);
void slotEventsAdded(Resource&, const QList<KAEvent>&);
void slotEventsToBeRemoved(Resource&, const QList<KAEvent>&);
void slotEventUpdated(Resource&, const KAEvent&);
......@@ -110,10 +111,10 @@ class AlarmCalendar : public QObject
bool saveCal(const QString& newFile = QString());
bool isValid() const { return mCalType == RESOURCES || mCalendarStorage; }
void addNewEvent(const Resource&, KAEvent*, bool replace = false);
CalEvent::Type deleteEventInternal(const KAEvent&, bool deleteFromAkonadi = true);
CalEvent::Type deleteEventInternal(const KAEvent&, Resource&, bool deleteFromAkonadi = true);
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 deleteFromAkonadi = true);
bool deleteFromResources = true);
void updateDisplayKAEvents();
void removeKAEvents(ResourceId, bool closing = false, CalEvent::Types = CalEvent::ACTIVE | CalEvent::ARCHIVED | CalEvent::TEMPLATE);
void findEarliestAlarm(const Resource&);
......@@ -125,7 +126,7 @@ class AlarmCalendar : public QObject
static AlarmCalendar* mDisplayCalendar; // the display calendar
static QUrl mLastImportUrl; // last URL for Import Alarms file dialogue
KCalendarCore::FileStorage::Ptr mCalendarStorage; // null pointer for Akonadi
KCalendarCore::FileStorage::Ptr mCalendarStorage; // for display calendar; null if resources calendar
ResourceMap mResourceMap;
KAEventMap mEventMap; // lookup of all events by UID
EarliestMap mEarliestAlarm; // alarm with earliest trigger time, by resource
......
/*
* eventid.cpp - KAlarm unique event identifier for Akonadi
* eventid.cpp - KAlarm unique event identifier for resources
* Program: kalarm
* Copyright © 2012,2019 David Jarvie <djarvie@kde.org>
* Copyright © 2012-2020 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
......@@ -48,4 +48,9 @@ EventId::EventId(const QString& resourceEventId)
}
}
ResourceId EventId::resourceDisplayId() const
{
return first;
}
// vim: et sw=4:
/*
* eventid.h - KAlarm unique event identifier for Akonadi
* eventid.h - KAlarm unique event identifier for resources
* Program: kalarm
* Copyright © 2012,2014 by David Jarvie <djarvie@kde.org>
* Copyright © 2012-2020 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
......@@ -30,29 +30,33 @@
using namespace KAlarmCal;
/**
* Unique event identifier for Akonadi.
* This consists of the event UID within the individual calendar,
* plus the collection ID.
* Unique event identifier for resources.
* This consists of the event UID within the individual calendar, plus the
* resource ID.
*
* Note that the collection ID of the display calendar is -1, since
* it is not an Akonadi calendar.
* Note that the resource ID of the display calendar is -1, since it is not a
* resources calendar.
*/
struct EventId : public QPair<Akonadi::Collection::Id, QString>
struct EventId : public QPair<ResourceId, QString>
{
EventId() {}
EventId(Akonadi::Collection::Id c, const QString& e)
: QPair<Akonadi::Collection::Id, QString>(c, e) {}
EventId(ResourceId c, const QString& e)
: QPair<ResourceId, QString>(c, e) {}
explicit EventId(const KAEvent& event)
: QPair<Akonadi::Collection::Id, QString>(event.collectionId(), event.id()) {}
: QPair<ResourceId, QString>(event.resourceId(), event.id()) {}
/** Set by event ID prefixed by optional resource ID, in the format "[rid:]eid". */
explicit EventId(const QString& resourceEventId);
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; }
void setCollectionId(Akonadi::Collection::Id id) { first = id; }
ResourceId resourceId() const { return first; }
ResourceId resourceDisplayId() const;
QString eventId() const { return second; }
void setResourceId(ResourceId id) { first = id; }
};
// Declare as a movable type (note that QString is movable).
......@@ -60,7 +64,7 @@ Q_DECLARE_TYPEINFO(EventId, Q_MOVABLE_TYPE);
inline QDebug operator<<(QDebug s, const EventId& id)
{
s.nospace() << "\"" << id.collectionId() << "::" << id.eventId().toLatin1().constData() << "\"";
s.nospace() << "\"" << id.resourceDisplayId() << "::" << id.eventId().toLatin1().constData() << "\"";
return s.space();
}
......
/*
* functions.cpp - miscellaneous functions
* Program: kalarm
* Copyright © 2001-2019 David Jarvie <djarvie@kde.org>
* Copyright © 2001-2020 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
......@@ -1162,7 +1162,7 @@ bool editAlarmById(const EventId& id, QWidget* parent)
KAEvent* event = AlarmCalendar::resources()->event(id, true);
if (!event)
{
if (id.collectionId() != -1)
if (id.resourceId() != -1)
qCWarning(KALARM_LOG) << "KAlarm::editAlarmById: Event ID not found, or duplicated:" << eventID;
else
qCWarning(KALARM_LOG) << "KAlarm::editAlarmById: Event ID not found:" << eventID;
......@@ -1388,7 +1388,7 @@ QStringList dontShowErrors(const EventId& eventId)
return QStringList();
KConfig config(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + ALARM_OPTS_FILE);
KConfigGroup group(&config, DONT_SHOW_ERRORS_GROUP);
const QString id = QStringLiteral("%1:%2").arg(eventId.collectionId()).arg(eventId.eventId());
const QString id = QStringLiteral("%1:%2").arg(eventId.resourceId()).arg(eventId.eventId());
return group.readEntry(id, QStringList());
}
......@@ -1414,7 +1414,7 @@ void setDontShowErrors(const EventId& eventId, const QStringList& tags)
return;
KConfig config(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + ALARM_OPTS_FILE);
KConfigGroup group(&config, DONT_SHOW_ERRORS_GROUP);
const QString id = QStringLiteral("%1:%2").arg(eventId.collectionId()).arg(eventId.eventId());
const QString id = QStringLiteral("%1:%2").arg(eventId.resourceId()).arg(eventId.eventId());
if (tags.isEmpty())
group.deleteEntry(id);
else
......@@ -1432,7 +1432,7 @@ void setDontShowErrors(const EventId& eventId, const QString& tag)
return;
KConfig config(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + ALARM_OPTS_FILE);
KConfigGroup group(&config, DONT_SHOW_ERRORS_GROUP);
const QString id = QStringLiteral("%1:%2").arg(eventId.collectionId()).arg(eventId.eventId());
const QString id = QStringLiteral("%1:%2").arg(eventId.resourceId()).arg(eventId.eventId());
QStringList tags = group.readEntry(id, QStringList());
if (tags.indexOf(tag) < 0)
{
......
......@@ -410,7 +410,7 @@ int KAlarmApp::activateInstance(const QStringList& args, const QString& workingD
const EventFunc function = (command == CommandOptions::TRIGGER_EVENT) ? EVENT_TRIGGER : EVENT_CANCEL;
// Open the calendar, don't start processing execution queue yet,
// and wait for the calendar resources to be populated.
if (!initCheck(true, true, options->eventId().collectionId()))
if (!initCheck(true, true, options->eventId().resourceId()))
exitCode = 1;
else
{
......@@ -443,7 +443,7 @@ int KAlarmApp::activateInstance(const QStringList& args, const QString& workingD
case CommandOptions::EDIT:
// Edit a specified existing alarm.
// Open the calendar and wait for the calendar resources to be populated.
if (!initCheck(false, true, options->eventId().collectionId()))
if (!initCheck(false, true, options->eventId().resourceId()))
exitCode = 1;
else if (!KAlarm::editAlarmById(options->eventId()))
{
......@@ -1427,7 +1427,7 @@ bool KAlarmApp::handleEvent(const EventId& id, EventFunc function, bool checkDup
KAEvent* event = AlarmCalendar::resources()->event(id, checkDuplicates);
if (!event)
{
if (id.collectionId() != -1)
if (id.resourceId() != -1)
qCWarning(KALARM_LOG) << "KAlarmApp::handleEvent: Event ID not found, or duplicated:" << eventID;
else
qCWarning(KALARM_LOG) << "KAlarmApp::handleEvent: Event ID not found:" << eventID;
......
/*
* messagewin.cpp - displays an alarm message
* Program: kalarm
* Copyright © 2001-2019 David Jarvie <djarvie@kde.org>
* Copyright © 2001-2020 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
......@@ -1057,7 +1057,7 @@ void MessageWin::showRestoredAlarm()
void MessageWin::redisplayAlarm()
{
mResource = Resources::resourceForEvent(mEventId.eventId());
mEventId.setCollectionId(mResource.id());
mEventId.setResourceId(mResource.id());
qCDebug(KALARM_LOG) << "MessageWin::redisplayAlarm:" << mEventId;
// Delete any already existing window for the same event
MessageWin* duplicate = findEvent(mEventId, this);
......
......@@ -395,6 +395,19 @@ void Resources::notifyResourcesMigrated()
Q_EMIT instance()->migrationCompleted();
}
/******************************************************************************
* Called to notify that a resource is about to be removed.
*/
void Resources::notifyResourceToBeRemoved(ResourceType* res)
{
if (res)
{
Resource r = resource(res->id());
if (r.isValid())
Q_EMIT instance()->resourceToBeRemoved(r);
}
}
/******************************************************************************
* Called by a resource to notify that its settings have changed.
* Emits the settingsChanged() signal.
......
......@@ -154,6 +154,9 @@ public:
/** Called to notify that migration/creation of resources has completed. */
static void notifyResourcesMigrated();
/** Called to notify that a resource is about to be removed. */
static void notifyResourceToBeRemoved(ResourceType*);
/** Called by a resource to notify that its settings have changed.
* This will cause the settingsChanged() signal to be emitted.
*/
......@@ -176,7 +179,9 @@ public:
/** Called by a resource to notify that it has added events. */
static void notifyEventsAdded(ResourceType*, const QList<KAEvent>&);
/** Called by a resource to notify that it has changed an event. */
/** Called by a resource to notify that it has changed an event.
* The event's UID must be unchanged.
*/
static void notifyEventUpdated(ResourceType*, const KAEvent& event);
/** Called by a resource to notify that it is about to delete events. */
......@@ -205,6 +210,9 @@ Q_SIGNALS:
/** Emitted when a resource's events have been successfully loaded. */
void resourcePopulated(Resource&);
/** Emitted when a resource's config and settings are about to be removed. */
void resourceToBeRemoved(Resource&);
/** Emitted when a resource's config and settings have been removed. */
void resourceRemoved(ResourceId);
......@@ -221,6 +229,7 @@ Q_SIGNALS:
/** Emitted when an event has been updated in a resource.
* Events are only notified whose alarm type is enabled.
* The event's UID is unchanged.
*/
void eventUpdated(Resource&, const KAEvent&);
......
......@@ -183,6 +183,7 @@ void ResourceType::removeResource(ResourceId id)
*/
void ResourceType::setLoadedEvents(QHash<QString, KAEvent>& newEvents)
{
qCDebug(KALARM_LOG) << "ResourceType::setLoadedEvents: count" << newEvents.count();
const CalEvent::Types types = enabledTypes();
// Replace existing events with the new ones, and find events which no
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment