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