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"
44 static const char* REQUEST_DBUS_OBJECT
= "/kalarm"; // D-Bus object path of KAlarm's request interface
47 /*=============================================================================
49 = This class's function is to handle D-Bus requests by other applications.
50 =============================================================================*/
51 DBusHandler::DBusHandler()
54 new KalarmAdaptor(this);
55 QDBusConnection::sessionBus().registerObject(QLatin1String(REQUEST_DBUS_OBJECT
), this);
59 bool DBusHandler::cancelEvent(const QString
& eventId
)
61 return theApp()->dbusDeleteEvent(EventId(eventId
));
64 bool DBusHandler::triggerEvent(const QString
& eventId
)
66 return theApp()->dbusTriggerEvent(EventId(eventId
));
69 QString
DBusHandler::list()
71 return theApp()->dbusList();
74 bool DBusHandler::scheduleMessage(const QString
& message
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
75 const QString
& bgColor
, const QString
& fgColor
, const QString
& font
,
76 const QString
& audioUrl
, int reminderMins
, const QString
& recurrence
,
77 int subRepeatInterval
, int subRepeatCount
)
81 Duration subRepeatDuration
;
82 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
84 return scheduleMessage(message
, start
, lateCancel
, flags
, bgColor
, fgColor
, font
, KUrl(audioUrl
), reminderMins
, recur
, subRepeatDuration
, subRepeatCount
);
87 bool DBusHandler::scheduleMessage(const QString
& message
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
88 const QString
& bgColor
, const QString
& fgColor
, const QString
& font
,
89 const QString
& audioUrl
, int reminderMins
,
90 int recurType
, int recurInterval
, int recurCount
)
94 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
96 return scheduleMessage(message
, start
, lateCancel
, flags
, bgColor
, fgColor
, font
, KUrl(audioUrl
), reminderMins
, recur
);
99 bool DBusHandler::scheduleMessage(const QString
& message
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
100 const QString
& bgColor
, const QString
& fgColor
, const QString
& font
,
101 const QString
& audioUrl
, int reminderMins
,
102 int recurType
, int recurInterval
, const QString
& endDateTime
)
106 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
108 return scheduleMessage(message
, start
, lateCancel
, flags
, bgColor
, fgColor
, font
, KUrl(audioUrl
), reminderMins
, recur
);
111 bool DBusHandler::scheduleFile(const QString
& url
, const QString
& startDateTime
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
112 const QString
& audioUrl
, int reminderMins
, const QString
& recurrence
,
113 int subRepeatInterval
, int subRepeatCount
)
117 Duration subRepeatDuration
;
118 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
120 return scheduleFile(KUrl(url
), start
, lateCancel
, flags
, bgColor
, KUrl(audioUrl
), reminderMins
, recur
, subRepeatDuration
, subRepeatCount
);
123 bool DBusHandler::scheduleFile(const QString
& url
, const QString
& startDateTime
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
124 const QString
& audioUrl
, int reminderMins
, int recurType
, int recurInterval
, int recurCount
)
128 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
130 return scheduleFile(KUrl(url
), start
, lateCancel
, flags
, bgColor
, KUrl(audioUrl
), reminderMins
, recur
);
133 bool DBusHandler::scheduleFile(const QString
& url
, const QString
& startDateTime
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
134 const QString
& audioUrl
, int reminderMins
, int recurType
, int recurInterval
, const QString
& endDateTime
)
138 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
140 return scheduleFile(KUrl(url
), start
, lateCancel
, flags
, bgColor
, KUrl(audioUrl
), reminderMins
, recur
);
143 bool DBusHandler::scheduleCommand(const QString
& commandLine
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
144 const QString
& recurrence
, int subRepeatInterval
, int subRepeatCount
)
148 Duration subRepeatDuration
;
149 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
151 return scheduleCommand(commandLine
, start
, lateCancel
, flags
, recur
, subRepeatDuration
, subRepeatCount
);
154 bool DBusHandler::scheduleCommand(const QString
& commandLine
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
155 int recurType
, int recurInterval
, int recurCount
)
157 KDateTime start
= convertDateTime(startDateTime
);
158 if (!start
.isValid())
161 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
163 return scheduleCommand(commandLine
, start
, lateCancel
, flags
, recur
);
166 bool DBusHandler::scheduleCommand(const QString
& commandLine
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
167 int recurType
, int recurInterval
, const QString
& endDateTime
)
171 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
173 return scheduleCommand(commandLine
, start
, lateCancel
, flags
, recur
);
176 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
, const QString
& message
,
177 const QString
& attachments
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
178 const QString
& recurrence
, int subRepeatInterval
, int subRepeatCount
)
182 Duration subRepeatDuration
;
183 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
185 return scheduleEmail(fromID
, addresses
, subject
, message
, attachments
, start
, lateCancel
, flags
, recur
, subRepeatDuration
, subRepeatCount
);
188 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
, const QString
& message
,
189 const QString
& attachments
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
190 int recurType
, int recurInterval
, int recurCount
)
194 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
196 return scheduleEmail(fromID
, addresses
, subject
, message
, attachments
, start
, lateCancel
, flags
, recur
);
199 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
, const QString
& message
,
200 const QString
& attachments
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
201 int recurType
, int recurInterval
, const QString
& endDateTime
)
205 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
207 return scheduleEmail(fromID
, addresses
, subject
, message
, attachments
, start
, lateCancel
, flags
, recur
);
210 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
, const QString
& startDateTime
, int lateCancel
,
211 unsigned flags
, const QString
& recurrence
, int subRepeatInterval
, int subRepeatCount
)
215 Duration subRepeatDuration
;
216 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
218 return scheduleAudio(audioUrl
, volumePercent
, start
, lateCancel
, flags
, recur
, subRepeatDuration
, subRepeatCount
);
221 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
, const QString
& startDateTime
, int lateCancel
,
222 unsigned flags
, int recurType
, int recurInterval
, int recurCount
)
224 KDateTime start
= convertDateTime(startDateTime
);
225 if (!start
.isValid())
228 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
230 return scheduleAudio(audioUrl
, volumePercent
, start
, lateCancel
, flags
, recur
);
233 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
, const QString
& startDateTime
, int lateCancel
,
234 unsigned flags
, int recurType
, int recurInterval
, const QString
& endDateTime
)
238 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
240 return scheduleAudio(audioUrl
, volumePercent
, start
, lateCancel
, flags
, recur
);
243 bool DBusHandler::edit(const QString
& eventID
)
245 return KAlarm::editAlarmById(EventId(eventID
));
248 bool DBusHandler::editNew(int type
)
250 EditAlarmDlg::Type dlgtype
;
253 case DISPLAY
: dlgtype
= EditAlarmDlg::DISPLAY
; break;
254 case COMMAND
: dlgtype
= EditAlarmDlg::COMMAND
; break;
255 case EMAIL
: dlgtype
= EditAlarmDlg::EMAIL
; break;
256 case AUDIO
: dlgtype
= EditAlarmDlg::AUDIO
; break;
258 qCritical() << "D-Bus call: invalid alarm type:" << type
;
261 KAlarm::editNewAlarm(dlgtype
);
265 bool DBusHandler::editNew(const QString
& templateName
)
267 return KAlarm::editNewAlarm(templateName
);
271 /******************************************************************************
272 * Schedule a message alarm, after converting the parameters from strings.
274 bool DBusHandler::scheduleMessage(const QString
& message
, const KDateTime
& start
, int lateCancel
, unsigned flags
,
275 const QString
& bgColor
, const QString
& fgColor
, const QString
& fontStr
,
276 const KUrl
& audioFile
, int reminderMins
, const KARecurrence
& recurrence
,
277 const Duration
& subRepeatDuration
, int subRepeatCount
)
279 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
280 KAEvent::SubAction action
= (kaEventFlags
& KAEvent::DISPLAY_COMMAND
) ? KAEvent::COMMAND
: KAEvent::MESSAGE
;
281 QColor bg
= convertBgColour(bgColor
);
285 if (fgColor
.isEmpty())
286 fg
= Preferences::defaultFgColour();
289 fg
.setNamedColor(fgColor
);
292 qCritical() << "D-Bus call: invalid foreground color:" << fgColor
;
297 if (fontStr
.isEmpty())
298 kaEventFlags
|= KAEvent::DEFAULT_FONT
;
301 if (!font
.fromString(fontStr
)) // N.B. this doesn't do good validation
303 qCritical() << "D-Bus call: invalid font:" << fontStr
;
307 return theApp()->scheduleEvent(action
, message
, start
, lateCancel
, kaEventFlags
, bg
, fg
, font
,
308 audioFile
.url(), -1, reminderMins
, recurrence
, subRepeatDuration
, subRepeatCount
);
311 /******************************************************************************
312 * Schedule a file alarm, after converting the parameters from strings.
314 bool DBusHandler::scheduleFile(const KUrl
& file
,
315 const KDateTime
& start
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
316 const KUrl
& audioFile
, int reminderMins
, const KARecurrence
& recurrence
,
317 const Duration
& subRepeatDuration
, int subRepeatCount
)
319 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
320 QColor bg
= convertBgColour(bgColor
);
323 return theApp()->scheduleEvent(KAEvent::FILE, file
.url(), start
, lateCancel
, kaEventFlags
, bg
, Qt::black
, QFont(),
324 audioFile
.url(), -1, reminderMins
, recurrence
, subRepeatDuration
, subRepeatCount
);
327 /******************************************************************************
328 * Schedule a command alarm, after converting the parameters from strings.
330 bool DBusHandler::scheduleCommand(const QString
& commandLine
,
331 const KDateTime
& start
, int lateCancel
, unsigned flags
,
332 const KARecurrence
& recurrence
, const Duration
& subRepeatDuration
, int subRepeatCount
)
334 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
335 return theApp()->scheduleEvent(KAEvent::COMMAND
, commandLine
, start
, lateCancel
, kaEventFlags
, Qt::black
, Qt::black
, QFont(),
336 QString(), -1, 0, recurrence
, subRepeatDuration
, subRepeatCount
);
339 /******************************************************************************
340 * Schedule an email alarm, after validating the addresses and attachments.
342 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
,
343 const QString
& message
, const QString
& attachments
,
344 const KDateTime
& start
, int lateCancel
, unsigned flags
,
345 const KARecurrence
& recurrence
, const Duration
& subRepeatDuration
, int subRepeatCount
)
347 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
349 if (!fromID
.isEmpty())
351 senderId
= Identities::identityUoid(fromID
);
354 qCritical() << "D-Bus call scheduleEmail(): unknown sender ID:" << fromID
;
358 KCalCore::Person::List addrs
;
359 QString bad
= KAMail::convertAddresses(addresses
, addrs
);
362 qCritical() << "D-Bus call scheduleEmail(): invalid email addresses:" << bad
;
367 qCritical() << "D-Bus call scheduleEmail(): no email address";
371 bad
= KAMail::convertAttachments(attachments
, atts
);
374 qCritical() << "D-Bus call scheduleEmail(): invalid email attachment:" << bad
;
377 return theApp()->scheduleEvent(KAEvent::EMAIL
, message
, start
, lateCancel
, kaEventFlags
, Qt::black
, Qt::black
, QFont(),
378 QString(), -1, 0, recurrence
, subRepeatDuration
, subRepeatCount
, senderId
, addrs
, subject
, atts
);
381 /******************************************************************************
382 * Schedule a audio alarm, after converting the parameters from strings.
384 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
,
385 const KDateTime
& start
, int lateCancel
, unsigned flags
,
386 const KARecurrence
& recurrence
, const Duration
& subRepeatDuration
, int subRepeatCount
)
388 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
389 float volume
= (volumePercent
>= 0) ? volumePercent
/ 100.0f
: -1;
390 return theApp()->scheduleEvent(KAEvent::AUDIO
, QString(), start
, lateCancel
, kaEventFlags
, Qt::black
, Qt::black
, QFont(),
391 audioUrl
, volume
, 0, recurrence
, subRepeatDuration
, subRepeatCount
);
395 /******************************************************************************
396 * Convert the start date/time string to a KDateTime. The date/time string is in
397 * the format YYYY-MM-DD[THH:MM[:SS]][ TZ] or [T]HH:MM[:SS].
398 * The time zone specifier (TZ) is a system time zone name, e.g. "Europe/London".
399 * If no time zone is specified, it defaults to the local clock time (which is
400 * not the same as the local time zone).
402 KDateTime
DBusHandler::convertDateTime(const QString
& dateTime
, const KDateTime
& defaultDt
)
404 int i
= dateTime
.indexOf(QLatin1Char(' '));
405 QString dtString
= dateTime
.left(i
);
406 QString zone
= dateTime
.mid(i
);
409 bool haveTime
= true;
411 if (dtString
.length() > 10)
413 // Both a date and a time are specified
414 QDateTime dt
= QDateTime::fromString(dtString
, Qt::ISODate
);
415 error
= !dt
.isValid();
421 // Check whether a time is specified
423 if (dtString
[0] == QLatin1Char('T'))
424 t
= dtString
.mid(1); // it's a time: remove the leading 'T'
425 else if (!dtString
[2].isDigit())
426 t
= dtString
; // it's a time with no leading 'T'
431 date
= QDate::fromString(dtString
, Qt::ISODate
);
432 error
= !date
.isValid();
438 time
= QTime::fromString(t
, Qt::ISODate
);
439 error
= !time
.isValid();
444 result
= AlarmTime::applyTimeZone(zone
, date
, time
, haveTime
, defaultDt
);
445 if (error
|| !result
.isValid())
447 if (!defaultDt
.isValid())
448 qCritical() << "D-Bus call: invalid start date/time: '" << dateTime
<< "'";
450 qCritical() << "D-Bus call: invalid recurrence end date/time: '" << dateTime
<< "'";
455 /******************************************************************************
456 * Convert the flag bits to KAEvent flag bits.
458 KAEvent::Flags
DBusHandler::convertStartFlags(const KDateTime
& start
, unsigned flags
)
460 KAEvent::Flags kaEventFlags
= 0;
461 if (flags
& REPEAT_AT_LOGIN
) kaEventFlags
|= KAEvent::REPEAT_AT_LOGIN
;
462 if (flags
& BEEP
) kaEventFlags
|= KAEvent::BEEP
;
463 if (flags
& SPEAK
) kaEventFlags
|= KAEvent::SPEAK
;
464 if (flags
& CONFIRM_ACK
) kaEventFlags
|= KAEvent::CONFIRM_ACK
;
465 if (flags
& REPEAT_SOUND
) kaEventFlags
|= KAEvent::REPEAT_SOUND
;
466 if (flags
& AUTO_CLOSE
) kaEventFlags
|= KAEvent::AUTO_CLOSE
;
467 if (flags
& EMAIL_BCC
) kaEventFlags
|= KAEvent::EMAIL_BCC
;
468 if (flags
& DISPLAY_COMMAND
) kaEventFlags
|= KAEvent::DISPLAY_COMMAND
;
469 if (flags
& SCRIPT
) kaEventFlags
|= KAEvent::SCRIPT
;
470 if (flags
& EXEC_IN_XTERM
) kaEventFlags
|= KAEvent::EXEC_IN_XTERM
;
471 if (flags
& SHOW_IN_KORG
) kaEventFlags
|= KAEvent::COPY_KORGANIZER
;
472 if (flags
& EXCL_HOLIDAYS
) kaEventFlags
|= KAEvent::EXCL_HOLIDAYS
;
473 if (flags
& WORK_TIME_ONLY
) kaEventFlags
|= KAEvent::WORK_TIME_ONLY
;
474 if (flags
& DISABLED
) kaEventFlags
|= KAEvent::DISABLED
;
475 if (start
.isDateOnly()) kaEventFlags
|= KAEvent::ANY_TIME
;
479 /******************************************************************************
480 * Convert the background colour string to a QColor.
482 QColor
DBusHandler::convertBgColour(const QString
& bgColor
)
484 if (bgColor
.isEmpty())
485 return Preferences::defaultBgColour();
488 qCritical() << "D-Bus call: invalid background color:" << bgColor
;
492 bool DBusHandler::convertRecurrence(KDateTime
& start
, KARecurrence
& recurrence
,
493 const QString
& startDateTime
, const QString
& icalRecurrence
,
494 int subRepeatInterval
, Duration
& subRepeatDuration
)
496 start
= convertDateTime(startDateTime
);
497 if (!start
.isValid())
499 if (!recurrence
.set(icalRecurrence
))
501 if (subRepeatInterval
&& recurrence
.type() == KARecurrence::NO_RECUR
)
503 subRepeatInterval
= 0;
504 qCWarning(KALARM_LOG
) << "D-Bus call: no recurrence specified, so sub-repetition ignored";
506 if (subRepeatInterval
&& !(subRepeatInterval
% (24*60)))
507 subRepeatDuration
= Duration(subRepeatInterval
/ (24*60), Duration::Days
);
509 subRepeatDuration
= Duration(subRepeatInterval
* 60, Duration::Seconds
);
513 bool DBusHandler::convertRecurrence(KDateTime
& start
, KARecurrence
& recurrence
, const QString
& startDateTime
,
514 int recurType
, int recurInterval
, int recurCount
)
516 start
= convertDateTime(startDateTime
);
517 if (!start
.isValid())
519 return convertRecurrence(recurrence
, start
, recurType
, recurInterval
, recurCount
, KDateTime());
522 bool DBusHandler::convertRecurrence(KDateTime
& start
, KARecurrence
& recurrence
, const QString
& startDateTime
,
523 int recurType
, int recurInterval
, const QString
& endDateTime
)
525 start
= convertDateTime(startDateTime
);
526 if (!start
.isValid())
528 KDateTime end
= convertDateTime(endDateTime
, start
);
529 if (end
.isDateOnly() && !start
.isDateOnly())
531 qCritical() << "D-Bus call: alarm is date-only, but recurrence end is date/time";
534 if (!end
.isDateOnly() && start
.isDateOnly())
536 qCritical() << "D-Bus call: alarm is timed, but recurrence end is date-only";
539 return convertRecurrence(recurrence
, start
, recurType
, recurInterval
, 0, end
);
542 bool DBusHandler::convertRecurrence(KARecurrence
& recurrence
, const KDateTime
& start
, int recurType
,
543 int recurInterval
, int recurCount
, const KDateTime
& end
)
545 KARecurrence::Type type
;
548 case MINUTELY
: type
= KARecurrence::MINUTELY
; break;
549 case DAILY
: type
= KARecurrence::DAILY
; break;
550 case WEEKLY
: type
= KARecurrence::WEEKLY
; break;
551 case MONTHLY
: type
= KARecurrence::MONTHLY_DAY
; break;
552 case YEARLY
: type
= KARecurrence::ANNUAL_DATE
; break;
554 qCritical() << "D-Bus call: invalid recurrence type:" << recurType
;
557 recurrence
.set(type
, recurInterval
, recurCount
, start
, end
);