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