2 * dbushandler.cpp - handler for D-Bus calls by other applications
4 * Copyright © 2002-2012 by David Jarvie <djarvie@kde.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "alarmcalendar.h"
24 #include "alarmtime.h"
25 #include "functions.h"
26 #include "kalarmapp.h"
28 #include "mainwindow.h"
29 #include "preferences.h"
30 #include "dbushandler.h"
31 #include <kalarmadaptor.h>
33 #include <kalarmcal/identities.h>
34 #include <kalarmcal/karecurrence.h>
36 #include <KCalCore/Duration>
37 using namespace KCalCore
;
39 #include <QtDBus/QtDBus>
40 #include "kalarm_debug.h"
46 const QString
REQUEST_DBUS_OBJECT(QStringLiteral("/kalarm")); // D-Bus object path of KAlarm's request interface
50 /*=============================================================================
52 = This class's function is to handle D-Bus requests by other applications.
53 =============================================================================*/
54 DBusHandler::DBusHandler()
57 new KalarmAdaptor(this);
58 QDBusConnection::sessionBus().registerObject(REQUEST_DBUS_OBJECT
, this);
62 bool DBusHandler::cancelEvent(const QString
& eventId
)
64 return theApp()->dbusDeleteEvent(EventId(eventId
));
67 bool DBusHandler::triggerEvent(const QString
& eventId
)
69 return theApp()->dbusTriggerEvent(EventId(eventId
));
72 QString
DBusHandler::list()
74 return theApp()->dbusList();
77 bool DBusHandler::scheduleMessage(const QString
& message
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
78 const QString
& bgColor
, const QString
& fgColor
, const QString
& font
,
79 const QString
& audioUrl
, int reminderMins
, const QString
& recurrence
,
80 int subRepeatInterval
, int subRepeatCount
)
84 Duration subRepeatDuration
;
85 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
87 return scheduleMessage(message
, start
, lateCancel
, flags
, bgColor
, fgColor
, font
,
88 QUrl::fromUserInput(audioUrl
, QString(), QUrl::AssumeLocalFile
),
89 reminderMins
, recur
, subRepeatDuration
, subRepeatCount
);
92 bool DBusHandler::scheduleMessage(const QString
& message
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
93 const QString
& bgColor
, const QString
& fgColor
, const QString
& font
,
94 const QString
& audioUrl
, int reminderMins
,
95 int recurType
, int recurInterval
, int recurCount
)
99 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
101 return scheduleMessage(message
, start
, lateCancel
, flags
, bgColor
, fgColor
, font
,
102 QUrl::fromUserInput(audioUrl
, QString(), QUrl::AssumeLocalFile
),
103 reminderMins
, recur
);
106 bool DBusHandler::scheduleMessage(const QString
& message
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
107 const QString
& bgColor
, const QString
& fgColor
, const QString
& font
,
108 const QString
& audioUrl
, int reminderMins
,
109 int recurType
, int recurInterval
, const QString
& endDateTime
)
113 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
115 return scheduleMessage(message
, start
, lateCancel
, flags
, bgColor
, fgColor
, font
,
116 QUrl::fromUserInput(audioUrl
, QString(), QUrl::AssumeLocalFile
),
117 reminderMins
, recur
);
120 bool DBusHandler::scheduleFile(const QString
& url
, const QString
& startDateTime
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
121 const QString
& audioUrl
, int reminderMins
, const QString
& recurrence
,
122 int subRepeatInterval
, int subRepeatCount
)
126 Duration subRepeatDuration
;
127 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
129 return scheduleFile(QUrl::fromUserInput(url
, QString(), QUrl::AssumeLocalFile
),
130 start
, lateCancel
, flags
, bgColor
,
131 QUrl::fromUserInput(audioUrl
, QString(), QUrl::AssumeLocalFile
),
132 reminderMins
, recur
, subRepeatDuration
, subRepeatCount
);
135 bool DBusHandler::scheduleFile(const QString
& url
, const QString
& startDateTime
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
136 const QString
& audioUrl
, int reminderMins
, int recurType
, int recurInterval
, int recurCount
)
140 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
142 return scheduleFile(QUrl::fromUserInput(url
, QString(), QUrl::AssumeLocalFile
),
143 start
, lateCancel
, flags
, bgColor
,
144 QUrl::fromUserInput(audioUrl
, QString(), QUrl::AssumeLocalFile
),
145 reminderMins
, recur
);
148 bool DBusHandler::scheduleFile(const QString
& url
, const QString
& startDateTime
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
149 const QString
& audioUrl
, int reminderMins
, int recurType
, int recurInterval
, const QString
& endDateTime
)
153 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
155 return scheduleFile(QUrl::fromUserInput(url
, QString(), QUrl::AssumeLocalFile
),
156 start
, lateCancel
, flags
, bgColor
,
157 QUrl::fromUserInput(audioUrl
, QString(), QUrl::AssumeLocalFile
),
158 reminderMins
, recur
);
161 bool DBusHandler::scheduleCommand(const QString
& commandLine
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
162 const QString
& recurrence
, int subRepeatInterval
, int subRepeatCount
)
166 Duration subRepeatDuration
;
167 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
169 return scheduleCommand(commandLine
, start
, lateCancel
, flags
, recur
, subRepeatDuration
, subRepeatCount
);
172 bool DBusHandler::scheduleCommand(const QString
& commandLine
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
173 int recurType
, int recurInterval
, int recurCount
)
175 KDateTime start
= convertDateTime(startDateTime
);
176 if (!start
.isValid())
179 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
181 return scheduleCommand(commandLine
, start
, lateCancel
, flags
, recur
);
184 bool DBusHandler::scheduleCommand(const QString
& commandLine
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
185 int recurType
, int recurInterval
, const QString
& endDateTime
)
189 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
191 return scheduleCommand(commandLine
, start
, lateCancel
, flags
, recur
);
194 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
, const QString
& message
,
195 const QString
& attachments
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
196 const QString
& recurrence
, int subRepeatInterval
, int subRepeatCount
)
200 Duration subRepeatDuration
;
201 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
203 return scheduleEmail(fromID
, addresses
, subject
, message
, attachments
, start
, lateCancel
, flags
, recur
, subRepeatDuration
, subRepeatCount
);
206 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
, const QString
& message
,
207 const QString
& attachments
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
208 int recurType
, int recurInterval
, int recurCount
)
212 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
214 return scheduleEmail(fromID
, addresses
, subject
, message
, attachments
, start
, lateCancel
, flags
, recur
);
217 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
, const QString
& message
,
218 const QString
& attachments
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
219 int recurType
, int recurInterval
, const QString
& endDateTime
)
223 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
225 return scheduleEmail(fromID
, addresses
, subject
, message
, attachments
, start
, lateCancel
, flags
, recur
);
228 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
, const QString
& startDateTime
, int lateCancel
,
229 unsigned flags
, const QString
& recurrence
, int subRepeatInterval
, int subRepeatCount
)
233 Duration subRepeatDuration
;
234 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
236 return scheduleAudio(audioUrl
, volumePercent
, start
, lateCancel
, flags
, recur
, subRepeatDuration
, subRepeatCount
);
239 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
, const QString
& startDateTime
, int lateCancel
,
240 unsigned flags
, int recurType
, int recurInterval
, int recurCount
)
242 KDateTime start
= convertDateTime(startDateTime
);
243 if (!start
.isValid())
246 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
248 return scheduleAudio(audioUrl
, volumePercent
, start
, lateCancel
, flags
, recur
);
251 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
, const QString
& startDateTime
, int lateCancel
,
252 unsigned flags
, int recurType
, int recurInterval
, const QString
& endDateTime
)
256 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
258 return scheduleAudio(audioUrl
, volumePercent
, start
, lateCancel
, flags
, recur
);
261 bool DBusHandler::edit(const QString
& eventID
)
263 return KAlarm::editAlarmById(EventId(eventID
));
266 bool DBusHandler::editNew(int type
)
268 EditAlarmDlg::Type dlgtype
;
271 case DISPLAY
: dlgtype
= EditAlarmDlg::DISPLAY
; break;
272 case COMMAND
: dlgtype
= EditAlarmDlg::COMMAND
; break;
273 case EMAIL
: dlgtype
= EditAlarmDlg::EMAIL
; break;
274 case AUDIO
: dlgtype
= EditAlarmDlg::AUDIO
; break;
276 qCCritical(KALARM_LOG
) << "D-Bus call: invalid alarm type:" << type
;
279 KAlarm::editNewAlarm(dlgtype
);
283 bool DBusHandler::editNew(const QString
& templateName
)
285 return KAlarm::editNewAlarm(templateName
);
289 /******************************************************************************
290 * Schedule a message alarm, after converting the parameters from strings.
292 bool DBusHandler::scheduleMessage(const QString
& message
, const KDateTime
& start
, int lateCancel
, unsigned flags
,
293 const QString
& bgColor
, const QString
& fgColor
, const QString
& fontStr
,
294 const QUrl
& audioFile
, int reminderMins
, const KARecurrence
& recurrence
,
295 const Duration
& subRepeatDuration
, int subRepeatCount
)
297 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
298 KAEvent::SubAction action
= (kaEventFlags
& KAEvent::DISPLAY_COMMAND
) ? KAEvent::COMMAND
: KAEvent::MESSAGE
;
299 QColor bg
= convertBgColour(bgColor
);
303 if (fgColor
.isEmpty())
304 fg
= Preferences::defaultFgColour();
307 fg
.setNamedColor(fgColor
);
310 qCCritical(KALARM_LOG
) << "D-Bus call: invalid foreground color:" << fgColor
;
315 if (fontStr
.isEmpty())
316 kaEventFlags
|= KAEvent::DEFAULT_FONT
;
319 if (!font
.fromString(fontStr
)) // N.B. this doesn't do good validation
321 qCCritical(KALARM_LOG
) << "D-Bus call: invalid font:" << fontStr
;
325 return theApp()->scheduleEvent(action
, message
, start
, lateCancel
, kaEventFlags
, bg
, fg
, font
,
326 audioFile
.toString(), -1, reminderMins
, recurrence
, subRepeatDuration
, subRepeatCount
);
329 /******************************************************************************
330 * Schedule a file alarm, after converting the parameters from strings.
332 bool DBusHandler::scheduleFile(const QUrl
& file
,
333 const KDateTime
& start
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
334 const QUrl
& audioFile
, int reminderMins
, const KARecurrence
& recurrence
,
335 const Duration
& subRepeatDuration
, int subRepeatCount
)
337 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
338 QColor bg
= convertBgColour(bgColor
);
341 return theApp()->scheduleEvent(KAEvent::FILE, file
.toString(), start
, lateCancel
, kaEventFlags
, bg
, Qt::black
, QFont(),
342 audioFile
.toString(), -1, reminderMins
, recurrence
, subRepeatDuration
, subRepeatCount
);
345 /******************************************************************************
346 * Schedule a command alarm, after converting the parameters from strings.
348 bool DBusHandler::scheduleCommand(const QString
& commandLine
,
349 const KDateTime
& start
, int lateCancel
, unsigned flags
,
350 const KARecurrence
& recurrence
, const Duration
& subRepeatDuration
, int subRepeatCount
)
352 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
353 return theApp()->scheduleEvent(KAEvent::COMMAND
, commandLine
, start
, lateCancel
, kaEventFlags
, Qt::black
, Qt::black
, QFont(),
354 QString(), -1, 0, recurrence
, subRepeatDuration
, subRepeatCount
);
357 /******************************************************************************
358 * Schedule an email alarm, after validating the addresses and attachments.
360 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
,
361 const QString
& message
, const QString
& attachments
,
362 const KDateTime
& start
, int lateCancel
, unsigned flags
,
363 const KARecurrence
& recurrence
, const Duration
& subRepeatDuration
, int subRepeatCount
)
365 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
367 if (!fromID
.isEmpty())
369 senderId
= Identities::identityUoid(fromID
);
372 qCCritical(KALARM_LOG
) << "D-Bus call scheduleEmail(): unknown sender ID:" << fromID
;
376 KCalCore::Person::List addrs
;
377 QString bad
= KAMail::convertAddresses(addresses
, addrs
);
380 qCCritical(KALARM_LOG
) << "D-Bus call scheduleEmail(): invalid email addresses:" << bad
;
385 qCCritical(KALARM_LOG
) << "D-Bus call scheduleEmail(): no email address";
389 bad
= KAMail::convertAttachments(attachments
, atts
);
392 qCCritical(KALARM_LOG
) << "D-Bus call scheduleEmail(): invalid email attachment:" << bad
;
395 return theApp()->scheduleEvent(KAEvent::EMAIL
, message
, start
, lateCancel
, kaEventFlags
, Qt::black
, Qt::black
, QFont(),
396 QString(), -1, 0, recurrence
, subRepeatDuration
, subRepeatCount
, senderId
, addrs
, subject
, atts
);
399 /******************************************************************************
400 * Schedule a audio alarm, after converting the parameters from strings.
402 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
,
403 const KDateTime
& start
, int lateCancel
, unsigned flags
,
404 const KARecurrence
& recurrence
, const Duration
& subRepeatDuration
, int subRepeatCount
)
406 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
407 float volume
= (volumePercent
>= 0) ? volumePercent
/ 100.0f
: -1;
408 return theApp()->scheduleEvent(KAEvent::AUDIO
, QString(), start
, lateCancel
, kaEventFlags
, Qt::black
, Qt::black
, QFont(),
409 audioUrl
, volume
, 0, recurrence
, subRepeatDuration
, subRepeatCount
);
413 /******************************************************************************
414 * Convert the start date/time string to a KDateTime. The date/time string is in
415 * the format YYYY-MM-DD[THH:MM[:SS]][ TZ] or [T]HH:MM[:SS].
416 * The time zone specifier (TZ) is a system time zone name, e.g. "Europe/London".
417 * If no time zone is specified, it defaults to the local clock time (which is
418 * not the same as the local time zone).
420 KDateTime
DBusHandler::convertDateTime(const QString
& dateTime
, const KDateTime
& defaultDt
)
422 int i
= dateTime
.indexOf(QLatin1Char(' '));
423 QString dtString
= dateTime
.left(i
);
424 QString zone
= dateTime
.mid(i
);
427 bool haveTime
= true;
429 if (dtString
.length() > 10)
431 // Both a date and a time are specified
432 QDateTime dt
= QDateTime::fromString(dtString
, Qt::ISODate
);
433 error
= !dt
.isValid();
439 // Check whether a time is specified
441 if (dtString
[0] == QLatin1Char('T'))
442 t
= dtString
.mid(1); // it's a time: remove the leading 'T'
443 else if (!dtString
[2].isDigit())
444 t
= dtString
; // it's a time with no leading 'T'
449 date
= QDate::fromString(dtString
, Qt::ISODate
);
450 error
= !date
.isValid();
456 time
= QTime::fromString(t
, Qt::ISODate
);
457 error
= !time
.isValid();
462 result
= AlarmTime::applyTimeZone(zone
, date
, time
, haveTime
, defaultDt
);
463 if (error
|| !result
.isValid())
465 if (!defaultDt
.isValid())
466 qCCritical(KALARM_LOG
) << "D-Bus call: invalid start date/time: '" << dateTime
<< "'";
468 qCCritical(KALARM_LOG
) << "D-Bus call: invalid recurrence end date/time: '" << dateTime
<< "'";
473 /******************************************************************************
474 * Convert the flag bits to KAEvent flag bits.
476 KAEvent::Flags
DBusHandler::convertStartFlags(const KDateTime
& start
, unsigned flags
)
478 KAEvent::Flags kaEventFlags
= 0;
479 if (flags
& REPEAT_AT_LOGIN
) kaEventFlags
|= KAEvent::REPEAT_AT_LOGIN
;
480 if (flags
& BEEP
) kaEventFlags
|= KAEvent::BEEP
;
481 if (flags
& SPEAK
) kaEventFlags
|= KAEvent::SPEAK
;
482 if (flags
& CONFIRM_ACK
) kaEventFlags
|= KAEvent::CONFIRM_ACK
;
483 if (flags
& REPEAT_SOUND
) kaEventFlags
|= KAEvent::REPEAT_SOUND
;
484 if (flags
& AUTO_CLOSE
) kaEventFlags
|= KAEvent::AUTO_CLOSE
;
485 if (flags
& EMAIL_BCC
) kaEventFlags
|= KAEvent::EMAIL_BCC
;
486 if (flags
& DISPLAY_COMMAND
) kaEventFlags
|= KAEvent::DISPLAY_COMMAND
;
487 if (flags
& SCRIPT
) kaEventFlags
|= KAEvent::SCRIPT
;
488 if (flags
& EXEC_IN_XTERM
) kaEventFlags
|= KAEvent::EXEC_IN_XTERM
;
489 if (flags
& SHOW_IN_KORG
) kaEventFlags
|= KAEvent::COPY_KORGANIZER
;
490 if (flags
& EXCL_HOLIDAYS
) kaEventFlags
|= KAEvent::EXCL_HOLIDAYS
;
491 if (flags
& WORK_TIME_ONLY
) kaEventFlags
|= KAEvent::WORK_TIME_ONLY
;
492 if (flags
& DISABLED
) kaEventFlags
|= KAEvent::DISABLED
;
493 if (start
.isDateOnly()) kaEventFlags
|= KAEvent::ANY_TIME
;
497 /******************************************************************************
498 * Convert the background colour string to a QColor.
500 QColor
DBusHandler::convertBgColour(const QString
& bgColor
)
502 if (bgColor
.isEmpty())
503 return Preferences::defaultBgColour();
506 qCCritical(KALARM_LOG
) << "D-Bus call: invalid background color:" << bgColor
;
510 bool DBusHandler::convertRecurrence(KDateTime
& start
, KARecurrence
& recurrence
,
511 const QString
& startDateTime
, const QString
& icalRecurrence
,
512 int subRepeatInterval
, Duration
& subRepeatDuration
)
514 start
= convertDateTime(startDateTime
);
515 if (!start
.isValid())
517 if (!recurrence
.set(icalRecurrence
))
519 if (subRepeatInterval
&& recurrence
.type() == KARecurrence::NO_RECUR
)
521 subRepeatInterval
= 0;
522 qCWarning(KALARM_LOG
) << "D-Bus call: no recurrence specified, so sub-repetition ignored";
524 if (subRepeatInterval
&& !(subRepeatInterval
% (24*60)))
525 subRepeatDuration
= Duration(subRepeatInterval
/ (24*60), Duration::Days
);
527 subRepeatDuration
= Duration(subRepeatInterval
* 60, Duration::Seconds
);
531 bool DBusHandler::convertRecurrence(KDateTime
& start
, KARecurrence
& recurrence
, const QString
& startDateTime
,
532 int recurType
, int recurInterval
, int recurCount
)
534 start
= convertDateTime(startDateTime
);
535 if (!start
.isValid())
537 return convertRecurrence(recurrence
, start
, recurType
, recurInterval
, recurCount
, KDateTime());
540 bool DBusHandler::convertRecurrence(KDateTime
& start
, KARecurrence
& recurrence
, const QString
& startDateTime
,
541 int recurType
, int recurInterval
, const QString
& endDateTime
)
543 start
= convertDateTime(startDateTime
);
544 if (!start
.isValid())
546 KDateTime end
= convertDateTime(endDateTime
, start
);
547 if (end
.isDateOnly() && !start
.isDateOnly())
549 qCCritical(KALARM_LOG
) << "D-Bus call: alarm is date-only, but recurrence end is date/time";
552 if (!end
.isDateOnly() && start
.isDateOnly())
554 qCCritical(KALARM_LOG
) << "D-Bus call: alarm is timed, but recurrence end is date-only";
557 return convertRecurrence(recurrence
, start
, recurType
, recurInterval
, 0, end
);
560 bool DBusHandler::convertRecurrence(KARecurrence
& recurrence
, const KDateTime
& start
, int recurType
,
561 int recurInterval
, int recurCount
, const KDateTime
& end
)
563 KARecurrence::Type type
;
566 case MINUTELY
: type
= KARecurrence::MINUTELY
; break;
567 case DAILY
: type
= KARecurrence::DAILY
; break;
568 case WEEKLY
: type
= KARecurrence::WEEKLY
; break;
569 case MONTHLY
: type
= KARecurrence::MONTHLY_DAY
; break;
570 case YEARLY
: type
= KARecurrence::ANNUAL_DATE
; break;
572 qCCritical(KALARM_LOG
) << "D-Bus call: invalid recurrence type:" << recurType
;
575 recurrence
.set(type
, recurInterval
, recurCount
, start
, end
);