Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
PIM
KAlarm
Commits
9e8e3f63
Commit
9e8e3f63
authored
Oct 22, 2020
by
David Jarvie
Browse files
Don't execute display alarms while desktop notifications are inhibited
parent
c1cb7f7a
Pipeline
#38352
canceled with stage
Changes
10
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Changelog
View file @
9e8e3f63
KAlarm Change Log
=== Version 3.1.0 (KDE Applications 20.12) --- 2
4 Septem
ber 2020 ===
=== Version 3.1.0 (KDE Applications 20.12) --- 2
2 Octo
ber 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]
...
...
doc/index.docbook
View file @
9e8e3f63
...
...
@@ -39,7 +39,7 @@
<!-- Don't change format of date and version of the documentation -->
<date>
2020-0
9
-2
4
</date>
<date>
2020-
1
0-2
2
</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>
...
...
src/CMakeLists.txt
View file @
9e8e3f63
...
...
@@ -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
)
...
...
src/data/org.freedesktop.DBus.Properties.xml
0 → 100644
View file @
9e8e3f63
<?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>
src/data/org.freedesktop.Notifications.xml
0 → 100644
View file @
9e8e3f63
<!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<Inhibition>"/>
<arg name="inhibitors" type="a(ssa{sv})" direction="out"/>
</method>-->
</interface>
</node>
src/editdlg.cpp
View file @
9e8e3f63
...
...
@@ -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
);
}
}
...
...
src/kalarmapp.cpp
View file @
9e8e3f63
...
...
@@ -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
();
...
...
src/kalarmapp.h
View file @
9e8e3f63
...
...
@@ -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
();
}
...
...
src/resourcescalendar.cpp
View file @
9e8e3f63
...
...
@@ -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
))
{
...
...
src/resourcescalendar.h
View file @
9e8e3f63
...
...
@@ -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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel