Commit 9e8e3f63 authored by David Jarvie's avatar David Jarvie

Don't execute display alarms while desktop notifications are inhibited

parent c1cb7f7a
Pipeline #38352 canceled with stage
KAlarm Change Log
=== Version 3.1.0 (KDE Applications 20.12) --- 24 September 2020 ===
=== Version 3.1.0 (KDE Applications 20.12) --- 22 October 2020 ===
+ Add option to show alarm message as a notification instead of in a window [KDE Bug 345922]
+ Don't execute display alarms while desktop notifications are inhibited.
=== Version 3.0.3 (KDE Applications 20.08.3) --- 15 October 2020 ===
+ Prevent resources being disabled at logout [KDE Bug 427722]
......
......@@ -39,7 +39,7 @@
<!-- Don't change format of date and version of the documentation -->
<date>2020-09-24</date>
<date>2020-10-22</date>
<releaseinfo>3.1.0 (Applications 20.12)</releaseinfo>
<abstract>
......@@ -1926,6 +1926,11 @@ depending on the option chosen in the
<link linkend="alarm-edit-dlg">Alarm Edit dialog</link>. These two
display options are described below.</para>
<para>If you inhibit notifications for the desktop, the execution of
display alarms will be suspended until notifications are re-enabled.
Note that this applies to all display alarms, regardless of whether
they are displayed in windows or as notifications.</para>
<sect2 id="message-window">
<title>Alarm Message Window</title>
......
......@@ -145,6 +145,9 @@ qt5_add_dbus_adaptor(kalarm_bin_SRCS data/org.kde.kalarm.kalarm.xml dbushandler.
qt5_add_dbus_interfaces(kalarm_bin_SRCS data/org.kde.kmail.kmail.xml)
qt5_add_dbus_interface(kalarm_bin_SRCS data/org.freedesktop.Notifications.xml notifications_interface)
qt5_add_dbus_interface(kalarm_bin_SRCS data/org.freedesktop.DBus.Properties.xml dbusproperties)
kcfg_generate_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/data/kalarmresource.kcfg org.kde.Akonadi.KAlarm.Settings)
qt5_add_dbus_interface(kalarm_bin_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.Akonadi.KAlarm.Settings.xml kalarmsettings KAlarmSettings)
......
<?xml version="1.0"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!-- GDBus 2.32.4 -->
<node>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg type="s" name="interface_name" direction="in"/>
<arg type="s" name="property_name" direction="in"/>
<arg type="v" name="value" direction="out"/>
</method>
<method name="GetAll">
<arg type="s" name="interface_name" direction="in"/>
<arg type="a{sv}" name="properties" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap" />
</method>
<method name="Set">
<arg type="s" name="interface_name" direction="in"/>
<arg type="s" name="property_name" direction="in"/>
<arg type="v" name="value" direction="in"/>
</method>
<signal name="PropertiesChanged">
<arg type="s" name="interface_name"/>
<arg type="a{sv}" name="changed_properties"/>
<arg type="as" name="invalidated_properties"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap" />
</signal>
</interface>
</node>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.Notifications">
<signal name="NotificationClosed">
<arg name="id" type="u" direction="out"/>
<arg name="reason" type="u" direction="out"/>
</signal>
<signal name="ActionInvoked">
<arg name="id" type="u" direction="out"/>
<arg name="action_key" type="s" direction="out"/>
</signal>
<method name="Notify">
<annotation name="org.qtproject.QtDBus.QtTypeName.In6" value="QVariantMap"/>
<arg type="u" direction="out"/>
<arg name="app_name" type="s" direction="in"/>
<arg name="replaces_id" type="u" direction="in"/>
<arg name="app_icon" type="s" direction="in"/>
<arg name="summary" type="s" direction="in"/>
<arg name="body" type="s" direction="in"/>
<arg name="actions" type="as" direction="in"/>
<arg name="hints" type="a{sv}" direction="in"/>
<arg name="timeout" type="i" direction="in"/>
</method>
<method name="CloseNotification">
<arg name="id" type="u" direction="in"/>
</method>
<method name="GetCapabilities">
<arg type="as" name="caps" direction="out"/>
</method>
<method name="GetServerInformation">
<arg type="s" name="name" direction="out"/>
<arg type="s" name="vendor" direction="out"/>
<arg type="s" name="version" direction="out"/>
<arg type="s" name="spec_version" direction="out"/>
</method>
<!-- Inhibitions -->
<method name="Inhibit">
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
<arg type="u" direction="out"/>
<arg name="desktop_entry" type="s" direction="in"/>
<arg name="reason" type="s" direction="in"/>
<arg name="hints" type="a{sv}" direction="in"/>
</method>
<method name="UnInhibit">
<arg type="u" direction="in"/>
</method>
<property name="Inhibited" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
</property>
<!--<method name="ListInhibitors">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;Inhibition&gt;"/>
<arg name="inhibitors" type="a(ssa{sv})" direction="out"/>
</method>-->
</interface>
</node>
......@@ -1166,7 +1166,7 @@ void EditAlarmDlg::slotTry()
event.setEventId(mEventId);
}
type_aboutToTry();
void* result = theApp()->execAlarm(event, event.firstAlarm(), KAlarmApp::NoRecordCmdError);
void* result = theApp()->execAlarm(event, event.firstAlarm(), KAlarmApp::NoRecordCmdError | KAlarmApp::NoNotifyInhibit);
type_executedTry(text, result);
}
}
......
......@@ -30,6 +30,8 @@
#include "lib/desktop.h"
#include "lib/messagebox.h"
#include "lib/shellprocess.h"
#include "notifications_interface.h" // DBUS-generated
#include "dbusproperties.h" // DBUS-generated
#include "kalarm_debug.h"
#include <KAlarmCal/DateTime>
......@@ -62,6 +64,9 @@ namespace
{
const int RESOURCES_TIMEOUT = 30; // timeout (seconds) for resources to be populated
const char FDO_NOTIFICATIONS_SERVICE[] = "org.freedesktop.Notifications";
const char FDO_NOTIFICATIONS_PATH[] = "/org/freedesktop/Notifications";
/******************************************************************************
* Find the maximum number of seconds late which a late-cancel alarm is allowed
* to be. This is calculated as the late cancel interval, plus a few seconds
......@@ -194,6 +199,23 @@ void KAlarmApp::initialise()
DateTime::setStartOfDay(Preferences::startOfDay());
mPrefsArchivedColour = Preferences::archivedColour();
}
// Get notified when the Freedesktop notifications properties have changed.
QDBusConnection conn = QDBusConnection::sessionBus();
if (conn.interface()->isServiceRegistered(QString::fromLatin1(FDO_NOTIFICATIONS_SERVICE)))
{
OrgFreedesktopDBusPropertiesInterface* piface = new OrgFreedesktopDBusPropertiesInterface(
QString::fromLatin1(FDO_NOTIFICATIONS_SERVICE),
QString::fromLatin1(FDO_NOTIFICATIONS_PATH),
conn, this);
connect(piface, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
this, &KAlarmApp::slotFDOPropertiesChanged);
OrgFreedesktopNotificationsInterface niface(
QString::fromLatin1(FDO_NOTIFICATIONS_SERVICE),
QString::fromLatin1(FDO_NOTIFICATIONS_PATH),
conn);
mNotificationsInhibited = niface.inhibited();
}
}
/******************************************************************************
......@@ -845,7 +867,7 @@ void KAlarmApp::checkNextDueAlarm()
return;
// Find the first alarm due
KADateTime nextDt;
const KAEvent nextEvent = ResourcesCalendar::earliestAlarm(nextDt);
const KAEvent nextEvent = ResourcesCalendar::earliestAlarm(nextDt, mNotificationsInhibited);
if (!nextEvent.isValid())
return; // there are no alarms pending
const KADateTime now = KADateTime::currentDateTime(Preferences::timeSpec());
......@@ -981,13 +1003,15 @@ void KAlarmApp::processQueue()
const QueuedAction action = static_cast<QueuedAction>(int(entry.action) & int(QueuedAction::ActionMask));
bool ok = true;
bool inhibit = false;
if (entry.eventId.isEmpty())
{
// It's a new alarm
switch (action)
{
case QueuedAction::Trigger:
execAlarm(entry.event, entry.event.firstAlarm());
if (execAlarm(entry.event, entry.event.firstAlarm()) == (void*)-2)
inhibit = true;
break;
case QueuedAction::Handle:
{
......@@ -1034,13 +1058,22 @@ void KAlarmApp::processQueue()
}
else
{
ok = handleEvent(entry.eventId, action, findUniqueId);
if (!ok && exitAfter)
// Trigger the event if it's due.
const int result = handleEvent(entry.eventId, action, findUniqueId);
if (!result)
inhibit = true;
else if (result < 0 && exitAfter)
CommandOptions::printError(xi18nc("@info:shell", "%1: Event <resource>%2</resource> not found, or not unique", mCommandOption, entry.eventId.eventId()));
}
}
if (exitAfter)
if (inhibit)
{
// It's a display event which can't be executed because notifications
// are inhibited. Move it to the inhibited queue until the inhibition
// is removed.
}
else if (exitAfter)
{
mActionQueue.clear(); // ensure that quitIf() actually exits the program
quitIf(ok ? 0 : 1);
......@@ -1506,6 +1539,29 @@ void KAlarmApp::purge(int daysToKeep)
processQueue();
}
/******************************************************************************
* Called when the Freedesktop notifications properties have changed.
* Check whether the inhibited property has changed.
*/
void KAlarmApp::slotFDOPropertiesChanged(const QString& interface,
const QVariantMap& changedProperties,
const QStringList& invalidatedProperties)
{
Q_UNUSED(interface); // always "org.freedesktop.Notifications"
Q_UNUSED(invalidatedProperties);
const auto it = changedProperties.find(QStringLiteral("Inhibited"));
if (it != changedProperties.end())
{
const bool inhibited = it.value().toBool();
if (inhibited != mNotificationsInhibited)
{
qCDebug(KALARM_LOG) << "KAlarmApp::slotFDOPropertiesChanged: Notifications inhibited ->" << inhibited;
mNotificationsInhibited = inhibited;
if (!mNotificationsInhibited)
QTimer::singleShot(0, this, &KAlarmApp::processQueue);
}
}
}
/******************************************************************************
* Output a list of pending alarms, with their next scheduled occurrence.
......@@ -1626,13 +1682,12 @@ bool KAlarmApp::scheduleEvent(KAEvent::SubAction action, const QString& text, co
event.endChanges();
if (alarmTime <= now)
{
// Alarm is due for display already.
// Alarm is due for execution already.
// First execute it once without adding it to the calendar file.
qCDebug(KALARM_LOG) << "KAlarmApp::scheduleEvent: executing" << text;
if (!mInitialised)
if (!mInitialised
|| execAlarm(event, event.firstAlarm()) == (void*)-2)
mActionQueue.enqueue(ActionQEntry(event, QueuedAction::Trigger));
else
execAlarm(event, event.firstAlarm());
// If it's a recurring alarm, reschedule it for its next occurrence
if (!event.recurs()
|| event.setNextOccurrence(now) == KAEvent::NO_OCCURRENCE)
......@@ -1673,17 +1728,20 @@ QString KAlarmApp::dbusList()
/******************************************************************************
* Either:
* a) Display the event and then delete it if it has no outstanding repetitions.
* a) Execute the event if it's due, and then delete it if it has no outstanding
* repetitions.
* b) Delete the event.
* 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.
* If 'findUniqueId' is true and 'id' does not specify a resource, all resources
* will be searched for the event's unique ID.
* Reply = false if event ID not found, or if more than one event with the same
* ID is found.
* Reply = -1 if event ID not found, or if more than one event with the same ID
* is found.
* = 0 if can't trigger display event because notifications are inhibited.
* = 1 if success.
*/
bool KAlarmApp::handleEvent(const EventId& id, QueuedAction action, bool findUniqueId)
int KAlarmApp::handleEvent(const EventId& id, QueuedAction action, bool findUniqueId)
{
Q_ASSERT(!(int(action) & ~int(QueuedAction::ActionMask)));
......@@ -1700,7 +1758,7 @@ bool KAlarmApp::handleEvent(const EventId& id, QueuedAction action, bool findUni
qCWarning(KALARM_LOG) << "KAlarmApp::handleEvent: Event ID not found, or duplicated:" << eventID;
else
qCCritical(KALARM_LOG) << "KAlarmApp::handleEvent: No resource ID specified for event:" << eventID;
return false;
return -1;
}
switch (action)
{
......@@ -1850,7 +1908,7 @@ bool KAlarmApp::handleEvent(const EventId& id, QueuedAction action, bool findUni
// All recurrences are finished, so cancel the event
event.setArchive();
if (cancelAlarm(event, alarm.type(), false))
return true; // event has been deleted
return 1; // event has been deleted
updateCalAndDisplay = true;
continue;
}
......@@ -1868,7 +1926,7 @@ bool KAlarmApp::handleEvent(const EventId& id, QueuedAction action, bool findUni
restart = true;
break;
case -1:
return true; // event has been deleted
return 1; // event has been deleted
default:
break;
}
......@@ -1888,7 +1946,10 @@ bool KAlarmApp::handleEvent(const EventId& id, QueuedAction action, bool findUni
// If there is an alarm to execute, do this last after rescheduling/cancelling
// any others. This ensures that the updated event is only saved once to the calendar.
if (alarmToExecute.isValid())
execAlarm(event, alarmToExecute, Reschedule | (alarmToExecute.repeatAtLogin() ? NoExecFlag : AllowDefer));
{
if (execAlarm(event, alarmToExecute, Reschedule | (alarmToExecute.repeatAtLogin() ? NoExecFlag : AllowDefer)) == (void*)-2)
return 0; // display alarm, but notifications are inhibited
}
else
{
if (action == QueuedAction::Trigger)
......@@ -1898,7 +1959,10 @@ bool KAlarmApp::handleEvent(const EventId& id, QueuedAction action, bool findUni
// identical messages, for example.
const KAAlarm alarm = event.firstAlarm();
if (alarm.isValid())
execAlarm(event, alarm);
{
if (execAlarm(event, alarm) == (void*)-2)
return 0; // display alarm, but notifications are inhibited
}
}
if (updateCalAndDisplay)
KAlarm::updateEvent(event); // update the window lists and calendar file
......@@ -1909,7 +1973,7 @@ bool KAlarmApp::handleEvent(const EventId& id, QueuedAction action, bool findUni
default:
break;
}
return true;
return 1;
}
/******************************************************************************
......@@ -2098,9 +2162,10 @@ bool KAlarmApp::cancelReminderAndDeferral(KAEvent& event)
* Execute an alarm by displaying its message or file, or executing its command.
* Reply = ShellProcess instance if a command alarm
* = MessageWindow if an audio alarm
* != 0 if successful
* != null if successful
* = -1 if execution has not completed
* = 0 if the alarm is disabled, or if an error message was output.
* = -2 if can't execute display event because notifications are inhibited.
* = null if the alarm is disabled, or if an error message was output.
*/
void* KAlarmApp::execAlarm(KAEvent& event, const KAAlarm& alarm, ExecAlarmFlags flags)
{
......@@ -2113,6 +2178,14 @@ void* KAlarmApp::execAlarm(KAEvent& event, const KAAlarm& alarm, ExecAlarmFlags
return nullptr;
}
if (mNotificationsInhibited && !(flags & NoNotifyInhibit)
&& (event.actionTypes() & KAEvent::ACT_DISPLAY))
{
// It's a display event and notifications are inhibited.
qCDebug(KALARM_LOG) << "KAlarmApp::execAlarm:" << event.id() << ": notifications inhibited";
return (void*)-2;
}
void* result = (void*)1;
event.setArchive();
......
......@@ -43,7 +43,8 @@ public:
Reschedule = 0x01, // reschedule the alarm after executing it
AllowDefer = 0x02, // allow the alarm to be deferred
NoRecordCmdError = 0x04, // don't record command errors
NoPreAction = 0x08
NoPreAction = 0x08, // it isn't a pre-alarm action
NoNotifyInhibit = 0x10 // ignore notification inhibit
};
Q_DECLARE_FLAGS(ExecAlarmFlags, ExecAlarmFlag)
......@@ -144,6 +145,9 @@ private Q_SLOTS:
void slotResourcePopulated(const Resource&);
void slotPurge() { purge(mArchivedPurgeDays); }
void slotCommandExited(ShellProcess*);
void slotFDOPropertiesChanged(const QString& interface,
const QVariantMap& changedProperties,
const QStringList& invalidatedProperties);
private:
// Actions to execute in processQueue(). May be OR'ed together.
......@@ -217,7 +221,7 @@ private:
void checkArchivedCalendar();
void queueAlarmId(const KAEvent&);
bool dbusHandleEvent(const EventId&, QueuedAction);
bool handleEvent(const EventId&, QueuedAction, bool findUniqueId = false);
int handleEvent(const EventId&, QueuedAction, bool findUniqueId = false);
int rescheduleAlarm(KAEvent&, const KAAlarm&, bool updateCalAndDisplay,
const KADateTime& nextDt = KADateTime());
bool cancelAlarm(KAEvent&, KAAlarm::Type, bool updateCalAndDisplay);
......@@ -266,6 +270,7 @@ private:
bool mKOrganizerEnabled; // KOrganizer options are enabled (korganizer exists)
bool mWindowFocusBroken; // keyboard focus transfer between windows doesn't work
bool mResourcesTimedOut {false}; // timeout has expired for populating resources
bool mNotificationsInhibited {false}; // Freedesktop notifications are inhibited
};
inline KAlarmApp* theApp() { return KAlarmApp::instance(); }
......
......@@ -20,6 +20,7 @@ using namespace KAlarmCal;
ResourcesCalendar* ResourcesCalendar::mInstance {nullptr};
ResourcesCalendar::ResourceMap ResourcesCalendar::mResourceMap;
ResourcesCalendar::EarliestMap ResourcesCalendar::mEarliestAlarm;
ResourcesCalendar::EarliestMap ResourcesCalendar::mEarliestNonDispAlarm;
QSet<QString> ResourcesCalendar::mPendingAlarms;
bool ResourcesCalendar::mIgnoreAtLogin {false};
bool ResourcesCalendar::mHaveDisabledAlarms {false};
......@@ -111,6 +112,7 @@ void ResourcesCalendar::removeKAEvents(ResourceId key, bool closing, CalEvent::T
if (removed)
{
mEarliestAlarm.remove(key);
mEarliestNonDispAlarm.remove(key);
// Emit signal only if we're not in the process of closing the calendar
if (!closing)
{
......@@ -193,17 +195,38 @@ void ResourcesCalendar::slotEventUpdated(Resource& resource, const KAEvent& even
&& event.category() == CalEvent::ACTIVE)
{
// Update the earliest alarm to trigger
const QString earliestId = mEarliestAlarm.value(key);
if (earliestId == event.id())
const QString earliestId = mEarliestAlarm.value(key);
const QString earliestNonDispId = mEarliestNonDispAlarm.value(key);
if (earliestId == event.id() || earliestNonDispId == event.id())
findEarliestAlarm(resource);
else
{
const KADateTime dt = event.nextTrigger(KAEvent::ALL_TRIGGER).effectiveKDateTime();
if (dt.isValid()
&& (earliestId.isEmpty() || dt < resource.event(earliestId).nextTrigger(KAEvent::ALL_TRIGGER)))
if (dt.isValid())
{
mEarliestAlarm[key] = event.id();
Q_EMIT earliestAlarmChanged();
bool changed = false;
DateTime next;
if (!earliestId.isEmpty())
next = resource.event(earliestId).nextTrigger(KAEvent::ALL_TRIGGER);
if (earliestId.isEmpty() || dt < next)
{
mEarliestAlarm[key] = event.id();
changed = true;
}
if (!(event.actionTypes() & KAEvent::ACT_DISPLAY))
{
// It is not a display event.
DateTime nextNonDisp;
if (!earliestNonDispId.isEmpty())
nextNonDisp = (earliestId == earliestNonDispId) ? next : resource.event(earliestNonDispId).nextTrigger(KAEvent::ALL_TRIGGER);
if (earliestNonDispId.isEmpty() || dt < nextNonDisp)
{
mEarliestNonDispAlarm[key] = event.id();
changed = true;
}
}
if (changed)
Q_EMIT earliestAlarmChanged();
}
}
}
......@@ -435,7 +458,8 @@ CalEvent::Type ResourcesCalendar::deleteEventInternal(const QString& eventID, co
{
const ResourceId key = resource.id();
mResourceMap[key].remove(eventID);
if (mEarliestAlarm.value(key) == eventID)
if (mEarliestAlarm.value(key) == eventID
|| mEarliestNonDispAlarm.value(key) == eventID)
mInstance->findEarliestAlarm(resource);
CalEvent::Type status = CalEvent::EMPTY;
......@@ -609,7 +633,8 @@ void ResourcesCalendar::checkForDisabledAlarms()
}
/******************************************************************************
* Find and note the active alarm with the earliest trigger time for a calendar.
* Find and note the active alarm with the earliest trigger time for a calendar,
* and the non-display active alarm with the earliest trigger time.
*/
void ResourcesCalendar::findEarliestAlarm(const Resource& resource)
{
......@@ -618,28 +643,46 @@ void ResourcesCalendar::findEarliestAlarm(const Resource& resource)
return;
if (!(resource.alarmTypes() & CalEvent::ACTIVE))
return;
// Invalidate any existing earliest alarms for the resource
EarliestMap::Iterator eit = mEarliestAlarm.find(key);
if (eit != mEarliestAlarm.end())
eit.value() = QString();
eit = mEarliestNonDispAlarm.find(key);
if (eit != mEarliestNonDispAlarm.end())
eit.value() = QString();
ResourceMap::ConstIterator rit = mResourceMap.constFind(key);
if (rit == mResourceMap.constEnd())
return;
const QVector<KAEvent> events = eventsForResource(resource, rit.value());
KAEvent earliest;
KADateTime earliestTime;
KAEvent earliest, earliestNonDisp;
KADateTime earliestTime, earliestNonDispTime;
for (const KAEvent& event : events)
{
if (event.category() != CalEvent::ACTIVE
|| mPendingAlarms.contains(event.id()))
continue;
const KADateTime dt = event.nextTrigger(KAEvent::ALL_TRIGGER).effectiveKDateTime();
if (dt.isValid() && (!earliest.isValid() || dt < earliestTime))
if (dt.isValid())
{
earliestTime = dt;
earliest = event;
if (!earliest.isValid() || dt < earliestTime)
{
earliestTime = dt;
earliest = event;
}
if (!(event.actionTypes() & KAEvent::ACT_DISPLAY))
{
if (!earliestNonDisp.isValid() || dt < earliestNonDispTime)
{
earliestNonDispTime = dt;
earliestNonDisp = event;
}
}
}
}
mEarliestAlarm[key] = earliest.id();
mEarliestAlarm[key] = earliest.id();
mEarliestNonDispAlarm[key] = earliestNonDisp.id();
Q_EMIT earliestAlarmChanged();
}
......@@ -647,11 +690,12 @@ void ResourcesCalendar::findEarliestAlarm(const Resource& resource)
* Return the active alarm with the earliest trigger time.
* Reply = invalid if none.
*/
KAEvent ResourcesCalendar::earliestAlarm(KADateTime& nextTriggerTime)
KAEvent ResourcesCalendar::earliestAlarm(KADateTime& nextTriggerTime, bool excludeDisplayAlarms)
{
KAEvent earliest;
KADateTime earliestTime;
for (EarliestMap::ConstIterator eit = mEarliestAlarm.constBegin(); eit != mEarliestAlarm.constEnd(); ++eit)
const EarliestMap& earliestAlarms(excludeDisplayAlarms ? mEarliestNonDispAlarm : mEarliestAlarm);
for (EarliestMap::ConstIterator eit = earliestAlarms.constBegin(); eit != earliestAlarms.constEnd(); ++eit)
{
const QString id = eit.value();
if (id.isEmpty())
......@@ -663,8 +707,9 @@ KAEvent ResourcesCalendar::earliestAlarm(KADateTime& nextTriggerTime)
// Something went wrong: mEarliestAlarm wasn't updated when it should have been!!
qCCritical(KALARM_LOG) << "ResourcesCalendar::earliestAlarm: resource" << eit.key() << "does not contain" << id;
mInstance->findEarliestAlarm(res);
return earliestAlarm(nextTriggerTime);
return earliestAlarm(nextTriggerTime, excludeDisplayAlarms);
}
//TODO: use next trigger calculated in findEarliestAlarm() (allowing for it being out of date)?
const KADateTime dt = event.nextTrigger(KAEvent::ALL_TRIGGER).effectiveKDateTime();
if (dt.isValid() && (!earliest.isValid() || dt < earliestTime))
{
......
......@@ -38,10 +38,11 @@ public:
static void terminate();
/** Return the active alarm with the earliest trigger time.
* @param nextTriggerTime The next trigger time of the earliest alarm.
* @param nextTriggerTime The next trigger time of the earliest alarm.
* @param excludeDisplayAlarms Ignore display alarms.
* @return The earliest alarm.
*/
static KAEvent earliestAlarm(KADateTime& nextTriggerTime);
static KAEvent earliestAlarm(KADateTime& nextTriggerTime, bool excludeDisplayAlarms = false);
static void setAlarmPending(const KAEvent&, bool pending = true);
static bool haveDisabledAlarms() { return mHaveDisabledAlarms; }
......@@ -90,7 +91,8 @@ private:
typedef QHash<ResourceId, QString> EarliestMap; // event ID of earliest alarm, for each resource
static ResourceMap mResourceMap;
static EarliestMap mEarliestAlarm; // alarm with earliest trigger time, by resource
static EarliestMap mEarliestAlarm; // alarm with earliest trigger time, by resource
static EarliestMap mEarliestNonDispAlarm; // non-display alarm with earliest trigger time, by resource
static QSet<QString> mPendingAlarms; // IDs of alarms which are currently being processed after triggering
static bool mIgnoreAtLogin; // ignore new/updated repeat-at-login alarms
static bool mHaveDisabledAlarms; // there is at least one individually disabled alarm
......
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