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