Updated the Tools menu to reflect current build.
[kdepim.git] / kalarm / dbushandler.cpp
blob63791ce8e0f80ff5b933a466d6afcda3004bfbba
1 /*
2 * dbushandler.cpp - handler for D-Bus calls by other applications
3 * Program: kalarm
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.
21 #include "kalarm.h"
23 #include "alarmcalendar.h"
24 #include "alarmtime.h"
25 #include "functions.h"
26 #include "kalarmapp.h"
27 #include "kamail.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>
36 #ifdef USE_AKONADI
37 #include <kcalcore/duration.h>
38 using namespace KCalCore;
39 #else
40 #include <kcal/duration.h>
41 using namespace KCal;
42 #endif
44 #include <kdebug.h>
46 #include <QtDBus/QtDBus>
48 #include <stdlib.h>
50 static const char* REQUEST_DBUS_OBJECT = "/kalarm"; // D-Bus object path of KAlarm's request interface
53 /*=============================================================================
54 = DBusHandler
55 = This class's function is to handle D-Bus requests by other applications.
56 =============================================================================*/
57 DBusHandler::DBusHandler()
59 kDebug();
60 new KalarmAdaptor(this);
61 QDBusConnection::sessionBus().registerObject(REQUEST_DBUS_OBJECT, this);
65 bool DBusHandler::cancelEvent(const QString& eventId)
67 #ifdef USE_AKONADI
68 return theApp()->dbusDeleteEvent(EventId(eventId));
69 #else
70 return theApp()->dbusDeleteEvent(eventId);
71 #endif
74 bool DBusHandler::triggerEvent(const QString& eventId)
76 #ifdef USE_AKONADI
77 return theApp()->dbusTriggerEvent(EventId(eventId));
78 #else
79 return theApp()->dbusTriggerEvent(eventId);
80 #endif
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)
93 KDateTime start;
94 KARecurrence recur;
95 Duration subRepeatDuration;
96 if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval, subRepeatDuration))
97 return false;
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)
106 KDateTime start;
107 KARecurrence recur;
108 if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
109 return false;
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)
118 KDateTime start;
119 KARecurrence recur;
120 if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
121 return false;
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)
129 KDateTime start;
130 KARecurrence recur;
131 Duration subRepeatDuration;
132 if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval, subRepeatDuration))
133 return false;
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)
140 KDateTime start;
141 KARecurrence recur;
142 if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
143 return false;
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)
150 KDateTime start;
151 KARecurrence recur;
152 if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
153 return false;
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)
160 KDateTime start;
161 KARecurrence recur;
162 Duration subRepeatDuration;
163 if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval, subRepeatDuration))
164 return false;
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())
173 return false;
174 KARecurrence recur;
175 if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
176 return false;
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)
183 KDateTime start;
184 KARecurrence recur;
185 if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
186 return false;
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)
194 KDateTime start;
195 KARecurrence recur;
196 Duration subRepeatDuration;
197 if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval, subRepeatDuration))
198 return false;
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)
206 KDateTime start;
207 KARecurrence recur;
208 if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
209 return false;
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)
217 KDateTime start;
218 KARecurrence recur;
219 if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
220 return false;
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)
227 KDateTime start;
228 KARecurrence recur;
229 Duration subRepeatDuration;
230 if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval, subRepeatDuration))
231 return false;
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())
240 return false;
241 KARecurrence recur;
242 if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
243 return false;
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)
250 KDateTime start;
251 KARecurrence recur;
252 if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
253 return false;
254 return scheduleAudio(audioUrl, volumePercent, start, lateCancel, flags, recur);
257 bool DBusHandler::edit(const QString& eventID)
259 #ifdef USE_AKONADI
260 return KAlarm::editAlarmById(EventId(eventID));
261 #else
262 return KAlarm::editAlarmById(eventID);
263 #endif
266 bool DBusHandler::editNew(int type)
268 EditAlarmDlg::Type dlgtype;
269 switch (type)
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;
275 default:
276 kError() << "D-Bus call: invalid alarm type:" << type;
277 return false;
279 KAlarm::editNewAlarm(dlgtype);
280 return true;
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);
300 if (!bg.isValid())
301 return false;
302 QColor fg;
303 if (fgColor.isEmpty())
304 fg = Preferences::defaultFgColour();
305 else
307 fg.setNamedColor(fgColor);
308 if (!fg.isValid())
310 kError() << "D-Bus call: invalid foreground color:" << fgColor;
311 return false;
314 QFont font;
315 if (fontStr.isEmpty())
316 kaEventFlags |= KAEvent::DEFAULT_FONT;
317 else
319 if (!font.fromString(fontStr)) // N.B. this doesn't do good validation
321 kError() << "D-Bus call: invalid font:" << fontStr;
322 return false;
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);
339 if (!bg.isValid())
340 return false;
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);
366 uint senderId = 0;
367 if (!fromID.isEmpty())
369 senderId = Identities::identityUoid(fromID);
370 if (!senderId)
372 kError() << "D-Bus call scheduleEmail(): unknown sender ID:" << fromID;
373 return false;
376 #ifdef USE_AKONADI
377 KCalCore::Person::List addrs;
378 #else
379 QList<KCal::Person> addrs;
380 #endif
381 QString bad = KAMail::convertAddresses(addresses, addrs);
382 if (!bad.isEmpty())
384 kError() << "D-Bus call scheduleEmail(): invalid email addresses:" << bad;
385 return false;
387 if (addrs.isEmpty())
389 kError() << "D-Bus call scheduleEmail(): no email address";
390 return false;
392 QStringList atts;
393 bad = KAMail::convertAttachments(attachments, atts);
394 if (!bad.isEmpty())
396 kError() << "D-Bus call scheduleEmail(): invalid email attachment:" << bad;
397 return false;
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);
429 QDate date;
430 QTime time;
431 bool haveTime = true;
432 bool error = false;
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();
438 date = dt.date();
439 time = dt.time();
441 else
443 // Check whether a time is specified
444 QString t;
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'
450 if (t.isEmpty())
452 // It's a date only
453 date = QDate::fromString(dtString, Qt::ISODate);
454 error = !date.isValid();
455 haveTime = false;
457 else
459 // It's a time only
460 time = QTime::fromString(t, Qt::ISODate);
461 error = !time.isValid();
464 KDateTime result;
465 if (!error)
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 << "'";
471 else
472 kError() << "D-Bus call: invalid recurrence end date/time: '" << dateTime << "'";
474 return result;
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;
498 return kaEventFlags;
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();
508 QColor bg(bgColor);
509 if (!bg.isValid())
510 kError() << "D-Bus call: invalid background color:" << bgColor;
511 return bg;
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())
520 return false;
521 if (!recurrence.set(icalRecurrence))
522 return false;
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);
530 else
531 subRepeatDuration = Duration(subRepeatInterval * 60, Duration::Seconds);
532 return true;
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())
540 return false;
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())
549 return false;
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";
554 return false;
556 if (!end.isDateOnly() && start.isDateOnly())
558 kError() << "D-Bus call: alarm is timed, but recurrence end is date-only";
559 return false;
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;
568 switch (recurType)
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;
575 default:
576 kError() << "D-Bus call: invalid recurrence type:" << recurType;
577 return false;
579 recurrence.set(type, recurInterval, recurCount, start, end);
580 return true;
583 // vim: et sw=4: