kde-playground/kdepim/kalarm/dbushandler.cpp
2015-04-14 21:49:29 +00:00

583 lines
24 KiB
C++

/*
* dbushandler.cpp - handler for D-Bus calls by other applications
* Program: kalarm
* Copyright © 2002-2012 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kalarm.h"
#include "alarmcalendar.h"
#include "alarmtime.h"
#include "functions.h"
#include "kalarmapp.h"
#include "kamail.h"
#include "mainwindow.h"
#include "preferences.h"
#include "dbushandler.h"
#include <kalarmadaptor.h>
#include <kalarmcal/identities.h>
#include <kalarmcal/karecurrence.h>
#ifdef USE_AKONADI
#include <kcalcore/duration.h>
using namespace KCalCore;
#else
#include <kcal/duration.h>
using namespace KCal;
#endif
#include <kdebug.h>
#include <QtDBus/QtDBus>
#include <stdlib.h>
static const char* REQUEST_DBUS_OBJECT = "/kalarm"; // D-Bus object path of KAlarm's request interface
/*=============================================================================
= DBusHandler
= This class's function is to handle D-Bus requests by other applications.
=============================================================================*/
DBusHandler::DBusHandler()
{
kDebug();
new KalarmAdaptor(this);
QDBusConnection::sessionBus().registerObject(QLatin1String(REQUEST_DBUS_OBJECT), this);
}
bool DBusHandler::cancelEvent(const QString& eventId)
{
#ifdef USE_AKONADI
return theApp()->dbusDeleteEvent(EventId(eventId));
#else
return theApp()->dbusDeleteEvent(eventId);
#endif
}
bool DBusHandler::triggerEvent(const QString& eventId)
{
#ifdef USE_AKONADI
return theApp()->dbusTriggerEvent(EventId(eventId));
#else
return theApp()->dbusTriggerEvent(eventId);
#endif
}
QString DBusHandler::list()
{
return theApp()->dbusList();
}
bool DBusHandler::scheduleMessage(const QString& message, const QString& startDateTime, int lateCancel, unsigned flags,
const QString& bgColor, const QString& fgColor, const QString& font,
const QString& audioUrl, int reminderMins, const QString& recurrence,
int subRepeatInterval, int subRepeatCount)
{
KDateTime start;
KARecurrence recur;
Duration subRepeatDuration;
if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval, subRepeatDuration))
return false;
return scheduleMessage(message, start, lateCancel, flags, bgColor, fgColor, font, KUrl(audioUrl), reminderMins, recur, subRepeatDuration, subRepeatCount);
}
bool DBusHandler::scheduleMessage(const QString& message, const QString& startDateTime, int lateCancel, unsigned flags,
const QString& bgColor, const QString& fgColor, const QString& font,
const QString& audioUrl, int reminderMins,
int recurType, int recurInterval, int recurCount)
{
KDateTime start;
KARecurrence recur;
if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
return false;
return scheduleMessage(message, start, lateCancel, flags, bgColor, fgColor, font, KUrl(audioUrl), reminderMins, recur);
}
bool DBusHandler::scheduleMessage(const QString& message, const QString& startDateTime, int lateCancel, unsigned flags,
const QString& bgColor, const QString& fgColor, const QString& font,
const QString& audioUrl, int reminderMins,
int recurType, int recurInterval, const QString& endDateTime)
{
KDateTime start;
KARecurrence recur;
if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
return false;
return scheduleMessage(message, start, lateCancel, flags, bgColor, fgColor, font, KUrl(audioUrl), reminderMins, recur);
}
bool DBusHandler::scheduleFile(const QString& url, const QString& startDateTime, int lateCancel, unsigned flags, const QString& bgColor,
const QString& audioUrl, int reminderMins, const QString& recurrence,
int subRepeatInterval, int subRepeatCount)
{
KDateTime start;
KARecurrence recur;
Duration subRepeatDuration;
if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval, subRepeatDuration))
return false;
return scheduleFile(KUrl(url), start, lateCancel, flags, bgColor, KUrl(audioUrl), reminderMins, recur, subRepeatDuration, subRepeatCount);
}
bool DBusHandler::scheduleFile(const QString& url, const QString& startDateTime, int lateCancel, unsigned flags, const QString& bgColor,
const QString& audioUrl, int reminderMins, int recurType, int recurInterval, int recurCount)
{
KDateTime start;
KARecurrence recur;
if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
return false;
return scheduleFile(KUrl(url), start, lateCancel, flags, bgColor, KUrl(audioUrl), reminderMins, recur);
}
bool DBusHandler::scheduleFile(const QString& url, const QString& startDateTime, int lateCancel, unsigned flags, const QString& bgColor,
const QString& audioUrl, int reminderMins, int recurType, int recurInterval, const QString& endDateTime)
{
KDateTime start;
KARecurrence recur;
if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
return false;
return scheduleFile(KUrl(url), start, lateCancel, flags, bgColor, KUrl(audioUrl), reminderMins, recur);
}
bool DBusHandler::scheduleCommand(const QString& commandLine, const QString& startDateTime, int lateCancel, unsigned flags,
const QString& recurrence, int subRepeatInterval, int subRepeatCount)
{
KDateTime start;
KARecurrence recur;
Duration subRepeatDuration;
if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval, subRepeatDuration))
return false;
return scheduleCommand(commandLine, start, lateCancel, flags, recur, subRepeatDuration, subRepeatCount);
}
bool DBusHandler::scheduleCommand(const QString& commandLine, const QString& startDateTime, int lateCancel, unsigned flags,
int recurType, int recurInterval, int recurCount)
{
KDateTime start = convertDateTime(startDateTime);
if (!start.isValid())
return false;
KARecurrence recur;
if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
return false;
return scheduleCommand(commandLine, start, lateCancel, flags, recur);
}
bool DBusHandler::scheduleCommand(const QString& commandLine, const QString& startDateTime, int lateCancel, unsigned flags,
int recurType, int recurInterval, const QString& endDateTime)
{
KDateTime start;
KARecurrence recur;
if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
return false;
return scheduleCommand(commandLine, start, lateCancel, flags, recur);
}
bool DBusHandler::scheduleEmail(const QString& fromID, const QString& addresses, const QString& subject, const QString& message,
const QString& attachments, const QString& startDateTime, int lateCancel, unsigned flags,
const QString& recurrence, int subRepeatInterval, int subRepeatCount)
{
KDateTime start;
KARecurrence recur;
Duration subRepeatDuration;
if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval, subRepeatDuration))
return false;
return scheduleEmail(fromID, addresses, subject, message, attachments, start, lateCancel, flags, recur, subRepeatDuration, subRepeatCount);
}
bool DBusHandler::scheduleEmail(const QString& fromID, const QString& addresses, const QString& subject, const QString& message,
const QString& attachments, const QString& startDateTime, int lateCancel, unsigned flags,
int recurType, int recurInterval, int recurCount)
{
KDateTime start;
KARecurrence recur;
if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
return false;
return scheduleEmail(fromID, addresses, subject, message, attachments, start, lateCancel, flags, recur);
}
bool DBusHandler::scheduleEmail(const QString& fromID, const QString& addresses, const QString& subject, const QString& message,
const QString& attachments, const QString& startDateTime, int lateCancel, unsigned flags,
int recurType, int recurInterval, const QString& endDateTime)
{
KDateTime start;
KARecurrence recur;
if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
return false;
return scheduleEmail(fromID, addresses, subject, message, attachments, start, lateCancel, flags, recur);
}
bool DBusHandler::scheduleAudio(const QString& audioUrl, int volumePercent, const QString& startDateTime, int lateCancel,
unsigned flags, const QString& recurrence, int subRepeatInterval, int subRepeatCount)
{
KDateTime start;
KARecurrence recur;
Duration subRepeatDuration;
if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval, subRepeatDuration))
return false;
return scheduleAudio(audioUrl, volumePercent, start, lateCancel, flags, recur, subRepeatDuration, subRepeatCount);
}
bool DBusHandler::scheduleAudio(const QString& audioUrl, int volumePercent, const QString& startDateTime, int lateCancel,
unsigned flags, int recurType, int recurInterval, int recurCount)
{
KDateTime start = convertDateTime(startDateTime);
if (!start.isValid())
return false;
KARecurrence recur;
if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
return false;
return scheduleAudio(audioUrl, volumePercent, start, lateCancel, flags, recur);
}
bool DBusHandler::scheduleAudio(const QString& audioUrl, int volumePercent, const QString& startDateTime, int lateCancel,
unsigned flags, int recurType, int recurInterval, const QString& endDateTime)
{
KDateTime start;
KARecurrence recur;
if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
return false;
return scheduleAudio(audioUrl, volumePercent, start, lateCancel, flags, recur);
}
bool DBusHandler::edit(const QString& eventID)
{
#ifdef USE_AKONADI
return KAlarm::editAlarmById(EventId(eventID));
#else
return KAlarm::editAlarmById(eventID);
#endif
}
bool DBusHandler::editNew(int type)
{
EditAlarmDlg::Type dlgtype;
switch (type)
{
case DISPLAY: dlgtype = EditAlarmDlg::DISPLAY; break;
case COMMAND: dlgtype = EditAlarmDlg::COMMAND; break;
case EMAIL: dlgtype = EditAlarmDlg::EMAIL; break;
case AUDIO: dlgtype = EditAlarmDlg::AUDIO; break;
default:
kError() << "D-Bus call: invalid alarm type:" << type;
return false;
}
KAlarm::editNewAlarm(dlgtype);
return true;
}
bool DBusHandler::editNew(const QString& templateName)
{
return KAlarm::editNewAlarm(templateName);
}
/******************************************************************************
* Schedule a message alarm, after converting the parameters from strings.
*/
bool DBusHandler::scheduleMessage(const QString& message, const KDateTime& start, int lateCancel, unsigned flags,
const QString& bgColor, const QString& fgColor, const QString& fontStr,
const KUrl& audioFile, int reminderMins, const KARecurrence& recurrence,
const Duration& subRepeatDuration, int subRepeatCount)
{
KAEvent::Flags kaEventFlags = convertStartFlags(start, flags);
KAEvent::SubAction action = (kaEventFlags & KAEvent::DISPLAY_COMMAND) ? KAEvent::COMMAND : KAEvent::MESSAGE;
QColor bg = convertBgColour(bgColor);
if (!bg.isValid())
return false;
QColor fg;
if (fgColor.isEmpty())
fg = Preferences::defaultFgColour();
else
{
fg.setNamedColor(fgColor);
if (!fg.isValid())
{
kError() << "D-Bus call: invalid foreground color:" << fgColor;
return false;
}
}
QFont font;
if (fontStr.isEmpty())
kaEventFlags |= KAEvent::DEFAULT_FONT;
else
{
if (!font.fromString(fontStr)) // N.B. this doesn't do good validation
{
kError() << "D-Bus call: invalid font:" << fontStr;
return false;
}
}
return theApp()->scheduleEvent(action, message, start, lateCancel, kaEventFlags, bg, fg, font,
audioFile.url(), -1, reminderMins, recurrence, subRepeatDuration, subRepeatCount);
}
/******************************************************************************
* Schedule a file alarm, after converting the parameters from strings.
*/
bool DBusHandler::scheduleFile(const KUrl& file,
const KDateTime& start, int lateCancel, unsigned flags, const QString& bgColor,
const KUrl& audioFile, int reminderMins, const KARecurrence& recurrence,
const Duration& subRepeatDuration, int subRepeatCount)
{
KAEvent::Flags kaEventFlags = convertStartFlags(start, flags);
QColor bg = convertBgColour(bgColor);
if (!bg.isValid())
return false;
return theApp()->scheduleEvent(KAEvent::FILE, file.url(), start, lateCancel, kaEventFlags, bg, Qt::black, QFont(),
audioFile.url(), -1, reminderMins, recurrence, subRepeatDuration, subRepeatCount);
}
/******************************************************************************
* Schedule a command alarm, after converting the parameters from strings.
*/
bool DBusHandler::scheduleCommand(const QString& commandLine,
const KDateTime& start, int lateCancel, unsigned flags,
const KARecurrence& recurrence, const Duration& subRepeatDuration, int subRepeatCount)
{
KAEvent::Flags kaEventFlags = convertStartFlags(start, flags);
return theApp()->scheduleEvent(KAEvent::COMMAND, commandLine, start, lateCancel, kaEventFlags, Qt::black, Qt::black, QFont(),
QString(), -1, 0, recurrence, subRepeatDuration, subRepeatCount);
}
/******************************************************************************
* Schedule an email alarm, after validating the addresses and attachments.
*/
bool DBusHandler::scheduleEmail(const QString& fromID, const QString& addresses, const QString& subject,
const QString& message, const QString& attachments,
const KDateTime& start, int lateCancel, unsigned flags,
const KARecurrence& recurrence, const Duration& subRepeatDuration, int subRepeatCount)
{
KAEvent::Flags kaEventFlags = convertStartFlags(start, flags);
uint senderId = 0;
if (!fromID.isEmpty())
{
senderId = Identities::identityUoid(fromID);
if (!senderId)
{
kError() << "D-Bus call scheduleEmail(): unknown sender ID:" << fromID;
return false;
}
}
#ifdef USE_AKONADI
KCalCore::Person::List addrs;
#else
QList<KCal::Person> addrs;
#endif
QString bad = KAMail::convertAddresses(addresses, addrs);
if (!bad.isEmpty())
{
kError() << "D-Bus call scheduleEmail(): invalid email addresses:" << bad;
return false;
}
if (addrs.isEmpty())
{
kError() << "D-Bus call scheduleEmail(): no email address";
return false;
}
QStringList atts;
bad = KAMail::convertAttachments(attachments, atts);
if (!bad.isEmpty())
{
kError() << "D-Bus call scheduleEmail(): invalid email attachment:" << bad;
return false;
}
return theApp()->scheduleEvent(KAEvent::EMAIL, message, start, lateCancel, kaEventFlags, Qt::black, Qt::black, QFont(),
QString(), -1, 0, recurrence, subRepeatDuration, subRepeatCount, senderId, addrs, subject, atts);
}
/******************************************************************************
* Schedule a audio alarm, after converting the parameters from strings.
*/
bool DBusHandler::scheduleAudio(const QString& audioUrl, int volumePercent,
const KDateTime& start, int lateCancel, unsigned flags,
const KARecurrence& recurrence, const Duration& subRepeatDuration, int subRepeatCount)
{
KAEvent::Flags kaEventFlags = convertStartFlags(start, flags);
float volume = (volumePercent >= 0) ? volumePercent / 100.0f : -1;
return theApp()->scheduleEvent(KAEvent::AUDIO, QString(), start, lateCancel, kaEventFlags, Qt::black, Qt::black, QFont(),
audioUrl, volume, 0, recurrence, subRepeatDuration, subRepeatCount);
}
/******************************************************************************
* Convert the start date/time string to a KDateTime. The date/time string is in
* the format YYYY-MM-DD[THH:MM[:SS]][ TZ] or [T]HH:MM[:SS].
* The time zone specifier (TZ) is a system time zone name, e.g. "Europe/London".
* If no time zone is specified, it defaults to the local clock time (which is
* not the same as the local time zone).
*/
KDateTime DBusHandler::convertDateTime(const QString& dateTime, const KDateTime& defaultDt)
{
int i = dateTime.indexOf(QLatin1Char(' '));
QString dtString = dateTime.left(i);
QString zone = dateTime.mid(i);
QDate date;
QTime time;
bool haveTime = true;
bool error = false;
if (dtString.length() > 10)
{
// Both a date and a time are specified
QDateTime dt = QDateTime::fromString(dtString, Qt::ISODate);
error = !dt.isValid();
date = dt.date();
time = dt.time();
}
else
{
// Check whether a time is specified
QString t;
if (dtString[0] == QLatin1Char('T'))
t = dtString.mid(1); // it's a time: remove the leading 'T'
else if (!dtString[2].isDigit())
t = dtString; // it's a time with no leading 'T'
if (t.isEmpty())
{
// It's a date only
date = QDate::fromString(dtString, Qt::ISODate);
error = !date.isValid();
haveTime = false;
}
else
{
// It's a time only
time = QTime::fromString(t, Qt::ISODate);
error = !time.isValid();
}
}
KDateTime result;
if (!error)
result = AlarmTime::applyTimeZone(zone, date, time, haveTime, defaultDt);
if (error || !result.isValid())
{
if (!defaultDt.isValid())
kError() << "D-Bus call: invalid start date/time: '" << dateTime << "'";
else
kError() << "D-Bus call: invalid recurrence end date/time: '" << dateTime << "'";
}
return result;
}
/******************************************************************************
* Convert the flag bits to KAEvent flag bits.
*/
KAEvent::Flags DBusHandler::convertStartFlags(const KDateTime& start, unsigned flags)
{
KAEvent::Flags kaEventFlags = 0;
if (flags & REPEAT_AT_LOGIN) kaEventFlags |= KAEvent::REPEAT_AT_LOGIN;
if (flags & BEEP) kaEventFlags |= KAEvent::BEEP;
if (flags & SPEAK) kaEventFlags |= KAEvent::SPEAK;
if (flags & CONFIRM_ACK) kaEventFlags |= KAEvent::CONFIRM_ACK;
if (flags & REPEAT_SOUND) kaEventFlags |= KAEvent::REPEAT_SOUND;
if (flags & AUTO_CLOSE) kaEventFlags |= KAEvent::AUTO_CLOSE;
if (flags & EMAIL_BCC) kaEventFlags |= KAEvent::EMAIL_BCC;
if (flags & DISPLAY_COMMAND) kaEventFlags |= KAEvent::DISPLAY_COMMAND;
if (flags & SCRIPT) kaEventFlags |= KAEvent::SCRIPT;
if (flags & EXEC_IN_XTERM) kaEventFlags |= KAEvent::EXEC_IN_XTERM;
if (flags & SHOW_IN_KORG) kaEventFlags |= KAEvent::COPY_KORGANIZER;
if (flags & EXCL_HOLIDAYS) kaEventFlags |= KAEvent::EXCL_HOLIDAYS;
if (flags & WORK_TIME_ONLY) kaEventFlags |= KAEvent::WORK_TIME_ONLY;
if (flags & DISABLED) kaEventFlags |= KAEvent::DISABLED;
if (start.isDateOnly()) kaEventFlags |= KAEvent::ANY_TIME;
return kaEventFlags;
}
/******************************************************************************
* Convert the background colour string to a QColor.
*/
QColor DBusHandler::convertBgColour(const QString& bgColor)
{
if (bgColor.isEmpty())
return Preferences::defaultBgColour();
QColor bg(bgColor);
if (!bg.isValid())
kError() << "D-Bus call: invalid background color:" << bgColor;
return bg;
}
bool DBusHandler::convertRecurrence(KDateTime& start, KARecurrence& recurrence,
const QString& startDateTime, const QString& icalRecurrence,
int subRepeatInterval, Duration& subRepeatDuration)
{
start = convertDateTime(startDateTime);
if (!start.isValid())
return false;
if (!recurrence.set(icalRecurrence))
return false;
if (subRepeatInterval && recurrence.type() == KARecurrence::NO_RECUR)
{
subRepeatInterval = 0;
kWarning() << "D-Bus call: no recurrence specified, so sub-repetition ignored";
}
if (subRepeatInterval && !(subRepeatInterval % (24*60)))
subRepeatDuration = Duration(subRepeatInterval / (24*60), Duration::Days);
else
subRepeatDuration = Duration(subRepeatInterval * 60, Duration::Seconds);
return true;
}
bool DBusHandler::convertRecurrence(KDateTime& start, KARecurrence& recurrence, const QString& startDateTime,
int recurType, int recurInterval, int recurCount)
{
start = convertDateTime(startDateTime);
if (!start.isValid())
return false;
return convertRecurrence(recurrence, start, recurType, recurInterval, recurCount, KDateTime());
}
bool DBusHandler::convertRecurrence(KDateTime& start, KARecurrence& recurrence, const QString& startDateTime,
int recurType, int recurInterval, const QString& endDateTime)
{
start = convertDateTime(startDateTime);
if (!start.isValid())
return false;
KDateTime end = convertDateTime(endDateTime, start);
if (end.isDateOnly() && !start.isDateOnly())
{
kError() << "D-Bus call: alarm is date-only, but recurrence end is date/time";
return false;
}
if (!end.isDateOnly() && start.isDateOnly())
{
kError() << "D-Bus call: alarm is timed, but recurrence end is date-only";
return false;
}
return convertRecurrence(recurrence, start, recurType, recurInterval, 0, end);
}
bool DBusHandler::convertRecurrence(KARecurrence& recurrence, const KDateTime& start, int recurType,
int recurInterval, int recurCount, const KDateTime& end)
{
KARecurrence::Type type;
switch (recurType)
{
case MINUTELY: type = KARecurrence::MINUTELY; break;
case DAILY: type = KARecurrence::DAILY; break;
case WEEKLY: type = KARecurrence::WEEKLY; break;
case MONTHLY: type = KARecurrence::MONTHLY_DAY; break;
case YEARLY: type = KARecurrence::ANNUAL_DATE; break;
default:
kError() << "D-Bus call: invalid recurrence type:" << recurType;
return false;
}
recurrence.set(type, recurInterval, recurCount, start, end);
return true;
}
#include "moc_dbushandler.cpp"
// vim: et sw=4: