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.moc"
31 #include <kalarmadaptor.h>
33 #include <kalarmcal/identities.h>
34 #include <kalarmcal/karecurrence.h>
37 #include <kcalcore/duration.h>
38 using namespace KCalCore
;
40 #include <kcal/duration.h>
46 #include <QtDBus/QtDBus>
50 static const char* REQUEST_DBUS_OBJECT
= "/kalarm"; // D-Bus object path of KAlarm's request interface
53 /*=============================================================================
55 = This class's function is to handle D-Bus requests by other applications.
56 =============================================================================*/
57 DBusHandler::DBusHandler()
60 new KalarmAdaptor(this);
61 QDBusConnection::sessionBus().registerObject(REQUEST_DBUS_OBJECT
, this);
65 bool DBusHandler::cancelEvent(const QString
& eventId
)
68 return theApp()->dbusDeleteEvent(EventId(eventId
));
70 return theApp()->dbusDeleteEvent(eventId
);
74 bool DBusHandler::triggerEvent(const QString
& eventId
)
77 return theApp()->dbusTriggerEvent(EventId(eventId
));
79 return theApp()->dbusTriggerEvent(eventId
);
83 QString
DBusHandler::list()
85 return theApp()->dbusList();
88 bool DBusHandler::scheduleMessage(const QString
& message
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
89 const QString
& bgColor
, const QString
& fgColor
, const QString
& font
,
90 const QString
& audioUrl
, int reminderMins
, const QString
& recurrence
,
91 int subRepeatInterval
, int subRepeatCount
)
95 Duration subRepeatDuration
;
96 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
98 return scheduleMessage(message
, start
, lateCancel
, flags
, bgColor
, fgColor
, font
, KUrl(audioUrl
), reminderMins
, recur
, subRepeatDuration
, subRepeatCount
);
101 bool DBusHandler::scheduleMessage(const QString
& message
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
102 const QString
& bgColor
, const QString
& fgColor
, const QString
& font
,
103 const QString
& audioUrl
, int reminderMins
,
104 int recurType
, int recurInterval
, int recurCount
)
108 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
110 return scheduleMessage(message
, start
, lateCancel
, flags
, bgColor
, fgColor
, font
, KUrl(audioUrl
), reminderMins
, recur
);
113 bool DBusHandler::scheduleMessage(const QString
& message
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
114 const QString
& bgColor
, const QString
& fgColor
, const QString
& font
,
115 const QString
& audioUrl
, int reminderMins
,
116 int recurType
, int recurInterval
, const QString
& endDateTime
)
120 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
122 return scheduleMessage(message
, start
, lateCancel
, flags
, bgColor
, fgColor
, font
, KUrl(audioUrl
), reminderMins
, recur
);
125 bool DBusHandler::scheduleFile(const QString
& url
, const QString
& startDateTime
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
126 const QString
& audioUrl
, int reminderMins
, const QString
& recurrence
,
127 int subRepeatInterval
, int subRepeatCount
)
131 Duration subRepeatDuration
;
132 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
134 return scheduleFile(KUrl(url
), start
, lateCancel
, flags
, bgColor
, KUrl(audioUrl
), reminderMins
, recur
, subRepeatDuration
, subRepeatCount
);
137 bool DBusHandler::scheduleFile(const QString
& url
, const QString
& startDateTime
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
138 const QString
& audioUrl
, int reminderMins
, int recurType
, int recurInterval
, int recurCount
)
142 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
144 return scheduleFile(KUrl(url
), start
, lateCancel
, flags
, bgColor
, KUrl(audioUrl
), reminderMins
, recur
);
147 bool DBusHandler::scheduleFile(const QString
& url
, const QString
& startDateTime
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
148 const QString
& audioUrl
, int reminderMins
, int recurType
, int recurInterval
, const QString
& endDateTime
)
152 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
154 return scheduleFile(KUrl(url
), start
, lateCancel
, flags
, bgColor
, KUrl(audioUrl
), reminderMins
, recur
);
157 bool DBusHandler::scheduleCommand(const QString
& commandLine
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
158 const QString
& recurrence
, int subRepeatInterval
, int subRepeatCount
)
162 Duration subRepeatDuration
;
163 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
165 return scheduleCommand(commandLine
, start
, lateCancel
, flags
, recur
, subRepeatDuration
, subRepeatCount
);
168 bool DBusHandler::scheduleCommand(const QString
& commandLine
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
169 int recurType
, int recurInterval
, int recurCount
)
171 KDateTime start
= convertDateTime(startDateTime
);
172 if (!start
.isValid())
175 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
177 return scheduleCommand(commandLine
, start
, lateCancel
, flags
, recur
);
180 bool DBusHandler::scheduleCommand(const QString
& commandLine
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
181 int recurType
, int recurInterval
, const QString
& endDateTime
)
185 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
187 return scheduleCommand(commandLine
, start
, lateCancel
, flags
, recur
);
190 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
, const QString
& message
,
191 const QString
& attachments
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
192 const QString
& recurrence
, int subRepeatInterval
, int subRepeatCount
)
196 Duration subRepeatDuration
;
197 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
199 return scheduleEmail(fromID
, addresses
, subject
, message
, attachments
, start
, lateCancel
, flags
, recur
, subRepeatDuration
, subRepeatCount
);
202 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
, const QString
& message
,
203 const QString
& attachments
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
204 int recurType
, int recurInterval
, int recurCount
)
208 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
210 return scheduleEmail(fromID
, addresses
, subject
, message
, attachments
, start
, lateCancel
, flags
, recur
);
213 bool DBusHandler::scheduleEmail(const QString
& fromID
, const QString
& addresses
, const QString
& subject
, const QString
& message
,
214 const QString
& attachments
, const QString
& startDateTime
, int lateCancel
, unsigned flags
,
215 int recurType
, int recurInterval
, const QString
& endDateTime
)
219 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
221 return scheduleEmail(fromID
, addresses
, subject
, message
, attachments
, start
, lateCancel
, flags
, recur
);
224 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
, const QString
& startDateTime
, int lateCancel
,
225 unsigned flags
, const QString
& recurrence
, int subRepeatInterval
, int subRepeatCount
)
229 Duration subRepeatDuration
;
230 if (!convertRecurrence(start
, recur
, startDateTime
, recurrence
, subRepeatInterval
, subRepeatDuration
))
232 return scheduleAudio(audioUrl
, volumePercent
, start
, lateCancel
, flags
, recur
, subRepeatDuration
, subRepeatCount
);
235 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
, const QString
& startDateTime
, int lateCancel
,
236 unsigned flags
, int recurType
, int recurInterval
, int recurCount
)
238 KDateTime start
= convertDateTime(startDateTime
);
239 if (!start
.isValid())
242 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, recurCount
))
244 return scheduleAudio(audioUrl
, volumePercent
, start
, lateCancel
, flags
, recur
);
247 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
, const QString
& startDateTime
, int lateCancel
,
248 unsigned flags
, int recurType
, int recurInterval
, const QString
& endDateTime
)
252 if (!convertRecurrence(start
, recur
, startDateTime
, recurType
, recurInterval
, endDateTime
))
254 return scheduleAudio(audioUrl
, volumePercent
, start
, lateCancel
, flags
, recur
);
257 bool DBusHandler::edit(const QString
& eventID
)
260 return KAlarm::editAlarmById(EventId(eventID
));
262 return KAlarm::editAlarmById(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 kError() << "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 KUrl
& 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 kError() << "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 kError() << "D-Bus call: invalid font:" << fontStr
;
325 return theApp()->scheduleEvent(action
, message
, start
, lateCancel
, kaEventFlags
, bg
, fg
, font
,
326 audioFile
.url(), -1, reminderMins
, recurrence
, subRepeatDuration
, subRepeatCount
);
329 /******************************************************************************
330 * Schedule a file alarm, after converting the parameters from strings.
332 bool DBusHandler::scheduleFile(const KUrl
& file
,
333 const KDateTime
& start
, int lateCancel
, unsigned flags
, const QString
& bgColor
,
334 const KUrl
& 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
.url(), start
, lateCancel
, kaEventFlags
, bg
, Qt::black
, QFont(),
342 audioFile
.url(), -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 kError() << "D-Bus call scheduleEmail(): unknown sender ID:" << fromID
;
377 KCalCore::Person::List addrs
;
379 QList
<KCal::Person
> addrs
;
381 QString bad
= KAMail::convertAddresses(addresses
, addrs
);
384 kError() << "D-Bus call scheduleEmail(): invalid email addresses:" << bad
;
389 kError() << "D-Bus call scheduleEmail(): no email address";
393 bad
= KAMail::convertAttachments(attachments
, atts
);
396 kError() << "D-Bus call scheduleEmail(): invalid email attachment:" << bad
;
399 return theApp()->scheduleEvent(KAEvent::EMAIL
, message
, start
, lateCancel
, kaEventFlags
, Qt::black
, Qt::black
, QFont(),
400 QString(), -1, 0, recurrence
, subRepeatDuration
, subRepeatCount
, senderId
, addrs
, subject
, atts
);
403 /******************************************************************************
404 * Schedule a audio alarm, after converting the parameters from strings.
406 bool DBusHandler::scheduleAudio(const QString
& audioUrl
, int volumePercent
,
407 const KDateTime
& start
, int lateCancel
, unsigned flags
,
408 const KARecurrence
& recurrence
, const Duration
& subRepeatDuration
, int subRepeatCount
)
410 KAEvent::Flags kaEventFlags
= convertStartFlags(start
, flags
);
411 float volume
= (volumePercent
>= 0) ? volumePercent
/ 100.0f
: -1;
412 return theApp()->scheduleEvent(KAEvent::AUDIO
, QString(), start
, lateCancel
, kaEventFlags
, Qt::black
, Qt::black
, QFont(),
413 audioUrl
, volume
, 0, recurrence
, subRepeatDuration
, subRepeatCount
);
417 /******************************************************************************
418 * Convert the start date/time string to a KDateTime. The date/time string is in
419 * the format YYYY-MM-DD[THH:MM[:SS]][ TZ] or [T]HH:MM[:SS].
420 * The time zone specifier (TZ) is a system time zone name, e.g. "Europe/London".
421 * If no time zone is specified, it defaults to the local clock time (which is
422 * not the same as the local time zone).
424 KDateTime
DBusHandler::convertDateTime(const QString
& dateTime
, const KDateTime
& defaultDt
)
426 int i
= dateTime
.indexOf(QChar(' '));
427 QString dtString
= dateTime
.left(i
);
428 QString zone
= dateTime
.mid(i
);
431 bool haveTime
= true;
433 if (dtString
.length() > 10)
435 // Both a date and a time are specified
436 QDateTime dt
= QDateTime::fromString(dtString
, Qt::ISODate
);
437 error
= !dt
.isValid();
443 // Check whether a time is specified
445 if (dtString
[0] == QChar('T'))
446 t
= dtString
.mid(1); // it's a time: remove the leading 'T'
447 else if (!dtString
[2].isDigit())
448 t
= dtString
; // it's a time with no leading 'T'
453 date
= QDate::fromString(dtString
, Qt::ISODate
);
454 error
= !date
.isValid();
460 time
= QTime::fromString(t
, Qt::ISODate
);
461 error
= !time
.isValid();
466 result
= AlarmTime::applyTimeZone(zone
, date
, time
, haveTime
, defaultDt
);
467 if (error
|| !result
.isValid())
469 if (!defaultDt
.isValid())
470 kError() << "D-Bus call: invalid start date/time: '" << dateTime
<< "'";
472 kError() << "D-Bus call: invalid recurrence end date/time: '" << dateTime
<< "'";
477 /******************************************************************************
478 * Convert the flag bits to KAEvent flag bits.
480 KAEvent::Flags
DBusHandler::convertStartFlags(const KDateTime
& start
, unsigned flags
)
482 KAEvent::Flags kaEventFlags
= 0;
483 if (flags
& REPEAT_AT_LOGIN
) kaEventFlags
|= KAEvent::REPEAT_AT_LOGIN
;
484 if (flags
& BEEP
) kaEventFlags
|= KAEvent::BEEP
;
485 if (flags
& SPEAK
) kaEventFlags
|= KAEvent::SPEAK
;
486 if (flags
& CONFIRM_ACK
) kaEventFlags
|= KAEvent::CONFIRM_ACK
;
487 if (flags
& REPEAT_SOUND
) kaEventFlags
|= KAEvent::REPEAT_SOUND
;
488 if (flags
& AUTO_CLOSE
) kaEventFlags
|= KAEvent::AUTO_CLOSE
;
489 if (flags
& EMAIL_BCC
) kaEventFlags
|= KAEvent::EMAIL_BCC
;
490 if (flags
& DISPLAY_COMMAND
) kaEventFlags
|= KAEvent::DISPLAY_COMMAND
;
491 if (flags
& SCRIPT
) kaEventFlags
|= KAEvent::SCRIPT
;
492 if (flags
& EXEC_IN_XTERM
) kaEventFlags
|= KAEvent::EXEC_IN_XTERM
;
493 if (flags
& SHOW_IN_KORG
) kaEventFlags
|= KAEvent::COPY_KORGANIZER
;
494 if (flags
& EXCL_HOLIDAYS
) kaEventFlags
|= KAEvent::EXCL_HOLIDAYS
;
495 if (flags
& WORK_TIME_ONLY
) kaEventFlags
|= KAEvent::WORK_TIME_ONLY
;
496 if (flags
& DISABLED
) kaEventFlags
|= KAEvent::DISABLED
;
497 if (start
.isDateOnly()) kaEventFlags
|= KAEvent::ANY_TIME
;
501 /******************************************************************************
502 * Convert the background colour string to a QColor.
504 QColor
DBusHandler::convertBgColour(const QString
& bgColor
)
506 if (bgColor
.isEmpty())
507 return Preferences::defaultBgColour();
510 kError() << "D-Bus call: invalid background color:" << bgColor
;
514 bool DBusHandler::convertRecurrence(KDateTime
& start
, KARecurrence
& recurrence
,
515 const QString
& startDateTime
, const QString
& icalRecurrence
,
516 int subRepeatInterval
, Duration
& subRepeatDuration
)
518 start
= convertDateTime(startDateTime
);
519 if (!start
.isValid())
521 if (!recurrence
.set(icalRecurrence
))
523 if (subRepeatInterval
&& recurrence
.type() == KARecurrence::NO_RECUR
)
525 subRepeatInterval
= 0;
526 kWarning() << "D-Bus call: no recurrence specified, so sub-repetition ignored";
528 if (subRepeatInterval
&& !(subRepeatInterval
% (24*60)))
529 subRepeatDuration
= Duration(subRepeatInterval
/ (24*60), Duration::Days
);
531 subRepeatDuration
= Duration(subRepeatInterval
* 60, Duration::Seconds
);
535 bool DBusHandler::convertRecurrence(KDateTime
& start
, KARecurrence
& recurrence
, const QString
& startDateTime
,
536 int recurType
, int recurInterval
, int recurCount
)
538 start
= convertDateTime(startDateTime
);
539 if (!start
.isValid())
541 return convertRecurrence(recurrence
, start
, recurType
, recurInterval
, recurCount
, KDateTime());
544 bool DBusHandler::convertRecurrence(KDateTime
& start
, KARecurrence
& recurrence
, const QString
& startDateTime
,
545 int recurType
, int recurInterval
, const QString
& endDateTime
)
547 start
= convertDateTime(startDateTime
);
548 if (!start
.isValid())
550 KDateTime end
= convertDateTime(endDateTime
, start
);
551 if (end
.isDateOnly() && !start
.isDateOnly())
553 kError() << "D-Bus call: alarm is date-only, but recurrence end is date/time";
556 if (!end
.isDateOnly() && start
.isDateOnly())
558 kError() << "D-Bus call: alarm is timed, but recurrence end is date-only";
561 return convertRecurrence(recurrence
, start
, recurType
, recurInterval
, 0, end
);
564 bool DBusHandler::convertRecurrence(KARecurrence
& recurrence
, const KDateTime
& start
, int recurType
,
565 int recurInterval
, int recurCount
, const KDateTime
& end
)
567 KARecurrence::Type type
;
570 case MINUTELY
: type
= KARecurrence::MINUTELY
; break;
571 case DAILY
: type
= KARecurrence::DAILY
; break;
572 case WEEKLY
: type
= KARecurrence::WEEKLY
; break;
573 case MONTHLY
: type
= KARecurrence::MONTHLY_DAY
; break;
574 case YEARLY
: type
= KARecurrence::ANNUAL_DATE
; break;
576 kError() << "D-Bus call: invalid recurrence type:" << recurType
;
579 recurrence
.set(type
, recurInterval
, recurCount
, start
, end
);