kalarm

dcophandler.cpp

00001 /*
00002  *  dcophandler.cpp  -  handler for DCOP calls by other applications
00003  *  Program:  kalarm
00004  *  Copyright © 2002-2006,2008 by David Jarvie <djarvie@kde.org>
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License along
00017  *  with this program; if not, write to the Free Software Foundation, Inc.,
00018  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "kalarm.h"
00022 
00023 #include <stdlib.h>
00024 
00025 #include <kdebug.h>
00026 
00027 #include "alarmcalendar.h"
00028 #include "daemon.h"
00029 #include "functions.h"
00030 #include "kalarmapp.h"
00031 #include "kamail.h"
00032 #include "karecurrence.h"
00033 #include "mainwindow.h"
00034 #include "preferences.h"
00035 #include "dcophandler.h"
00036 #include "dcophandler.moc"
00037 
00038 static const char*  DCOP_OBJECT_NAME = "request";   // DCOP name of KAlarm's request interface
00039 
00040 
00041 /*=============================================================================
00042 = DcopHandler
00043 = This class's function is to handle DCOP requests by other applications.
00044 =============================================================================*/
00045 DcopHandler::DcopHandler()
00046     : DCOPObject(DCOP_OBJECT_NAME),
00047       TQWidget()
00048 {
00049     kdDebug(5950) << "DcopHandler::DcopHandler()\n";
00050 }
00051 
00052 
00053 bool DcopHandler::cancelEvent(const TQString& url,const TQString& eventId)
00054 {
00055     return theApp()->deleteEvent(url, eventId);
00056 }
00057 
00058 bool DcopHandler::triggerEvent(const TQString& url,const TQString& eventId)
00059 {
00060     return theApp()->triggerEvent(url, eventId);
00061 }
00062 
00063 bool DcopHandler::scheduleMessage(const TQString& message, const TQString& startDateTime, int lateCancel, unsigned flags,
00064                                   const TQString& bgColor, const TQString& fgColor, const TQString& font,
00065                                   const KURL& audioFile, int reminderMins, const TQString& recurrence,
00066                                   int subRepeatInterval, int subRepeatCount)
00067 {
00068     DateTime start;
00069     KARecurrence recur;
00070     if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval))
00071         return false;
00072     return scheduleMessage(message, start, lateCancel, flags, bgColor, fgColor, font, audioFile, reminderMins, recur, subRepeatInterval, subRepeatCount);
00073 }
00074 
00075 bool DcopHandler::scheduleMessage(const TQString& message, const TQString& startDateTime, int lateCancel, unsigned flags,
00076                                   const TQString& bgColor, const TQString& fgColor, const TQString& font,
00077                                   const KURL& audioFile, int reminderMins,
00078                                   int recurType, int recurInterval, int recurCount)
00079 {
00080     DateTime start;
00081     KARecurrence recur;
00082     if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
00083         return false;
00084     return scheduleMessage(message, start, lateCancel, flags, bgColor, fgColor, font, audioFile, reminderMins, recur);
00085 }
00086 
00087 bool DcopHandler::scheduleMessage(const TQString& message, const TQString& startDateTime, int lateCancel, unsigned flags,
00088                                   const TQString& bgColor, const TQString& fgColor, const TQString& font,
00089                                   const KURL& audioFile, int reminderMins,
00090                                   int recurType, int recurInterval, const TQString& endDateTime)
00091 {
00092     DateTime start;
00093     KARecurrence recur;
00094     if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
00095         return false;
00096     return scheduleMessage(message, start, lateCancel, flags, bgColor, fgColor, font, audioFile, reminderMins, recur);
00097 }
00098 
00099 bool DcopHandler::scheduleFile(const KURL& file, const TQString& startDateTime, int lateCancel, unsigned flags, const TQString& bgColor,
00100                                const KURL& audioFile, int reminderMins, const TQString& recurrence,
00101                                int subRepeatInterval, int subRepeatCount)
00102 {
00103     DateTime start;
00104     KARecurrence recur;
00105     if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval))
00106         return false;
00107     return scheduleFile(file, start, lateCancel, flags, bgColor, audioFile, reminderMins, recur, subRepeatInterval, subRepeatCount);
00108 }
00109 
00110 bool DcopHandler::scheduleFile(const KURL& file, const TQString& startDateTime, int lateCancel, unsigned flags, const TQString& bgColor,
00111                                const KURL& audioFile, int reminderMins, int recurType, int recurInterval, int recurCount)
00112 {
00113     DateTime start;
00114     KARecurrence recur;
00115     if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
00116         return false;
00117     return scheduleFile(file, start, lateCancel, flags, bgColor, audioFile, reminderMins, recur);
00118 }
00119 
00120 bool DcopHandler::scheduleFile(const KURL& file, const TQString& startDateTime, int lateCancel, unsigned flags, const TQString& bgColor,
00121                                const KURL& audioFile, int reminderMins, int recurType, int recurInterval, const TQString& endDateTime)
00122 {
00123     DateTime start;
00124     KARecurrence recur;
00125     if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
00126         return false;
00127     return scheduleFile(file, start, lateCancel, flags, bgColor, audioFile, reminderMins, recur);
00128 }
00129 
00130 bool DcopHandler::scheduleCommand(const TQString& commandLine, const TQString& startDateTime, int lateCancel, unsigned flags,
00131                                   const TQString& recurrence, int subRepeatInterval, int subRepeatCount)
00132 {
00133     DateTime start;
00134     KARecurrence recur;
00135     if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval))
00136         return false;
00137     return scheduleCommand(commandLine, start, lateCancel, flags, recur, subRepeatInterval, subRepeatCount);
00138 }
00139 
00140 bool DcopHandler::scheduleCommand(const TQString& commandLine, const TQString& startDateTime, int lateCancel, unsigned flags,
00141                                   int recurType, int recurInterval, int recurCount)
00142 {
00143     DateTime start = convertStartDateTime(startDateTime);
00144     if (!start.isValid())
00145         return false;
00146     KARecurrence recur;
00147     if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
00148         return false;
00149     return scheduleCommand(commandLine, start, lateCancel, flags, recur);
00150 }
00151 
00152 bool DcopHandler::scheduleCommand(const TQString& commandLine, const TQString& startDateTime, int lateCancel, unsigned flags,
00153                                   int recurType, int recurInterval, const TQString& endDateTime)
00154 {
00155     DateTime start;
00156     KARecurrence recur;
00157     if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
00158         return false;
00159     return scheduleCommand(commandLine, start, lateCancel, flags, recur);
00160 }
00161 
00162 bool DcopHandler::scheduleEmail(const TQString& fromID, const TQString& addresses, const TQString& subject, const TQString& message,
00163                                 const TQString& attachments, const TQString& startDateTime, int lateCancel, unsigned flags,
00164                                 const TQString& recurrence, int subRepeatInterval, int subRepeatCount)
00165 {
00166     DateTime start;
00167     KARecurrence recur;
00168     if (!convertRecurrence(start, recur, startDateTime, recurrence, subRepeatInterval))
00169         return false;
00170     return scheduleEmail(fromID, addresses, subject, message, attachments, start, lateCancel, flags, recur, subRepeatInterval, subRepeatCount);
00171 }
00172 
00173 bool DcopHandler::scheduleEmail(const TQString& fromID, const TQString& addresses, const TQString& subject, const TQString& message,
00174                                 const TQString& attachments, const TQString& startDateTime, int lateCancel, unsigned flags,
00175                                 int recurType, int recurInterval, int recurCount)
00176 {
00177     DateTime start;
00178     KARecurrence recur;
00179     if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, recurCount))
00180         return false;
00181     return scheduleEmail(fromID, addresses, subject, message, attachments, start, lateCancel, flags, recur);
00182 }
00183 
00184 bool DcopHandler::scheduleEmail(const TQString& fromID, const TQString& addresses, const TQString& subject, const TQString& message,
00185                                 const TQString& attachments, const TQString& startDateTime, int lateCancel, unsigned flags,
00186                                 int recurType, int recurInterval, const TQString& endDateTime)
00187 {
00188     DateTime start;
00189     KARecurrence recur;
00190     if (!convertRecurrence(start, recur, startDateTime, recurType, recurInterval, endDateTime))
00191         return false;
00192     return scheduleEmail(fromID, addresses, subject, message, attachments, start, lateCancel, flags, recur);
00193 }
00194 
00195 bool DcopHandler::edit(const TQString& eventID)
00196 {
00197     return KAlarm::edit(eventID);
00198 }
00199 
00200 bool DcopHandler::editNew(const TQString& templateName)
00201 {
00202     return KAlarm::editNew(templateName);
00203 }
00204 
00205 
00206 /******************************************************************************
00207 * Schedule a message alarm, after converting the parameters from strings.
00208 */
00209 bool DcopHandler::scheduleMessage(const TQString& message, const DateTime& start, int lateCancel, unsigned flags,
00210                                   const TQString& bgColor, const TQString& fgColor, const TQString& fontStr,
00211                                   const KURL& audioFile, int reminderMins, const KARecurrence& recurrence,
00212                                   int subRepeatInterval, int subRepeatCount)
00213 {
00214     unsigned kaEventFlags = convertStartFlags(start, flags);
00215     TQColor bg = convertBgColour(bgColor);
00216     if (!bg.isValid())
00217         return false;
00218     TQColor fg;
00219     if (fgColor.isEmpty())
00220         fg = Preferences::defaultFgColour();
00221     else
00222     {
00223         fg.setNamedColor(fgColor);
00224         if (!fg.isValid())
00225         {
00226             kdError(5950) << "DCOP call: invalid foreground color: " << fgColor << endl;
00227             return false;
00228         }
00229     }
00230     TQFont font;
00231     if (fontStr.isEmpty())
00232         kaEventFlags |= KAEvent::DEFAULT_FONT;
00233     else
00234     {
00235         if (!font.fromString(fontStr))    // N.B. this doesn't do good validation
00236         {
00237             kdError(5950) << "DCOP call: invalid font: " << fontStr << endl;
00238             return false;
00239         }
00240     }
00241     return theApp()->scheduleEvent(KAEvent::MESSAGE, message, start.dateTime(), lateCancel, kaEventFlags, bg, fg, font,
00242                                    audioFile.url(), -1, reminderMins, recurrence, subRepeatInterval, subRepeatCount);
00243 }
00244 
00245 /******************************************************************************
00246 * Schedule a file alarm, after converting the parameters from strings.
00247 */
00248 bool DcopHandler::scheduleFile(const KURL& file,
00249                                const DateTime& start, int lateCancel, unsigned flags, const TQString& bgColor,
00250                                const KURL& audioFile, int reminderMins, const KARecurrence& recurrence,
00251                                int subRepeatInterval, int subRepeatCount)
00252 {
00253     unsigned kaEventFlags = convertStartFlags(start, flags);
00254     TQColor bg = convertBgColour(bgColor);
00255     if (!bg.isValid())
00256         return false;
00257     return theApp()->scheduleEvent(KAEvent::FILE, file.url(), start.dateTime(), lateCancel, kaEventFlags, bg, TQt::black, TQFont(),
00258                                    audioFile.url(), -1, reminderMins, recurrence, subRepeatInterval, subRepeatCount);
00259 }
00260 
00261 /******************************************************************************
00262 * Schedule a command alarm, after converting the parameters from strings.
00263 */
00264 bool DcopHandler::scheduleCommand(const TQString& commandLine,
00265                                   const DateTime& start, int lateCancel, unsigned flags,
00266                                   const KARecurrence& recurrence, int subRepeatInterval, int subRepeatCount)
00267 {
00268     unsigned kaEventFlags = convertStartFlags(start, flags);
00269     return theApp()->scheduleEvent(KAEvent::COMMAND, commandLine, start.dateTime(), lateCancel, kaEventFlags, TQt::black, TQt::black, TQFont(),
00270                                    TQString(), -1, 0, recurrence, subRepeatInterval, subRepeatCount);
00271 }
00272 
00273 /******************************************************************************
00274 * Schedule an email alarm, after validating the addresses and attachments.
00275 */
00276 bool DcopHandler::scheduleEmail(const TQString& fromID, const TQString& addresses, const TQString& subject,
00277                                 const TQString& message, const TQString& attachments,
00278                                 const DateTime& start, int lateCancel, unsigned flags,
00279                                 const KARecurrence& recurrence, int subRepeatInterval, int subRepeatCount)
00280 {
00281     unsigned kaEventFlags = convertStartFlags(start, flags);
00282     uint senderId = 0;
00283     if (!fromID.isEmpty())
00284     {
00285         senderId = KAMail::identityUoid(fromID);
00286         if (!senderId)
00287         {
00288             kdError(5950) << "DCOP call scheduleEmail(): unknown sender ID: " << fromID << endl;
00289             return false;
00290         }
00291     }
00292     EmailAddressList addrs;
00293     TQString bad = KAMail::convertAddresses(addresses, addrs);
00294     if (!bad.isEmpty())
00295     {
00296         kdError(5950) << "DCOP call scheduleEmail(): invalid email addresses: " << bad << endl;
00297         return false;
00298     }
00299     if (addrs.isEmpty())
00300     {
00301         kdError(5950) << "DCOP call scheduleEmail(): no email address\n";
00302         return false;
00303     }
00304     TQStringList atts;
00305     bad = KAMail::convertAttachments(attachments, atts);
00306     if (!bad.isEmpty())
00307     {
00308         kdError(5950) << "DCOP call scheduleEmail(): invalid email attachment: " << bad << endl;
00309         return false;
00310     }
00311     return theApp()->scheduleEvent(KAEvent::EMAIL, message, start.dateTime(), lateCancel, kaEventFlags, TQt::black, TQt::black, TQFont(),
00312                                    TQString(), -1, 0, recurrence, subRepeatInterval, subRepeatCount, senderId, addrs, subject, atts);
00313 }
00314 
00315 
00316 /******************************************************************************
00317 * Convert the start date/time string to a DateTime. The date/time string is in
00318 * the format YYYY-MM-DD[THH:MM[:SS]] or [T]HH:MM[:SS]
00319 */
00320 DateTime DcopHandler::convertStartDateTime(const TQString& startDateTime)
00321 {
00322     DateTime start;
00323     if (startDateTime.length() > 10)
00324     {
00325         // Both a date and a time are specified
00326         start = TQDateTime::fromString(startDateTime, Qt::ISODate);
00327     }
00328     else
00329     {
00330         // Check whether a time is specified
00331         TQString t;
00332         if (startDateTime[0] == 'T')
00333             t = startDateTime.mid(1);     // it's a time: remove the leading 'T'
00334         else if (!startDateTime[2].isDigit())
00335             t = startDateTime;            // it's a time with no leading 'T'
00336 
00337         if (t.isEmpty())
00338         {
00339             // It's a date
00340             start = TQDate::fromString(startDateTime, Qt::ISODate);
00341         }
00342         else
00343         {
00344             // It's a time, so use today as the date
00345             start.set(TQDate::currentDate(), TQTime::fromString(t, Qt::ISODate));
00346         }
00347     }
00348     if (!start.isValid())
00349         kdError(5950) << "DCOP call: invalid start date/time: " << startDateTime << endl;
00350     return start;
00351 }
00352 
00353 /******************************************************************************
00354 * Convert the flag bits to KAEvent flag bits.
00355 */
00356 unsigned DcopHandler::convertStartFlags(const DateTime& start, unsigned flags)
00357 {
00358     unsigned kaEventFlags = 0;
00359     if (flags & REPEAT_AT_LOGIN) kaEventFlags |= KAEvent::REPEAT_AT_LOGIN;
00360     if (flags & BEEP)            kaEventFlags |= KAEvent::BEEP;
00361     if (flags & SPEAK)           kaEventFlags |= KAEvent::SPEAK;
00362     if (flags & CONFIRM_ACK)     kaEventFlags |= KAEvent::CONFIRM_ACK;
00363     if (flags & REPEAT_SOUND)    kaEventFlags |= KAEvent::REPEAT_SOUND;
00364     if (flags & AUTO_CLOSE)      kaEventFlags |= KAEvent::AUTO_CLOSE;
00365     if (flags & EMAIL_BCC)       kaEventFlags |= KAEvent::EMAIL_BCC;
00366     if (flags & SCRIPT)          kaEventFlags |= KAEvent::SCRIPT;
00367     if (flags & EXEC_IN_XTERM)   kaEventFlags |= KAEvent::EXEC_IN_XTERM;
00368     if (flags & SHOW_IN_KORG)    kaEventFlags |= KAEvent::COPY_KORGANIZER;
00369     if (flags & DISABLED)        kaEventFlags |= KAEvent::DISABLED;
00370     if (start.isDateOnly())      kaEventFlags |= KAEvent::ANY_TIME;
00371     return kaEventFlags;
00372 }
00373 
00374 /******************************************************************************
00375 * Convert the background colour string to a TQColor.
00376 */
00377 TQColor DcopHandler::convertBgColour(const TQString& bgColor)
00378 {
00379     if (bgColor.isEmpty())
00380         return Preferences::defaultBgColour();
00381     TQColor bg(bgColor);
00382     if (!bg.isValid())
00383             kdError(5950) << "DCOP call: invalid background color: " << bgColor << endl;
00384     return bg;
00385 }
00386 
00387 bool DcopHandler::convertRecurrence(DateTime& start, KARecurrence& recurrence, 
00388                                     const TQString& startDateTime, const TQString& icalRecurrence,
00389                                     int& subRepeatInterval)
00390 {
00391     start = convertStartDateTime(startDateTime);
00392     if (!start.isValid())
00393         return false;
00394     if (!recurrence.set(icalRecurrence))
00395         return false;
00396     if (subRepeatInterval  &&  recurrence.type() == KARecurrence::NO_RECUR)
00397     {
00398         subRepeatInterval = 0;
00399         kdWarning(5950) << "DCOP call: no recurrence specified, so sub-repetition ignored" << endl;
00400     }
00401     return true;
00402 }
00403 
00404 bool DcopHandler::convertRecurrence(DateTime& start, KARecurrence& recurrence, const TQString& startDateTime,
00405                                     int recurType, int recurInterval, int recurCount)
00406 {
00407     start = convertStartDateTime(startDateTime);
00408     if (!start.isValid())
00409         return false;
00410     return convertRecurrence(recurrence, start, recurType, recurInterval, recurCount, TQDateTime());
00411 }
00412 
00413 bool DcopHandler::convertRecurrence(DateTime& start, KARecurrence& recurrence, const TQString& startDateTime,
00414                                     int recurType, int recurInterval, const TQString& endDateTime)
00415 {
00416     start = convertStartDateTime(startDateTime);
00417     if (!start.isValid())
00418         return false;
00419     TQDateTime end;
00420     if (endDateTime.find('T') < 0)
00421     {
00422         if (!start.isDateOnly())
00423         {
00424             kdError(5950) << "DCOP call: alarm is date-only, but recurrence end is date/time" << endl;
00425             return false;
00426         }
00427         end.setDate(TQDate::fromString(endDateTime, Qt::ISODate));
00428     }
00429     else
00430     {
00431         if (start.isDateOnly())
00432         {
00433             kdError(5950) << "DCOP call: alarm is timed, but recurrence end is date-only" << endl;
00434             return false;
00435         }
00436         end = TQDateTime::fromString(endDateTime, Qt::ISODate);
00437     }
00438     if (!end.isValid())
00439     {
00440         kdError(5950) << "DCOP call: invalid recurrence end date/time: " << endDateTime << endl;
00441         return false;
00442     }
00443     return convertRecurrence(recurrence, start, recurType, recurInterval, 0, end);
00444 }
00445 
00446 bool DcopHandler::convertRecurrence(KARecurrence& recurrence, const DateTime& start, int recurType,
00447                                     int recurInterval, int recurCount, const TQDateTime& end)
00448 {
00449     KARecurrence::Type type;
00450     switch (recurType)
00451     {
00452         case MINUTELY:  type = KARecurrence::MINUTELY;  break;
00453         case DAILY:     type = KARecurrence::DAILY;  break;
00454         case WEEKLY:    type = KARecurrence::WEEKLY;  break;
00455         case MONTHLY:   type = KARecurrence::MONTHLY_DAY;  break;
00456         case YEARLY:    type = KARecurrence::ANNUAL_DATE;  break;
00457             break;
00458         default:
00459             kdError(5950) << "DCOP call: invalid recurrence type: " << recurType << endl;
00460             return false;
00461     }
00462     recurrence.set(type, recurInterval, recurCount, start, end);
00463     return true;
00464 }