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