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 <time.h>
00025 #include <ctype.h>
00026 #include <qcolor.h>
00027 #include <qregexp.h>
00028
00029 #include <klocale.h>
00030 #include <kdebug.h>
00031
00032 #include "alarmtext.h"
00033 #include "functions.h"
00034 #include "kalarmapp.h"
00035 #include "preferences.h"
00036 #include "alarmcalendar.h"
00037 #include "alarmevent.h"
00038 using namespace KCal;
00039
00040
00041 const QCString APPNAME("KALARM");
00042
00043
00044
00045
00046 static const QCString TYPE_PROPERTY("TYPE");
00047 static const QString FILE_TYPE = QString::fromLatin1("FILE");
00048 static const QString AT_LOGIN_TYPE = QString::fromLatin1("LOGIN");
00049 static const QString REMINDER_TYPE = QString::fromLatin1("REMINDER");
00050 static const QString REMINDER_ONCE_TYPE = QString::fromLatin1("REMINDER_ONCE");
00051 static const QString ARCHIVE_REMINDER_ONCE_TYPE = QString::fromLatin1("ONCE");
00052 static const QString TIME_DEFERRAL_TYPE = QString::fromLatin1("DEFERRAL");
00053 static const QString DATE_DEFERRAL_TYPE = QString::fromLatin1("DATE_DEFERRAL");
00054 static const QString DISPLAYING_TYPE = QString::fromLatin1("DISPLAYING");
00055 static const QString PRE_ACTION_TYPE = QString::fromLatin1("PRE");
00056 static const QString POST_ACTION_TYPE = QString::fromLatin1("POST");
00057
00058 static const QCString FONT_COLOUR_PROPERTY("FONTCOLOR");
00059
00060 static const QCString KMAIL_ID_PROPERTY("KMAILID");
00061
00062 static const QCString VOLUME_PROPERTY("VOLUME");
00063 static const QCString SPEAK_PROPERTY("SPEAK");
00064
00065
00066 static const QString DATE_ONLY_CATEGORY = QString::fromLatin1("DATE");
00067 static const QString EMAIL_BCC_CATEGORY = QString::fromLatin1("BCC");
00068 static const QString CONFIRM_ACK_CATEGORY = QString::fromLatin1("ACKCONF");
00069 static const QString LATE_CANCEL_CATEGORY = QString::fromLatin1("LATECANCEL;");
00070 static const QString AUTO_CLOSE_CATEGORY = QString::fromLatin1("LATECLOSE;");
00071 static const QString TEMPL_AFTER_TIME_CATEGORY = QString::fromLatin1("TMPLAFTTIME;");
00072 static const QString KMAIL_SERNUM_CATEGORY = QString::fromLatin1("KMAIL:");
00073 static const QString KORGANIZER_CATEGORY = QString::fromLatin1("KORG");
00074 static const QString ARCHIVE_CATEGORY = QString::fromLatin1("SAVE");
00075 static const QString ARCHIVE_CATEGORIES = QString::fromLatin1("SAVE:");
00076 static const QString LOG_CATEGORY = QString::fromLatin1("LOG:");
00077 static const QString xtermURL = QString::fromLatin1("xterm:");
00078
00079
00080 static const QString DISABLED_STATUS = QString::fromLatin1("DISABLED");
00081
00082 static const QString EXPIRED_UID = QString::fromLatin1("-exp-");
00083 static const QString DISPLAYING_UID = QString::fromLatin1("-disp-");
00084 static const QString TEMPLATE_UID = QString::fromLatin1("-tmpl-");
00085 static const QString KORGANIZER_UID = QString::fromLatin1("-korg-");
00086
00087 struct AlarmData
00088 {
00089 const Alarm* alarm;
00090 QString cleanText;
00091 QString emailFromKMail;
00092 EmailAddressList emailAddresses;
00093 QString emailSubject;
00094 QStringList emailAttachments;
00095 QDateTime dateTime;
00096 QFont font;
00097 QColor bgColour, fgColour;
00098 float soundVolume;
00099 float fadeVolume;
00100 int fadeSeconds;
00101 bool speak;
00102 KAAlarm::SubType type;
00103 KAAlarmEventBase::Type action;
00104 int displayingFlags;
00105 bool defaultFont;
00106 bool reminderOnceOnly;
00107 bool isEmailText;
00108 bool commandScript;
00109 int repeatCount;
00110 int repeatInterval;
00111 };
00112 typedef QMap<KAAlarm::SubType, AlarmData> AlarmMap;
00113
00114 static void setProcedureAlarm(Alarm*, const QString& commandLine);
00115
00116
00117
00118
00119
00120
00121
00122 inline void KAEvent::set_deferral(DeferType type)
00123 {
00124 if (type)
00125 {
00126 if (!mDeferral)
00127 ++mAlarmCount;
00128 }
00129 else
00130 {
00131 if (mDeferral)
00132 --mAlarmCount;
00133 }
00134 mDeferral = type;
00135 }
00136
00137 inline void KAEvent::set_reminder(int minutes)
00138 {
00139 if (!mReminderMinutes)
00140 ++mAlarmCount;
00141 mReminderMinutes = minutes;
00142 mArchiveReminderMinutes = 0;
00143 }
00144
00145 inline void KAEvent::set_archiveReminder()
00146 {
00147 if (mReminderMinutes)
00148 --mAlarmCount;
00149 mArchiveReminderMinutes = mReminderMinutes;
00150 mReminderMinutes = 0;
00151 }
00152
00153
00154 void KAEvent::copy(const KAEvent& event)
00155 {
00156 KAAlarmEventBase::copy(event);
00157 mTemplateName = event.mTemplateName;
00158 mAudioFile = event.mAudioFile;
00159 mPreAction = event.mPreAction;
00160 mPostAction = event.mPostAction;
00161 mStartDateTime = event.mStartDateTime;
00162 mSaveDateTime = event.mSaveDateTime;
00163 mAtLoginDateTime = event.mAtLoginDateTime;
00164 mDeferralTime = event.mDeferralTime;
00165 mDisplayingTime = event.mDisplayingTime;
00166 mDisplayingFlags = event.mDisplayingFlags;
00167 mReminderMinutes = event.mReminderMinutes;
00168 mArchiveReminderMinutes = event.mArchiveReminderMinutes;
00169 mRevision = event.mRevision;
00170 mRemainingRecurrences = event.mRemainingRecurrences;
00171 mAlarmCount = event.mAlarmCount;
00172 mDeferral = event.mDeferral;
00173 mLogFile = event.mLogFile;
00174 mCommandXterm = event.mCommandXterm;
00175 mKMailSerialNumber = event.mKMailSerialNumber;
00176 mCopyToKOrganizer = event.mCopyToKOrganizer;
00177 mReminderOnceOnly = event.mReminderOnceOnly;
00178 mMainExpired = event.mMainExpired;
00179 mArchiveRepeatAtLogin = event.mArchiveRepeatAtLogin;
00180 mArchive = event.mArchive;
00181 mTemplateAfterTime = event.mTemplateAfterTime;
00182 mEnabled = event.mEnabled;
00183 mUpdated = event.mUpdated;
00184 delete mRecurrence;
00185 if (event.mRecurrence)
00186 mRecurrence = new KARecurrence(*event.mRecurrence);
00187 else
00188 mRecurrence = 0;
00189 }
00190
00191
00192
00193
00194 void KAEvent::set(const Event& event)
00195 {
00196
00197 mEventID = event.uid();
00198 mRevision = event.revision();
00199 mTemplateName = QString::null;
00200 mLogFile = QString::null;
00201 mTemplateAfterTime = -1;
00202 mBeep = false;
00203 mSpeak = false;
00204 mEmailBcc = false;
00205 mCommandXterm = false;
00206 mCopyToKOrganizer = false;
00207 mConfirmAck = false;
00208 mArchive = false;
00209 mReminderOnceOnly = false;
00210 mAutoClose = false;
00211 mArchiveRepeatAtLogin = false;
00212 mArchiveReminderMinutes = 0;
00213 mLateCancel = 0;
00214 mKMailSerialNumber = 0;
00215 mBgColour = QColor(255, 255, 255);
00216 mFgColour = QColor(0, 0, 0);
00217 mDefaultFont = true;
00218 mEnabled = true;
00219 bool floats = false;
00220 const QStringList& cats = event.categories();
00221 for (unsigned int i = 0; i < cats.count(); ++i)
00222 {
00223 if (cats[i] == DATE_ONLY_CATEGORY)
00224 floats = true;
00225 else if (cats[i] == CONFIRM_ACK_CATEGORY)
00226 mConfirmAck = true;
00227 else if (cats[i] == EMAIL_BCC_CATEGORY)
00228 mEmailBcc = true;
00229 else if (cats[i] == ARCHIVE_CATEGORY)
00230 mArchive = true;
00231 else if (cats[i] == KORGANIZER_CATEGORY)
00232 mCopyToKOrganizer = true;
00233 else if (cats[i].startsWith(KMAIL_SERNUM_CATEGORY))
00234 mKMailSerialNumber = cats[i].mid(KMAIL_SERNUM_CATEGORY.length()).toULong();
00235 else if (cats[i].startsWith(LOG_CATEGORY))
00236 {
00237 QString logUrl = cats[i].mid(LOG_CATEGORY.length());
00238 if (logUrl == xtermURL)
00239 mCommandXterm = true;
00240 else
00241 mLogFile = logUrl;
00242 }
00243 else if (cats[i].startsWith(ARCHIVE_CATEGORIES))
00244 {
00245
00246 mArchive = true;
00247 QStringList list = QStringList::split(';', cats[i].mid(ARCHIVE_CATEGORIES.length()));
00248 for (unsigned int j = 0; j < list.count(); ++j)
00249 {
00250 if (list[j] == AT_LOGIN_TYPE)
00251 mArchiveRepeatAtLogin = true;
00252 else if (list[j] == ARCHIVE_REMINDER_ONCE_TYPE)
00253 mReminderOnceOnly = true;
00254 else
00255 {
00256 char ch;
00257 const char* cat = list[j].latin1();
00258 while ((ch = *cat) != 0 && (ch < '0' || ch > '9'))
00259 ++cat;
00260 if (ch)
00261 {
00262 mArchiveReminderMinutes = ch - '0';
00263 while ((ch = *++cat) >= '0' && ch <= '9')
00264 mArchiveReminderMinutes = mArchiveReminderMinutes * 10 + ch - '0';
00265 switch (ch)
00266 {
00267 case 'M': break;
00268 case 'H': mArchiveReminderMinutes *= 60; break;
00269 case 'D': mArchiveReminderMinutes *= 1440; break;
00270 }
00271 }
00272 }
00273 }
00274 }
00275 else if (cats[i].startsWith(TEMPL_AFTER_TIME_CATEGORY))
00276 {
00277 bool ok;
00278 mTemplateAfterTime = static_cast<int>(cats[i].mid(TEMPL_AFTER_TIME_CATEGORY.length()).toUInt(&ok));
00279 if (!ok)
00280 mTemplateAfterTime = -1;
00281 }
00282 else if (cats[i].startsWith(LATE_CANCEL_CATEGORY))
00283 {
00284 bool ok;
00285 mLateCancel = static_cast<int>(cats[i].mid(LATE_CANCEL_CATEGORY.length()).toUInt(&ok));
00286 if (!ok || !mLateCancel)
00287 mLateCancel = 1;
00288 }
00289 else if (cats[i].startsWith(AUTO_CLOSE_CATEGORY))
00290 {
00291 bool ok;
00292 mLateCancel = static_cast<int>(cats[i].mid(AUTO_CLOSE_CATEGORY.length()).toUInt(&ok));
00293 if (!ok || !mLateCancel)
00294 mLateCancel = 1;
00295 mAutoClose = true;
00296 }
00297 }
00298 mStartDateTime.set(event.dtStart(), floats);
00299 mNextMainDateTime = mStartDateTime;
00300 mSaveDateTime = event.created();
00301 if (uidStatus() == TEMPLATE)
00302 mTemplateName = event.summary();
00303 if (event.statusStr() == DISABLED_STATUS)
00304 mEnabled = false;
00305
00306
00307
00308 mActionType = T_MESSAGE;
00309 mMainExpired = true;
00310 mRepeatAtLogin = false;
00311 mDisplaying = false;
00312 mRepeatSound = false;
00313 mCommandScript = false;
00314 mDeferral = NO_DEFERRAL;
00315 mSoundVolume = -1;
00316 mFadeVolume = -1;
00317 mFadeSeconds = 0;
00318 mReminderMinutes = 0;
00319 mRepeatInterval = 0;
00320 mRepeatCount = 0;
00321 mText = "";
00322 mAudioFile = "";
00323 mPreAction = "";
00324 mPostAction = "";
00325 mEmailFromKMail = "";
00326 mEmailSubject = "";
00327 mEmailAddresses.clear();
00328 mEmailAttachments.clear();
00329 clearRecur();
00330
00331
00332 AlarmMap alarmMap;
00333 readAlarms(event, &alarmMap);
00334
00335
00336 AlarmMap::ConstIterator it = alarmMap.begin();
00337 mAlarmCount = 0;
00338 DateTime reminderTime;
00339 DateTime alTime;
00340 bool set = false;
00341 bool isEmailText = false;
00342 for ( ; it != alarmMap.end(); ++it)
00343 {
00344 const AlarmData& data = it.data();
00345 switch (data.type)
00346 {
00347 case KAAlarm::MAIN__ALARM:
00348 mMainExpired = false;
00349 alTime.set(data.dateTime, mStartDateTime.isDateOnly());
00350 if (data.repeatCount && data.repeatInterval)
00351 {
00352 mRepeatInterval = data.repeatInterval;
00353 mRepeatCount = data.repeatCount;
00354 }
00355 break;
00356 case KAAlarm::AT_LOGIN__ALARM:
00357 mRepeatAtLogin = true;
00358 mAtLoginDateTime = data.dateTime;
00359 alTime = mAtLoginDateTime;
00360 break;
00361 case KAAlarm::REMINDER__ALARM:
00362 reminderTime.set(data.dateTime, mStartDateTime.isDateOnly());
00363 alTime = reminderTime;
00364 break;
00365 case KAAlarm::DEFERRED_REMINDER_DATE__ALARM:
00366 case KAAlarm::DEFERRED_DATE__ALARM:
00367 mDeferral = (data.type == KAAlarm::DEFERRED_REMINDER_DATE__ALARM) ? REMINDER_DEFERRAL : NORMAL_DEFERRAL;
00368 mDeferralTime.set(data.dateTime, false);
00369 break;
00370 case KAAlarm::DEFERRED_REMINDER_TIME__ALARM:
00371 case KAAlarm::DEFERRED_TIME__ALARM:
00372 mDeferral = (data.type == KAAlarm::DEFERRED_REMINDER_TIME__ALARM) ? REMINDER_DEFERRAL : NORMAL_DEFERRAL;
00373 mDeferralTime.set(data.dateTime);
00374 break;
00375 case KAAlarm::DISPLAYING__ALARM:
00376 {
00377 mDisplaying = true;
00378 mDisplayingFlags = data.displayingFlags;
00379 bool dateOnly = (mDisplayingFlags & DEFERRAL) ? !(mDisplayingFlags & TIMED_FLAG)
00380 : mStartDateTime.isDateOnly();
00381 mDisplayingTime.set(data.dateTime, dateOnly);
00382 alTime = mDisplayingTime;
00383 break;
00384 }
00385 case KAAlarm::AUDIO__ALARM:
00386 mAudioFile = data.cleanText;
00387 mSpeak = data.speak && mAudioFile.isEmpty();
00388 mBeep = !mSpeak && mAudioFile.isEmpty();
00389 mSoundVolume = (!mBeep && !mSpeak) ? data.soundVolume : -1;
00390 mFadeVolume = (mSoundVolume >= 0 && data.fadeSeconds > 0) ? data.fadeVolume : -1;
00391 mFadeSeconds = (mFadeVolume >= 0) ? data.fadeSeconds : 0;
00392 mRepeatSound = (!mBeep && !mSpeak) && (data.repeatCount < 0);
00393 break;
00394 case KAAlarm::PRE_ACTION__ALARM:
00395 mPreAction = data.cleanText;
00396 break;
00397 case KAAlarm::POST_ACTION__ALARM:
00398 mPostAction = data.cleanText;
00399 break;
00400 case KAAlarm::INVALID__ALARM:
00401 default:
00402 break;
00403 }
00404
00405 if (data.reminderOnceOnly)
00406 mReminderOnceOnly = true;
00407 switch (data.type)
00408 {
00409 case KAAlarm::DEFERRED_REMINDER_DATE__ALARM:
00410 case KAAlarm::DEFERRED_DATE__ALARM:
00411 case KAAlarm::DEFERRED_REMINDER_TIME__ALARM:
00412 case KAAlarm::DEFERRED_TIME__ALARM:
00413 alTime = mDeferralTime;
00414 if (mNextMainDateTime == mDeferralTime)
00415 mDeferral = CANCEL_DEFERRAL;
00416
00417 case KAAlarm::MAIN__ALARM:
00418 case KAAlarm::AT_LOGIN__ALARM:
00419 case KAAlarm::REMINDER__ALARM:
00420 case KAAlarm::DISPLAYING__ALARM:
00421
00422
00423 if (!set)
00424 {
00425 mNextMainDateTime = alTime;
00426 mActionType = data.action;
00427 mText = (mActionType == T_COMMAND) ? data.cleanText.stripWhiteSpace() : data.cleanText;
00428 switch (data.action)
00429 {
00430 case T_MESSAGE:
00431 mFont = data.font;
00432 mDefaultFont = data.defaultFont;
00433 if (data.isEmailText)
00434 isEmailText = true;
00435
00436 case T_FILE:
00437 mBgColour = data.bgColour;
00438 mFgColour = data.fgColour;
00439 break;
00440 case T_COMMAND:
00441 mCommandScript = data.commandScript;
00442 break;
00443 case T_EMAIL:
00444 mEmailFromKMail = data.emailFromKMail;
00445 mEmailAddresses = data.emailAddresses;
00446 mEmailSubject = data.emailSubject;
00447 mEmailAttachments = data.emailAttachments;
00448 break;
00449 default:
00450 break;
00451 }
00452 set = true;
00453 }
00454 if (data.action == T_FILE && mActionType == T_MESSAGE)
00455 mActionType = T_FILE;
00456 ++mAlarmCount;
00457 break;
00458 case KAAlarm::AUDIO__ALARM:
00459 case KAAlarm::PRE_ACTION__ALARM:
00460 case KAAlarm::POST_ACTION__ALARM:
00461 case KAAlarm::INVALID__ALARM:
00462 default:
00463 break;
00464 }
00465 }
00466 if (!isEmailText)
00467 mKMailSerialNumber = 0;
00468 if (reminderTime.isValid())
00469 {
00470 mReminderMinutes = reminderTime.secsTo(mNextMainDateTime) / 60;
00471 if (mReminderMinutes)
00472 mArchiveReminderMinutes = 0;
00473 }
00474 if (mRepeatAtLogin)
00475 mArchiveRepeatAtLogin = false;
00476
00477 Recurrence* recur = event.recurrence();
00478 if (recur && recur->doesRecur())
00479 setRecurrence(*recur);
00480
00481 mUpdated = false;
00482 }
00483
00484
00485
00486
00487
00488 void KAEvent::readAlarms(const Event& event, void* almap)
00489 {
00490 AlarmMap* alarmMap = (AlarmMap*)almap;
00491 Alarm::List alarms = event.alarms();
00492 for (Alarm::List::ConstIterator it = alarms.begin(); it != alarms.end(); ++it)
00493 {
00494
00495 AlarmData data;
00496 readAlarm(**it, data);
00497 if (data.type != KAAlarm::INVALID__ALARM)
00498 alarmMap->insert(data.type, data);
00499 }
00500 }
00501
00502
00503
00504
00505
00506 void KAEvent::readAlarm(const Alarm& alarm, AlarmData& data)
00507 {
00508
00509 data.alarm = &alarm;
00510 data.dateTime = alarm.time();
00511 data.displayingFlags = 0;
00512 data.isEmailText = false;
00513 data.repeatCount = alarm.repeatCount();
00514 data.repeatInterval = alarm.snoozeTime();
00515 switch (alarm.type())
00516 {
00517 case Alarm::Procedure:
00518 data.action = T_COMMAND;
00519 data.cleanText = alarm.programFile();
00520 data.commandScript = data.cleanText.isEmpty();
00521 if (!alarm.programArguments().isEmpty())
00522 {
00523 if (!data.commandScript)
00524 data.cleanText += " ";
00525 data.cleanText += alarm.programArguments();
00526 }
00527 break;
00528 case Alarm::Email:
00529 data.action = T_EMAIL;
00530 data.emailFromKMail = alarm.customProperty(APPNAME, KMAIL_ID_PROPERTY);
00531 data.emailAddresses = alarm.mailAddresses();
00532 data.emailSubject = alarm.mailSubject();
00533 data.emailAttachments = alarm.mailAttachments();
00534 data.cleanText = alarm.mailText();
00535 break;
00536 case Alarm::Display:
00537 {
00538 data.action = T_MESSAGE;
00539 data.cleanText = AlarmText::fromCalendarText(alarm.text(), data.isEmailText);
00540 QString property = alarm.customProperty(APPNAME, FONT_COLOUR_PROPERTY);
00541 QStringList list = QStringList::split(QChar(';'), property, true);
00542 data.bgColour = QColor(255, 255, 255);
00543 data.fgColour = QColor(0, 0, 0);
00544 int n = list.count();
00545 if (n > 0)
00546 {
00547 if (!list[0].isEmpty())
00548 {
00549 QColor c(list[0]);
00550 if (c.isValid())
00551 data.bgColour = c;
00552 }
00553 if (n > 1 && !list[1].isEmpty())
00554 {
00555 QColor c(list[1]);
00556 if (c.isValid())
00557 data.fgColour = c;
00558 }
00559 }
00560 data.defaultFont = (n <= 2 || list[2].isEmpty());
00561 if (!data.defaultFont)
00562 data.font.fromString(list[2]);
00563 break;
00564 }
00565 case Alarm::Audio:
00566 {
00567 data.action = T_AUDIO;
00568 data.cleanText = alarm.audioFile();
00569 data.type = KAAlarm::AUDIO__ALARM;
00570 data.soundVolume = -1;
00571 data.fadeVolume = -1;
00572 data.fadeSeconds = 0;
00573 data.speak = !alarm.customProperty(APPNAME, SPEAK_PROPERTY).isNull();
00574 QString property = alarm.customProperty(APPNAME, VOLUME_PROPERTY);
00575 if (!property.isEmpty())
00576 {
00577 bool ok;
00578 float fadeVolume;
00579 int fadeSecs = 0;
00580 QStringList list = QStringList::split(QChar(';'), property, true);
00581 data.soundVolume = list[0].toFloat(&ok);
00582 if (!ok)
00583 data.soundVolume = -1;
00584 if (data.soundVolume >= 0 && list.count() >= 3)
00585 {
00586 fadeVolume = list[1].toFloat(&ok);
00587 if (ok)
00588 fadeSecs = static_cast<int>(list[2].toUInt(&ok));
00589 if (ok && fadeVolume >= 0 && fadeSecs > 0)
00590 {
00591 data.fadeVolume = fadeVolume;
00592 data.fadeSeconds = fadeSecs;
00593 }
00594 }
00595 }
00596 return;
00597 }
00598 case Alarm::Invalid:
00599 data.type = KAAlarm::INVALID__ALARM;
00600 return;
00601 }
00602
00603 bool atLogin = false;
00604 bool reminder = false;
00605 bool deferral = false;
00606 bool dateDeferral = false;
00607 data.reminderOnceOnly = false;
00608 data.type = KAAlarm::MAIN__ALARM;
00609 QString property = alarm.customProperty(APPNAME, TYPE_PROPERTY);
00610 QStringList types = QStringList::split(QChar(','), property);
00611 for (unsigned int i = 0; i < types.count(); ++i)
00612 {
00613 QString type = types[i];
00614 if (type == AT_LOGIN_TYPE)
00615 atLogin = true;
00616 else if (type == FILE_TYPE && data.action == T_MESSAGE)
00617 data.action = T_FILE;
00618 else if (type == REMINDER_TYPE)
00619 reminder = true;
00620 else if (type == REMINDER_ONCE_TYPE)
00621 reminder = data.reminderOnceOnly = true;
00622 else if (type == TIME_DEFERRAL_TYPE)
00623 deferral = true;
00624 else if (type == DATE_DEFERRAL_TYPE)
00625 dateDeferral = deferral = true;
00626 else if (type == DISPLAYING_TYPE)
00627 data.type = KAAlarm::DISPLAYING__ALARM;
00628 else if (type == PRE_ACTION_TYPE && data.action == T_COMMAND)
00629 data.type = KAAlarm::PRE_ACTION__ALARM;
00630 else if (type == POST_ACTION_TYPE && data.action == T_COMMAND)
00631 data.type = KAAlarm::POST_ACTION__ALARM;
00632 }
00633
00634 if (reminder)
00635 {
00636 if (data.type == KAAlarm::MAIN__ALARM)
00637 data.type = dateDeferral ? KAAlarm::DEFERRED_REMINDER_DATE__ALARM
00638 : deferral ? KAAlarm::DEFERRED_REMINDER_TIME__ALARM : KAAlarm::REMINDER__ALARM;
00639 else if (data.type == KAAlarm::DISPLAYING__ALARM)
00640 data.displayingFlags = dateDeferral ? REMINDER | DATE_DEFERRAL
00641 : deferral ? REMINDER | TIME_DEFERRAL : REMINDER;
00642 }
00643 else if (deferral)
00644 {
00645 if (data.type == KAAlarm::MAIN__ALARM)
00646 data.type = dateDeferral ? KAAlarm::DEFERRED_DATE__ALARM : KAAlarm::DEFERRED_TIME__ALARM;
00647 else if (data.type == KAAlarm::DISPLAYING__ALARM)
00648 data.displayingFlags = dateDeferral ? DATE_DEFERRAL : TIME_DEFERRAL;
00649 }
00650 if (atLogin)
00651 {
00652 if (data.type == KAAlarm::MAIN__ALARM)
00653 data.type = KAAlarm::AT_LOGIN__ALARM;
00654 else if (data.type == KAAlarm::DISPLAYING__ALARM)
00655 data.displayingFlags = REPEAT_AT_LOGIN;
00656 }
00657
00658 }
00659
00660
00661
00662
00663 void KAEvent::set(const QDateTime& dateTime, const QString& text, const QColor& bg, const QColor& fg,
00664 const QFont& font, Action action, int lateCancel, int flags)
00665 {
00666 clearRecur();
00667 mStartDateTime.set(dateTime, flags & ANY_TIME);
00668 mNextMainDateTime = mStartDateTime;
00669 switch (action)
00670 {
00671 case MESSAGE:
00672 case FILE:
00673 case COMMAND:
00674 case EMAIL:
00675 mActionType = (KAAlarmEventBase::Type)action;
00676 break;
00677 default:
00678 mActionType = T_MESSAGE;
00679 break;
00680 }
00681 mText = (mActionType == T_COMMAND) ? text.stripWhiteSpace() : text;
00682 mEventID = QString::null;
00683 mTemplateName = QString::null;
00684 mPreAction = QString::null;
00685 mPostAction = QString::null;
00686 mAudioFile = "";
00687 mSoundVolume = -1;
00688 mFadeVolume = -1;
00689 mTemplateAfterTime = -1;
00690 mFadeSeconds = 0;
00691 mBgColour = bg;
00692 mFgColour = fg;
00693 mFont = font;
00694 mAlarmCount = 1;
00695 mLateCancel = lateCancel;
00696 mDeferral = NO_DEFERRAL;
00697 set(flags);
00698 mKMailSerialNumber = 0;
00699 mReminderMinutes = 0;
00700 mArchiveReminderMinutes = 0;
00701 mRepeatInterval = 0;
00702 mRepeatCount = 0;
00703 mArchiveRepeatAtLogin = false;
00704 mReminderOnceOnly = false;
00705 mDisplaying = false;
00706 mMainExpired = false;
00707 mArchive = false;
00708 mUpdated = false;
00709 }
00710
00711
00712
00713
00714 void KAEvent::setCommand(const QDate& d, const QString& command, int lateCancel, int flags, const QString& logfile)
00715 {
00716 if (!logfile.isEmpty())
00717 flags &= ~EXEC_IN_XTERM;
00718 set(d, command, QColor(), QColor(), QFont(), COMMAND, lateCancel, flags | ANY_TIME);
00719 mLogFile = logfile;
00720 }
00721
00722 void KAEvent::setCommand(const QDateTime& dt, const QString& command, int lateCancel, int flags, const QString& logfile)
00723 {
00724 if (!logfile.isEmpty())
00725 flags &= ~EXEC_IN_XTERM;
00726 set(dt, command, QColor(), QColor(), QFont(), COMMAND, lateCancel, flags);
00727 mLogFile = logfile;
00728 }
00729
00730 void KAEvent::setLogFile(const QString& logfile)
00731 {
00732 mLogFile = logfile;
00733 if (!logfile.isEmpty())
00734 mCommandXterm = false;
00735 }
00736
00737
00738
00739
00740 void KAEvent::setEmail(const QDate& d, const QString& from, const EmailAddressList& addresses, const QString& subject,
00741 const QString& message, const QStringList& attachments, int lateCancel, int flags)
00742 {
00743 set(d, message, QColor(), QColor(), QFont(), EMAIL, lateCancel, flags | ANY_TIME);
00744 mEmailFromKMail = from;
00745 mEmailAddresses = addresses;
00746 mEmailSubject = subject;
00747 mEmailAttachments = attachments;
00748 }
00749
00750 void KAEvent::setEmail(const QDateTime& dt, const QString& from, const EmailAddressList& addresses, const QString& subject,
00751 const QString& message, const QStringList& attachments, int lateCancel, int flags)
00752 {
00753 set(dt, message, QColor(), QColor(), QFont(), EMAIL, lateCancel, flags);
00754 mEmailFromKMail = from;
00755 mEmailAddresses = addresses;
00756 mEmailSubject = subject;
00757 mEmailAttachments = attachments;
00758 }
00759
00760 void KAEvent::setEmail(const QString& from, const EmailAddressList& addresses, const QString& subject, const QStringList& attachments)
00761 {
00762 mEmailFromKMail = from;
00763 mEmailAddresses = addresses;
00764 mEmailSubject = subject;
00765 mEmailAttachments = attachments;
00766 }
00767
00768 void KAEvent::setAudioFile(const QString& filename, float volume, float fadeVolume, int fadeSeconds)
00769 {
00770 mAudioFile = filename;
00771 mSoundVolume = filename.isEmpty() ? -1 : volume;
00772 if (mSoundVolume >= 0)
00773 {
00774 mFadeVolume = (fadeSeconds > 0) ? fadeVolume : -1;
00775 mFadeSeconds = (mFadeVolume >= 0) ? fadeSeconds : 0;
00776 }
00777 else
00778 {
00779 mFadeVolume = -1;
00780 mFadeSeconds = 0;
00781 }
00782 mUpdated = true;
00783 }
00784
00785 void KAEvent::setReminder(int minutes, bool onceOnly)
00786 {
00787 set_reminder(minutes);
00788 mReminderOnceOnly = onceOnly;
00789 mUpdated = true;
00790 }
00791
00792
00793
00794
00795
00796 void KAEvent::adjustStartDate(const QDate& d)
00797 {
00798 if (mStartDateTime.isDateOnly())
00799 {
00800 mStartDateTime = d;
00801 if (mRecurrence)
00802 mRecurrence->setStartDate(d);
00803 }
00804 else
00805 {
00806 mStartDateTime.set(d, mStartDateTime.time());
00807 if (mRecurrence)
00808 mRecurrence->setStartDateTime(mStartDateTime.dateTime());
00809 }
00810 mNextMainDateTime = mStartDateTime;
00811 }
00812
00813
00814
00815
00816
00817 DateTime KAEvent::nextDateTime(bool includeReminders) const
00818 {
00819 if (includeReminders && mReminderMinutes)
00820 {
00821 if (!mReminderOnceOnly || mNextMainDateTime == mStartDateTime)
00822 return mNextMainDateTime.addSecs(-mReminderMinutes * 60);
00823 }
00824 DateTime dt = mNextMainDateTime;
00825 if (mRepeatCount)
00826 {
00827
00828
00829 QDateTime now = QDateTime::currentDateTime();
00830 if (now > mNextMainDateTime)
00831 {
00832 dt = mainEndRepeatTime();
00833 if (dt > now)
00834 {
00835 int repeatSecs = mRepeatInterval * 60;
00836 int repetition = (mNextMainDateTime.secsTo(now) + repeatSecs - 1) / repeatSecs;
00837 dt = mNextMainDateTime.addSecs(repetition * repeatSecs);
00838 }
00839 }
00840 }
00841 if (mDeferral > 0
00842 && (includeReminders || mDeferral != REMINDER_DEFERRAL))
00843 {
00844 if (mMainExpired)
00845 return mDeferralTime;
00846 return QMIN(mDeferralTime, dt);
00847 }
00848 return dt;
00849 }
00850
00851
00852
00853
00854 QString KAEvent::uid(const QString& id, Status status)
00855 {
00856 QString result = id;
00857 Status oldStatus;
00858 int i, len;
00859 if ((i = result.find(EXPIRED_UID)) > 0)
00860 {
00861 oldStatus = EXPIRED;
00862 len = EXPIRED_UID.length();
00863 }
00864 else if ((i = result.find(DISPLAYING_UID)) > 0)
00865 {
00866 oldStatus = DISPLAYING;
00867 len = DISPLAYING_UID.length();
00868 }
00869 else if ((i = result.find(TEMPLATE_UID)) > 0)
00870 {
00871 oldStatus = TEMPLATE;
00872 len = TEMPLATE_UID.length();
00873 }
00874 else if ((i = result.find(KORGANIZER_UID)) > 0)
00875 {
00876 oldStatus = KORGANIZER;
00877 len = KORGANIZER_UID.length();
00878 }
00879 else
00880 {
00881 oldStatus = ACTIVE;
00882 i = result.findRev('-');
00883 len = 1;
00884 }
00885 if (status != oldStatus && i > 0)
00886 {
00887 QString part;
00888 switch (status)
00889 {
00890 case ACTIVE: part = "-"; break;
00891 case EXPIRED: part = EXPIRED_UID; break;
00892 case DISPLAYING: part = DISPLAYING_UID; break;
00893 case TEMPLATE: part = TEMPLATE_UID; break;
00894 case KORGANIZER: part = KORGANIZER_UID; break;
00895 }
00896 result.replace(i, len, part);
00897 }
00898 return result;
00899 }
00900
00901
00902
00903
00904 KAEvent::Status KAEvent::uidStatus(const QString& uid)
00905 {
00906 if (uid.find(EXPIRED_UID) > 0)
00907 return EXPIRED;
00908 if (uid.find(DISPLAYING_UID) > 0)
00909 return DISPLAYING;
00910 if (uid.find(TEMPLATE_UID) > 0)
00911 return TEMPLATE;
00912 if (uid.find(KORGANIZER_UID) > 0)
00913 return KORGANIZER;
00914 return ACTIVE;
00915 }
00916
00917 void KAEvent::set(int flags)
00918 {
00919 KAAlarmEventBase::set(flags & ~READ_ONLY_FLAGS);
00920 mStartDateTime.setDateOnly(flags & ANY_TIME);
00921 set_deferral((flags & DEFERRAL) ? NORMAL_DEFERRAL : NO_DEFERRAL);
00922 mCommandXterm = flags & EXEC_IN_XTERM;
00923 mCopyToKOrganizer = flags & COPY_KORGANIZER;
00924 mEnabled = !(flags & DISABLED);
00925 mUpdated = true;
00926 }
00927
00928 int KAEvent::flags() const
00929 {
00930 return KAAlarmEventBase::flags()
00931 | (mStartDateTime.isDateOnly() ? ANY_TIME : 0)
00932 | (mDeferral > 0 ? DEFERRAL : 0)
00933 | (mCommandXterm ? EXEC_IN_XTERM : 0)
00934 | (mCopyToKOrganizer ? COPY_KORGANIZER : 0)
00935 | (mEnabled ? 0 : DISABLED);
00936 }
00937
00938
00939
00940
00941 Event* KAEvent::event() const
00942 {
00943 KCal::Event* ev = new KCal::Event;
00944 ev->setUid(mEventID);
00945 updateKCalEvent(*ev, false);
00946 return ev;
00947 }
00948
00949
00950
00951
00952
00953
00954
00955 bool KAEvent::updateKCalEvent(Event& ev, bool checkUid, bool original, bool cancelCancelledDefer) const
00956 {
00957 if (checkUid && !mEventID.isEmpty() && mEventID != ev.uid()
00958 || !mAlarmCount && (!original || !mMainExpired))
00959 return false;
00960
00961 checkRecur();
00962 bool readOnly = ev.isReadOnly();
00963 ev.setReadOnly(false);
00964 ev.setTransparency(Event::Transparent);
00965
00966
00967 QStringList cats;
00968 if (mStartDateTime.isDateOnly())
00969 cats.append(DATE_ONLY_CATEGORY);
00970 if (mConfirmAck)
00971 cats.append(CONFIRM_ACK_CATEGORY);
00972 if (mEmailBcc)
00973 cats.append(EMAIL_BCC_CATEGORY);
00974 if (mKMailSerialNumber)
00975 cats.append(QString("%1%2").arg(KMAIL_SERNUM_CATEGORY).arg(mKMailSerialNumber));
00976 if (mCopyToKOrganizer)
00977 cats.append(KORGANIZER_CATEGORY);
00978 if (mCommandXterm)
00979 cats.append(LOG_CATEGORY + xtermURL);
00980 else if (!mLogFile.isEmpty())
00981 cats.append(LOG_CATEGORY + mLogFile);
00982 if (mLateCancel)
00983 cats.append(QString("%1%2").arg(mAutoClose ? AUTO_CLOSE_CATEGORY : LATE_CANCEL_CATEGORY).arg(mLateCancel));
00984 if (!mTemplateName.isEmpty() && mTemplateAfterTime >= 0)
00985 cats.append(QString("%1%2").arg(TEMPL_AFTER_TIME_CATEGORY).arg(mTemplateAfterTime));
00986 if (mArchive && !original)
00987 {
00988 QStringList params;
00989 if (mArchiveReminderMinutes)
00990 {
00991 if (mReminderOnceOnly)
00992 params += ARCHIVE_REMINDER_ONCE_TYPE;
00993 char unit = 'M';
00994 int count = mArchiveReminderMinutes;
00995 if (count % 1440 == 0)
00996 {
00997 unit = 'D';
00998 count /= 1440;
00999 }
01000 else if (count % 60 == 0)
01001 {
01002 unit = 'H';
01003 count /= 60;
01004 }
01005 params += QString("%1%2").arg(count).arg(unit);
01006 }
01007 if (mArchiveRepeatAtLogin)
01008 params += AT_LOGIN_TYPE;
01009 if (params.count() > 0)
01010 {
01011 QString cat = ARCHIVE_CATEGORIES;
01012 cat += params.join(QString::fromLatin1(";"));
01013 cats.append(cat);
01014 }
01015 else
01016 cats.append(ARCHIVE_CATEGORY);
01017 }
01018 ev.setCategories(cats);
01019 ev.setCustomStatus(mEnabled ? QString::null : DISABLED_STATUS);
01020 ev.setRevision(mRevision);
01021 ev.clearAlarms();
01022
01023
01024
01025
01026
01027 ev.setDtStart(mStartDateTime.dateTime());
01028 ev.setFloats(false);
01029 ev.setHasEndDate(false);
01030
01031 DateTime dtMain = original ? mStartDateTime : mNextMainDateTime;
01032 DateTime ancillaryTime;
01033 if (!mMainExpired || original)
01034 {
01035
01036 initKcalAlarm(ev, dtMain, QStringList(), KAAlarm::MAIN_ALARM);
01037 ancillaryTime = dtMain;
01038 }
01039
01040
01041 if (mRepeatAtLogin || mArchiveRepeatAtLogin && original)
01042 {
01043 DateTime dtl;
01044 if (mArchiveRepeatAtLogin)
01045 dtl = mStartDateTime.dateTime().addDays(-1);
01046 else if (mAtLoginDateTime.isValid())
01047 dtl = mAtLoginDateTime;
01048 else if (mStartDateTime.isDateOnly())
01049 dtl = QDate::currentDate().addDays(-1);
01050 else
01051 dtl = QDateTime::currentDateTime();
01052 initKcalAlarm(ev, dtl, AT_LOGIN_TYPE);
01053 if (!ancillaryTime.isValid())
01054 ancillaryTime = dtl;
01055 }
01056 if (mReminderMinutes || mArchiveReminderMinutes && original)
01057 {
01058 int minutes = mReminderMinutes ? mReminderMinutes : mArchiveReminderMinutes;
01059 DateTime reminderTime = dtMain.addSecs(-minutes * 60);
01060 initKcalAlarm(ev, reminderTime, QStringList(mReminderOnceOnly ? REMINDER_ONCE_TYPE : REMINDER_TYPE));
01061 if (!ancillaryTime.isValid())
01062 ancillaryTime = reminderTime;
01063 }
01064 if (mDeferral > 0 || mDeferral == CANCEL_DEFERRAL && !cancelCancelledDefer)
01065 {
01066 QStringList list;
01067 if (mDeferralTime.isDateOnly())
01068 list += DATE_DEFERRAL_TYPE;
01069 else
01070 list += TIME_DEFERRAL_TYPE;
01071 if (mDeferral == REMINDER_DEFERRAL)
01072 list += mReminderOnceOnly ? REMINDER_ONCE_TYPE : REMINDER_TYPE;
01073 initKcalAlarm(ev, mDeferralTime, list);
01074 if (!ancillaryTime.isValid())
01075 ancillaryTime = mDeferralTime;
01076 }
01077 if (!mTemplateName.isEmpty())
01078 ev.setSummary(mTemplateName);
01079 else if (mDisplaying)
01080 {
01081 QStringList list(DISPLAYING_TYPE);
01082 if (mDisplayingFlags & REPEAT_AT_LOGIN)
01083 list += AT_LOGIN_TYPE;
01084 else if (mDisplayingFlags & DEFERRAL)
01085 {
01086 if (mDisplayingFlags & TIMED_FLAG)
01087 list += TIME_DEFERRAL_TYPE;
01088 else
01089 list += DATE_DEFERRAL_TYPE;
01090 }
01091 if (mDisplayingFlags & REMINDER)
01092 list += mReminderOnceOnly ? REMINDER_ONCE_TYPE : REMINDER_TYPE;
01093 initKcalAlarm(ev, mDisplayingTime, list);
01094 if (!ancillaryTime.isValid())
01095 ancillaryTime = mDisplayingTime;
01096 }
01097 if (mBeep || mSpeak || !mAudioFile.isEmpty())
01098 {
01099
01100 initKcalAlarm(ev, ancillaryTime, QStringList(), KAAlarm::AUDIO_ALARM);
01101 }
01102 if (!mPreAction.isEmpty())
01103 {
01104
01105 initKcalAlarm(ev, ancillaryTime, QStringList(PRE_ACTION_TYPE), KAAlarm::PRE_ACTION_ALARM);
01106 }
01107 if (!mPostAction.isEmpty())
01108 {
01109
01110 initKcalAlarm(ev, ancillaryTime, QStringList(POST_ACTION_TYPE), KAAlarm::POST_ACTION_ALARM);
01111 }
01112
01113 if (mRecurrence)
01114 mRecurrence->writeRecurrence(*ev.recurrence());
01115 else
01116 ev.clearRecurrence();
01117 if (mSaveDateTime.isValid())
01118 ev.setCreated(mSaveDateTime);
01119 ev.setReadOnly(readOnly);
01120 return true;
01121 }
01122
01123
01124
01125
01126
01127
01128 Alarm* KAEvent::initKcalAlarm(Event& event, const DateTime& dt, const QStringList& types, KAAlarm::Type type) const
01129 {
01130 QStringList alltypes;
01131 Alarm* alarm = event.newAlarm();
01132 alarm->setEnabled(true);
01133
01134
01135 alarm->setStartOffset(dt.isDateOnly() ? mStartDateTime.secsTo(dt)
01136 : mStartDateTime.dateTime().secsTo(dt.dateTime()));
01137
01138 switch (type)
01139 {
01140 case KAAlarm::AUDIO_ALARM:
01141 alarm->setAudioAlarm(mAudioFile);
01142 if (mSpeak)
01143 alarm->setCustomProperty(APPNAME, SPEAK_PROPERTY, QString::fromLatin1("Y"));
01144 if (mRepeatSound)
01145 {
01146 alarm->setRepeatCount(-1);
01147 alarm->setSnoozeTime(0);
01148 }
01149 if (!mAudioFile.isEmpty() && mSoundVolume >= 0)
01150 alarm->setCustomProperty(APPNAME, VOLUME_PROPERTY,
01151 QString::fromLatin1("%1;%2;%3").arg(QString::number(mSoundVolume, 'f', 2))
01152 .arg(QString::number(mFadeVolume, 'f', 2))
01153 .arg(mFadeSeconds));
01154 break;
01155 case KAAlarm::PRE_ACTION_ALARM:
01156 setProcedureAlarm(alarm, mPreAction);
01157 break;
01158 case KAAlarm::POST_ACTION_ALARM:
01159 setProcedureAlarm(alarm, mPostAction);
01160 break;
01161 case KAAlarm::MAIN_ALARM:
01162 alarm->setSnoozeTime(mRepeatInterval);
01163 alarm->setRepeatCount(mRepeatCount);
01164
01165 case KAAlarm::INVALID_ALARM:
01166 switch (mActionType)
01167 {
01168 case T_FILE:
01169 alltypes += FILE_TYPE;
01170
01171 case T_MESSAGE:
01172 alarm->setDisplayAlarm(AlarmText::toCalendarText(mText));
01173 alarm->setCustomProperty(APPNAME, FONT_COLOUR_PROPERTY,
01174 QString::fromLatin1("%1;%2;%3").arg(mBgColour.name())
01175 .arg(mFgColour.name())
01176 .arg(mDefaultFont ? QString::null : mFont.toString()));
01177 break;
01178 case T_COMMAND:
01179 if (mCommandScript)
01180 alarm->setProcedureAlarm("", mText);
01181 else
01182 setProcedureAlarm(alarm, mText);
01183 break;
01184 case T_EMAIL:
01185 alarm->setEmailAlarm(mEmailSubject, mText, mEmailAddresses, mEmailAttachments);
01186 if (!mEmailFromKMail.isEmpty())
01187 alarm->setCustomProperty(APPNAME, KMAIL_ID_PROPERTY, mEmailFromKMail);
01188 break;
01189 case T_AUDIO:
01190 break;
01191 }
01192 break;
01193 case KAAlarm::REMINDER_ALARM:
01194 case KAAlarm::DEFERRED_ALARM:
01195 case KAAlarm::DEFERRED_REMINDER_ALARM:
01196 case KAAlarm::AT_LOGIN_ALARM:
01197 case KAAlarm::DISPLAYING_ALARM:
01198 break;
01199 }
01200 alltypes += types;
01201 if (alltypes.count() > 0)
01202 alarm->setCustomProperty(APPNAME, TYPE_PROPERTY, alltypes.join(","));
01203 return alarm;
01204 }
01205
01206
01207
01208
01209 KAAlarm KAEvent::alarm(KAAlarm::Type type) const
01210 {
01211 checkRecur();
01212 KAAlarm al;
01213 if (mAlarmCount)
01214 {
01215 al.mEventID = mEventID;
01216 al.mActionType = mActionType;
01217 al.mText = mText;
01218 al.mBgColour = mBgColour;
01219 al.mFgColour = mFgColour;
01220 al.mFont = mFont;
01221 al.mDefaultFont = mDefaultFont;
01222 al.mBeep = mBeep;
01223 al.mSpeak = mSpeak;
01224 al.mSoundVolume = mSoundVolume;
01225 al.mFadeVolume = mFadeVolume;
01226 al.mFadeSeconds = mFadeSeconds;
01227 al.mRepeatSound = mRepeatSound;
01228 al.mConfirmAck = mConfirmAck;
01229 al.mRepeatAtLogin = false;
01230 al.mDeferred = false;
01231 al.mLateCancel = mLateCancel;
01232 al.mAutoClose = mAutoClose;
01233 al.mEmailBcc = mEmailBcc;
01234 al.mCommandScript = mCommandScript;
01235 if (mActionType == T_EMAIL)
01236 {
01237 al.mEmailFromKMail = mEmailFromKMail;
01238 al.mEmailAddresses = mEmailAddresses;
01239 al.mEmailSubject = mEmailSubject;
01240 al.mEmailAttachments = mEmailAttachments;
01241 }
01242 switch (type)
01243 {
01244 case KAAlarm::MAIN_ALARM:
01245 if (!mMainExpired)
01246 {
01247 al.mType = KAAlarm::MAIN__ALARM;
01248 al.mNextMainDateTime = mNextMainDateTime;
01249 al.mRepeatCount = mRepeatCount;
01250 al.mRepeatInterval = mRepeatInterval;
01251 }
01252 break;
01253 case KAAlarm::REMINDER_ALARM:
01254 if (mReminderMinutes)
01255 {
01256 al.mType = KAAlarm::REMINDER__ALARM;
01257 if (mReminderOnceOnly)
01258 al.mNextMainDateTime = mStartDateTime.addMins(-mReminderMinutes);
01259 else
01260 al.mNextMainDateTime = mNextMainDateTime.addMins(-mReminderMinutes);
01261 }
01262 break;
01263 case KAAlarm::DEFERRED_REMINDER_ALARM:
01264 if (mDeferral != REMINDER_DEFERRAL)
01265 break;
01266
01267 case KAAlarm::DEFERRED_ALARM:
01268 if (mDeferral > 0)
01269 {
01270 al.mType = static_cast<KAAlarm::SubType>((mDeferral == REMINDER_DEFERRAL ? KAAlarm::DEFERRED_REMINDER_ALARM : KAAlarm::DEFERRED_ALARM)
01271 | (mDeferralTime.isDateOnly() ? 0 : KAAlarm::TIMED_DEFERRAL_FLAG));
01272 al.mNextMainDateTime = mDeferralTime;
01273 al.mDeferred = true;
01274 }
01275 break;
01276 case KAAlarm::AT_LOGIN_ALARM:
01277 if (mRepeatAtLogin)
01278 {
01279 al.mType = KAAlarm::AT_LOGIN__ALARM;
01280 al.mNextMainDateTime = mAtLoginDateTime;
01281 al.mRepeatAtLogin = true;
01282 al.mLateCancel = 0;
01283 al.mAutoClose = false;
01284 }
01285 break;
01286 case KAAlarm::DISPLAYING_ALARM:
01287 if (mDisplaying)
01288 {
01289 al.mType = KAAlarm::DISPLAYING__ALARM;
01290 al.mNextMainDateTime = mDisplayingTime;
01291 al.mDisplaying = true;
01292 }
01293 break;
01294 case KAAlarm::AUDIO_ALARM:
01295 case KAAlarm::PRE_ACTION_ALARM:
01296 case KAAlarm::POST_ACTION_ALARM:
01297 case KAAlarm::INVALID_ALARM:
01298 default:
01299 break;
01300 }
01301 }
01302 return al;
01303 }
01304
01305
01306
01307
01308
01309
01310
01311
01312 KAAlarm KAEvent::firstAlarm() const
01313 {
01314 if (mAlarmCount)
01315 {
01316 if (!mMainExpired)
01317 return alarm(KAAlarm::MAIN_ALARM);
01318 return nextAlarm(KAAlarm::MAIN_ALARM);
01319 }
01320 return KAAlarm();
01321 }
01322
01323
01324
01325
01326
01327
01328 KAAlarm KAEvent::nextAlarm(KAAlarm::Type prevType) const
01329 {
01330 switch (prevType)
01331 {
01332 case KAAlarm::MAIN_ALARM:
01333 if (mReminderMinutes)
01334 return alarm(KAAlarm::REMINDER_ALARM);
01335
01336 case KAAlarm::REMINDER_ALARM:
01337
01338 if (mDeferral == REMINDER_DEFERRAL)
01339 return alarm(KAAlarm::DEFERRED_REMINDER_ALARM);
01340 if (mDeferral == NORMAL_DEFERRAL)
01341 return alarm(KAAlarm::DEFERRED_ALARM);
01342
01343 case KAAlarm::DEFERRED_REMINDER_ALARM:
01344 case KAAlarm::DEFERRED_ALARM:
01345 if (mRepeatAtLogin)
01346 return alarm(KAAlarm::AT_LOGIN_ALARM);
01347
01348 case KAAlarm::AT_LOGIN_ALARM:
01349 if (mDisplaying)
01350 return alarm(KAAlarm::DISPLAYING_ALARM);
01351
01352 case KAAlarm::DISPLAYING_ALARM:
01353
01354 case KAAlarm::AUDIO_ALARM:
01355 case KAAlarm::PRE_ACTION_ALARM:
01356 case KAAlarm::POST_ACTION_ALARM:
01357 case KAAlarm::INVALID_ALARM:
01358 default:
01359 break;
01360 }
01361 return KAAlarm();
01362 }
01363
01364
01365
01366
01367
01368
01369 void KAEvent::removeExpiredAlarm(KAAlarm::Type type)
01370 {
01371 int count = mAlarmCount;
01372 switch (type)
01373 {
01374 case KAAlarm::MAIN_ALARM:
01375 mAlarmCount = 0;
01376 break;
01377 case KAAlarm::AT_LOGIN_ALARM:
01378 if (mRepeatAtLogin)
01379 {
01380
01381 mArchiveRepeatAtLogin = true;
01382 mRepeatAtLogin = false;
01383 --mAlarmCount;
01384 }
01385 break;
01386 case KAAlarm::REMINDER_ALARM:
01387
01388 set_archiveReminder();
01389 break;
01390 case KAAlarm::DEFERRED_REMINDER_ALARM:
01391 case KAAlarm::DEFERRED_ALARM:
01392 set_deferral(NO_DEFERRAL);
01393 break;
01394 case KAAlarm::DISPLAYING_ALARM:
01395 if (mDisplaying)
01396 {
01397 mDisplaying = false;
01398 --mAlarmCount;
01399 }
01400 break;
01401 case KAAlarm::AUDIO_ALARM:
01402 case KAAlarm::PRE_ACTION_ALARM:
01403 case KAAlarm::POST_ACTION_ALARM:
01404 case KAAlarm::INVALID_ALARM:
01405 default:
01406 break;
01407 }
01408 if (mAlarmCount != count)
01409 mUpdated = true;
01410 }
01411
01412
01413
01414
01415
01416
01417
01418
01419 bool KAEvent::defer(const DateTime& dateTime, bool reminder, bool adjustRecurrence)
01420 {
01421 bool result = false;
01422 cancelCancelledDeferral();
01423 if (checkRecur() == KARecurrence::NO_RECUR)
01424 {
01425 if (mReminderMinutes || mDeferral == REMINDER_DEFERRAL || mArchiveReminderMinutes)
01426 {
01427 if (dateTime < mNextMainDateTime.dateTime())
01428 {
01429 set_deferral(REMINDER_DEFERRAL);
01430 mDeferralTime = dateTime;
01431 }
01432 else
01433 {
01434
01435 if (mReminderMinutes || mDeferral == REMINDER_DEFERRAL)
01436 set_deferral(NO_DEFERRAL);
01437 }
01438
01439 set_archiveReminder();
01440 }
01441 if (mDeferral != REMINDER_DEFERRAL)
01442 {
01443
01444 if (mRepeatCount && dateTime < mainEndRepeatTime())
01445 {
01446
01447 set_deferral(NORMAL_DEFERRAL);
01448 mDeferralTime = dateTime;
01449 result = true;
01450 }
01451 else
01452 {
01453
01454 mNextMainDateTime = mDeferralTime = dateTime;
01455 set_deferral(NORMAL_DEFERRAL);
01456 if (!mMainExpired)
01457 {
01458
01459 mMainExpired = true;
01460 --mAlarmCount;
01461 if (mRepeatAtLogin)
01462 {
01463
01464 mArchiveRepeatAtLogin = true;
01465 mRepeatAtLogin = false;
01466 --mAlarmCount;
01467 }
01468 }
01469 }
01470 }
01471 }
01472 else if (reminder)
01473 {
01474
01475 if (dateTime >= mNextMainDateTime.dateTime())
01476 set_deferral(NO_DEFERRAL);
01477 else
01478 {
01479 set_deferral(REMINDER_DEFERRAL);
01480 mDeferralTime = dateTime;
01481 }
01482 }
01483 else
01484 {
01485 mDeferralTime = dateTime;
01486 if (mDeferral <= 0)
01487 set_deferral(NORMAL_DEFERRAL);
01488 if (adjustRecurrence)
01489 {
01490 QDateTime now = QDateTime::currentDateTime();
01491 if (mainEndRepeatTime() < now)
01492 {
01493
01494
01495 if (!mMainExpired && setNextOccurrence(now, true) == NO_OCCURRENCE)
01496 {
01497 mMainExpired = true;
01498 --mAlarmCount;
01499 }
01500 }
01501 }
01502 }
01503 mUpdated = true;
01504 return result;
01505 }
01506
01507
01508
01509
01510 void KAEvent::cancelDefer()
01511 {
01512 if (mDeferral > 0)
01513 {
01514
01515
01516 if (mMainExpired
01517 || nextOccurrence(QDateTime::currentDateTime(), mDeferralTime, RETURN_REPETITION) == NO_OCCURRENCE)
01518 {
01519
01520 mDeferralTime = DateTime();
01521 set_deferral(NO_DEFERRAL);
01522 }
01523 else
01524 set_deferral(CANCEL_DEFERRAL);
01525 mUpdated = true;
01526 }
01527 }
01528
01529
01530
01531
01532 void KAEvent::cancelCancelledDeferral()
01533 {
01534 if (mDeferral == CANCEL_DEFERRAL)
01535 {
01536 mDeferralTime = DateTime();
01537 set_deferral(NO_DEFERRAL);
01538 }
01539 }
01540
01541
01542
01543
01544 DateTime KAEvent::deferralLimit(KAEvent::DeferLimitType* limitType) const
01545 {
01546 DeferLimitType ltype;
01547 DateTime endTime;
01548 bool recurs = (checkRecur() != KARecurrence::NO_RECUR);
01549 if (recurs || mRepeatCount)
01550 {
01551
01552
01553 DateTime reminderTime;
01554 QDateTime now = QDateTime::currentDateTime();
01555 OccurType type = nextOccurrence(now, endTime, RETURN_REPETITION);
01556 if (type & OCCURRENCE_REPEAT)
01557 ltype = LIMIT_REPETITION;
01558 else if (type == NO_OCCURRENCE)
01559 ltype = LIMIT_NONE;
01560 else if (mReminderMinutes && (now < (reminderTime = endTime.addMins(-mReminderMinutes))))
01561 {
01562 endTime = reminderTime;
01563 ltype = LIMIT_REMINDER;
01564 }
01565 else if (type == FIRST_OCCURRENCE && !recurs)
01566 ltype = LIMIT_REPETITION;
01567 else
01568 ltype = LIMIT_RECURRENCE;
01569 }
01570 else if ((mReminderMinutes || mDeferral == REMINDER_DEFERRAL || mArchiveReminderMinutes)
01571 && QDateTime::currentDateTime() < mNextMainDateTime.dateTime())
01572 {
01573
01574 endTime = mNextMainDateTime;
01575 ltype = LIMIT_REMINDER;
01576 }
01577 else
01578 ltype = LIMIT_NONE;
01579 if (ltype != LIMIT_NONE)
01580 endTime = endTime.addMins(-1);
01581 if (limitType)
01582 *limitType = ltype;
01583 return endTime;
01584 }
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595 bool KAEvent::setDisplaying(const KAEvent& event, KAAlarm::Type alarmType, const QDateTime& repeatAtLoginTime)
01596 {
01597 if (!mDisplaying
01598 && (alarmType == KAAlarm::MAIN_ALARM
01599 || alarmType == KAAlarm::REMINDER_ALARM
01600 || alarmType == KAAlarm::DEFERRED_REMINDER_ALARM
01601 || alarmType == KAAlarm::DEFERRED_ALARM
01602 || alarmType == KAAlarm::AT_LOGIN_ALARM))
01603 {
01604
01605 KAAlarm al = event.alarm(alarmType);
01606 if (al.valid())
01607 {
01608 *this = event;
01609 setUid(DISPLAYING);
01610 mDisplaying = true;
01611 mDisplayingTime = (alarmType == KAAlarm::AT_LOGIN_ALARM) ? repeatAtLoginTime : al.dateTime();
01612 switch (al.type())
01613 {
01614 case KAAlarm::AT_LOGIN__ALARM: mDisplayingFlags = REPEAT_AT_LOGIN; break;
01615 case KAAlarm::REMINDER__ALARM: mDisplayingFlags = REMINDER; break;
01616 case KAAlarm::DEFERRED_REMINDER_TIME__ALARM: mDisplayingFlags = REMINDER | TIME_DEFERRAL; break;
01617 case KAAlarm::DEFERRED_REMINDER_DATE__ALARM: mDisplayingFlags = REMINDER | DATE_DEFERRAL; break;
01618 case KAAlarm::DEFERRED_TIME__ALARM: mDisplayingFlags = TIME_DEFERRAL; break;
01619 case KAAlarm::DEFERRED_DATE__ALARM: mDisplayingFlags = DATE_DEFERRAL; break;
01620 default: mDisplayingFlags = 0; break;
01621 }
01622 ++mAlarmCount;
01623 mUpdated = true;
01624 return true;
01625 }
01626 }
01627 return false;
01628 }
01629
01630
01631
01632
01633 KAAlarm KAEvent::convertDisplayingAlarm() const
01634 {
01635 KAAlarm al;
01636 if (mDisplaying)
01637 {
01638 al = alarm(KAAlarm::DISPLAYING_ALARM);
01639 if (mDisplayingFlags & REPEAT_AT_LOGIN)
01640 {
01641 al.mRepeatAtLogin = true;
01642 al.mType = KAAlarm::AT_LOGIN__ALARM;
01643 }
01644 else if (mDisplayingFlags & DEFERRAL)
01645 {
01646 al.mDeferred = true;
01647 al.mType = (mDisplayingFlags == REMINDER | DATE_DEFERRAL) ? KAAlarm::DEFERRED_REMINDER_DATE__ALARM
01648 : (mDisplayingFlags == REMINDER | TIME_DEFERRAL) ? KAAlarm::DEFERRED_REMINDER_TIME__ALARM
01649 : (mDisplayingFlags == DATE_DEFERRAL) ? KAAlarm::DEFERRED_DATE__ALARM
01650 : KAAlarm::DEFERRED_TIME__ALARM;
01651 }
01652 else if (mDisplayingFlags & REMINDER)
01653 al.mType = KAAlarm::REMINDER__ALARM;
01654 else
01655 al.mType = KAAlarm::MAIN__ALARM;
01656 }
01657 return al;
01658 }
01659
01660
01661
01662
01663 void KAEvent::reinstateFromDisplaying(const KAEvent& dispEvent)
01664 {
01665 if (dispEvent.mDisplaying)
01666 {
01667 *this = dispEvent;
01668 setUid(ACTIVE);
01669 mDisplaying = false;
01670 --mAlarmCount;
01671 mUpdated = true;
01672 }
01673 }
01674
01675
01676
01677
01678
01679
01680 bool KAEvent::occursAfter(const QDateTime& preDateTime, bool includeRepetitions) const
01681 {
01682 QDateTime dt;
01683 if (checkRecur() != KARecurrence::NO_RECUR)
01684 {
01685 if (mRecurrence->duration() < 0)
01686 return true;
01687 dt = mRecurrence->endDateTime();
01688 }
01689 else
01690 dt = mNextMainDateTime.dateTime();
01691 if (mStartDateTime.isDateOnly())
01692 {
01693 QDate pre = preDateTime.date();
01694 if (preDateTime.time() < Preferences::startOfDay())
01695 pre = pre.addDays(-1);
01696 if (pre < dt.date())
01697 return true;
01698 }
01699 else if (preDateTime < dt)
01700 return true;
01701
01702 if (includeRepetitions && mRepeatCount)
01703 {
01704 dt.addSecs(mRepeatCount * mRepeatInterval * 60);
01705 if (preDateTime < dt)
01706 return true;
01707 }
01708 return false;
01709 }
01710
01711
01712
01713
01714
01715
01716 KAEvent::OccurType KAEvent::nextOccurrence(const QDateTime& preDateTime, DateTime& result,
01717 KAEvent::OccurOption includeRepetitions) const
01718 {
01719 int repeatSecs = 0;
01720 QDateTime pre = preDateTime;
01721 if (includeRepetitions != IGNORE_REPETITION)
01722 {
01723 if (!mRepeatCount)
01724 includeRepetitions = IGNORE_REPETITION;
01725 else
01726 {
01727 repeatSecs = mRepeatInterval * 60;
01728 pre = preDateTime.addSecs(-mRepeatCount * repeatSecs);
01729 }
01730 }
01731
01732 OccurType type;
01733 bool recurs = (checkRecur() != KARecurrence::NO_RECUR);
01734 if (recurs)
01735 {
01736 int remainingCount;
01737 type = nextRecurrence(pre, result, remainingCount);
01738 }
01739 else if (pre < mNextMainDateTime.dateTime())
01740 {
01741 result = mNextMainDateTime;
01742 type = FIRST_OCCURRENCE;
01743 }
01744 else
01745 {
01746 result = DateTime();
01747 type = NO_OCCURRENCE;
01748 }
01749
01750 if (type != NO_OCCURRENCE && result <= preDateTime)
01751 {
01752
01753 int repetition = result.secsTo(preDateTime) / repeatSecs + 1;
01754 DateTime repeatDT = result.addSecs(repetition * repeatSecs);
01755 if (recurs)
01756 {
01757
01758
01759
01760
01761 DateTime dt;
01762 OccurType newType = previousOccurrence(repeatDT.dateTime(), dt, false);
01763 if (dt > result)
01764 {
01765 type = newType;
01766 result = dt;
01767 if (includeRepetitions == RETURN_REPETITION && result <= preDateTime)
01768 {
01769
01770 int repetition = result.secsTo(preDateTime) / repeatSecs + 1;
01771 result = result.addSecs(repetition * repeatSecs);
01772 type = static_cast<OccurType>(type | OCCURRENCE_REPEAT);
01773 }
01774 return type;
01775 }
01776 }
01777 if (includeRepetitions == RETURN_REPETITION)
01778 {
01779
01780 result = repeatDT;
01781 type = static_cast<OccurType>(type | OCCURRENCE_REPEAT);
01782 }
01783 }
01784 return type;
01785 }
01786
01787
01788
01789
01790
01791
01792
01793
01794 KAEvent::OccurType KAEvent::previousOccurrence(const QDateTime& afterDateTime, DateTime& result, bool includeRepetitions) const
01795 {
01796 if (mStartDateTime >= afterDateTime)
01797 {
01798 result = QDateTime();
01799 return NO_OCCURRENCE;
01800 }
01801
01802
01803 OccurType type;
01804 if (checkRecur() == KARecurrence::NO_RECUR)
01805 {
01806 result = mStartDateTime;
01807 type = FIRST_OCCURRENCE;
01808 }
01809 else
01810 {
01811 QDateTime recurStart = mRecurrence->startDateTime();
01812 QDateTime after = afterDateTime;
01813 if (mStartDateTime.isDateOnly() && afterDateTime.time() > Preferences::startOfDay())
01814 after = after.addDays(1);
01815 QDateTime dt = mRecurrence->getPreviousDateTime(after);
01816 result.set(dt, mStartDateTime.isDateOnly());
01817 if (!dt.isValid())
01818 return NO_OCCURRENCE;
01819 if (dt == recurStart)
01820 type = FIRST_OCCURRENCE;
01821 else if (mRecurrence->getNextDateTime(dt).isValid())
01822 type = result.isDateOnly() ? RECURRENCE_DATE : RECURRENCE_DATE_TIME;
01823 else
01824 type = LAST_RECURRENCE;
01825 }
01826
01827 if (includeRepetitions && mRepeatCount)
01828 {
01829
01830
01831
01832 int repeatSecs = mRepeatInterval * 60;
01833 DateTime lastRepetition = result.addSecs(mRepeatCount * repeatSecs);
01834 if (lastRepetition < afterDateTime)
01835 {
01836 result = lastRepetition;
01837 return static_cast<OccurType>(type | OCCURRENCE_REPEAT);
01838 }
01839 int repetition = (result.dateTime().secsTo(afterDateTime) - 1) / repeatSecs;
01840 if (repetition > 0)
01841 {
01842 result = result.addSecs(repetition * repeatSecs);
01843 return static_cast<OccurType>(type | OCCURRENCE_REPEAT);
01844 }
01845 }
01846 return type;
01847 }
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857 KAEvent::OccurType KAEvent::setNextOccurrence(const QDateTime& preDateTime, bool includeRepetitions)
01858 {
01859 if (preDateTime < mNextMainDateTime.dateTime())
01860 return FIRST_OCCURRENCE;
01861 QDateTime pre = preDateTime;
01862 if (includeRepetitions)
01863 {
01864 if (!mRepeatCount)
01865 includeRepetitions = false;
01866 else
01867 pre = preDateTime.addSecs(-mRepeatCount * mRepeatInterval * 60);
01868 }
01869
01870 DateTime dt;
01871 OccurType type;
01872 if (pre < mNextMainDateTime.dateTime())
01873 {
01874 dt = mNextMainDateTime;
01875 type = FIRST_OCCURRENCE;
01876 }
01877 else if (checkRecur() != KARecurrence::NO_RECUR)
01878 {
01879 int remainingCount;
01880 type = nextRecurrence(pre, dt, remainingCount);
01881 if (type == NO_OCCURRENCE)
01882 return NO_OCCURRENCE;
01883 if (type != FIRST_OCCURRENCE && dt != mNextMainDateTime)
01884 {
01885
01886 mNextMainDateTime = dt;
01887 if (mRecurrence->duration() > 0)
01888 mRemainingRecurrences = remainingCount;
01889
01890 if (mDeferral == REMINDER_DEFERRAL || mArchiveReminderMinutes)
01891 {
01892 if (mReminderOnceOnly)
01893 {
01894 if (mReminderMinutes)
01895 set_archiveReminder();
01896 }
01897 else
01898 set_reminder(mArchiveReminderMinutes);
01899 }
01900 if (mDeferral == REMINDER_DEFERRAL)
01901 set_deferral(NO_DEFERRAL);
01902 mUpdated = true;
01903 }
01904 }
01905 else
01906 return NO_OCCURRENCE;
01907
01908 if (includeRepetitions && dt.dateTime() <= preDateTime)
01909 {
01910
01911 type = static_cast<OccurType>(type | OCCURRENCE_REPEAT);
01912
01913 if (mReminderMinutes)
01914 set_archiveReminder();
01915 if (mDeferral == REMINDER_DEFERRAL)
01916 set_deferral(NO_DEFERRAL);
01917 mUpdated = true;
01918 }
01919 return type;
01920 }
01921
01922
01923
01924
01925
01926
01927
01928 KAEvent::OccurType KAEvent::nextRecurrence(const QDateTime& preDateTime, DateTime& result, int& remainingCount) const
01929 {
01930 QDateTime recurStart = mRecurrence->startDateTime();
01931 QDateTime pre = preDateTime;
01932 if (mStartDateTime.isDateOnly() && preDateTime.time() < Preferences::startOfDay())
01933 pre = pre.addDays(-1);
01934 remainingCount = 0;
01935 QDateTime dt = mRecurrence->getNextDateTime(pre);
01936 result.set(dt, mStartDateTime.isDateOnly());
01937 if (!dt.isValid())
01938 return NO_OCCURRENCE;
01939 if (dt == recurStart)
01940 {
01941 remainingCount = mRecurrence->duration();
01942 return FIRST_OCCURRENCE;
01943 }
01944 remainingCount = mRecurrence->duration() - mRecurrence->durationTo(dt) + 1;
01945 if (remainingCount == 1)
01946 return LAST_RECURRENCE;
01947 return result.isDateOnly() ? RECURRENCE_DATE : RECURRENCE_DATE_TIME;
01948 }
01949
01950
01951
01952
01953 QString KAEvent::recurrenceText(bool brief) const
01954 {
01955 if (mRepeatAtLogin)
01956 return brief ? i18n("Brief form of 'At Login'", "Login") : i18n("At login");
01957 if (mRecurrence)
01958 {
01959 int frequency = mRecurrence->frequency();
01960 switch (mRecurrence->defaultRRuleConst()->recurrenceType())
01961 {
01962 case RecurrenceRule::rMinutely:
01963 if (frequency < 60)
01964 return i18n("1 Minute", "%n Minutes", frequency);
01965 else if (frequency % 60 == 0)
01966 return i18n("1 Hour", "%n Hours", frequency/60);
01967 else
01968 {
01969 QString mins;
01970 return i18n("Hours and Minutes", "%1H %2M").arg(QString::number(frequency/60)).arg(mins.sprintf("%02d", frequency%60));
01971 }
01972 case RecurrenceRule::rDaily:
01973 return i18n("1 Day", "%n Days", frequency);
01974 case RecurrenceRule::rWeekly:
01975 return i18n("1 Week", "%n Weeks", frequency);
01976 case RecurrenceRule::rMonthly:
01977 return i18n("1 Month", "%n Months", frequency);
01978 case RecurrenceRule::rYearly:
01979 return i18n("1 Year", "%n Years", frequency);
01980 case RecurrenceRule::rNone:
01981 default:
01982 break;
01983 }
01984 }
01985 return brief ? QString::null : i18n("None");
01986 }
01987
01988
01989
01990
01991 QString KAEvent::repetitionText(bool brief) const
01992 {
01993 if (mRepeatCount)
01994 {
01995 if (mRepeatInterval % 1440)
01996 {
01997 if (mRepeatInterval < 60)
01998 return i18n("1 Minute", "%n Minutes", mRepeatInterval);
01999 if (mRepeatInterval % 60 == 0)
02000 return i18n("1 Hour", "%n Hours", mRepeatInterval/60);
02001 QString mins;
02002 return i18n("Hours and Minutes", "%1H %2M").arg(QString::number(mRepeatInterval/60)).arg(mins.sprintf("%02d", mRepeatInterval%60));
02003 }
02004 if (mRepeatInterval % (7*1440))
02005 return i18n("1 Day", "%n Days", mRepeatInterval/1440);
02006 return i18n("1 Week", "%n Weeks", mRepeatInterval/(7*1440));
02007 }
02008 return brief ? QString::null : i18n("None");
02009 }
02010
02011
02012
02013
02014
02015
02016 void KAEvent::setFirstRecurrence()
02017 {
02018 switch (checkRecur())
02019 {
02020 case KARecurrence::NO_RECUR:
02021 case KARecurrence::MINUTELY:
02022 return;
02023 case KARecurrence::ANNUAL_DATE:
02024 case KARecurrence::ANNUAL_POS:
02025 if (mRecurrence->yearMonths().isEmpty())
02026 return;
02027 break;
02028 case KARecurrence::DAILY:
02029 case KARecurrence::WEEKLY:
02030 case KARecurrence::MONTHLY_POS:
02031 case KARecurrence::MONTHLY_DAY:
02032 break;
02033 }
02034 QDateTime recurStart = mRecurrence->startDateTime();
02035 if (mRecurrence->recursOn(recurStart.date()))
02036 return;
02037
02038
02039 int frequency = mRecurrence->frequency();
02040 mRecurrence->setFrequency(1);
02041 int remainingCount;
02042 DateTime next;
02043 nextRecurrence(mNextMainDateTime.dateTime(), next, remainingCount);
02044 if (!next.isValid())
02045 mRecurrence->setStartDateTime(recurStart);
02046 else
02047 {
02048 mRecurrence->setStartDateTime(next.dateTime());
02049 mStartDateTime = mNextMainDateTime = next;
02050 mUpdated = true;
02051 }
02052 mRecurrence->setFrequency(frequency);
02053 }
02054
02055
02056
02057
02058
02059 void KAEvent::setRecurrence(const KARecurrence& recurrence)
02060 {
02061 mUpdated = true;
02062 delete mRecurrence;
02063 if (recurrence.doesRecur())
02064 {
02065 mRecurrence = new KARecurrence(recurrence);
02066 mRecurrence->setStartDateTime(mStartDateTime.dateTime());
02067 mRecurrence->setFloats(mStartDateTime.isDateOnly());
02068 mRemainingRecurrences = mRecurrence->duration();
02069 if (mRemainingRecurrences > 0 && !isTemplate())
02070 mRemainingRecurrences -= mRecurrence->durationTo(mNextMainDateTime.dateTime()) - 1;
02071 }
02072 else
02073 {
02074 mRecurrence = 0;
02075 mRemainingRecurrences = 0;
02076 }
02077
02078
02079 setRepetition(mRepeatInterval, mRepeatCount);
02080 }
02081
02082
02083
02084
02085
02086
02087 bool KAEvent::setRepetition(int interval, int count)
02088 {
02089 mUpdated = true;
02090 mRepeatInterval = 0;
02091 mRepeatCount = 0;
02092 if (interval > 0 && count > 0 && !mRepeatAtLogin)
02093 {
02094 if (interval % 1440 && mStartDateTime.isDateOnly())
02095 return false;
02096 if (checkRecur() != KARecurrence::NO_RECUR)
02097 {
02098 int longestInterval = mRecurrence->longestInterval() - 1;
02099 if (interval * count > longestInterval)
02100 count = longestInterval / interval;
02101 }
02102 mRepeatInterval = interval;
02103 mRepeatCount = count;
02104 }
02105 return true;
02106 }
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117 bool KAEvent::setRecurMinutely(int freq, int count, const QDateTime& end)
02118 {
02119 return setRecur(RecurrenceRule::rMinutely, freq, count, end);
02120 }
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132 bool KAEvent::setRecurDaily(int freq, const QBitArray& days, int count, const QDate& end)
02133 {
02134 if (!setRecur(RecurrenceRule::rDaily, freq, count, end))
02135 return false;
02136 int n = 0;
02137 for (int i = 0; i < 7; ++i)
02138 {
02139 if (days.testBit(i))
02140 ++n;
02141 }
02142 if (n < 7)
02143 mRecurrence->addWeeklyDays(days);
02144 return true;
02145 }
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157 bool KAEvent::setRecurWeekly(int freq, const QBitArray& days, int count, const QDate& end)
02158 {
02159 if (!setRecur(RecurrenceRule::rWeekly, freq, count, end))
02160 return false;
02161 mRecurrence->addWeeklyDays(days);
02162 return true;
02163 }
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175 bool KAEvent::setRecurMonthlyByDate(int freq, const QValueList<int>& days, int count, const QDate& end)
02176 {
02177 if (!setRecur(RecurrenceRule::rMonthly, freq, count, end))
02178 return false;
02179 for (QValueListConstIterator<int> it = days.begin(); it != days.end(); ++it)
02180 mRecurrence->addMonthlyDate(*it);
02181 return true;
02182 }
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195 bool KAEvent::setRecurMonthlyByPos(int freq, const QValueList<MonthPos>& posns, int count, const QDate& end)
02196 {
02197 if (!setRecur(RecurrenceRule::rMonthly, freq, count, end))
02198 return false;
02199 for (QValueListConstIterator<MonthPos> it = posns.begin(); it != posns.end(); ++it)
02200 mRecurrence->addMonthlyPos((*it).weeknum, (*it).days);
02201 return true;
02202 }
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217 bool KAEvent::setRecurAnnualByDate(int freq, const QValueList<int>& months, int day, KARecurrence::Feb29Type feb29, int count, const QDate& end)
02218 {
02219 if (!setRecur(RecurrenceRule::rYearly, freq, count, end, feb29))
02220 return false;
02221 for (QValueListConstIterator<int> it = months.begin(); it != months.end(); ++it)
02222 mRecurrence->addYearlyMonth(*it);
02223 if (day)
02224 mRecurrence->addMonthlyDate(day);
02225 return true;
02226 }
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240 bool KAEvent::setRecurAnnualByPos(int freq, const QValueList<MonthPos>& posns, const QValueList<int>& months, int count, const QDate& end)
02241 {
02242 if (!setRecur(RecurrenceRule::rYearly, freq, count, end))
02243 return false;
02244 for (QValueListConstIterator<int> it = months.begin(); it != months.end(); ++it)
02245 mRecurrence->addYearlyMonth(*it);
02246 for (QValueListConstIterator<MonthPos> it = posns.begin(); it != posns.end(); ++it)
02247 mRecurrence->addYearlyPos((*it).weeknum, (*it).days);
02248 return true;
02249 }
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260 bool KAEvent::setRecur(RecurrenceRule::PeriodType recurType, int freq, int count, const QDateTime& end, KARecurrence::Feb29Type feb29)
02261 {
02262 if (count >= -1 && (count || end.date().isValid()))
02263 {
02264 if (!mRecurrence)
02265 mRecurrence = new KARecurrence;
02266 if (mRecurrence->init(recurType, freq, count, mNextMainDateTime, end, feb29))
02267 {
02268 mUpdated = true;
02269 mRemainingRecurrences = count;
02270 return true;
02271 }
02272 }
02273 clearRecur();
02274 return false;
02275 }
02276
02277
02278
02279
02280 void KAEvent::clearRecur()
02281 {
02282 mUpdated = true;
02283 delete mRecurrence;
02284 mRecurrence = 0;
02285 mRemainingRecurrences = 0;
02286 }
02287
02288
02289
02290
02291
02292
02293 KARecurrence::Type KAEvent::checkRecur() const
02294 {
02295 if (mRecurrence)
02296 {
02297 KARecurrence::Type type = mRecurrence->type();
02298 switch (type)
02299 {
02300 case KARecurrence::MINUTELY:
02301 case KARecurrence::DAILY:
02302 case KARecurrence::WEEKLY:
02303 case KARecurrence::MONTHLY_DAY:
02304 case KARecurrence::MONTHLY_POS:
02305 case KARecurrence::ANNUAL_DATE:
02306 case KARecurrence::ANNUAL_POS:
02307 return type;
02308 default:
02309 if (mRecurrence)
02310 {
02311 delete mRecurrence;
02312 const_cast<KAEvent*>(this)->mRecurrence = 0;
02313 }
02314 break;
02315 }
02316 }
02317 return KARecurrence::NO_RECUR;
02318 }
02319
02320
02321
02322
02323
02324 int KAEvent::recurInterval() const
02325 {
02326 if (mRecurrence)
02327 {
02328 switch (mRecurrence->type())
02329 {
02330 case KARecurrence::MINUTELY:
02331 case KARecurrence::DAILY:
02332 case KARecurrence::WEEKLY:
02333 case KARecurrence::MONTHLY_DAY:
02334 case KARecurrence::MONTHLY_POS:
02335 case KARecurrence::ANNUAL_DATE:
02336 case KARecurrence::ANNUAL_POS:
02337 return mRecurrence->frequency();
02338 default:
02339 break;
02340 }
02341 }
02342 return 0;
02343 }
02344
02345 #if 0
02346
02347
02348
02349 QValueList<KAEvent::MonthPos> KAEvent::convRecurPos(const QValueList<KCal::RecurrenceRule::WDayPos>& wdaypos)
02350 {
02351 QValueList<MonthPos> mposns;
02352 for (QValueList<KCal::RecurrenceRule::WDayPos>::ConstIterator it = wdaypos.begin(); it != wdaypos.end(); ++it)
02353 {
02354 int daybit = (*it).day() - 1;
02355 int weeknum = (*it).pos();
02356 bool found = false;
02357 for (QValueList<MonthPos>::Iterator mit = mposns.begin(); mit != mposns.end(); ++mit)
02358 {
02359 if ((*mit).weeknum == weeknum)
02360 {
02361 (*mit).days.setBit(daybit);
02362 found = true;
02363 break;
02364 }
02365 }
02366 if (!found)
02367 {
02368 MonthPos mpos;
02369 mpos.days.fill(false);
02370 mpos.days.setBit(daybit);
02371 mpos.weeknum = weeknum;
02372 mposns.append(mpos);
02373 }
02374 }
02375 return mposns;
02376 }
02377 #endif
02378
02379
02380
02381
02382
02383 KAEvent KAEvent::findTemplateName(AlarmCalendar& calendar, const QString& name)
02384 {
02385 KAEvent event;
02386 Event::List events = calendar.events();
02387 for (Event::List::ConstIterator evit = events.begin(); evit != events.end(); ++evit)
02388 {
02389 Event* ev = *evit;
02390 if (ev->summary() == name)
02391 {
02392 event.set(*ev);
02393 if (!event.isTemplate())
02394 return KAEvent();
02395 break;
02396 }
02397 }
02398 return event;
02399 }
02400
02401
02402
02403
02404
02405
02406
02407 bool KAEvent::adjustStartOfDay(const Event::List& events)
02408 {
02409 bool changed = false;
02410 QTime startOfDay = Preferences::startOfDay();
02411 for (Event::List::ConstIterator evit = events.begin(); evit != events.end(); ++evit)
02412 {
02413 Event* event = *evit;
02414 const QStringList& cats = event->categories();
02415 if (cats.find(DATE_ONLY_CATEGORY) != cats.end())
02416 {
02417
02418 QTime oldTime = event->dtStart().time();
02419 int adjustment = oldTime.secsTo(startOfDay);
02420 if (adjustment)
02421 {
02422 event->setDtStart(QDateTime(event->dtStart().date(), startOfDay));
02423 Alarm::List alarms = event->alarms();
02424 int deferralOffset = 0;
02425 for (Alarm::List::ConstIterator alit = alarms.begin(); alit != alarms.end(); ++alit)
02426 {
02427
02428 Alarm& alarm = **alit;
02429 AlarmData data;
02430 readAlarm(alarm, data);
02431 if (data.type & KAAlarm::TIMED_DEFERRAL_FLAG)
02432 {
02433
02434 deferralOffset = alarm.startOffset().asSeconds();
02435 alarm.setStartOffset(deferralOffset - adjustment);
02436 }
02437 else if (data.type == KAAlarm::AUDIO__ALARM
02438 && alarm.startOffset().asSeconds() == deferralOffset)
02439 {
02440
02441 alarm.setStartOffset(deferralOffset - adjustment);
02442 }
02443 }
02444 changed = true;
02445 }
02446 }
02447 else
02448 {
02449
02450 int deferralOffset = 0;
02451 int newDeferralOffset = 0;
02452 AlarmMap alarmMap;
02453 readAlarms(*event, &alarmMap);
02454 for (AlarmMap::Iterator it = alarmMap.begin(); it != alarmMap.end(); ++it)
02455 {
02456 const AlarmData& data = it.data();
02457 if ((data.type & KAAlarm::DEFERRED_ALARM)
02458 && !(data.type & KAAlarm::TIMED_DEFERRAL_FLAG))
02459 {
02460
02461 QDateTime altime = data.alarm->time();
02462 altime.setTime(startOfDay);
02463 deferralOffset = data.alarm->startOffset().asSeconds();
02464 newDeferralOffset = event->dtStart().secsTo(altime);
02465 const_cast<Alarm*>(data.alarm)->setStartOffset(newDeferralOffset);
02466 changed = true;
02467 }
02468 else if (data.type == KAAlarm::AUDIO__ALARM
02469 && data.alarm->startOffset().asSeconds() == deferralOffset)
02470 {
02471
02472 const_cast<Alarm*>(data.alarm)->setStartOffset(newDeferralOffset);
02473 changed = true;
02474 }
02475 }
02476 }
02477 }
02478 return changed;
02479 }
02480
02481
02482
02483
02484
02485
02486 void KAEvent::convertKCalEvents(KCal::Calendar& calendar, int version, bool adjustSummerTime)
02487 {
02488
02489 static const QChar SEPARATOR = ';';
02490 static const QChar LATE_CANCEL_CODE = 'C';
02491 static const QChar AT_LOGIN_CODE = 'L';
02492 static const QChar DEFERRAL_CODE = 'D';
02493 static const QString TEXT_PREFIX = QString::fromLatin1("TEXT:");
02494 static const QString FILE_PREFIX = QString::fromLatin1("FILE:");
02495 static const QString COMMAND_PREFIX = QString::fromLatin1("CMD:");
02496
02497
02498 static const QString BEEP_CATEGORY = QString::fromLatin1("BEEP");
02499
02500
02501 static const QString LATE_CANCEL_CAT = QString::fromLatin1("LATECANCEL");
02502
02503
02504 static const QString TEMPL_DEF_TIME_CAT = QString::fromLatin1("TMPLDEFTIME");
02505
02506
02507 static const QString EXEC_IN_XTERM_CAT = QString::fromLatin1("XTERM");
02508
02509 if (version >= KAlarm::Version(1,3,1))
02510 return;
02511
02512 kdDebug(5950) << "KAEvent::convertKCalEvents(): adjusting version " << version << endl;
02513 bool pre_0_7 = (version < KAlarm::Version(0,7,0));
02514 bool pre_0_9 = (version < KAlarm::Version(0,9,0));
02515 bool pre_0_9_2 = (version < KAlarm::Version(0,9,2));
02516 bool pre_1_1_1 = (version < KAlarm::Version(1,1,1));
02517 bool pre_1_2_1 = (version < KAlarm::Version(1,2,1));
02518 bool pre_1_3_0 = (version < KAlarm::Version(1,3,0));
02519 bool pre_1_3_1 = (version < KAlarm::Version(1,3,1));
02520 QDateTime dt0(QDate(1970,1,1), QTime(0,0,0));
02521 QTime startOfDay = Preferences::startOfDay();
02522
02523 Event::List events = calendar.rawEvents();
02524 for (Event::List::ConstIterator evit = events.begin(); evit != events.end(); ++evit)
02525 {
02526 Event* event = *evit;
02527 Alarm::List alarms = event->alarms();
02528 if (alarms.isEmpty())
02529 continue;
02530 QStringList cats = event->categories();
02531 bool addLateCancel = false;
02532
02533 if (pre_0_7 && event->doesFloat())
02534 {
02535
02536
02537 event->setFloats(false);
02538 }
02539
02540 if (pre_0_9)
02541 {
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554 for (Alarm::List::ConstIterator alit = alarms.begin(); alit != alarms.end(); ++alit)
02555 {
02556 Alarm* alarm = *alit;
02557 bool atLogin = false;
02558 bool deferral = false;
02559 bool lateCancel = false;
02560 KAAlarmEventBase::Type action = T_MESSAGE;
02561 QString txt = alarm->text();
02562 int length = txt.length();
02563 int i = 0;
02564 if (txt[0].isDigit())
02565 {
02566 while (++i < length && txt[i].isDigit()) ;
02567 if (i < length && txt[i++] == SEPARATOR)
02568 {
02569 while (i < length)
02570 {
02571 QChar ch = txt[i++];
02572 if (ch == SEPARATOR)
02573 break;
02574 if (ch == LATE_CANCEL_CODE)
02575 lateCancel = true;
02576 else if (ch == AT_LOGIN_CODE)
02577 atLogin = true;
02578 else if (ch == DEFERRAL_CODE)
02579 deferral = true;
02580 }
02581 }
02582 else
02583 i = 0;
02584 }
02585 if (txt.find(TEXT_PREFIX, i) == i)
02586 i += TEXT_PREFIX.length();
02587 else if (txt.find(FILE_PREFIX, i) == i)
02588 {
02589 action = T_FILE;
02590 i += FILE_PREFIX.length();
02591 }
02592 else if (txt.find(COMMAND_PREFIX, i) == i)
02593 {
02594 action = T_COMMAND;
02595 i += COMMAND_PREFIX.length();
02596 }
02597 else
02598 i = 0;
02599 txt = txt.mid(i);
02600
02601 QStringList types;
02602 switch (action)
02603 {
02604 case T_FILE:
02605 types += FILE_TYPE;
02606
02607 case T_MESSAGE:
02608 alarm->setDisplayAlarm(txt);
02609 break;
02610 case T_COMMAND:
02611 setProcedureAlarm(alarm, txt);
02612 break;
02613 case T_EMAIL:
02614 case T_AUDIO:
02615 break;
02616 }
02617 if (atLogin)
02618 {
02619 types += AT_LOGIN_TYPE;
02620 lateCancel = false;
02621 }
02622 else if (deferral)
02623 types += TIME_DEFERRAL_TYPE;
02624 if (lateCancel)
02625 addLateCancel = true;
02626 if (types.count() > 0)
02627 alarm->setCustomProperty(APPNAME, TYPE_PROPERTY, types.join(","));
02628
02629 if (pre_0_7 && alarm->repeatCount() > 0 && alarm->snoozeTime() > 0)
02630 {
02631
02632
02633 Recurrence* recur = event->recurrence();
02634 if (recur && recur->doesRecur())
02635 {
02636 recur->setMinutely(alarm->snoozeTime());
02637 recur->setDuration(alarm->repeatCount() + 1);
02638 alarm->setRepeatCount(0);
02639 alarm->setSnoozeTime(0);
02640 }
02641 }
02642
02643 if (adjustSummerTime)
02644 {
02645
02646
02647 QDateTime dt = alarm->time();
02648 time_t t = dt0.secsTo(dt);
02649 struct tm* dtm = localtime(&t);
02650 if (dtm->tm_isdst)
02651 {
02652 dt = dt.addSecs(-3600);
02653 alarm->setTime(dt);
02654 }
02655 }
02656 }
02657 }
02658
02659 if (pre_0_9_2)
02660 {
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671 if (uidStatus(event->uid()) == EXPIRED)
02672 event->setCreated(event->dtEnd());
02673 QDateTime start = event->dtStart();
02674 if (event->doesFloat())
02675 {
02676 event->setFloats(false);
02677 start.setTime(startOfDay);
02678 cats.append(DATE_ONLY_CATEGORY);
02679 }
02680 event->setHasEndDate(false);
02681
02682 Alarm::List::ConstIterator alit;
02683 for (alit = alarms.begin(); alit != alarms.end(); ++alit)
02684 {
02685 Alarm* alarm = *alit;
02686 QDateTime dt = alarm->time();
02687 alarm->setStartOffset(start.secsTo(dt));
02688 }
02689
02690 if (cats.count() > 0)
02691 {
02692 for (alit = alarms.begin(); alit != alarms.end(); ++alit)
02693 {
02694 Alarm* alarm = *alit;
02695 if (alarm->type() == Alarm::Display)
02696 alarm->setCustomProperty(APPNAME, FONT_COLOUR_PROPERTY,
02697 QString::fromLatin1("%1;;").arg(cats[0]));
02698 }
02699 cats.remove(cats.begin());
02700 }
02701
02702 for (QStringList::Iterator it = cats.begin(); it != cats.end(); ++it)
02703 {
02704 if (*it == BEEP_CATEGORY)
02705 {
02706 cats.remove(it);
02707
02708 Alarm* alarm = event->newAlarm();
02709 alarm->setEnabled(true);
02710 alarm->setAudioAlarm();
02711 QDateTime dt = event->dtStart();
02712
02713
02714 AlarmMap alarmMap;
02715 readAlarms(*event, &alarmMap);
02716 AlarmMap::ConstIterator it = alarmMap.begin();
02717 if (it != alarmMap.end())
02718 {
02719 dt = it.data().alarm->time();
02720 break;
02721 }
02722 alarm->setStartOffset(start.secsTo(dt));
02723 break;
02724 }
02725 }
02726
02727 }
02728
02729 if (pre_1_1_1)
02730 {
02731
02732
02733
02734
02735 QStringList::Iterator it;
02736 while ((it = cats.find(LATE_CANCEL_CAT)) != cats.end())
02737 {
02738 cats.remove(it);
02739 addLateCancel = true;
02740 }
02741 }
02742
02743 if (pre_1_2_1)
02744 {
02745
02746
02747
02748
02749 for (Alarm::List::ConstIterator alit = alarms.begin(); alit != alarms.end(); ++alit)
02750 {
02751 Alarm* alarm = *alit;
02752 if (alarm->type() == Alarm::Display)
02753 {
02754 QString oldtext = alarm->text();
02755 QString newtext = AlarmText::toCalendarText(oldtext);
02756 if (oldtext != newtext)
02757 alarm->setDisplayAlarm(newtext);
02758 }
02759 }
02760 }
02761
02762 if (pre_1_3_0)
02763 {
02764
02765
02766
02767
02768 QStringList::Iterator it;
02769 while ((it = cats.find(TEMPL_DEF_TIME_CAT)) != cats.end())
02770 {
02771 cats.remove(it);
02772 cats.append(QString("%1%2").arg(TEMPL_AFTER_TIME_CATEGORY).arg(0));
02773 }
02774 }
02775
02776 if (pre_1_3_1)
02777 {
02778
02779
02780
02781
02782 QStringList::Iterator it;
02783 while ((it = cats.find(EXEC_IN_XTERM_CAT)) != cats.end())
02784 {
02785 cats.remove(it);
02786 cats.append(LOG_CATEGORY + xtermURL);
02787 }
02788 }
02789
02790 if (addLateCancel)
02791 cats.append(QString("%1%2").arg(LATE_CANCEL_CATEGORY).arg(1));
02792
02793 event->setCategories(cats);
02794 }
02795 }
02796
02797 #ifndef NDEBUG
02798 void KAEvent::dumpDebug() const
02799 {
02800 kdDebug(5950) << "KAEvent dump:\n";
02801 KAAlarmEventBase::dumpDebug();
02802 if (!mTemplateName.isEmpty())
02803 {
02804 kdDebug(5950) << "-- mTemplateName:" << mTemplateName << ":\n";
02805 kdDebug(5950) << "-- mTemplateAfterTime:" << mTemplateAfterTime << ":\n";
02806 }
02807 if (mActionType == T_MESSAGE || mActionType == T_FILE)
02808 {
02809 kdDebug(5950) << "-- mAudioFile:" << mAudioFile << ":\n";
02810 kdDebug(5950) << "-- mPreAction:" << mPreAction << ":\n";
02811 kdDebug(5950) << "-- mPostAction:" << mPostAction << ":\n";
02812 }
02813 else if (mActionType == T_COMMAND)
02814 {
02815 kdDebug(5950) << "-- mCommandXterm:" << (mCommandXterm ? "true" : "false") << ":\n";
02816 kdDebug(5950) << "-- mLogFile:" << mLogFile << ":\n";
02817 }
02818 kdDebug(5950) << "-- mKMailSerialNumber:" << mKMailSerialNumber << ":\n";
02819 kdDebug(5950) << "-- mCopyToKOrganizer:" << (mCopyToKOrganizer ? "true" : "false") << ":\n";
02820 kdDebug(5950) << "-- mStartDateTime:" << mStartDateTime.toString() << ":\n";
02821 kdDebug(5950) << "-- mSaveDateTime:" << mSaveDateTime.toString() << ":\n";
02822 if (mRepeatAtLogin)
02823 kdDebug(5950) << "-- mAtLoginDateTime:" << mAtLoginDateTime.toString() << ":\n";
02824 kdDebug(5950) << "-- mArchiveRepeatAtLogin:" << (mArchiveRepeatAtLogin ? "true" : "false") << ":\n";
02825 kdDebug(5950) << "-- mEnabled:" << (mEnabled ? "true" : "false") << ":\n";
02826 if (mReminderMinutes)
02827 kdDebug(5950) << "-- mReminderMinutes:" << mReminderMinutes << ":\n";
02828 if (mArchiveReminderMinutes)
02829 kdDebug(5950) << "-- mArchiveReminderMinutes:" << mArchiveReminderMinutes << ":\n";
02830 if (mReminderMinutes || mArchiveReminderMinutes)
02831 kdDebug(5950) << "-- mReminderOnceOnly:" << mReminderOnceOnly << ":\n";
02832 else if (mDeferral > 0)
02833 {
02834 kdDebug(5950) << "-- mDeferral:" << (mDeferral == NORMAL_DEFERRAL ? "normal" : "reminder") << ":\n";
02835 kdDebug(5950) << "-- mDeferralTime:" << mDeferralTime.toString() << ":\n";
02836 }
02837 else if (mDeferral == CANCEL_DEFERRAL)
02838 kdDebug(5950) << "-- mDeferral:cancel:\n";
02839 if (mDisplaying)
02840 {
02841 kdDebug(5950) << "-- mDisplayingTime:" << mDisplayingTime.toString() << ":\n";
02842 kdDebug(5950) << "-- mDisplayingFlags:" << mDisplayingFlags << ":\n";
02843 }
02844 kdDebug(5950) << "-- mRevision:" << mRevision << ":\n";
02845 kdDebug(5950) << "-- mRecurrence:" << (mRecurrence ? "true" : "false") << ":\n";
02846 if (mRecurrence)
02847 kdDebug(5950) << "-- mRemainingRecurrences:" << mRemainingRecurrences << ":\n";
02848 kdDebug(5950) << "-- mAlarmCount:" << mAlarmCount << ":\n";
02849 kdDebug(5950) << "-- mMainExpired:" << (mMainExpired ? "true" : "false") << ":\n";
02850 kdDebug(5950) << "KAEvent dump end\n";
02851 }
02852 #endif
02853
02854
02855
02856
02857
02858
02859
02860 KAAlarm::KAAlarm(const KAAlarm& alarm)
02861 : KAAlarmEventBase(alarm),
02862 mType(alarm.mType),
02863 mRecurs(alarm.mRecurs),
02864 mDeferred(alarm.mDeferred)
02865 { }
02866
02867
02868 int KAAlarm::flags() const
02869 {
02870 return KAAlarmEventBase::flags()
02871 | (mDeferred ? KAEvent::DEFERRAL : 0);
02872
02873 }
02874
02875 #ifndef NDEBUG
02876 void KAAlarm::dumpDebug() const
02877 {
02878 kdDebug(5950) << "KAAlarm dump:\n";
02879 KAAlarmEventBase::dumpDebug();
02880 const char* altype = 0;
02881 switch (mType)
02882 {
02883 case MAIN__ALARM: altype = "MAIN"; break;
02884 case REMINDER__ALARM: altype = "REMINDER"; break;
02885 case DEFERRED_DATE__ALARM: altype = "DEFERRED(DATE)"; break;
02886 case DEFERRED_TIME__ALARM: altype = "DEFERRED(TIME)"; break;
02887 case DEFERRED_REMINDER_DATE__ALARM: altype = "DEFERRED_REMINDER(DATE)"; break;
02888 case DEFERRED_REMINDER_TIME__ALARM: altype = "DEFERRED_REMINDER(TIME)"; break;
02889 case AT_LOGIN__ALARM: altype = "LOGIN"; break;
02890 case DISPLAYING__ALARM: altype = "DISPLAYING"; break;
02891 case AUDIO__ALARM: altype = "AUDIO"; break;
02892 case PRE_ACTION__ALARM: altype = "PRE_ACTION"; break;
02893 case POST_ACTION__ALARM: altype = "POST_ACTION"; break;
02894 default: altype = "INVALID"; break;
02895 }
02896 kdDebug(5950) << "-- mType:" << altype << ":\n";
02897 kdDebug(5950) << "-- mRecurs:" << (mRecurs ? "true" : "false") << ":\n";
02898 kdDebug(5950) << "-- mDeferred:" << (mDeferred ? "true" : "false") << ":\n";
02899 kdDebug(5950) << "KAAlarm dump end\n";
02900 }
02901
02902 const char* KAAlarm::debugType(Type type)
02903 {
02904 switch (type)
02905 {
02906 case MAIN_ALARM: return "MAIN";
02907 case REMINDER_ALARM: return "REMINDER";
02908 case DEFERRED_ALARM: return "DEFERRED";
02909 case DEFERRED_REMINDER_ALARM: return "DEFERRED_REMINDER";
02910 case AT_LOGIN_ALARM: return "LOGIN";
02911 case DISPLAYING_ALARM: return "DISPLAYING";
02912 case AUDIO_ALARM: return "AUDIO";
02913 case PRE_ACTION_ALARM: return "PRE_ACTION";
02914 case POST_ACTION_ALARM: return "POST_ACTION";
02915 default: return "INVALID";
02916 }
02917 }
02918 #endif
02919
02920
02921
02922
02923
02924
02925 void KAAlarmEventBase::copy(const KAAlarmEventBase& rhs)
02926 {
02927 mEventID = rhs.mEventID;
02928 mText = rhs.mText;
02929 mNextMainDateTime = rhs.mNextMainDateTime;
02930 mBgColour = rhs.mBgColour;
02931 mFgColour = rhs.mFgColour;
02932 mFont = rhs.mFont;
02933 mEmailFromKMail = rhs.mEmailFromKMail;
02934 mEmailAddresses = rhs.mEmailAddresses;
02935 mEmailSubject = rhs.mEmailSubject;
02936 mEmailAttachments = rhs.mEmailAttachments;
02937 mSoundVolume = rhs.mSoundVolume;
02938 mFadeVolume = rhs.mFadeVolume;
02939 mFadeSeconds = rhs.mFadeSeconds;
02940 mActionType = rhs.mActionType;
02941 mCommandScript = rhs.mCommandScript;
02942 mRepeatCount = rhs.mRepeatCount;
02943 mRepeatInterval = rhs.mRepeatInterval;
02944 mBeep = rhs.mBeep;
02945 mSpeak = rhs.mSpeak;
02946 mRepeatSound = rhs.mRepeatSound;
02947 mRepeatAtLogin = rhs.mRepeatAtLogin;
02948 mDisplaying = rhs.mDisplaying;
02949 mLateCancel = rhs.mLateCancel;
02950 mAutoClose = rhs.mAutoClose;
02951 mEmailBcc = rhs.mEmailBcc;
02952 mConfirmAck = rhs.mConfirmAck;
02953 mDefaultFont = rhs.mDefaultFont;
02954 }
02955
02956 void KAAlarmEventBase::set(int flags)
02957 {
02958 mSpeak = flags & KAEvent::SPEAK;
02959 mBeep = (flags & KAEvent::BEEP) && !mSpeak;
02960 mRepeatSound = flags & KAEvent::REPEAT_SOUND;
02961 mRepeatAtLogin = flags & KAEvent::REPEAT_AT_LOGIN;
02962 mAutoClose = (flags & KAEvent::AUTO_CLOSE) && mLateCancel;
02963 mEmailBcc = flags & KAEvent::EMAIL_BCC;
02964 mConfirmAck = flags & KAEvent::CONFIRM_ACK;
02965 mDisplaying = flags & KAEvent::DISPLAYING_;
02966 mDefaultFont = flags & KAEvent::DEFAULT_FONT;
02967 mCommandScript = flags & KAEvent::SCRIPT;
02968 }
02969
02970 int KAAlarmEventBase::flags() const
02971 {
02972 return (mBeep && !mSpeak ? KAEvent::BEEP : 0)
02973 | (mSpeak ? KAEvent::SPEAK : 0)
02974 | (mRepeatSound ? KAEvent::REPEAT_SOUND : 0)
02975 | (mRepeatAtLogin ? KAEvent::REPEAT_AT_LOGIN : 0)
02976 | (mAutoClose ? KAEvent::AUTO_CLOSE : 0)
02977 | (mEmailBcc ? KAEvent::EMAIL_BCC : 0)
02978 | (mConfirmAck ? KAEvent::CONFIRM_ACK : 0)
02979 | (mDisplaying ? KAEvent::DISPLAYING_ : 0)
02980 | (mDefaultFont ? KAEvent::DEFAULT_FONT : 0)
02981 | (mCommandScript ? KAEvent::SCRIPT : 0);
02982 }
02983
02984 const QFont& KAAlarmEventBase::font() const
02985 {
02986 return mDefaultFont ? Preferences::messageFont() : mFont;
02987 }
02988
02989 #ifndef NDEBUG
02990 void KAAlarmEventBase::dumpDebug() const
02991 {
02992 kdDebug(5950) << "-- mEventID:" << mEventID << ":\n";
02993 kdDebug(5950) << "-- mActionType:" << (mActionType == T_MESSAGE ? "MESSAGE" : mActionType == T_FILE ? "FILE" : mActionType == T_COMMAND ? "COMMAND" : mActionType == T_EMAIL ? "EMAIL" : mActionType == T_AUDIO ? "AUDIO" : "??") << ":\n";
02994 kdDebug(5950) << "-- mText:" << mText << ":\n";
02995 if (mActionType == T_COMMAND)
02996 kdDebug(5950) << "-- mCommandScript:" << (mCommandScript ? "true" : "false") << ":\n";
02997 kdDebug(5950) << "-- mNextMainDateTime:" << mNextMainDateTime.toString() << ":\n";
02998 if (mActionType == T_EMAIL)
02999 {
03000 kdDebug(5950) << "-- mEmail: FromKMail:" << mEmailFromKMail << ":\n";
03001 kdDebug(5950) << "-- Addresses:" << mEmailAddresses.join(", ") << ":\n";
03002 kdDebug(5950) << "-- Subject:" << mEmailSubject << ":\n";
03003 kdDebug(5950) << "-- Attachments:" << mEmailAttachments.join(", ") << ":\n";
03004 kdDebug(5950) << "-- Bcc:" << (mEmailBcc ? "true" : "false") << ":\n";
03005 }
03006 kdDebug(5950) << "-- mBgColour:" << mBgColour.name() << ":\n";
03007 kdDebug(5950) << "-- mFgColour:" << mFgColour.name() << ":\n";
03008 kdDebug(5950) << "-- mDefaultFont:" << (mDefaultFont ? "true" : "false") << ":\n";
03009 if (!mDefaultFont)
03010 kdDebug(5950) << "-- mFont:" << mFont.toString() << ":\n";
03011 kdDebug(5950) << "-- mBeep:" << (mBeep ? "true" : "false") << ":\n";
03012 kdDebug(5950) << "-- mSpeak:" << (mSpeak ? "true" : "false") << ":\n";
03013 if (mActionType == T_AUDIO)
03014 {
03015 if (mSoundVolume >= 0)
03016 {
03017 kdDebug(5950) << "-- mSoundVolume:" << mSoundVolume << ":\n";
03018 if (mFadeVolume >= 0)
03019 {
03020 kdDebug(5950) << "-- mFadeVolume:" << mFadeVolume << ":\n";
03021 kdDebug(5950) << "-- mFadeSeconds:" << mFadeSeconds << ":\n";
03022 }
03023 else
03024 kdDebug(5950) << "-- mFadeVolume:-:\n";
03025 }
03026 else
03027 kdDebug(5950) << "-- mSoundVolume:-:\n";
03028 kdDebug(5950) << "-- mRepeatSound:" << (mRepeatSound ? "true" : "false") << ":\n";
03029 }
03030 kdDebug(5950) << "-- mConfirmAck:" << (mConfirmAck ? "true" : "false") << ":\n";
03031 kdDebug(5950) << "-- mRepeatAtLogin:" << (mRepeatAtLogin ? "true" : "false") << ":\n";
03032 kdDebug(5950) << "-- mRepeatCount:" << mRepeatCount << ":\n";
03033 kdDebug(5950) << "-- mRepeatInterval:" << mRepeatInterval << ":\n";
03034 kdDebug(5950) << "-- mDisplaying:" << (mDisplaying ? "true" : "false") << ":\n";
03035 kdDebug(5950) << "-- mLateCancel:" << mLateCancel << ":\n";
03036 kdDebug(5950) << "-- mAutoClose:" << (mAutoClose ? "true" : "false") << ":\n";
03037 }
03038 #endif
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049 EmailAddressList& EmailAddressList::operator=(const QValueList<Person>& addresses)
03050 {
03051 clear();
03052 for (QValueList<Person>::ConstIterator it = addresses.begin(); it != addresses.end(); ++it)
03053 {
03054 if (!(*it).email().isEmpty())
03055 append(*it);
03056 }
03057 return *this;
03058 }
03059
03060
03061
03062
03063
03064 QString EmailAddressList::join(const QString& separator) const
03065 {
03066 QString result;
03067 bool first = true;
03068 for (QValueList<Person>::ConstIterator it = begin(); it != end(); ++it)
03069 {
03070 if (first)
03071 first = false;
03072 else
03073 result += separator;
03074
03075 bool quote = false;
03076 QString name = (*it).name();
03077 if (!name.isEmpty())
03078 {
03079
03080 int len = name.length();
03081 for (int i = 0; i < len; ++i)
03082 {
03083 QChar ch = name[i];
03084 if (!ch.isLetterOrNumber())
03085 {
03086 quote = true;
03087 result += '\"';
03088 break;
03089 }
03090 }
03091 result += (*it).name();
03092 result += (quote ? "\" <" : " <");
03093 quote = true;
03094 }
03095
03096 result += (*it).email();
03097 if (quote)
03098 result += ">";
03099 }
03100 return result;
03101 }
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113 static void setProcedureAlarm(Alarm* alarm, const QString& commandLine)
03114 {
03115 QString command = QString::null;
03116 QString arguments = QString::null;
03117 QChar quoteChar;
03118 bool quoted = false;
03119 uint posMax = commandLine.length();
03120 uint pos;
03121 for (pos = 0; pos < posMax; ++pos)
03122 {
03123 QChar ch = commandLine[pos];
03124 if (quoted)
03125 {
03126 if (ch == quoteChar)
03127 {
03128 ++pos;
03129 break;
03130 }
03131 command += ch;
03132 }
03133 else
03134 {
03135 bool done = false;
03136 switch (ch)
03137 {
03138 case ' ':
03139 case ';':
03140 case '|':
03141 case '<':
03142 case '>':
03143 done = !command.isEmpty();
03144 break;
03145 case '\'':
03146 case '"':
03147 if (command.isEmpty())
03148 {
03149
03150 quoted = true;
03151 quoteChar = ch;
03152 break;
03153 }
03154
03155 default:
03156 command += ch;
03157 break;
03158 }
03159 if (done)
03160 break;
03161 }
03162 }
03163
03164
03165 for ( ; pos < posMax && commandLine[pos] == ' '; ++pos) ;
03166 arguments = commandLine.mid(pos);
03167
03168 alarm->setProcedureAlarm(command, arguments);
03169 }