00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kalarm.h"
00022
00023 #include <stdlib.h>
00024 #include <ctype.h>
00025 #include <iostream>
00026
00027 #include <qobjectlist.h>
00028 #include <qtimer.h>
00029 #include <qregexp.h>
00030 #include <qfile.h>
00031
00032 #include <kcmdlineargs.h>
00033 #include <klocale.h>
00034 #include <kstandarddirs.h>
00035 #include <kconfig.h>
00036 #include <kaboutdata.h>
00037 #include <dcopclient.h>
00038 #include <kprocess.h>
00039 #include <ktempfile.h>
00040 #include <kfileitem.h>
00041 #include <kstdguiitem.h>
00042 #include <ktrader.h>
00043 #include <kstaticdeleter.h>
00044 #include <kdebug.h>
00045
00046 #include <libkcal/calformat.h>
00047
00048 #include <kalarmd/clientinfo.h>
00049
00050 #include "alarmcalendar.h"
00051 #include "alarmlistview.h"
00052 #include "editdlg.h"
00053 #include "daemon.h"
00054 #include "dcophandler.h"
00055 #include "functions.h"
00056 #include "kamail.h"
00057 #include "karecurrence.h"
00058 #include "mainwindow.h"
00059 #include "messagebox.h"
00060 #include "messagewin.h"
00061 #include "preferences.h"
00062 #include "prefdlg.h"
00063 #include "shellprocess.h"
00064 #include "traywindow.h"
00065 #include "kalarmapp.moc"
00066
00067 #include <netwm.h>
00068
00069
00070 static bool convWakeTime(const QCString timeParam, QDateTime&, bool& noTime);
00071 static bool convInterval(QCString timeParam, KARecurrence::Type&, int& timeInterval, bool allowMonthYear = true);
00072
00073
00074
00075
00076
00077
00078 static inline int maxLateness(int lateCancel)
00079 {
00080 static const int LATENESS_LEEWAY = 5;
00081 int lc = (lateCancel >= 1) ? (lateCancel - 1)*60 : 0;
00082 return Daemon::maxTimeSinceCheck() + LATENESS_LEEWAY + lc;
00083 }
00084
00085
00086 KAlarmApp* KAlarmApp::theInstance = 0;
00087 int KAlarmApp::mActiveCount = 0;
00088 int KAlarmApp::mFatalError = 0;
00089 QString KAlarmApp::mFatalMessage;
00090
00091
00092
00093
00094
00095 KAlarmApp::KAlarmApp()
00096 : KUniqueApplication(),
00097 mInitialised(false),
00098 mDcopHandler(new DcopHandler()),
00099 #ifdef OLD_DCOP
00100 mDcopHandlerOld(new DcopHandlerOld()),
00101 #endif
00102 mTrayWindow(0),
00103 mPendingQuit(false),
00104 mProcessingQueue(false),
00105 mCheckingSystemTray(false),
00106 mSessionClosingDown(false),
00107 mRefreshExpiredAlarms(false),
00108 mSpeechEnabled(false)
00109 {
00110 Preferences::initialise();
00111 Preferences::connect(SIGNAL(preferencesChanged()), this, SLOT(slotPreferencesChanged()));
00112 KCal::CalFormat::setApplication(aboutData()->programName(), AlarmCalendar::icalProductId());
00113 KARecurrence::setDefaultFeb29Type(Preferences::defaultFeb29Type());
00114
00115
00116 mHaveSystemTray = true;
00117
00118 if (AlarmCalendar::initialiseCalendars())
00119 {
00120 connect(AlarmCalendar::expiredCalendar(), SIGNAL(purged()), SLOT(slotExpiredPurged()));
00121
00122 KConfig* config = kapp->config();
00123 config->setGroup(QString::fromLatin1("General"));
00124 mNoSystemTray = config->readBoolEntry(QString::fromLatin1("NoSystemTray"), false);
00125 mSavedNoSystemTray = mNoSystemTray;
00126 mOldRunInSystemTray = wantRunInSystemTray();
00127 mDisableAlarmsIfStopped = mOldRunInSystemTray && !mNoSystemTray && Preferences::disableAlarmsIfStopped();
00128 mStartOfDay = Preferences::startOfDay();
00129 if (Preferences::hasStartOfDayChanged())
00130 mStartOfDay.setHMS(100,0,0);
00131 mPrefsExpiredColour = Preferences::expiredColour();
00132 mPrefsExpiredKeepDays = Preferences::expiredKeepDays();
00133 mPrefsShowTime = Preferences::showAlarmTime();
00134 mPrefsShowTimeTo = Preferences::showTimeToAlarm();
00135 }
00136
00137
00138 mSpeechEnabled = (KTrader::self()->query("DCOP/Text-to-Speech", "Name == 'KTTSD'").count() > 0);
00139 if (!mSpeechEnabled)
00140 kdDebug(5950) << "KAlarmApp::KAlarmApp(): speech synthesis disabled (KTTSD not found)" << endl;
00141
00142 QString korg = QString::fromLatin1("korganizer");
00143 mKOrganizerEnabled = !locate("exe", korg).isNull() || !KStandardDirs::findExe(korg).isNull();
00144 if (!mKOrganizerEnabled)
00145 kdDebug(5950) << "KAlarmApp::KAlarmApp(): KOrganizer options disabled (KOrganizer not found)" << endl;
00146 }
00147
00148
00149
00150 KAlarmApp::~KAlarmApp()
00151 {
00152 while (!mCommandProcesses.isEmpty())
00153 {
00154 ProcData* pd = mCommandProcesses.first();
00155 mCommandProcesses.pop_front();
00156 delete pd;
00157 }
00158 AlarmCalendar::terminateCalendars();
00159 }
00160
00161
00162
00163
00164
00165 KAlarmApp* KAlarmApp::getInstance()
00166 {
00167 if (!theInstance)
00168 {
00169 theInstance = new KAlarmApp;
00170
00171 if (mFatalError)
00172 theInstance->quitFatal();
00173 else
00174 {
00175
00176 Daemon::initialise();
00177 }
00178 }
00179 return theInstance;
00180 }
00181
00182
00183
00184
00185 bool KAlarmApp::restoreSession()
00186 {
00187 if (!isRestored())
00188 return false;
00189 if (mFatalError)
00190 {
00191 quitFatal();
00192 return false;
00193 }
00194
00195
00196 kdDebug(5950) << "KAlarmApp::restoreSession(): Restoring\n";
00197 ++mActiveCount;
00198 if (!initCheck(true))
00199 {
00200 --mActiveCount;
00201 quitIf(1, true);
00202 return true;
00203 }
00204 MainWindow* trayParent = 0;
00205 for (int i = 1; KMainWindow::canBeRestored(i); ++i)
00206 {
00207 QString type = KMainWindow::classNameOfToplevel(i);
00208 if (type == QString::fromLatin1("MainWindow"))
00209 {
00210 MainWindow* win = MainWindow::create(true);
00211 win->restore(i, false);
00212 if (win->isHiddenTrayParent())
00213 trayParent = win;
00214 else
00215 win->show();
00216 }
00217 else if (type == QString::fromLatin1("MessageWin"))
00218 {
00219 MessageWin* win = new MessageWin;
00220 win->restore(i, false);
00221 if (win->isValid())
00222 win->show();
00223 else
00224 delete win;
00225 }
00226 }
00227 initCheck();
00228
00229
00230
00231 if (Preferences::autostartTrayIcon()
00232 || MainWindow::count() && wantRunInSystemTray())
00233 {
00234 displayTrayIcon(true, trayParent);
00235
00236
00237 if (trayParent)
00238 trayParent->hide();
00239 }
00240
00241 --mActiveCount;
00242 quitIf(0);
00243 return true;
00244 }
00245
00246
00247
00248
00249
00250 int KAlarmApp::newInstance()
00251 {
00252 kdDebug(5950)<<"KAlarmApp::newInstance()\n";
00253 if (mFatalError)
00254 {
00255 quitFatal();
00256 return 1;
00257 }
00258 ++mActiveCount;
00259 int exitCode = 0;
00260 static bool firstInstance = true;
00261 bool dontRedisplay = false;
00262 if (!firstInstance || !isRestored())
00263 {
00264 QString usage;
00265 KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
00266
00267
00268
00269
00270
00271
00272
00273 do
00274 {
00275 #define USAGE(message) { usage = message; break; }
00276 if (args->isSet("stop"))
00277 {
00278
00279 kdDebug(5950)<<"KAlarmApp::newInstance(): stop\n";
00280 args->clear();
00281 if (!Daemon::stop())
00282 {
00283 exitCode = 1;
00284 break;
00285 }
00286 dontRedisplay = true;
00287 }
00288 else
00289 if (args->isSet("reset"))
00290 {
00291
00292
00293 kdDebug(5950)<<"KAlarmApp::newInstance(): reset\n";
00294 args->clear();
00295 Daemon::reset();
00296 dontRedisplay = true;
00297 }
00298 else
00299 if (args->isSet("tray"))
00300 {
00301
00302 kdDebug(5950)<<"KAlarmApp::newInstance(): tray\n";
00303 args->clear();
00304 if (!mHaveSystemTray)
00305 {
00306 exitCode = 1;
00307 break;
00308 }
00309 if (!initCheck())
00310 {
00311 exitCode = 1;
00312 break;
00313 }
00314 if (!displayTrayIcon(true))
00315 {
00316 exitCode = 1;
00317 break;
00318 }
00319 }
00320 else
00321 if (args->isSet("handleEvent") || args->isSet("triggerEvent") || args->isSet("cancelEvent") || args->isSet("calendarURL"))
00322 {
00323
00324 kdDebug(5950)<<"KAlarmApp::newInstance(): handle event\n";
00325 EventFunc function = EVENT_HANDLE;
00326 int count = 0;
00327 const char* option = 0;
00328 if (args->isSet("handleEvent")) { function = EVENT_HANDLE; option = "handleEvent"; ++count; }
00329 if (args->isSet("triggerEvent")) { function = EVENT_TRIGGER; option = "triggerEvent"; ++count; }
00330 if (args->isSet("cancelEvent")) { function = EVENT_CANCEL; option = "cancelEvent"; ++count; }
00331 if (!count)
00332 USAGE(i18n("%1 requires %2, %3 or %4").arg(QString::fromLatin1("--calendarURL")).arg(QString::fromLatin1("--handleEvent")).arg(QString::fromLatin1("--triggerEvent")).arg(QString::fromLatin1("--cancelEvent")))
00333 if (count > 1)
00334 USAGE(i18n("%1, %2, %3 mutually exclusive").arg(QString::fromLatin1("--handleEvent")).arg(QString::fromLatin1("--triggerEvent")).arg(QString::fromLatin1("--cancelEvent")));
00335 if (!initCheck(true))
00336 {
00337 exitCode = 1;
00338 break;
00339 }
00340 if (args->isSet("calendarURL"))
00341 {
00342 QString calendarUrl = args->getOption("calendarURL");
00343 if (KURL(calendarUrl).url() != AlarmCalendar::activeCalendar()->urlString())
00344 USAGE(i18n("%1: wrong calendar file").arg(QString::fromLatin1("--calendarURL")))
00345 }
00346 QString eventID = args->getOption(option);
00347 args->clear();
00348 if (eventID.startsWith(QString::fromLatin1("ad:")))
00349 {
00350
00351 eventID = eventID.mid(3);
00352 Daemon::queueEvent(eventID);
00353 }
00354 setUpDcop();
00355 if (!handleEvent(eventID, function))
00356 {
00357 exitCode = 1;
00358 break;
00359 }
00360 }
00361 else
00362 if (args->isSet("edit"))
00363 {
00364 QString eventID = args->getOption("edit");
00365 if (!initCheck())
00366 {
00367 exitCode = 1;
00368 break;
00369 }
00370 if (!KAlarm::edit(eventID))
00371 {
00372 USAGE(i18n("%1: Event %2 not found, or not editable").arg(QString::fromLatin1("--edit")).arg(eventID))
00373 exitCode = 1;
00374 break;
00375 }
00376 }
00377 else
00378 if (args->isSet("edit-new") || args->isSet("edit-new-preset"))
00379 {
00380 QString templ;
00381 if (args->isSet("edit-new-preset"))
00382 templ = args->getOption("edit-new-preset");
00383 if (!initCheck())
00384 {
00385 exitCode = 1;
00386 break;
00387 }
00388 KAlarm::editNew(templ);
00389 }
00390 else
00391 if (args->isSet("file") || args->isSet("exec") || args->isSet("mail") || args->count())
00392 {
00393
00394 KAEvent::Action action = KAEvent::MESSAGE;
00395 QCString alMessage;
00396 QCString alFromID;
00397 EmailAddressList alAddresses;
00398 QStringList alAttachments;
00399 QCString alSubject;
00400 if (args->isSet("file"))
00401 {
00402 kdDebug(5950)<<"KAlarmApp::newInstance(): file\n";
00403 if (args->isSet("exec"))
00404 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--exec")).arg(QString::fromLatin1("--file")))
00405 if (args->isSet("mail"))
00406 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--mail")).arg(QString::fromLatin1("--file")))
00407 if (args->count())
00408 USAGE(i18n("message incompatible with %1").arg(QString::fromLatin1("--file")))
00409 alMessage = args->getOption("file");
00410 action = KAEvent::FILE;
00411 }
00412 else if (args->isSet("exec"))
00413 {
00414 kdDebug(5950)<<"KAlarmApp::newInstance(): exec\n";
00415 if (args->isSet("mail"))
00416 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--mail")).arg(QString::fromLatin1("--exec")))
00417 alMessage = args->getOption("exec");
00418 int n = args->count();
00419 for (int i = 0; i < n; ++i)
00420 {
00421 alMessage += ' ';
00422 alMessage += args->arg(i);
00423 }
00424 action = KAEvent::COMMAND;
00425 }
00426 else if (args->isSet("mail"))
00427 {
00428 kdDebug(5950)<<"KAlarmApp::newInstance(): mail\n";
00429 if (args->isSet("subject"))
00430 alSubject = args->getOption("subject");
00431 if (args->isSet("from-id"))
00432 alFromID = args->getOption("from-id");
00433 QCStringList params = args->getOptionList("mail");
00434 for (QCStringList::Iterator i = params.begin(); i != params.end(); ++i)
00435 {
00436 QString addr = QString::fromLocal8Bit(*i);
00437 if (!KAMail::checkAddress(addr))
00438 USAGE(i18n("%1: invalid email address").arg(QString::fromLatin1("--mail")))
00439 alAddresses += KCal::Person(QString::null, addr);
00440 }
00441 params = args->getOptionList("attach");
00442 for (QCStringList::Iterator i = params.begin(); i != params.end(); ++i)
00443 alAttachments += QString::fromLocal8Bit(*i);
00444 alMessage = args->arg(0);
00445 action = KAEvent::EMAIL;
00446 }
00447 else
00448 {
00449 kdDebug(5950)<<"KAlarmApp::newInstance(): message\n";
00450 alMessage = args->arg(0);
00451 }
00452
00453 if (action != KAEvent::EMAIL)
00454 {
00455 if (args->isSet("subject"))
00456 USAGE(i18n("%1 requires %2").arg(QString::fromLatin1("--subject")).arg(QString::fromLatin1("--mail")))
00457 if (args->isSet("from-id"))
00458 USAGE(i18n("%1 requires %2").arg(QString::fromLatin1("--from-id")).arg(QString::fromLatin1("--mail")))
00459 if (args->isSet("attach"))
00460 USAGE(i18n("%1 requires %2").arg(QString::fromLatin1("--attach")).arg(QString::fromLatin1("--mail")))
00461 if (args->isSet("bcc"))
00462 USAGE(i18n("%1 requires %2").arg(QString::fromLatin1("--bcc")).arg(QString::fromLatin1("--mail")))
00463 }
00464
00465 bool alarmNoTime = false;
00466 QDateTime alarmTime, endTime;
00467 QColor bgColour = Preferences::defaultBgColour();
00468 QColor fgColour = Preferences::defaultFgColour();
00469 KARecurrence recurrence;
00470 int repeatCount = 0;
00471 int repeatInterval = 0;
00472 if (args->isSet("color"))
00473 {
00474
00475 QCString colourText = args->getOption("color");
00476 if (static_cast<const char*>(colourText)[0] == '0'
00477 && tolower(static_cast<const char*>(colourText)[1]) == 'x')
00478 colourText.replace(0, 2, "#");
00479 bgColour.setNamedColor(colourText);
00480 if (!bgColour.isValid())
00481 USAGE(i18n("Invalid %1 parameter").arg(QString::fromLatin1("--color")))
00482 }
00483 if (args->isSet("colorfg"))
00484 {
00485
00486 QCString colourText = args->getOption("colorfg");
00487 if (static_cast<const char*>(colourText)[0] == '0'
00488 && tolower(static_cast<const char*>(colourText)[1]) == 'x')
00489 colourText.replace(0, 2, "#");
00490 fgColour.setNamedColor(colourText);
00491 if (!fgColour.isValid())
00492 USAGE(i18n("Invalid %1 parameter").arg(QString::fromLatin1("--colorfg")))
00493 }
00494
00495 if (args->isSet("time"))
00496 {
00497 QCString dateTime = args->getOption("time");
00498 if (!convWakeTime(dateTime, alarmTime, alarmNoTime))
00499 USAGE(i18n("Invalid %1 parameter").arg(QString::fromLatin1("--time")))
00500 }
00501 else
00502 alarmTime = QDateTime::currentDateTime();
00503
00504 bool haveRecurrence = args->isSet("recurrence");
00505 if (haveRecurrence)
00506 {
00507 if (args->isSet("login"))
00508 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--login")).arg(QString::fromLatin1("--recurrence")))
00509 if (args->isSet("until"))
00510 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--until")).arg(QString::fromLatin1("--recurrence")))
00511 QCString rule = args->getOption("recurrence");
00512 recurrence.set(QString::fromLocal8Bit(static_cast<const char*>(rule)));
00513 }
00514 if (args->isSet("interval"))
00515 {
00516
00517 int count;
00518 if (args->isSet("login"))
00519 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--login")).arg(QString::fromLatin1("--interval")))
00520 bool ok;
00521 if (args->isSet("repeat"))
00522 {
00523 count = args->getOption("repeat").toInt(&ok);
00524 if (!ok || !count || count < -1 || (count < 0 && haveRecurrence))
00525 USAGE(i18n("Invalid %1 parameter").arg(QString::fromLatin1("--repeat")))
00526 }
00527 else if (haveRecurrence)
00528 USAGE(i18n("%1 requires %2").arg(QString::fromLatin1("--interval")).arg(QString::fromLatin1("--repeat")))
00529 else if (args->isSet("until"))
00530 {
00531 count = 0;
00532 QCString dateTime = args->getOption("until");
00533 if (!convWakeTime(dateTime, endTime, alarmNoTime))
00534 USAGE(i18n("Invalid %1 parameter").arg(QString::fromLatin1("--until")))
00535 if (endTime < alarmTime)
00536 USAGE(i18n("%1 earlier than %2").arg(QString::fromLatin1("--until")).arg(QString::fromLatin1("--time")))
00537 }
00538 else
00539 count = -1;
00540
00541
00542 int interval;
00543 KARecurrence::Type recurType;
00544 if (!convInterval(args->getOption("interval"), recurType, interval, !haveRecurrence)
00545 || interval < 0)
00546 USAGE(i18n("Invalid %1 parameter").arg(QString::fromLatin1("--interval")))
00547 if (alarmNoTime && recurType == KARecurrence::MINUTELY)
00548 USAGE(i18n("Invalid %1 parameter for date-only alarm").arg(QString::fromLatin1("--interval")))
00549
00550 if (haveRecurrence)
00551 {
00552
00553 int longestInterval = recurrence.longestInterval();
00554 if (count * interval > longestInterval)
00555 USAGE(i18n("Invalid %1 and %2 parameters: repetition is longer than %3 interval").arg(QString::fromLatin1("--interval")).arg(QString::fromLatin1("--repeat")).arg(QString::fromLatin1("--recurrence")));
00556 repeatCount = count;
00557 repeatInterval = interval;
00558 }
00559 else
00560 {
00561
00562
00563 recurrence.set(recurType, interval, count, DateTime(alarmTime, alarmNoTime), endTime);
00564 }
00565 }
00566 else
00567 {
00568 if (args->isSet("repeat"))
00569 USAGE(i18n("%1 requires %2").arg(QString::fromLatin1("--repeat")).arg(QString::fromLatin1("--interval")))
00570 if (args->isSet("until"))
00571 USAGE(i18n("%1 requires %2").arg(QString::fromLatin1("--until")).arg(QString::fromLatin1("--interval")))
00572 }
00573
00574 QCString audioFile;
00575 float audioVolume = -1;
00576 #ifdef WITHOUT_ARTS
00577 bool audioRepeat = false;
00578 #else
00579 bool audioRepeat = args->isSet("play-repeat");
00580 #endif
00581 if (audioRepeat || args->isSet("play"))
00582 {
00583
00584 if (audioRepeat && args->isSet("play"))
00585 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--play")).arg(QString::fromLatin1("--play-repeat")))
00586 if (args->isSet("beep"))
00587 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--beep")).arg(QString::fromLatin1(audioRepeat ? "--play-repeat" : "--play")))
00588 if (args->isSet("speak"))
00589 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--speak")).arg(QString::fromLatin1(audioRepeat ? "--play-repeat" : "--play")))
00590 audioFile = args->getOption(audioRepeat ? "play-repeat" : "play");
00591 #ifndef WITHOUT_ARTS
00592 if (args->isSet("volume"))
00593 {
00594 bool ok;
00595 int volumepc = args->getOption("volume").toInt(&ok);
00596 if (!ok || volumepc < 0 || volumepc > 100)
00597 USAGE(i18n("Invalid %1 parameter").arg(QString::fromLatin1("--volume")))
00598 audioVolume = static_cast<float>(volumepc) / 100;
00599 }
00600 #endif
00601 }
00602 #ifndef WITHOUT_ARTS
00603 else if (args->isSet("volume"))
00604 USAGE(i18n("%1 requires %2 or %3").arg(QString::fromLatin1("--volume")).arg(QString::fromLatin1("--play")).arg(QString::fromLatin1("--play-repeat")))
00605 #endif
00606 if (args->isSet("speak"))
00607 {
00608 if (args->isSet("beep"))
00609 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--beep")).arg(QString::fromLatin1("--speak")))
00610 if (!mSpeechEnabled)
00611 USAGE(i18n("%1 requires speech synthesis to be configured using KTTSD").arg(QString::fromLatin1("--speak")))
00612 }
00613 int reminderMinutes = 0;
00614 bool onceOnly = args->isSet("reminder-once");
00615 if (args->isSet("reminder") || onceOnly)
00616 {
00617
00618 if (onceOnly && args->isSet("reminder"))
00619 USAGE(i18n("%1 incompatible with %2").arg(QString::fromLatin1("--reminder")).arg(QString::fromLatin1("--reminder-once")))
00620 QString opt = onceOnly ? QString::fromLatin1("--reminder-once") : QString::fromLatin1("--reminder");
00621 if (args->isSet("exec"))
00622 USAGE(i18n("%1 incompatible with %2").arg(opt).arg(QString::fromLatin1("--exec")))
00623 if (args->isSet("mail"))
00624 USAGE(i18n("%1 incompatible with %2").arg(opt).arg(QString::fromLatin1("--mail")))
00625 KARecurrence::Type recurType;
00626 QString optval = args->getOption(onceOnly ? "reminder-once" : "reminder");
00627 bool ok = convInterval(args->getOption(onceOnly ? "reminder-once" : "reminder"), recurType, reminderMinutes);
00628 if (ok)
00629 {
00630 switch (recurType)
00631 {
00632 case KARecurrence::MINUTELY:
00633 if (alarmNoTime)
00634 USAGE(i18n("Invalid %1 parameter for date-only alarm").arg(opt))
00635 break;
00636 case KARecurrence::DAILY: reminderMinutes *= 1440; break;
00637 case KARecurrence::WEEKLY: reminderMinutes *= 7*1440; break;
00638 default: ok = false; break;
00639 }
00640 }
00641 if (!ok)
00642 USAGE(i18n("Invalid %1 parameter").arg(opt))
00643 }
00644
00645 int lateCancel = 0;
00646 if (args->isSet("late-cancel"))
00647 {
00648 KARecurrence::Type recurType;
00649 bool ok = convInterval(args->getOption("late-cancel"), recurType, lateCancel, false);
00650 if (!ok || lateCancel <= 0)
00651 USAGE(i18n("Invalid %1 parameter").arg(QString::fromLatin1("late-cancel")))
00652 }
00653 else if (args->isSet("auto-close"))
00654 USAGE(i18n("%1 requires %2").arg(QString::fromLatin1("--auto-close")).arg(QString::fromLatin1("--late-cancel")))
00655
00656 int flags = KAEvent::DEFAULT_FONT;
00657 if (args->isSet("ack-confirm"))
00658 flags |= KAEvent::CONFIRM_ACK;
00659 if (args->isSet("auto-close"))
00660 flags |= KAEvent::AUTO_CLOSE;
00661 if (args->isSet("beep"))
00662 flags |= KAEvent::BEEP;
00663 if (args->isSet("speak"))
00664 flags |= KAEvent::SPEAK;
00665 if (args->isSet("korganizer"))
00666 flags |= KAEvent::COPY_KORGANIZER;
00667 if (args->isSet("disable"))
00668 flags |= KAEvent::DISABLED;
00669 if (audioRepeat)
00670 flags |= KAEvent::REPEAT_SOUND;
00671 if (args->isSet("login"))
00672 flags |= KAEvent::REPEAT_AT_LOGIN;
00673 if (args->isSet("bcc"))
00674 flags |= KAEvent::EMAIL_BCC;
00675 if (alarmNoTime)
00676 flags |= KAEvent::ANY_TIME;
00677 args->clear();
00678
00679
00680 if (!initCheck())
00681 {
00682 exitCode = 1;
00683 break;
00684 }
00685 if (!scheduleEvent(action, alMessage, alarmTime, lateCancel, flags, bgColour, fgColour, QFont(), audioFile,
00686 audioVolume, reminderMinutes, recurrence, repeatInterval, repeatCount,
00687 alFromID, alAddresses, alSubject, alAttachments))
00688 {
00689 exitCode = 1;
00690 break;
00691 }
00692 }
00693 else
00694 {
00695
00696 kdDebug(5950)<<"KAlarmApp::newInstance(): interactive\n";
00697 if (args->isSet("ack-confirm"))
00698 usage += QString::fromLatin1("--ack-confirm ");
00699 if (args->isSet("attach"))
00700 usage += QString::fromLatin1("--attach ");
00701 if (args->isSet("auto-close"))
00702 usage += QString::fromLatin1("--auto-close ");
00703 if (args->isSet("bcc"))
00704 usage += QString::fromLatin1("--bcc ");
00705 if (args->isSet("beep"))
00706 usage += QString::fromLatin1("--beep ");
00707 if (args->isSet("color"))
00708 usage += QString::fromLatin1("--color ");
00709 if (args->isSet("colorfg"))
00710 usage += QString::fromLatin1("--colorfg ");
00711 if (args->isSet("disable"))
00712 usage += QString::fromLatin1("--disable ");
00713 if (args->isSet("from-id"))
00714 usage += QString::fromLatin1("--from-id ");
00715 if (args->isSet("korganizer"))
00716 usage += QString::fromLatin1("--korganizer ");
00717 if (args->isSet("late-cancel"))
00718 usage += QString::fromLatin1("--late-cancel ");
00719 if (args->isSet("login"))
00720 usage += QString::fromLatin1("--login ");
00721 if (args->isSet("play"))
00722 usage += QString::fromLatin1("--play ");
00723 #ifndef WITHOUT_ARTS
00724 if (args->isSet("play-repeat"))
00725 usage += QString::fromLatin1("--play-repeat ");
00726 #endif
00727 if (args->isSet("reminder"))
00728 usage += QString::fromLatin1("--reminder ");
00729 if (args->isSet("reminder-once"))
00730 usage += QString::fromLatin1("--reminder-once ");
00731 if (args->isSet("speak"))
00732 usage += QString::fromLatin1("--speak ");
00733 if (args->isSet("subject"))
00734 usage += QString::fromLatin1("--subject ");
00735 if (args->isSet("time"))
00736 usage += QString::fromLatin1("--time ");
00737 #ifndef WITHOUT_ARTS
00738 if (args->isSet("volume"))
00739 usage += QString::fromLatin1("--volume ");
00740 #endif
00741 if (!usage.isEmpty())
00742 {
00743 usage += i18n(": option(s) only valid with a message/%1/%2").arg(QString::fromLatin1("--file")).arg(QString::fromLatin1("--exec"));
00744 break;
00745 }
00746
00747 args->clear();
00748
00749
00750
00751
00752
00753 if (!initCheck(true))
00754 {
00755 exitCode = 1;
00756 break;
00757 }
00758
00759 (MainWindow::create())->show();
00760 }
00761 } while (0);
00762
00763 if (!usage.isEmpty())
00764 {
00765
00766
00767 std::cerr << usage.local8Bit().data()
00768 << i18n("\nUse --help to get a list of available command line options.\n").local8Bit().data();
00769 exitCode = 1;
00770 }
00771 }
00772 if (firstInstance && !dontRedisplay && !exitCode)
00773 redisplayAlarms();
00774
00775 --mActiveCount;
00776 firstInstance = false;
00777
00778
00779
00780
00781 quitIf(exitCode);
00782 return exitCode;
00783 }
00784
00785
00786
00787
00788 void KAlarmApp::quitIf(int exitCode, bool force)
00789 {
00790 if (force)
00791 {
00792
00793 MainWindow::closeAll();
00794 displayTrayIcon(false);
00795 if (MessageWin::instanceCount())
00796 return;
00797 }
00798 else
00799 {
00800
00801 mPendingQuit = false;
00802 if (mActiveCount > 0 || MessageWin::instanceCount())
00803 return;
00804 int mwcount = MainWindow::count();
00805 MainWindow* mw = mwcount ? MainWindow::firstWindow() : 0;
00806 if (mwcount > 1 || mwcount && (!mw->isHidden() || !mw->isTrayParent()))
00807 return;
00808
00809 if (mTrayWindow)
00810 {
00811
00812
00813 if (checkSystemTray())
00814 return;
00815 }
00816 if (!mDcopQueue.isEmpty() || !mCommandProcesses.isEmpty())
00817 {
00818
00819 mPendingQuit = true;
00820 mPendingQuitCode = exitCode;
00821 return;
00822 }
00823 }
00824
00825
00826 kdDebug(5950) << "KAlarmApp::quitIf(" << exitCode << "): quitting" << endl;
00827 exit(exitCode);
00828 }
00829
00830
00831
00832
00833
00834
00835 void KAlarmApp::doQuit(QWidget* parent)
00836 {
00837 kdDebug(5950) << "KAlarmApp::doQuit()\n";
00838 if (mDisableAlarmsIfStopped
00839 && MessageBox::warningContinueCancel(parent, KMessageBox::Cancel,
00840 i18n("Quitting will disable alarms\n(once any alarm message windows are closed)."),
00841 QString::null, KStdGuiItem::quit(), Preferences::QUIT_WARN
00842 ) != KMessageBox::Yes)
00843 return;
00844 quitIf(0, true);
00845 }
00846
00847
00848
00849
00850 void KAlarmApp::commitData(QSessionManager& sm)
00851 {
00852 mSessionClosingDown = true;
00853 KUniqueApplication::commitData(sm);
00854 mSessionClosingDown = false;
00855 }
00856
00857
00858
00859
00860
00861 void KAlarmApp::displayFatalError(const QString& message)
00862 {
00863 if (!mFatalError)
00864 {
00865 mFatalError = 1;
00866 mFatalMessage = message;
00867 if (theInstance)
00868 QTimer::singleShot(0, theInstance, SLOT(quitFatal()));
00869 }
00870 }
00871
00872
00873
00874
00875 void KAlarmApp::quitFatal()
00876 {
00877 switch (mFatalError)
00878 {
00879 case 0:
00880 case 2:
00881 return;
00882 case 1:
00883 mFatalError = 2;
00884 KMessageBox::error(0, mFatalMessage);
00885 mFatalError = 3;
00886
00887 case 3:
00888 if (theInstance)
00889 theInstance->quitIf(1, true);
00890 break;
00891 }
00892 QTimer::singleShot(1000, this, SLOT(quitFatal()));
00893 }
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 void KAlarmApp::processQueue()
00908 {
00909 if (mInitialised && !mProcessingQueue)
00910 {
00911 kdDebug(5950) << "KAlarmApp::processQueue()\n";
00912 mProcessingQueue = true;
00913
00914
00915 KAlarm::resetDaemonIfQueued();
00916
00917
00918 while (!mDcopQueue.isEmpty())
00919 {
00920 DcopQEntry& entry = mDcopQueue.first();
00921 if (entry.eventId.isEmpty())
00922 {
00923
00924 switch (entry.function)
00925 {
00926 case EVENT_TRIGGER:
00927 execAlarm(entry.event, entry.event.firstAlarm(), false);
00928 break;
00929 case EVENT_HANDLE:
00930 KAlarm::addEvent(entry.event, 0);
00931 break;
00932 case EVENT_CANCEL:
00933 break;
00934 }
00935 }
00936 else
00937 handleEvent(entry.eventId, entry.function);
00938 mDcopQueue.pop_front();
00939 }
00940
00941
00942 AlarmCalendar::expiredCalendar()->purgeIfQueued();
00943
00944
00945 if (mPendingQuit)
00946 quitIf(mPendingQuitCode);
00947
00948 mProcessingQueue = false;
00949 }
00950 }
00951
00952
00953
00954
00955
00956
00957
00958 void KAlarmApp::redisplayAlarms()
00959 {
00960 AlarmCalendar* cal = AlarmCalendar::displayCalendar();
00961 if (cal->isOpen())
00962 {
00963 KCal::Event::List events = cal->events();
00964 for (KCal::Event::List::ConstIterator it = events.begin(); it != events.end(); ++it)
00965 {
00966 KCal::Event* kcalEvent = *it;
00967 KAEvent event(*kcalEvent);
00968 event.setUid(KAEvent::ACTIVE);
00969 if (!MessageWin::findEvent(event.id()))
00970 {
00971
00972 kdDebug(5950) << "KAlarmApp::redisplayAlarms(): " << event.id() << endl;
00973 KAAlarm alarm = event.convertDisplayingAlarm();
00974 (new MessageWin(event, alarm, false, !alarm.repeatAtLogin()))->show();
00975 }
00976 }
00977 }
00978 }
00979
00980
00981
00982
00983 void KAlarmApp::removeWindow(TrayWindow*)
00984 {
00985 mTrayWindow = 0;
00986 quitIf();
00987 }
00988
00989
00990
00991
00992 bool KAlarmApp::displayTrayIcon(bool show, MainWindow* parent)
00993 {
00994 static bool creating = false;
00995 if (show)
00996 {
00997 if (!mTrayWindow && !creating)
00998 {
00999 if (!mHaveSystemTray)
01000 return false;
01001 if (!MainWindow::count() && wantRunInSystemTray())
01002 {
01003 creating = true;
01004 parent = MainWindow::create();
01005 creating = false;
01006 }
01007 mTrayWindow = new TrayWindow(parent ? parent : MainWindow::firstWindow());
01008 connect(mTrayWindow, SIGNAL(deleted()), SIGNAL(trayIconToggled()));
01009 mTrayWindow->show();
01010 emit trayIconToggled();
01011
01012
01013
01014 mCheckingSystemTray = true;
01015 mSavedNoSystemTray = mNoSystemTray;
01016 mNoSystemTray = false;
01017 QTimer::singleShot(0, this, SLOT(slotSystemTrayTimer()));
01018 }
01019 }
01020 else if (mTrayWindow)
01021 {
01022 delete mTrayWindow;
01023 mTrayWindow = 0;
01024 }
01025 return true;
01026 }
01027
01028
01029
01030
01031
01032
01033
01034
01035 void KAlarmApp::slotSystemTrayTimer()
01036 {
01037 mCheckingSystemTray = false;
01038 if (!checkSystemTray())
01039 quitIf(0);
01040 }
01041
01042
01043
01044
01045
01046
01047 bool KAlarmApp::checkSystemTray()
01048 {
01049 if (mCheckingSystemTray || !mTrayWindow)
01050 return true;
01051 if (mTrayWindow->inSystemTray() != !mSavedNoSystemTray)
01052 {
01053 kdDebug(5950) << "KAlarmApp::checkSystemTray(): changed -> " << mSavedNoSystemTray << endl;
01054 mNoSystemTray = mSavedNoSystemTray = !mSavedNoSystemTray;
01055
01056
01057
01058
01059
01060
01061 KConfig* config = kapp->config();
01062 config->setGroup(QString::fromLatin1("General"));
01063 config->writeEntry(QString::fromLatin1("NoSystemTray"), mNoSystemTray);
01064 config->sync();
01065
01066
01067 slotPreferencesChanged();
01068 }
01069 else
01070 {
01071 kdDebug(5950) << "KAlarmApp::checkSystemTray(): no change = " << !mSavedNoSystemTray << endl;
01072 mNoSystemTray = mSavedNoSystemTray;
01073 }
01074 return !mNoSystemTray;
01075 }
01076
01077
01078
01079
01080 MainWindow* KAlarmApp::trayMainWindow() const
01081 {
01082 return mTrayWindow ? mTrayWindow->assocMainWindow() : 0;
01083 }
01084
01085
01086
01087
01088 void KAlarmApp::slotPreferencesChanged()
01089 {
01090 bool newRunInSysTray = wantRunInSystemTray();
01091 if (newRunInSysTray != mOldRunInSystemTray)
01092 {
01093
01094 ++mActiveCount;
01095 MainWindow* win = mTrayWindow ? mTrayWindow->assocMainWindow() : 0;
01096 delete mTrayWindow;
01097 mTrayWindow = 0;
01098 mOldRunInSystemTray = newRunInSysTray;
01099 if (!newRunInSysTray)
01100 {
01101 if (win && win->isHidden())
01102 delete win;
01103 }
01104 displayTrayIcon(true);
01105 --mActiveCount;
01106 }
01107
01108 bool newDisableIfStopped = wantRunInSystemTray() && !mNoSystemTray && Preferences::disableAlarmsIfStopped();
01109 if (newDisableIfStopped != mDisableAlarmsIfStopped)
01110 {
01111 mDisableAlarmsIfStopped = newDisableIfStopped;
01112 Preferences::setQuitWarn(true);
01113 Daemon::reregister();
01114 }
01115
01116
01117 if (Preferences::startOfDay() != mStartOfDay)
01118 changeStartOfDay();
01119
01120
01121 KARecurrence::setDefaultFeb29Type(Preferences::defaultFeb29Type());
01122
01123 if (Preferences::showAlarmTime() != mPrefsShowTime
01124 || Preferences::showTimeToAlarm() != mPrefsShowTimeTo)
01125 {
01126
01127 MainWindow::updateTimeColumns(mPrefsShowTime, mPrefsShowTimeTo);
01128 mPrefsShowTime = Preferences::showAlarmTime();
01129 mPrefsShowTimeTo = Preferences::showTimeToAlarm();
01130 }
01131
01132 if (Preferences::expiredColour() != mPrefsExpiredColour)
01133 {
01134
01135 mRefreshExpiredAlarms = true;
01136 mPrefsExpiredColour = Preferences::expiredColour();
01137 }
01138
01139 if (Preferences::expiredKeepDays() != mPrefsExpiredKeepDays)
01140 {
01141
01142
01143 mPrefsExpiredKeepDays = Preferences::expiredKeepDays();
01144 AlarmCalendar::expiredCalendar()->setPurgeDays(mPrefsExpiredKeepDays);
01145 }
01146
01147 if (mRefreshExpiredAlarms)
01148 {
01149 mRefreshExpiredAlarms = false;
01150 MainWindow::updateExpired();
01151 }
01152 }
01153
01154
01155
01156
01157 void KAlarmApp::changeStartOfDay()
01158 {
01159 QTime sod = Preferences::startOfDay();
01160 DateTime::setStartOfDay(sod);
01161 AlarmCalendar* cal = AlarmCalendar::activeCalendar();
01162 if (KAEvent::adjustStartOfDay(cal->events()))
01163 cal->save();
01164 Preferences::updateStartOfDayCheck();
01165 mStartOfDay = sod;
01166 }
01167
01168
01169
01170
01171
01172 void KAlarmApp::slotExpiredPurged()
01173 {
01174 mRefreshExpiredAlarms = false;
01175 MainWindow::updateExpired();
01176 }
01177
01178
01179
01180
01181 bool KAlarmApp::wantRunInSystemTray() const
01182 {
01183 return Preferences::runInSystemTray() && mHaveSystemTray;
01184 }
01185
01186
01187
01188
01189
01190
01191 bool KAlarmApp::scheduleEvent(KAEvent::Action action, const QString& text, const QDateTime& dateTime,
01192 int lateCancel, int flags, const QColor& bg, const QColor& fg, const QFont& font,
01193 const QString& audioFile, float audioVolume, int reminderMinutes,
01194 const KARecurrence& recurrence, int repeatInterval, int repeatCount,
01195 const QString& mailFromID, const EmailAddressList& mailAddresses,
01196 const QString& mailSubject, const QStringList& mailAttachments)
01197 {
01198 kdDebug(5950) << "KAlarmApp::scheduleEvent(): " << text << endl;
01199 if (!dateTime.isValid())
01200 return false;
01201 QDateTime now = QDateTime::currentDateTime();
01202 if (lateCancel && dateTime < now.addSecs(-maxLateness(lateCancel)))
01203 return true;
01204 QDateTime alarmTime = dateTime;
01205
01206 alarmTime.setTime(QTime(alarmTime.time().hour(), alarmTime.time().minute(), 0));
01207
01208 KAEvent event(alarmTime, text, bg, fg, font, action, lateCancel, flags);
01209 if (reminderMinutes)
01210 {
01211 bool onceOnly = (reminderMinutes < 0);
01212 event.setReminder((onceOnly ? -reminderMinutes : reminderMinutes), onceOnly);
01213 }
01214 if (!audioFile.isEmpty())
01215 event.setAudioFile(audioFile, audioVolume, -1, 0);
01216 if (!mailAddresses.isEmpty())
01217 event.setEmail(mailFromID, mailAddresses, mailSubject, mailAttachments);
01218 event.setRecurrence(recurrence);
01219 event.setFirstRecurrence();
01220 event.setRepetition(repeatInterval, repeatCount - 1);
01221 if (alarmTime <= now)
01222 {
01223
01224
01225 if (!mInitialised)
01226 mDcopQueue.append(DcopQEntry(event, EVENT_TRIGGER));
01227 else
01228 execAlarm(event, event.firstAlarm(), false);
01229
01230 if (!event.recurs()
01231 || event.setNextOccurrence(now, true) == KAEvent::NO_OCCURRENCE)
01232 return true;
01233
01234 }
01235
01236
01237 mDcopQueue.append(DcopQEntry(event));
01238 if (mInitialised)
01239 QTimer::singleShot(0, this, SLOT(processQueue()));
01240 return true;
01241 }
01242
01243
01244
01245
01246
01247
01248
01249 bool KAlarmApp::handleEvent(const QString& urlString, const QString& eventID, EventFunc function)
01250 {
01251 kdDebug(5950) << "KAlarmApp::handleEvent(DCOP): " << eventID << endl;
01252 AlarmCalendar* cal = AlarmCalendar::activeCalendar();
01253 if (cal && KURL(urlString).url() != cal->urlString())
01254 {
01255 kdError(5950) << "KAlarmApp::handleEvent(DCOP): wrong calendar file " << urlString << endl;
01256 Daemon::eventHandled(eventID, false);
01257 return false;
01258 }
01259 mDcopQueue.append(DcopQEntry(function, eventID));
01260 if (mInitialised)
01261 QTimer::singleShot(0, this, SLOT(processQueue()));
01262 return true;
01263 }
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273 bool KAlarmApp::handleEvent(const QString& eventID, EventFunc function)
01274 {
01275 kdDebug(5950) << "KAlarmApp::handleEvent(): " << eventID << ", " << (function==EVENT_TRIGGER?"TRIGGER":function==EVENT_CANCEL?"CANCEL":function==EVENT_HANDLE?"HANDLE":"?") << endl;
01276 KCal::Event* kcalEvent = AlarmCalendar::activeCalendar()->event(eventID);
01277 if (!kcalEvent)
01278 {
01279 kdError(5950) << "KAlarmApp::handleEvent(): event ID not found: " << eventID << endl;
01280 Daemon::eventHandled(eventID, false);
01281 return false;
01282 }
01283 KAEvent event(*kcalEvent);
01284 switch (function)
01285 {
01286 case EVENT_CANCEL:
01287 KAlarm::deleteEvent(event, true);
01288 break;
01289
01290 case EVENT_TRIGGER:
01291 case EVENT_HANDLE:
01292 {
01293 QDateTime now = QDateTime::currentDateTime();
01294 DateTime repeatDT;
01295 bool updateCalAndDisplay = false;
01296 bool alarmToExecuteValid = false;
01297 KAAlarm alarmToExecute;
01298
01299
01300 for (KAAlarm alarm = event.firstAlarm(); alarm.valid(); alarm = event.nextAlarm(alarm))
01301 {
01302 if (alarm.deferred() && event.repeatCount()
01303 && repeatDT.isValid() && alarm.dateTime() > repeatDT)
01304 {
01305
01306
01307
01308
01309
01310 alarmToExecute = KAAlarm();
01311 alarmToExecuteValid = false;
01312 updateCalAndDisplay = false;
01313 }
01314
01315
01316
01317 int secs = alarm.dateTime().secsTo(now);
01318 if (secs < 0
01319 && (alarm.date() != now.date() || alarm.time() > now.time()))
01320 {
01321
01322 kdDebug(5950) << "KAlarmApp::handleEvent(): alarm " << alarm.type() << ": not due\n";
01323 continue;
01324 }
01325 if (alarm.repeatAtLogin())
01326 {
01327
01328
01329
01330
01331 kdDebug(5950) << "KAlarmApp::handleEvent(): REPEAT_AT_LOGIN\n";
01332 if (secs < maxLateness(1))
01333 continue;
01334
01335
01336
01337 if (alarmToExecute.valid())
01338 continue;
01339
01340
01341 alarm.setTime(now);
01342 }
01343 if (event.repeatCount() && alarm.type() == KAAlarm::MAIN_ALARM)
01344 {
01345
01346
01347 KAEvent::OccurType type = event.previousOccurrence(now.addSecs(1), repeatDT, true);
01348 if (type & KAEvent::OCCURRENCE_REPEAT)
01349 {
01350 alarm.setTime(repeatDT);
01351 secs = repeatDT.secsTo(now);
01352 }
01353 }
01354 if (alarm.lateCancel())
01355 {
01356
01357 kdDebug(5950) << "KAlarmApp::handleEvent(): LATE_CANCEL\n";
01358 bool late = false;
01359 bool cancel = false;
01360 if (alarm.dateTime().isDateOnly())
01361 {
01362
01363 int maxlate = alarm.lateCancel() / 1440;
01364 QDateTime limit(alarm.date().addDays(maxlate + 1), Preferences::startOfDay());
01365 if (now >= limit)
01366 {
01367
01368
01369 DateTime next;
01370 KAEvent::OccurType type = event.previousOccurrence(now, next, true);
01371 switch (type & ~KAEvent::OCCURRENCE_REPEAT)
01372 {
01373 case KAEvent::FIRST_OR_ONLY_OCCURRENCE:
01374 case KAEvent::RECURRENCE_DATE:
01375 case KAEvent::RECURRENCE_DATE_TIME:
01376 case KAEvent::LAST_RECURRENCE:
01377 limit.setDate(next.date().addDays(maxlate + 1));
01378 limit.setTime(Preferences::startOfDay());
01379 if (now >= limit)
01380 {
01381 if (type == KAEvent::LAST_RECURRENCE
01382 || type == KAEvent::FIRST_OR_ONLY_OCCURRENCE && !event.recurs())
01383 cancel = true;
01384 else
01385 late = true;
01386 }
01387 break;
01388 case KAEvent::NO_OCCURRENCE:
01389 default:
01390 late = true;
01391 break;
01392 }
01393 }
01394 }
01395 else
01396 {
01397
01398 int maxlate = maxLateness(alarm.lateCancel());
01399 if (secs > maxlate)
01400 {
01401
01402
01403 DateTime next;
01404 KAEvent::OccurType type = event.previousOccurrence(now, next, true);
01405 switch (type & ~KAEvent::OCCURRENCE_REPEAT)
01406 {
01407 case KAEvent::FIRST_OR_ONLY_OCCURRENCE:
01408 case KAEvent::RECURRENCE_DATE:
01409 case KAEvent::RECURRENCE_DATE_TIME:
01410 case KAEvent::LAST_RECURRENCE:
01411 if (next.dateTime().secsTo(now) > maxlate)
01412 {
01413 if (type == KAEvent::LAST_RECURRENCE
01414 || type == KAEvent::FIRST_OR_ONLY_OCCURRENCE && !event.recurs())
01415 cancel = true;
01416 else
01417 late = true;
01418 }
01419 break;
01420 case KAEvent::NO_OCCURRENCE:
01421 default:
01422 late = true;
01423 break;
01424 }
01425 }
01426 }
01427
01428 if (cancel)
01429 {
01430
01431 event.setArchive();
01432 cancelAlarm(event, alarm.type(), false);
01433 updateCalAndDisplay = true;
01434 continue;
01435 }
01436 if (late)
01437 {
01438
01439 rescheduleAlarm(event, alarm, false);
01440 updateCalAndDisplay = true;
01441 continue;
01442 }
01443 }
01444 if (!alarmToExecuteValid)
01445 {
01446 kdDebug(5950) << "KAlarmApp::handleEvent(): alarm " << alarm.type() << ": execute\n";
01447 alarmToExecute = alarm;
01448 alarmToExecuteValid = true;
01449 }
01450 else
01451 kdDebug(5950) << "KAlarmApp::handleEvent(): alarm " << alarm.type() << ": skip\n";
01452 }
01453
01454
01455
01456 if (alarmToExecute.valid())
01457 execAlarm(event, alarmToExecute, true, !alarmToExecute.repeatAtLogin());
01458 else
01459 {
01460 if (function == EVENT_TRIGGER)
01461 {
01462
01463
01464
01465 KAAlarm alarm = event.firstAlarm();
01466 if (alarm.valid())
01467 execAlarm(event, alarm, false);
01468 }
01469 if (updateCalAndDisplay)
01470 KAlarm::updateEvent(event, 0);
01471 else if (function != EVENT_TRIGGER)
01472 {
01473 kdDebug(5950) << "KAlarmApp::handleEvent(): no action\n";
01474 Daemon::eventHandled(eventID, false);
01475 }
01476 }
01477 break;
01478 }
01479 }
01480 return true;
01481 }
01482
01483
01484
01485
01486
01487
01488 void KAlarmApp::alarmShowing(KAEvent& event, KAAlarm::Type alarmType, const DateTime& alarmTime)
01489 {
01490 kdDebug(5950) << "KAlarmApp::alarmShowing(" << event.id() << ", " << KAAlarm::debugType(alarmType) << ")\n";
01491 KCal::Event* kcalEvent = AlarmCalendar::activeCalendar()->event(event.id());
01492 if (!kcalEvent)
01493 kdError(5950) << "KAlarmApp::alarmShowing(): event ID not found: " << event.id() << endl;
01494 else
01495 {
01496 KAAlarm alarm = event.alarm(alarmType);
01497 if (!alarm.valid())
01498 kdError(5950) << "KAlarmApp::alarmShowing(): alarm type not found: " << event.id() << ":" << alarmType << endl;
01499 else
01500 {
01501
01502 KAEvent dispEvent;
01503 dispEvent.setDisplaying(event, alarmType, alarmTime.dateTime());
01504 AlarmCalendar* cal = AlarmCalendar::displayCalendarOpen();
01505 if (cal)
01506 {
01507 cal->deleteEvent(dispEvent.id());
01508 cal->addEvent(dispEvent);
01509 cal->save();
01510 }
01511
01512 rescheduleAlarm(event, alarm, true);
01513 return;
01514 }
01515 }
01516 Daemon::eventHandled(event.id(), false);
01517 }
01518
01519
01520
01521
01522 void KAlarmApp::alarmCompleted(const KAEvent& event)
01523 {
01524 if (!event.postAction().isEmpty() && ShellProcess::authorised())
01525 {
01526 QString command = event.postAction();
01527 kdDebug(5950) << "KAlarmApp::alarmCompleted(" << event.id() << "): " << command << endl;
01528 doShellCommand(command, event, 0, ProcData::POST_ACTION);
01529 }
01530 }
01531
01532
01533
01534
01535
01536
01537 void KAlarmApp::rescheduleAlarm(KAEvent& event, const KAAlarm& alarm, bool updateCalAndDisplay)
01538 {
01539 kdDebug(5950) << "KAlarmApp::rescheduleAlarm()" << endl;
01540 bool update = false;
01541 bool updateDisplay = false;
01542 if (alarm.reminder() || alarm.deferred())
01543 {
01544
01545 event.removeExpiredAlarm(alarm.type());
01546 update = true;
01547 }
01548 else if (alarm.repeatAtLogin())
01549 {
01550
01551 if (updateCalAndDisplay && event.updated())
01552 update = true;
01553 }
01554 else
01555 {
01556 QDateTime now = QDateTime::currentDateTime();
01557 if (event.repeatCount() && event.mainEndRepeatTime() > now)
01558 updateDisplay = true;
01559 else
01560 {
01561
01562
01563 switch (event.setNextOccurrence(now))
01564 {
01565 case KAEvent::NO_OCCURRENCE:
01566
01567 cancelAlarm(event, alarm.type(), updateCalAndDisplay);
01568 break;
01569 case KAEvent::RECURRENCE_DATE:
01570 case KAEvent::RECURRENCE_DATE_TIME:
01571 case KAEvent::LAST_RECURRENCE:
01572
01573 if (updateCalAndDisplay)
01574 update = true;
01575 else
01576 {
01577 event.cancelCancelledDeferral();
01578 event.setUpdated();
01579 }
01580 break;
01581 case KAEvent::FIRST_OR_ONLY_OCCURRENCE:
01582
01583 default:
01584 break;
01585 }
01586 }
01587 if (event.deferred())
01588 {
01589
01590 event.removeExpiredAlarm(KAAlarm::DEFERRED_ALARM);
01591 update = true;
01592 }
01593 }
01594 if (update)
01595 {
01596 event.cancelCancelledDeferral();
01597 KAlarm::updateEvent(event, 0);
01598 }
01599 else if (updateDisplay)
01600 {
01601 Daemon::eventHandled(event.id(), false);
01602 AlarmListView::modifyEvent(event, 0);
01603 }
01604 }
01605
01606
01607
01608
01609
01610 void KAlarmApp::cancelAlarm(KAEvent& event, KAAlarm::Type alarmType, bool updateCalAndDisplay)
01611 {
01612 kdDebug(5950) << "KAlarmApp::cancelAlarm()" << endl;
01613 event.cancelCancelledDeferral();
01614 if (alarmType == KAAlarm::MAIN_ALARM && !event.displaying() && event.toBeArchived())
01615 {
01616
01617 QString id = event.id();
01618 KAlarm::addExpiredEvent(event);
01619 event.setEventID(id);
01620 }
01621 event.removeExpiredAlarm(alarmType);
01622 if (!event.alarmCount())
01623 KAlarm::deleteEvent(event, false);
01624 else if (updateCalAndDisplay)
01625 KAlarm::updateEvent(event, 0);
01626 }
01627
01628
01629
01630
01631
01632
01633
01634 void* KAlarmApp::execAlarm(KAEvent& event, const KAAlarm& alarm, bool reschedule, bool allowDefer, bool noPreAction)
01635 {
01636 if (!event.enabled())
01637 {
01638
01639 if (reschedule)
01640 rescheduleAlarm(event, alarm, true);
01641 return 0;
01642 }
01643
01644 void* result = (void*)1;
01645 event.setArchive();
01646 switch (alarm.action())
01647 {
01648 case KAAlarm::MESSAGE:
01649 case KAAlarm::FILE:
01650 {
01651
01652 MessageWin* win = MessageWin::findEvent(event.id());
01653 if (!win && !noPreAction && !event.preAction().isEmpty() && ShellProcess::authorised())
01654 {
01655
01656
01657 QString command = event.preAction();
01658 kdDebug(5950) << "KAlarmApp::execAlarm(): pre-DISPLAY command: " << command << endl;
01659 int flags = (reschedule ? ProcData::RESCHEDULE : 0) | (allowDefer ? ProcData::ALLOW_DEFER : 0);
01660 if (doShellCommand(command, event, &alarm, (flags | ProcData::PRE_ACTION)))
01661 return result;
01662
01663 }
01664 if (!event.enabled())
01665 delete win;
01666 else if (!win
01667 || !win->hasDefer() && !alarm.repeatAtLogin()
01668 || (win->alarmType() & KAAlarm::REMINDER_ALARM) && !(alarm.type() & KAAlarm::REMINDER_ALARM))
01669 {
01670
01671
01672
01673
01674 if (win)
01675 win->setRecreating();
01676 delete win;
01677 (new MessageWin(event, alarm, reschedule, allowDefer))->show();
01678 }
01679 else
01680 {
01681
01682 win->repeat(alarm);
01683 }
01684 break;
01685 }
01686 case KAAlarm::COMMAND:
01687 {
01688 int flags = event.commandXterm() ? ProcData::EXEC_IN_XTERM : 0;
01689 QString command = event.cleanText();
01690 if (event.commandScript())
01691 {
01692
01693 kdDebug(5950) << "KAlarmApp::execAlarm(): COMMAND: (script)" << endl;
01694 QString tmpfile = createTempScriptFile(command, false, event, alarm);
01695 if (tmpfile.isEmpty())
01696 {
01697 QStringList errmsgs(i18n("Error creating temporary script file"));
01698 (new MessageWin(event, alarm.dateTime(), errmsgs))->show();
01699 result = 0;
01700 }
01701 else
01702 result = doShellCommand(tmpfile, event, &alarm, (flags | ProcData::TEMP_FILE));
01703 }
01704 else
01705 {
01706 kdDebug(5950) << "KAlarmApp::execAlarm(): COMMAND: " << command << endl;
01707 result = doShellCommand(command, event, &alarm, flags);
01708 }
01709 if (reschedule)
01710 rescheduleAlarm(event, alarm, true);
01711 break;
01712 }
01713 case KAAlarm::EMAIL:
01714 {
01715 kdDebug(5950) << "KAlarmApp::execAlarm(): EMAIL to: " << event.emailAddresses(", ") << endl;
01716 QStringList errmsgs;
01717 if (!KAMail::send(event, errmsgs, (reschedule || allowDefer)))
01718 result = 0;
01719 if (!errmsgs.isEmpty())
01720 {
01721
01722 if (result)
01723 kdDebug(5950) << "KAlarmApp::execAlarm(): copy error: " << errmsgs[1] << endl;
01724 else
01725 kdDebug(5950) << "KAlarmApp::execAlarm(): failed: " << errmsgs[1] << endl;
01726 (new MessageWin(event, alarm.dateTime(), errmsgs))->show();
01727 }
01728 if (reschedule)
01729 rescheduleAlarm(event, alarm, true);
01730 break;
01731 }
01732 default:
01733 return 0;
01734 }
01735 return result;
01736 }
01737
01738
01739
01740
01741
01742
01743
01744 ShellProcess* KAlarmApp::doShellCommand(const QString& command, const KAEvent& event, const KAAlarm* alarm, int flags)
01745 {
01746 KProcess::Communication comms = KProcess::NoCommunication;
01747 QString cmd;
01748 QString tmpXtermFile;
01749 if (flags & ProcData::EXEC_IN_XTERM)
01750 {
01751
01752 cmd = Preferences::cmdXTermCommand();
01753 cmd.replace("%t", aboutData()->programName());
01754 if (cmd.find("%C") >= 0)
01755 {
01756
01757 if (flags & ProcData::TEMP_FILE)
01758 cmd.replace("%C", command);
01759 else
01760 {
01761 tmpXtermFile = createTempScriptFile(command, true, event, *alarm);
01762 if (tmpXtermFile.isEmpty())
01763 return 0;
01764 cmd.replace("%C", tmpXtermFile);
01765 }
01766 }
01767 else if (cmd.find("%W") >= 0)
01768 {
01769
01770
01771 tmpXtermFile = createTempScriptFile(command + QString::fromLatin1("\nsleep 86400\n"), true, event, *alarm);
01772 if (tmpXtermFile.isEmpty())
01773 return 0;
01774 cmd.replace("%W", tmpXtermFile);
01775 }
01776 else if (cmd.find("%w") >= 0)
01777 {
01778
01779
01780 QString exec = KShellProcess::quote(command + QString::fromLatin1("; sleep 86400"));
01781 cmd.replace("%w", exec);
01782 }
01783 else
01784 {
01785
01786
01787 QString exec = KShellProcess::quote(command);
01788 if (cmd.find("%c") >= 0)
01789 cmd.replace("%c", exec);
01790 else
01791 cmd.append(exec);
01792 }
01793 }
01794 else
01795 {
01796 cmd = command;
01797 comms = KProcess::AllOutput;
01798 }
01799 ShellProcess* proc = new ShellProcess(cmd);
01800 connect(proc, SIGNAL(shellExited(ShellProcess*)), SLOT(slotCommandExited(ShellProcess*)));
01801 QGuardedPtr<ShellProcess> logproc = 0;
01802 if (comms == KProcess::AllOutput && !event.logFile().isEmpty())
01803 {
01804
01805
01806 connect(proc, SIGNAL(receivedStdout(KProcess*,char*,int)), SLOT(slotCommandOutput(KProcess*,char*,int)));
01807 connect(proc, SIGNAL(receivedStderr(KProcess*,char*,int)), SLOT(slotCommandOutput(KProcess*,char*,int)));
01808 logproc = new ShellProcess(QString::fromLatin1("cat >>%1").arg(event.logFile()));
01809 connect(logproc, SIGNAL(shellExited(ShellProcess*)), SLOT(slotLogProcExited(ShellProcess*)));
01810 logproc->start(KProcess::Stdin);
01811 QCString heading;
01812 if (alarm && alarm->dateTime().isValid())
01813 {
01814 QString dateTime = alarm->dateTime().isDateOnly()
01815 ? KGlobal::locale()->formatDate(alarm->dateTime().date(), true)
01816 : KGlobal::locale()->formatDateTime(alarm->dateTime().dateTime());
01817 heading.sprintf("\n******* KAlarm %s *******\n", dateTime.latin1());
01818 }
01819 else
01820 heading = "\n******* KAlarm *******\n";
01821 logproc->writeStdin(heading, heading.length()+1);
01822 }
01823 ProcData* pd = new ProcData(proc, logproc, new KAEvent(event), (alarm ? new KAAlarm(*alarm) : 0), flags);
01824 if (flags & ProcData::TEMP_FILE)
01825 pd->tempFiles += command;
01826 if (!tmpXtermFile.isEmpty())
01827 pd->tempFiles += tmpXtermFile;
01828 mCommandProcesses.append(pd);
01829 if (proc->start(comms))
01830 return proc;
01831
01832
01833 kdError(5950) << "KAlarmApp::doShellCommand(): command failed to start\n";
01834 commandErrorMsg(proc, event, alarm, flags);
01835 mCommandProcesses.remove(pd);
01836 delete pd;
01837 return 0;
01838 }
01839
01840
01841
01842
01843
01844 QString KAlarmApp::createTempScriptFile(const QString& command, bool insertShell, const KAEvent& event, const KAAlarm& alarm)
01845 {
01846 KTempFile tmpFile(QString::null, QString::null, 0700);
01847 tmpFile.setAutoDelete(false);
01848 QTextStream* stream = tmpFile.textStream();
01849 if (!stream)
01850 kdError(5950) << "KAlarmApp::createTempScript(): Unable to create a temporary script file" << endl;
01851 else
01852 {
01853 if (insertShell)
01854 *stream << "#!" << ShellProcess::shellPath() << "\n";
01855 *stream << command;
01856 tmpFile.close();
01857 if (tmpFile.status())
01858 kdError(5950) << "KAlarmApp::createTempScript(): Error " << tmpFile.status() << " writing to temporary script file" << endl;
01859 else
01860 return tmpFile.name();
01861 }
01862
01863 QStringList errmsgs(i18n("Error creating temporary script file"));
01864 (new MessageWin(event, alarm.dateTime(), errmsgs))->show();
01865 return QString::null;
01866 }
01867
01868
01869
01870
01871 void KAlarmApp::slotCommandOutput(KProcess* proc, char* buffer, int bufflen)
01872 {
01873
01874
01875 for (QValueList<ProcData*>::Iterator it = mCommandProcesses.begin(); it != mCommandProcesses.end(); ++it)
01876 {
01877 ProcData* pd = *it;
01878 if (pd->process == proc && pd->logProcess)
01879 {
01880 pd->logProcess->writeStdin(buffer, bufflen);
01881 break;
01882 }
01883 }
01884 }
01885
01886
01887
01888
01889 void KAlarmApp::slotLogProcExited(ShellProcess* proc)
01890 {
01891
01892
01893 delete proc;
01894 }
01895
01896
01897
01898
01899 void KAlarmApp::slotCommandExited(ShellProcess* proc)
01900 {
01901 kdDebug(5950) << "KAlarmApp::slotCommandExited()\n";
01902
01903 for (QValueList<ProcData*>::Iterator it = mCommandProcesses.begin(); it != mCommandProcesses.end(); ++it)
01904 {
01905 ProcData* pd = *it;
01906 if (pd->process == proc)
01907 {
01908
01909 if (pd->logProcess)
01910 pd->logProcess->stdinExit();
01911
01912
01913 if (!proc->normalExit())
01914 {
01915 QString errmsg = proc->errorMessage();
01916 kdWarning(5950) << "KAlarmApp::slotCommandExited(" << pd->event->cleanText() << "): " << errmsg << endl;
01917 if (pd->messageBoxParent)
01918 {
01919
01920 QObjectList* dialogs = pd->messageBoxParent->queryList("KDialogBase", 0, false, true);
01921 KDialogBase* dialog = (KDialogBase*)dialogs->getFirst();
01922 delete dialog;
01923 delete dialogs;
01924 if (!pd->tempFile())
01925 {
01926 errmsg += "\n";
01927 errmsg += proc->command();
01928 }
01929 KMessageBox::error(pd->messageBoxParent, errmsg);
01930 }
01931 else
01932 commandErrorMsg(proc, *pd->event, pd->alarm, pd->flags);
01933 }
01934 if (pd->preAction())
01935 execAlarm(*pd->event, *pd->alarm, pd->reschedule(), pd->allowDefer(), true);
01936 mCommandProcesses.remove(it);
01937 delete pd;
01938 break;
01939 }
01940 }
01941
01942
01943 if (mPendingQuit && mCommandProcesses.isEmpty())
01944 quitIf(mPendingQuitCode);
01945 }
01946
01947
01948
01949
01950 void KAlarmApp::commandErrorMsg(const ShellProcess* proc, const KAEvent& event, const KAAlarm* alarm, int flags)
01951 {
01952 QStringList errmsgs;
01953 if (flags & ProcData::PRE_ACTION)
01954 errmsgs += i18n("Pre-alarm action:");
01955 else if (flags & ProcData::POST_ACTION)
01956 errmsgs += i18n("Post-alarm action:");
01957 errmsgs += proc->errorMessage();
01958 if (!(flags & ProcData::TEMP_FILE))
01959 errmsgs += proc->command();
01960 (new MessageWin(event, (alarm ? alarm->dateTime() : DateTime()), errmsgs))->show();
01961 }
01962
01963
01964
01965
01966 void KAlarmApp::commandMessage(ShellProcess* proc, QWidget* parent)
01967 {
01968
01969 for (QValueList<ProcData*>::Iterator it = mCommandProcesses.begin(); it != mCommandProcesses.end(); ++it)
01970 {
01971 ProcData* pd = *it;
01972 if (pd->process == proc)
01973 {
01974 pd->messageBoxParent = parent;
01975 break;
01976 }
01977 }
01978 }
01979
01980
01981
01982
01983 void KAlarmApp::setUpDcop()
01984 {
01985 if (!mInitialised)
01986 {
01987 mInitialised = true;
01988 Daemon::createDcopHandler();
01989 QTimer::singleShot(0, this, SLOT(processQueue()));
01990 }
01991 }
01992
01993
01994
01995
01996
01997 bool KAlarmApp::initCheck(bool calendarOnly)
01998 {
01999 bool startdaemon;
02000 AlarmCalendar* cal = AlarmCalendar::activeCalendar();
02001 if (!cal->isOpen())
02002 {
02003 kdDebug(5950) << "KAlarmApp::initCheck(): opening active calendar\n";
02004
02005
02006 if (!cal->open())
02007 return false;
02008
02009 if (!mStartOfDay.isValid())
02010 changeStartOfDay();
02011
02012
02013
02014
02015
02016
02017 AlarmCalendar::displayCalendar()->open();
02018
02019
02020
02021
02022
02023
02024 AlarmCalendar::expiredCalendar()->open();
02025 AlarmCalendar::expiredCalendar()->setPurgeDays(theInstance->mPrefsExpiredKeepDays);
02026
02027 startdaemon = true;
02028 }
02029 else
02030 startdaemon = !Daemon::isRegistered();
02031
02032 if (!calendarOnly)
02033 {
02034 setUpDcop();
02035 if (startdaemon)
02036 Daemon::start();
02037 }
02038 return true;
02039 }
02040
02041
02042
02043
02044
02045
02046 static bool convWakeTime(const QCString timeParam, QDateTime& dateTime, bool& noTime)
02047 {
02048 if (timeParam.length() > 19)
02049 return false;
02050 char timeStr[20];
02051 strcpy(timeStr, timeParam);
02052 int dt[5] = { -1, -1, -1, -1, -1 };
02053 char* s;
02054 char* end;
02055
02056 if ((s = strchr(timeStr, ':')) == 0)
02057 noTime = true;
02058 else
02059 {
02060 noTime = false;
02061 *s++ = 0;
02062 dt[4] = strtoul(s, &end, 10);
02063 if (end == s || *end || dt[4] >= 60)
02064 return false;
02065
02066 if ((s = strrchr(timeStr, '-')) == 0)
02067 s = timeStr;
02068 else
02069 *s++ = 0;
02070 dt[3] = strtoul(s, &end, 10);
02071 if (end == s || *end || dt[3] >= 24)
02072 return false;
02073 }
02074 bool dateSet = false;
02075 if (s != timeStr)
02076 {
02077 dateSet = true;
02078
02079 if ((s = strrchr(timeStr, '-')) == 0)
02080 s = timeStr;
02081 else
02082 *s++ = 0;
02083 dt[2] = strtoul(s, &end, 10);
02084 if (end == s || *end || dt[2] == 0 || dt[2] > 31)
02085 return false;
02086 if (s != timeStr)
02087 {
02088
02089 if ((s = strrchr(timeStr, '-')) == 0)
02090 s = timeStr;
02091 else
02092 *s++ = 0;
02093 dt[1] = strtoul(s, &end, 10);
02094 if (end == s || *end || dt[1] == 0 || dt[1] > 12)
02095 return false;
02096 if (s != timeStr)
02097 {
02098
02099 dt[0] = strtoul(timeStr, &end, 10);
02100 if (end == timeStr || *end)
02101 return false;
02102 }
02103 }
02104 }
02105
02106 QDate date(dt[0], dt[1], dt[2]);
02107 QTime time(0, 0, 0);
02108 if (noTime)
02109 {
02110
02111 if (dt[0] < 0)
02112 return false;
02113 }
02114 else
02115 {
02116
02117 QDateTime now = QDateTime::currentDateTime();
02118 if (dt[0] < 0)
02119 date.setYMD(now.date().year(),
02120 (dt[1] < 0 ? now.date().month() : dt[1]),
02121 (dt[2] < 0 ? now.date().day() : dt[2]));
02122 time.setHMS(dt[3], dt[4], 0);
02123 if (!dateSet && time < now.time())
02124 date = date.addDays(1);
02125 }
02126 if (!date.isValid())
02127 return false;
02128 dateTime.setDate(date);
02129 dateTime.setTime(time);
02130 return true;
02131 }
02132
02133
02134
02135
02136
02137 static bool convInterval(QCString timeParam, KARecurrence::Type& recurType, int& timeInterval, bool allowMonthYear)
02138 {
02139
02140 bool ok = true;
02141 uint interval = 0;
02142 bool negative = (timeParam[0] == '-');
02143 if (negative)
02144 timeParam = timeParam.right(1);
02145 uint length = timeParam.length();
02146 switch (timeParam[length - 1])
02147 {
02148 case 'Y':
02149 if (!allowMonthYear)
02150 ok = false;
02151 recurType = KARecurrence::ANNUAL_DATE;
02152 timeParam = timeParam.left(length - 1);
02153 break;
02154 case 'W':
02155 recurType = KARecurrence::WEEKLY;
02156 timeParam = timeParam.left(length - 1);
02157 break;
02158 case 'D':
02159 recurType = KARecurrence::DAILY;
02160 timeParam = timeParam.left(length - 1);
02161 break;
02162 case 'M':
02163 {
02164 int i = timeParam.find('H');
02165 if (i < 0)
02166 {
02167 if (!allowMonthYear)
02168 ok = false;
02169 recurType = KARecurrence::MONTHLY_DAY;
02170 timeParam = timeParam.left(length - 1);
02171 }
02172 else
02173 {
02174 recurType = KARecurrence::MINUTELY;
02175 interval = timeParam.left(i).toUInt(&ok) * 60;
02176 timeParam = timeParam.mid(i + 1, length - i - 2);
02177 }
02178 break;
02179 }
02180 default:
02181 recurType = KARecurrence::MINUTELY;
02182 break;
02183 }
02184 if (ok)
02185 interval += timeParam.toUInt(&ok);
02186 timeInterval = static_cast<int>(interval);
02187 if (negative)
02188 timeInterval = -timeInterval;
02189 return ok;
02190 }
02191
02192 KAlarmApp::ProcData::ProcData(ShellProcess* p, ShellProcess* logp, KAEvent* e, KAAlarm* a, int f)
02193 : process(p),
02194 logProcess(logp),
02195 event(e),
02196 alarm(a),
02197 messageBoxParent(0),
02198 flags(f)
02199 { }
02200
02201 KAlarmApp::ProcData::~ProcData()
02202 {
02203 while (!tempFiles.isEmpty())
02204 {
02205
02206 QFile f(tempFiles.first());
02207 f.remove();
02208 tempFiles.remove(tempFiles.begin());
02209 }
02210 delete process;
02211 delete event;
02212 delete alarm;
02213 }