Commit 05bf384f authored by David Jarvie's avatar David Jarvie
Browse files

Bug 417108: Fix error creating alarm from command line

If there is only one active alarm calendar but it is not the default,
set it as the default to allow the alarm to be created.
parent 252faa93
Pipeline #51448 failed with stage
in 6 minutes and 38 seconds
......@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5)
set(PIM_VERSION "5.16.3")
set(PIM_VERSION ${PIM_VERSION})
set(RELEASE_SERVICE_VERSION "20.12.3")
set(KALARM_VERSION "3.1.2")
set(KALARM_VERSION "3.1.3")
project(kalarm VERSION ${KALARM_VERSION})
......
KAlarm Change Log
=== Version 3.1.3 (KDE Applications 20.12.3) --- 18 February 2021 ===
* Fix error creating alarm from command line if the only active alarm calendar is not the default [KDE Bug 417108].
=== Version 3.1.2 (KDE Applications 20.12.2) --- 26 January 2021 ===
* Default to using alarm names.
* Fix hang when an alarm is triggered in a read-only resource.
......
......@@ -1146,7 +1146,7 @@ bool EditAlarmDlg::validate()
bool cancelled = false;
CalEvent::Type type = mTemplate ? CalEvent::TEMPLATE : CalEvent::ACTIVE;
if (!mResource.isWritable(type))
mResource = Resources::destination(type, this, false, &cancelled);
mResource = Resources::destination(type, this, Resources::NoDestOption, &cancelled);
if (!mResource.isValid())
{
if (!cancelled)
......
......@@ -235,7 +235,14 @@ UpdateResult addEvent(KAEvent& event, Resource& resource, QWidget* msgParent, in
{
// Save the event details in the calendar file, and get the new event ID
// Note that ResourcesCalendar::addEvent() updates 'event'.
if (!ResourcesCalendar::addEvent(event, resource, msgParent, (options & USE_EVENT_ID), (options & NO_RESOURCE_PROMPT), &cancelled))
ResourcesCalendar::AddEventOptions rc_options = {};
if (options & USE_EVENT_ID)
rc_options |= ResourcesCalendar::UseEventId;
if (options & NO_RESOURCE_PROMPT)
rc_options |= ResourcesCalendar::NoResourcePrompt;
if (options & USE_ONLY_RESOURCE)
rc_options |= ResourcesCalendar::UseOnlyResource;
if (!ResourcesCalendar::addEvent(event, resource, msgParent, rc_options, &cancelled))
{
status.status = UPDATE_FAILED;
}
......@@ -289,7 +296,7 @@ UpdateResult addEvents(QVector<KAEvent>& events, Resource& resource, QWidget* ms
{
// Save the event details in the calendar file, and get the new event ID
KAEvent& event = events[i];
if (!ResourcesCalendar::addEvent(event, resource, msgParent, false))
if (!ResourcesCalendar::addEvent(event, resource, msgParent))
{
status.appendFailed(i);
status.setError(UPDATE_ERROR);
......@@ -337,7 +344,7 @@ bool addArchivedEvent(KAEvent& event, Resource& resource)
// Add the event from the archived resource. It's not too important whether
// the resource is saved successfully after the deletion, so allow it to be
// saved automatically.
if (!ResourcesCalendar::addEvent(newevent, resource, nullptr, false))
if (!ResourcesCalendar::addEvent(newevent, resource))
return false;
event = *newev; // update event ID etc.
......@@ -356,7 +363,7 @@ UpdateResult addTemplate(KAEvent& event, Resource& resource, QWidget* msgParent)
// Add the template to the calendar file
KAEvent newev(event);
if (!ResourcesCalendar::addEvent(newev, resource, msgParent, false))
if (!ResourcesCalendar::addEvent(newev, resource, msgParent))
status.status = UPDATE_FAILED;
else
{
......@@ -646,7 +653,7 @@ UpdateResult reactivateEvents(QVector<KAEvent>& events, QVector<int>& ineligible
// Save the event details in the calendar file.
// This converts the event ID.
if (!ResourcesCalendar::addEvent(newevent, resource, msgParent, true))
if (!ResourcesCalendar::addEvent(newevent, resource, msgParent, ResourcesCalendar::UseEventId))
{
status.appendFailed(i);
continue;
......@@ -777,7 +784,7 @@ void purgeArchive(int purgeDays)
return;
qCDebug(KALARM_LOG) << "KAlarm::purgeArchive:" << purgeDays;
const QDate cutoff = KADateTime::currentLocalDate().addDays(-purgeDays);
const Resource resource = Resources::getStandard(CalEvent::ARCHIVED);
const Resource resource = Resources::getStandard(CalEvent::ARCHIVED, true);
if (!resource.isValid())
return;
QVector<KAEvent> events = ResourcesCalendar::events(resource);
......
......@@ -104,7 +104,8 @@ enum // 'options' parameter values for addEvent(). May be OR'ed together
{
USE_EVENT_ID = 0x01, // use event ID if it's provided
NO_RESOURCE_PROMPT = 0x02, // don't prompt for resource
ALLOW_KORG_UPDATE = 0x04 // allow change to be sent to KOrganizer
USE_ONLY_RESOURCE = 0x04, // if there is only one enabled resource, use it as the default
ALLOW_KORG_UPDATE = 0x08 // allow change to be sent to KOrganizer
};
/** Add a new active (non-archived) alarm to a resource.
......
......@@ -1037,7 +1037,7 @@ void KAlarmApp::processQueue()
case QueuedAction::Handle:
{
Resource resource;
KAlarm::addEvent(entry.event, resource, nullptr, KAlarm::ALLOW_KORG_UPDATE | KAlarm::NO_RESOURCE_PROMPT);
KAlarm::addEvent(entry.event, resource, nullptr, KAlarm::ALLOW_KORG_UPDATE | KAlarm::NO_RESOURCE_PROMPT | KAlarm::USE_ONLY_RESOURCE);
break;
}
case QueuedAction::List:
......@@ -1415,7 +1415,7 @@ void KAlarmApp::checkArchivedCalendar()
// calendar is writable.
if (Preferences::archivedKeepDays())
{
Resource standard = Resources::getStandard(CalEvent::ARCHIVED);
Resource standard = Resources::getStandard(CalEvent::ARCHIVED, true);
if (!standard.isValid())
{
// Schedule the display of a user prompt, without holding up
......
/*
* messagedisplay.cpp - base class to display an alarm or error message
* Program: kalarm
* SPDX-FileCopyrightText: 2001-2020 David Jarvie <djarvie@kde.org>
* SPDX-FileCopyrightText: 2001-2021 David Jarvie <djarvie@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -151,7 +151,7 @@ bool MessageDisplay::retrieveEvent(const EventId& evntId, KAEvent& event, Resour
// The event isn't in the displaying calendar.
// Try to retrieve it from the archive calendar.
KAEvent ev;
Resource archiveRes = Resources::getStandard(CalEvent::ARCHIVED);
Resource archiveRes = Resources::getStandard(CalEvent::ARCHIVED, true);
if (archiveRes.isValid())
ev = ResourcesCalendar::event(EventId(archiveRes.id(), CalEvent::uid(eventId, CalEvent::ARCHIVED)));
if (!ev.isValid())
......
......@@ -943,7 +943,7 @@ void StorePrefTab::slotArchivedToggled(bool)
{
const bool keep = mKeepArchived->isChecked();
if (keep && !mOldKeepArchived && mCheckKeepChanges
&& !Resources::getStandard(CalEvent::ARCHIVED).isValid())
&& !Resources::getStandard(CalEvent::ARCHIVED, true).isValid())
{
KAMessageBox::sorry(topLayout()->parentWidget(),
xi18nc("@info", "<para>A default calendar is required in order to archive alarms, but none is currently enabled.</para>"
......
/*
* resource.cpp - generic class containing an alarm calendar resource
* Program: kalarm
* SPDX-FileCopyrightText: 2019-2020 David Jarvie <djarvie@kde.org>
* SPDX-FileCopyrightText: 2019-2021 David Jarvie <djarvie@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -78,11 +78,10 @@ QVector<Resource> Resources::enabledResources(CalEvent::Type type, bool writable
/******************************************************************************
* Return the standard resource for an alarm type.
*/
Resource Resources::getStandard(CalEvent::Type type)
Resource Resources::getStandard(CalEvent::Type type, bool useOnlyResource)
{
Resources* manager = instance();
bool wantDefaultArchived = (type == CalEvent::ARCHIVED);
Resource defaultArchived;
Resource defaultResource;
for (auto it = manager->mResources.constBegin(); it != manager->mResources.constEnd(); ++it)
{
const Resource& res = it.value();
......@@ -90,23 +89,23 @@ Resource Resources::getStandard(CalEvent::Type type)
{
if (res.configIsStandard(type))
return res;
if (wantDefaultArchived)
if (useOnlyResource)
{
if (defaultArchived.isValid())
wantDefaultArchived = false; // found two archived alarm resources
if (defaultResource.isValid())
useOnlyResource = false; // found two resources for the type
else
defaultArchived = res; // this is the first archived alarm resource
defaultResource = res; // this is the first resource for the type
}
}
}
if (wantDefaultArchived && defaultArchived.isValid())
if (useOnlyResource && defaultResource.isValid())
{
// There is no resource specified as the standard archived alarm
// resource, but there is exactly one writable archived alarm
// resource. Set that resource to be the standard.
defaultArchived.configSetStandard(CalEvent::ARCHIVED, true);
return defaultArchived;
// There is no resource specified as the standard resource for the
// alarm type, but there is exactly one writable reseource for the
// type. Set that resource to be the standard.
defaultResource.configSetStandard(type, true);
return defaultResource;
}
return Resource();
......@@ -121,7 +120,7 @@ bool Resources::isStandard(const Resource& resource, CalEvent::Type type)
// If it's for archived alarms, get and also set the standard resource if
// necessary.
if (type == CalEvent::ARCHIVED)
return getStandard(type) == resource;
return getStandard(type, true) == resource;
return resource.configIsStandard(type) && resource.isWritable(type);
}
......@@ -147,7 +146,7 @@ CalEvent::Types Resources::standardTypes(const Resource& resource, bool useDefau
if (!(stdTypes & CalEvent::ARCHIVED) && resource.isEnabled(CalEvent::ARCHIVED))
{
// If it's the only enabled archived alarm resource, set it as standard.
getStandard(CalEvent::ARCHIVED);
getStandard(CalEvent::ARCHIVED, true);
stdTypes = resource.configStandardTypes() & resource.enabledTypes();
}
CalEvent::Types enabledNotStd = resource.enabledTypes() & ~stdTypes;
......@@ -239,17 +238,17 @@ void Resources::setStandard(Resource& resource, CalEvent::Types types)
* This will be the standard resource for the type, but if this is not valid,
* the user will be prompted to select a resource.
*/
Resource Resources::destination(CalEvent::Type type, QWidget* promptParent, bool noPrompt, bool* cancelled)
Resource Resources::destination(CalEvent::Type type, QWidget* promptParent, DestOptions options, bool* cancelled)
{
if (cancelled)
*cancelled = false;
Resource standard;
if (type == CalEvent::EMPTY)
return standard;
standard = getStandard(type);
standard = getStandard(type, (options & UseOnlyResource));
// Archived alarms are always saved in the default resource,
// else only prompt if necessary.
if (type == CalEvent::ARCHIVED || noPrompt
if (type == CalEvent::ARCHIVED || (options & NoResourcePrompt)
|| (!Preferences::askResource() && standard.isValid()))
return standard;
......
......@@ -73,10 +73,12 @@ public:
* as standard and there is exactly one writable archived alarm resource,
* that resource will be automatically set as standard.
*
* @param type alarm type
* @param type Alarm type.
* @param useOnlyResource If there is only one resource for the alarm type,
* set it as standard.
* @return standard resource, or null if none.
*/
static Resource getStandard(CalEvent::Type type);
static Resource getStandard(CalEvent::Type type, bool useOnlyResource = false);
/** Return whether a resource is the standard resource for a specified alarm
* type. Only enabled and writable resources can be standard.
......@@ -112,16 +114,25 @@ public:
*/
static void setStandard(Resource& resource, CalEvent::Types);
/** Options for destination(). May be OR'ed together. */
enum DestOption
{
NoDestOption = 0,
NoResourcePrompt = 0x01, //!< Don't prompt the user even if the standard resource is not valid.
UseOnlyResource = 0x02 //!< If there is only one enabled resource, set it as standard.
};
Q_DECLARE_FLAGS(DestOptions, DestOption)
/** Find the resource to be used to store an event of a given type.
* This will be the standard resource for the type, but if this is not valid,
* the user will be prompted to select a resource.
* @param type The event type
* @param promptParent The parent widget for the prompt
* @param noPrompt Don't prompt the user even if the standard resource is not valid
* @param options Options to use
* @param cancelled If non-null: set to true if the user cancelled the
* prompt dialogue; set to false if any other error
*/
static Resource destination(CalEvent::Type type, QWidget* promptParent = nullptr, bool noPrompt = false, bool* cancelled = nullptr);
static Resource destination(CalEvent::Type type, QWidget* promptParent = nullptr, DestOptions options = NoDestOption, bool* cancelled = nullptr);
/** Return whether all configured and migrated resources have been created. */
static bool allCreated();
......@@ -280,6 +291,7 @@ private:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Resources::Sorting)
Q_DECLARE_OPERATORS_FOR_FLAGS(Resources::DestOptions)
/*=============================================================================
......@@ -297,7 +309,7 @@ QVector<Resource> Resources::allResources(CalEvent::Type type, Sorting sorting)
Resource std;
if ((sorting & DefaultFirst) && type != CalEvent::EMPTY)
{
std = getStandard(type);
std = getStandard(type, (type == CalEvent::ARCHIVED));
if (std.isValid() && std.is<RType>())
result += std;
}
......
......@@ -285,8 +285,9 @@ void ResourcesCalendar::purgeEvents(const QVector<KAEvent>& events)
* 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, Resource& resource, QWidget* promptParent, bool useEventID, bool noPrompt, bool* cancelled)
bool ResourcesCalendar::addEvent(KAEvent& evnt, Resource& resource, QWidget* promptParent, AddEventOptions options, bool* cancelled)
{
bool useEventID = options & UseEventId;
if (cancelled)
*cancelled = false;
qCDebug(KALARM_LOG) << "ResourcesCalendar::addEvent:" << evnt.id() << ", resource" << resource.displayId();
......@@ -323,7 +324,12 @@ bool ResourcesCalendar::addEvent(KAEvent& evnt, Resource& resource, QWidget* pro
bool ok = false;
if (!resource.isEnabled(type))
{
resource = Resources::destination(type, promptParent, noPrompt, cancelled);
Resources::DestOptions destOptions {};
if (options & NoResourcePrompt)
destOptions |= Resources::NoResourcePrompt;
if (options & UseOnlyResource)
destOptions |= Resources::UseOnlyResource;
resource = Resources::destination(type, promptParent, destOptions, cancelled);
if (!resource.isValid())
qCWarning(KALARM_LOG) << "ResourcesCalendar::addEvent: Error! Cannot create" << type << "(No default calendar is defined)";
}
......
......@@ -53,7 +53,18 @@ public:
static QVector<KAEvent> events(const QString& uniqueId);
static QVector<KAEvent> events(const Resource&, CalEvent::Types = CalEvent::EMPTY);
static QVector<KAEvent> events(CalEvent::Types s = CalEvent::EMPTY);
static bool addEvent(KAEvent&, Resource&, QWidget* promptparent = nullptr, bool useEventID = false, bool noPrompt = false, bool* cancelled = nullptr);
/** Options for addEvent(). May be OR'ed together. */
enum AddEventOption
{
NoOption = 0,
UseEventId = 0x01, // use event ID if it's provided
NoResourcePrompt = 0x02, // don't prompt for resource
UseOnlyResource = 0x04 // if there is only one enabled resource, use it as the default
};
Q_DECLARE_FLAGS(AddEventOptions, AddEventOption)
static bool addEvent(KAEvent&, Resource&, QWidget* promptparent = nullptr, AddEventOptions options = NoOption, bool* cancelled = nullptr);
static bool modifyEvent(const EventId& oldEventId, KAEvent& newEvent);
static KAEvent updateEvent(const KAEvent&, bool saveIfReadOnly = true);
static bool deleteEvent(const KAEvent&, Resource&, bool save = false);
......@@ -98,6 +109,8 @@ private:
static bool mHaveDisabledAlarms; // there is at least one individually disabled alarm
};
Q_DECLARE_OPERATORS_FOR_FLAGS(ResourcesCalendar::AddEventOptions)
#endif // RESOURCESCALENDAR_H
// vim: et sw=4:
/*
* resourceselector.cpp - calendar resource selection widget
* Program: kalarm
* SPDX-FileCopyrightText: 2006-2020 David Jarvie <djarvie@kde.org>
* SPDX-FileCopyrightText: 2006-2021 David Jarvie <djarvie@kde.org>
* Based on KOrganizer's ResourceView class and KAddressBook's ResourceSelection class,
* SPDX-FileCopyrightText: 2003, 2004 Cornelius Schumacher <schumacher@kde.org>
* SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
......@@ -412,7 +412,7 @@ void ResourceSelector::archiveDaysChanged(int days)
{
if (days)
{
const Resource resource = Resources::getStandard(CalEvent::ARCHIVED);
const Resource resource = Resources::getStandard(CalEvent::ARCHIVED, true);
if (resource.isValid())
theApp()->purgeNewArchivedDefault(resource);
}
......
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