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, false);
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
00838
00839 QDateTime now = QDateTime::currentDateTime();
00840 if (now > mNextMainDateTime)
00841 {
00842 dt = mainEndRepeatTime();
00843 if (dt > now)
00844 {
00845 int repeatSecs = mRepeatInterval * 60;
00846 int repetition = (mNextMainDateTime.secsTo(now) + repeatSecs - 1) / repeatSecs;
00847 dt = mNextMainDateTime.addSecs(repetition * repeatSecs);
00848 }
00849 }
00850 }
00851 if (mDeferral > 0
00852 && (includeReminders || mDeferral != REMINDER_DEFERRAL))
00853 {
00854 if (mMainExpired)
00855 return mDeferralTime;
00856 return QMIN(mDeferralTime, dt);
00857 }
00858 return dt;
00859 }
00860
00861
00862
00863
00864 QString KAEvent::uid(const QString& id, Status status)
00865 {
00866 QString result = id;
00867 Status oldStatus;
00868 int i, len;
00869 if ((i = result.find(EXPIRED_UID)) > 0)
00870 {
00871 oldStatus = EXPIRED;
00872 len = EXPIRED_UID.length();
00873 }
00874 else if ((i = result.find(DISPLAYING_UID)) > 0)
00875 {
00876 oldStatus = DISPLAYING;
00877 len = DISPLAYING_UID.length();
00878 }
00879 else if ((i = result.find(TEMPLATE_UID)) > 0)
00880 {
00881 oldStatus = TEMPLATE;
00882 len = TEMPLATE_UID.length();
00883 }
00884 else if ((i = result.find(KORGANIZER_UID)) > 0)
00885 {
00886 oldStatus = KORGANIZER;
00887 len = KORGANIZER_UID.length();
00888 }
00889 else
00890 {
00891 oldStatus = ACTIVE;
00892 i = result.findRev('-');
00893 len = 1;
00894 }
00895 if (status != oldStatus && i > 0)
00896 {
00897 QString part;
00898 switch (status)
00899 {
00900 case ACTIVE: part = "-"; break;
00901 case EXPIRED: part = EXPIRED_UID; break;
00902 case DISPLAYING: part = DISPLAYING_UID; break;
00903 case TEMPLATE: part = TEMPLATE_UID; break;
00904 case KORGANIZER: part = KORGANIZER_UID; break;
00905 }
00906 result.replace(i, len, part);
00907 }
00908 return result;
00909 }
00910
00911
00912
00913
00914 KAEvent::Status KAEvent::uidStatus(const QString& uid)
00915 {
00916 if (uid.find(EXPIRED_UID) > 0)
00917 return EXPIRED;
00918 if (uid.find(DISPLAYING_UID) > 0)
00919 return DISPLAYING;
00920 if (uid.find(TEMPLATE_UID) > 0)
00921 return TEMPLATE;
00922 if (uid.find(KORGANIZER_UID) > 0)
00923 return KORGANIZER;
00924 return ACTIVE;
00925 }
00926
00927 void KAEvent::set(int flags)
00928 {
00929 KAAlarmEventBase::set(flags & ~READ_ONLY_FLAGS);
00930 mStartDateTime.setDateOnly(flags & ANY_TIME);
00931 set_deferral((flags & DEFERRAL) ? NORMAL_DEFERRAL : NO_DEFERRAL);
00932 mCommandXterm = flags & EXEC_IN_XTERM;
00933 mCopyToKOrganizer = flags & COPY_KORGANIZER;
00934 mEnabled = !(flags & DISABLED);
00935 mUpdated = true;
00936 }
00937
00938 int KAEvent::flags() const
00939 {
00940 return KAAlarmEventBase::flags()
00941 | (mStartDateTime.isDateOnly() ? ANY_TIME : 0)
00942 | (mDeferral > 0 ? DEFERRAL : 0)
00943 | (mCommandXterm ? EXEC_IN_XTERM : 0)
00944 | (mCopyToKOrganizer ? COPY_KORGANIZER : 0)
00945 | (mEnabled ? 0 : DISABLED);
00946 }
00947
00948
00949
00950
00951 Event* KAEvent::event() const
00952 {
00953 KCal::Event* ev = new KCal::Event;
00954 ev->setUid(mEventID);
00955 updateKCalEvent(*ev, false);
00956 return ev;
00957 }
00958
00959
00960
00961
00962
00963
00964
00965 bool KAEvent::updateKCalEvent(Event& ev, bool checkUid, bool original, bool cancelCancelledDefer) const
00966 {
00967 if (checkUid && !mEventID.isEmpty() && mEventID != ev.uid()
00968 || !mAlarmCount && (!original || !mMainExpired))
00969 return false;
00970
00971 checkRecur();
00972 bool readOnly = ev.isReadOnly();
00973 ev.setReadOnly(false);
00974 ev.setTransparency(Event::Transparent);
00975
00976
00977 QStringList cats;
00978 if (mStartDateTime.isDateOnly())
00979 cats.append(DATE_ONLY_CATEGORY);
00980 if (mConfirmAck)
00981 cats.append(CONFIRM_ACK_CATEGORY);
00982 if (mEmailBcc)
00983 cats.append(EMAIL_BCC_CATEGORY);
00984 if (mKMailSerialNumber)
00985 cats.append(QString("%1%2").arg(KMAIL_SERNUM_CATEGORY).arg(mKMailSerialNumber));
00986 if (mCopyToKOrganizer)
00987 cats.append(KORGANIZER_CATEGORY);
00988 if (mCommandXterm)
00989 cats.append(LOG_CATEGORY + xtermURL);
00990 else if (!mLogFile.isEmpty())
00991 cats.append(LOG_CATEGORY + mLogFile);
00992 if (mLateCancel)
00993 cats.append(QString("%1%2").arg(mAutoClose ? AUTO_CLOSE_CATEGORY : LATE_CANCEL_CATEGORY).arg(mLateCancel));
00994 if (mDeferDefaultMinutes)
00995 cats.append(QString("%1%2").arg(DEFER_CATEGORY).arg(mDeferDefaultMinutes));
00996 if (!mTemplateName.isEmpty() && mTemplateAfterTime >= 0)
00997 cats.append(QString("%1%2").arg(TEMPL_AFTER_TIME_CATEGORY).arg(mTemplateAfterTime));
00998 if (mArchive && !original)
00999 {
01000 QStringList params;
01001 if (mArchiveReminderMinutes)
01002 {
01003 if (mReminderOnceOnly)
01004 params += ARCHIVE_REMINDER_ONCE_TYPE;
01005 char unit = 'M';
01006 int count = mArchiveReminderMinutes;
01007 if (count % 1440 == 0)
01008 {
01009 unit = 'D';
01010 count /= 1440;
01011 }
01012 else if (count % 60 == 0)
01013 {
01014 unit = 'H';
01015 count /= 60;
01016 }
01017 params += QString("%1%2").arg(count).arg(unit);
01018 }
01019 if (mArchiveRepeatAtLogin)
01020 params += AT_LOGIN_TYPE;
01021 if (params.count() > 0)
01022 {
01023 QString cat = ARCHIVE_CATEGORIES;
01024 cat += params.join(QString::fromLatin1(";"));
01025 cats.append(cat);
01026 }
01027 else
01028 cats.append(ARCHIVE_CATEGORY);
01029 }
01030 ev.setCategories(cats);
01031 ev.setCustomStatus(mEnabled ? QString::null : DISABLED_STATUS);
01032 ev.setRevision(mRevision);
01033 ev.clearAlarms();
01034
01035
01036
01037
01038
01039 ev.setDtStart(mStartDateTime.dateTime());
01040 ev.setFloats(false);
01041 ev.setHasEndDate(false);
01042
01043 DateTime dtMain = original ? mStartDateTime : mNextMainDateTime;
01044 int ancillaryType = 0;
01045 DateTime ancillaryTime;
01046 int ancillaryOffset = 0;
01047 if (!mMainExpired || original)
01048 {
01049
01050 initKcalAlarm(ev, dtMain, QStringList(), KAAlarm::MAIN_ALARM);
01051 ancillaryTime = dtMain;
01052 ancillaryType = dtMain.isValid() ? 1 : 0;
01053 }
01054
01055
01056 if (mRepeatAtLogin || mArchiveRepeatAtLogin && original)
01057 {
01058 DateTime dtl;
01059 if (mArchiveRepeatAtLogin)
01060 dtl = mStartDateTime.dateTime().addDays(-1);
01061 else if (mAtLoginDateTime.isValid())
01062 dtl = mAtLoginDateTime;
01063 else if (mStartDateTime.isDateOnly())
01064 dtl = QDate::currentDate().addDays(-1);
01065 else
01066 dtl = QDateTime::currentDateTime();
01067 initKcalAlarm(ev, dtl, AT_LOGIN_TYPE);
01068 if (!ancillaryType && dtl.isValid())
01069 {
01070 ancillaryTime = dtl;
01071 ancillaryType = 1;
01072 }
01073 }
01074 if (mReminderMinutes || mArchiveReminderMinutes && original)
01075 {
01076 int minutes = mReminderMinutes ? mReminderMinutes : mArchiveReminderMinutes;
01077 initKcalAlarm(ev, -minutes * 60, QStringList(mReminderOnceOnly ? REMINDER_ONCE_TYPE : REMINDER_TYPE));
01078 if (!ancillaryType)
01079 {
01080 ancillaryOffset = -minutes * 60;
01081 ancillaryType = 2;
01082 }
01083 }
01084 if (mDeferral > 0 || mDeferral == CANCEL_DEFERRAL && !cancelCancelledDefer)
01085 {
01086 QStringList list;
01087 if (mDeferralTime.isDateOnly())
01088 list += DATE_DEFERRAL_TYPE;
01089 else
01090 list += TIME_DEFERRAL_TYPE;
01091 if (mDeferral == REMINDER_DEFERRAL)
01092 list += mReminderOnceOnly ? REMINDER_ONCE_TYPE : REMINDER_TYPE;
01093 initKcalAlarm(ev, mDeferralTime, list);
01094 if (!ancillaryType && mDeferralTime.isValid())
01095 {
01096 ancillaryTime = mDeferralTime;
01097 ancillaryType = 1;
01098 }
01099 }
01100 if (!mTemplateName.isEmpty())
01101 ev.setSummary(mTemplateName);
01102 else if (mDisplaying)
01103 {
01104 QStringList list(DISPLAYING_TYPE);
01105 if (mDisplayingFlags & REPEAT_AT_LOGIN)
01106 list += AT_LOGIN_TYPE;
01107 else if (mDisplayingFlags & DEFERRAL)
01108 {
01109 if (mDisplayingFlags & TIMED_FLAG)
01110 list += TIME_DEFERRAL_TYPE;
01111 else
01112 list += DATE_DEFERRAL_TYPE;
01113 }
01114 if (mDisplayingFlags & REMINDER)
01115 list += mReminderOnceOnly ? REMINDER_ONCE_TYPE : REMINDER_TYPE;
01116 initKcalAlarm(ev, mDisplayingTime, list);
01117 if (!ancillaryType && mDisplayingTime.isValid())
01118 {
01119 ancillaryTime = mDisplayingTime;
01120 ancillaryType = 1;
01121 }
01122 }
01123 if (mBeep || mSpeak || !mAudioFile.isEmpty())
01124 {
01125
01126 if (ancillaryType == 2)
01127 initKcalAlarm(ev, ancillaryOffset, QStringList(), KAAlarm::AUDIO_ALARM);
01128 else
01129 initKcalAlarm(ev, ancillaryTime, QStringList(), KAAlarm::AUDIO_ALARM);
01130 }
01131 if (!mPreAction.isEmpty())
01132 {
01133
01134 if (ancillaryType == 2)
01135 initKcalAlarm(ev, ancillaryOffset, QStringList(PRE_ACTION_TYPE), KAAlarm::PRE_ACTION_ALARM);
01136 else
01137 initKcalAlarm(ev, ancillaryTime, QStringList(PRE_ACTION_TYPE), KAAlarm::PRE_ACTION_ALARM);
01138 }
01139 if (!mPostAction.isEmpty())
01140 {
01141
01142 if (ancillaryType == 2)
01143 initKcalAlarm(ev, ancillaryOffset, QStringList(POST_ACTION_TYPE), KAAlarm::POST_ACTION_ALARM);
01144 else
01145 initKcalAlarm(ev, ancillaryTime, QStringList(POST_ACTION_TYPE), KAAlarm::POST_ACTION_ALARM);
01146 }
01147
01148 if (mRecurrence)
01149 mRecurrence->writeRecurrence(*ev.recurrence());
01150 else
01151 ev.clearRecurrence();
01152 if (mSaveDateTime.isValid())
01153 ev.setCreated(mSaveDateTime);
01154 ev.setReadOnly(readOnly);
01155 return true;
01156 }
01157
01158
01159
01160
01161
01162
01163 Alarm* KAEvent::initKcalAlarm(Event& event, const DateTime& dt, const QStringList& types, KAAlarm::Type type) const
01164 {
01165 int startOffset = dt.isDateOnly() ? mStartDateTime.secsTo(dt)
01166 : mStartDateTime.dateTime().secsTo(dt.dateTime());
01167 return initKcalAlarm(event, startOffset, types, type);
01168 }
01169
01170 Alarm* KAEvent::initKcalAlarm(Event& event, int startOffsetSecs, const QStringList& types, KAAlarm::Type type) const
01171 {
01172 QStringList alltypes;
01173 Alarm* alarm = event.newAlarm();
01174 alarm->setEnabled(true);
01175
01176
01177 alarm->setStartOffset(startOffsetSecs);
01178
01179 switch (type)
01180 {
01181 case KAAlarm::AUDIO_ALARM:
01182 alarm->setAudioAlarm(mAudioFile);
01183 if (mSpeak)
01184 alarm->setCustomProperty(APPNAME, SPEAK_PROPERTY, QString::fromLatin1("Y"));
01185 if (mRepeatSound)
01186 {
01187 alarm->setRepeatCount(-1);
01188 alarm->setSnoozeTime(0);
01189 }
01190 if (!mAudioFile.isEmpty() && mSoundVolume >= 0)
01191 alarm->setCustomProperty(APPNAME, VOLUME_PROPERTY,
01192 QString::fromLatin1("%1;%2;%3").arg(QString::number(mSoundVolume, 'f', 2))
01193 .arg(QString::number(mFadeVolume, 'f', 2))
01194 .arg(mFadeSeconds));
01195 break;
01196 case KAAlarm::PRE_ACTION_ALARM:
01197 setProcedureAlarm(alarm, mPreAction);
01198 break;
01199 case KAAlarm::POST_ACTION_ALARM:
01200 setProcedureAlarm(alarm, mPostAction);
01201 break;
01202 case KAAlarm::MAIN_ALARM:
01203 alarm->setSnoozeTime(mRepeatInterval);
01204 alarm->setRepeatCount(mRepeatCount);
01205
01206 case KAAlarm::INVALID_ALARM:
01207 switch (mActionType)
01208 {
01209 case T_FILE:
01210 alltypes += FILE_TYPE;
01211
01212 case T_MESSAGE:
01213 alarm->setDisplayAlarm(AlarmText::toCalendarText(mText));
01214 alarm->setCustomProperty(APPNAME, FONT_COLOUR_PROPERTY,
01215 QString::fromLatin1("%1;%2;%3").arg(mBgColour.name())
01216 .arg(mFgColour.name())
01217 .arg(mDefaultFont ? QString::null : mFont.toString()));
01218 break;
01219 case T_COMMAND:
01220 if (mCommandScript)
01221 alarm->setProcedureAlarm("", mText);
01222 else
01223 setProcedureAlarm(alarm, mText);
01224 break;
01225 case T_EMAIL:
01226 alarm->setEmailAlarm(mEmailSubject, mText, mEmailAddresses, mEmailAttachments);
01227 if (!mEmailFromKMail.isEmpty())
01228 alarm->setCustomProperty(APPNAME, KMAIL_ID_PROPERTY, mEmailFromKMail);
01229 break;
01230 case T_AUDIO:
01231 break;
01232 }
01233 break;
01234 case KAAlarm::REMINDER_ALARM:
01235 case KAAlarm::DEFERRED_ALARM:
01236 case KAAlarm::DEFERRED_REMINDER_ALARM:
01237 case KAAlarm::AT_LOGIN_ALARM:
01238 case KAAlarm::DISPLAYING_ALARM:
01239 break;
01240 }
01241 alltypes += types;
01242 if (alltypes.count() > 0)
01243 alarm->setCustomProperty(APPNAME, TYPE_PROPERTY, alltypes.join(","));
01244 return alarm;
01245 }
01246
01247
01248
01249
01250 KAAlarm KAEvent::alarm(KAAlarm::Type type) const
01251 {
01252 checkRecur();
01253 KAAlarm al;
01254 if (mAlarmCount)
01255 {
01256 al.mEventID = mEventID;
01257 al.mActionType = mActionType;
01258 al.mText = mText;
01259 al.mBgColour = mBgColour;
01260 al.mFgColour = mFgColour;
01261 al.mFont = mFont;
01262 al.mDefaultFont = mDefaultFont;
01263 al.mBeep = mBeep;
01264 al.mSpeak = mSpeak;
01265 al.mSoundVolume = mSoundVolume;
01266 al.mFadeVolume = mFadeVolume;
01267 al.mFadeSeconds = mFadeSeconds;
01268 al.mRepeatSound = mRepeatSound;
01269 al.mConfirmAck = mConfirmAck;
01270 al.mRepeatAtLogin = false;
01271 al.mDeferred = false;
01272 al.mLateCancel = mLateCancel;
01273 al.mAutoClose = mAutoClose;
01274 al.mEmailBcc = mEmailBcc;
01275 al.mCommandScript = mCommandScript;
01276 if (mActionType == T_EMAIL)
01277 {
01278 al.mEmailFromKMail = mEmailFromKMail;
01279 al.mEmailAddresses = mEmailAddresses;
01280 al.mEmailSubject = mEmailSubject;
01281 al.mEmailAttachments = mEmailAttachments;
01282 }
01283 switch (type)
01284 {
01285 case KAAlarm::MAIN_ALARM:
01286 if (!mMainExpired)
01287 {
01288 al.mType = KAAlarm::MAIN__ALARM;
01289 al.mNextMainDateTime = mNextMainDateTime;
01290 al.mRepeatCount = mRepeatCount;
01291 al.mRepeatInterval = mRepeatInterval;
01292 }
01293 break;
01294 case KAAlarm::REMINDER_ALARM:
01295 if (mReminderMinutes)
01296 {
01297 al.mType = KAAlarm::REMINDER__ALARM;
01298 if (mReminderOnceOnly)
01299 al.mNextMainDateTime = mStartDateTime.addMins(-mReminderMinutes);
01300 else
01301 al.mNextMainDateTime = mNextMainDateTime.addMins(-mReminderMinutes);
01302 }
01303 break;
01304 case KAAlarm::DEFERRED_REMINDER_ALARM:
01305 if (mDeferral != REMINDER_DEFERRAL)
01306 break;
01307
01308 case KAAlarm::DEFERRED_ALARM:
01309 if (mDeferral > 0)
01310 {
01311 al.mType = static_cast<KAAlarm::SubType>((mDeferral == REMINDER_DEFERRAL ? KAAlarm::DEFERRED_REMINDER_ALARM : KAAlarm::DEFERRED_ALARM)
01312 | (mDeferralTime.isDateOnly() ? 0 : KAAlarm::TIMED_DEFERRAL_FLAG));
01313 al.mNextMainDateTime = mDeferralTime;
01314 al.mDeferred = true;
01315 }
01316 break;
01317 case KAAlarm::AT_LOGIN_ALARM:
01318 if (mRepeatAtLogin)
01319 {
01320 al.mType = KAAlarm::AT_LOGIN__ALARM;
01321 al.mNextMainDateTime = mAtLoginDateTime;
01322 al.mRepeatAtLogin = true;
01323 al.mLateCancel = 0;
01324 al.mAutoClose = false;
01325 }
01326 break;
01327 case KAAlarm::DISPLAYING_ALARM:
01328 if (mDisplaying)
01329 {
01330 al.mType = KAAlarm::DISPLAYING__ALARM;
01331 al.mNextMainDateTime = mDisplayingTime;
01332 al.mDisplaying = true;
01333 }
01334 break;
01335 case KAAlarm::AUDIO_ALARM:
01336 case KAAlarm::PRE_ACTION_ALARM:
01337 case KAAlarm::POST_ACTION_ALARM:
01338 case KAAlarm::INVALID_ALARM:
01339 default:
01340 break;
01341 }
01342 }
01343 return al;
01344 }
01345
01346
01347
01348
01349
01350
01351
01352
01353 KAAlarm KAEvent::firstAlarm() const
01354 {
01355 if (mAlarmCount)
01356 {
01357 if (!mMainExpired)
01358 return alarm(KAAlarm::MAIN_ALARM);
01359 return nextAlarm(KAAlarm::MAIN_ALARM);
01360 }
01361 return KAAlarm();
01362 }
01363
01364
01365
01366
01367
01368
01369 KAAlarm KAEvent::nextAlarm(KAAlarm::Type prevType) const
01370 {
01371 switch (prevType)
01372 {
01373 case KAAlarm::MAIN_ALARM:
01374 if (mReminderMinutes)
01375 return alarm(KAAlarm::REMINDER_ALARM);
01376
01377 case KAAlarm::REMINDER_ALARM:
01378
01379 if (mDeferral == REMINDER_DEFERRAL)
01380 return alarm(KAAlarm::DEFERRED_REMINDER_ALARM);
01381 if (mDeferral == NORMAL_DEFERRAL)
01382 return alarm(KAAlarm::DEFERRED_ALARM);
01383
01384 case KAAlarm::DEFERRED_REMINDER_ALARM:
01385 case KAAlarm::DEFERRED_ALARM:
01386 if (mRepeatAtLogin)
01387 return alarm(KAAlarm::AT_LOGIN_ALARM);
01388
01389 case KAAlarm::AT_LOGIN_ALARM:
01390 if (mDisplaying)
01391 return alarm(KAAlarm::DISPLAYING_ALARM);
01392
01393 case KAAlarm::DISPLAYING_ALARM:
01394
01395 case KAAlarm::AUDIO_ALARM:
01396 case KAAlarm::PRE_ACTION_ALARM:
01397 case KAAlarm::POST_ACTION_ALARM:
01398 case KAAlarm::INVALID_ALARM:
01399 default:
01400 break;
01401 }
01402 return KAAlarm();
01403 }
01404
01405
01406
01407
01408
01409
01410 void KAEvent::removeExpiredAlarm(KAAlarm::Type type)
01411 {
01412 int count = mAlarmCount;
01413 switch (type)
01414 {
01415 case KAAlarm::MAIN_ALARM:
01416 mAlarmCount = 0;
01417 break;
01418 case KAAlarm::AT_LOGIN_ALARM:
01419 if (mRepeatAtLogin)
01420 {
01421
01422 mArchiveRepeatAtLogin = true;
01423 mRepeatAtLogin = false;
01424 --mAlarmCount;
01425 }
01426 break;
01427 case KAAlarm::REMINDER_ALARM:
01428
01429 set_archiveReminder();
01430 break;
01431 case KAAlarm::DEFERRED_REMINDER_ALARM:
01432 case KAAlarm::DEFERRED_ALARM:
01433 set_deferral(NO_DEFERRAL);
01434 break;
01435 case KAAlarm::DISPLAYING_ALARM:
01436 if (mDisplaying)
01437 {
01438 mDisplaying = false;
01439 --mAlarmCount;
01440 }
01441 break;
01442 case KAAlarm::AUDIO_ALARM:
01443 case KAAlarm::PRE_ACTION_ALARM:
01444 case KAAlarm::POST_ACTION_ALARM:
01445 case KAAlarm::INVALID_ALARM:
01446 default:
01447 break;
01448 }
01449 if (mAlarmCount != count)
01450 mUpdated = true;
01451 }
01452
01453
01454
01455
01456
01457
01458
01459
01460 bool KAEvent::defer(const DateTime& dateTime, bool reminder, bool adjustRecurrence)
01461 {
01462 bool result = false;
01463 cancelCancelledDeferral();
01464 if (checkRecur() == KARecurrence::NO_RECUR)
01465 {
01466 if (mReminderMinutes || mDeferral == REMINDER_DEFERRAL || mArchiveReminderMinutes)
01467 {
01468 if (dateTime < mNextMainDateTime.dateTime())
01469 {
01470 set_deferral(REMINDER_DEFERRAL);
01471 mDeferralTime = dateTime;
01472 }
01473 else
01474 {
01475
01476 if (mReminderMinutes || mDeferral == REMINDER_DEFERRAL)
01477 set_deferral(NO_DEFERRAL);
01478 }
01479
01480 set_archiveReminder();
01481 }
01482 if (mDeferral != REMINDER_DEFERRAL)
01483 {
01484
01485 if (mRepeatCount && dateTime < mainEndRepeatTime())
01486 {
01487
01488 set_deferral(NORMAL_DEFERRAL);
01489 mDeferralTime = dateTime;
01490 result = true;
01491 }
01492 else
01493 {
01494
01495 mNextMainDateTime = mDeferralTime = dateTime;
01496 set_deferral(NORMAL_DEFERRAL);
01497 if (!mMainExpired)
01498 {
01499
01500 mMainExpired = true;
01501 --mAlarmCount;
01502 if (mRepeatAtLogin)
01503 {
01504
01505 mArchiveRepeatAtLogin = true;
01506 mRepeatAtLogin = false;
01507 --mAlarmCount;
01508 }
01509 }
01510 }
01511 }
01512 }
01513 else if (reminder)
01514 {
01515
01516 if (dateTime >= mNextMainDateTime.dateTime())
01517 set_deferral(NO_DEFERRAL);
01518 else
01519 {
01520 set_deferral(REMINDER_DEFERRAL);
01521 mDeferralTime = dateTime;
01522 }
01523 }
01524 else
01525 {
01526 mDeferralTime = dateTime;
01527 if (mDeferral <= 0)
01528 set_deferral(NORMAL_DEFERRAL);
01529 if (adjustRecurrence)
01530 {
01531 QDateTime now = QDateTime::currentDateTime();
01532 if (mainEndRepeatTime() < now)
01533 {
01534
01535
01536 if (!mMainExpired && setNextOccurrence(now, true) == NO_OCCURRENCE)
01537 {
01538 mMainExpired = true;
01539 --mAlarmCount;
01540 }
01541 }
01542 }
01543 }
01544 mUpdated = true;
01545 return result;
01546 }
01547
01548
01549
01550
01551 void KAEvent::cancelDefer()
01552 {
01553 if (mDeferral > 0)
01554 {
01555
01556
01557 if (mMainExpired
01558 || nextOccurrence(QDateTime::currentDateTime(), mDeferralTime, RETURN_REPETITION) == NO_OCCURRENCE)
01559 {
01560
01561 mDeferralTime = DateTime();
01562 set_deferral(NO_DEFERRAL);
01563 }
01564 else
01565 set_deferral(CANCEL_DEFERRAL);
01566 mUpdated = true;
01567 }
01568 }
01569
01570
01571
01572
01573 void KAEvent::cancelCancelledDeferral()
01574 {
01575 if (mDeferral == CANCEL_DEFERRAL)
01576 {
01577 mDeferralTime = DateTime();
01578 set_deferral(NO_DEFERRAL);
01579 }
01580 }
01581
01582
01583
01584
01585 DateTime KAEvent::deferralLimit(KAEvent::DeferLimitType* limitType) const
01586 {
01587 DeferLimitType ltype;
01588 DateTime endTime;
01589 bool recurs = (checkRecur() != KARecurrence::NO_RECUR);
01590 if (recurs || mRepeatCount)
01591 {
01592
01593
01594 DateTime reminderTime;
01595 QDateTime now = QDateTime::currentDateTime();
01596 OccurType type = nextOccurrence(now, endTime, RETURN_REPETITION);
01597 if (type & OCCURRENCE_REPEAT)
01598 ltype = LIMIT_REPETITION;
01599 else if (type == NO_OCCURRENCE)
01600 ltype = LIMIT_NONE;
01601 else if (mReminderMinutes && (now < (reminderTime = endTime.addMins(-mReminderMinutes))))
01602 {
01603 endTime = reminderTime;
01604 ltype = LIMIT_REMINDER;
01605 }
01606 else if (type == FIRST_OR_ONLY_OCCURRENCE && !recurs)
01607 ltype = LIMIT_REPETITION;
01608 else
01609 ltype = LIMIT_RECURRENCE;
01610 }
01611 else if ((mReminderMinutes || mDeferral == REMINDER_DEFERRAL || mArchiveReminderMinutes)
01612 && QDateTime::currentDateTime() < mNextMainDateTime.dateTime())
01613 {
01614
01615 endTime = mNextMainDateTime;
01616 ltype = LIMIT_REMINDER;
01617 }
01618 else
01619 ltype = LIMIT_NONE;
01620 if (ltype != LIMIT_NONE)
01621 endTime = endTime.addMins(-1);
01622 if (limitType)
01623 *limitType = ltype;
01624 return endTime;
01625 }
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636 bool KAEvent::setDisplaying(const KAEvent& event, KAAlarm::Type alarmType, const QDateTime& repeatAtLoginTime)
01637 {
01638 if (!mDisplaying
01639 && (alarmType == KAAlarm::MAIN_ALARM
01640 || alarmType == KAAlarm::REMINDER_ALARM
01641 || alarmType == KAAlarm::DEFERRED_REMINDER_ALARM
01642 || alarmType == KAAlarm::DEFERRED_ALARM
01643 || alarmType == KAAlarm::AT_LOGIN_ALARM))
01644 {
01645
01646 KAAlarm al = event.alarm(alarmType);
01647 if (al.valid())
01648 {
01649 *this = event;
01650 setUid(DISPLAYING);
01651 mDisplaying = true;
01652 mDisplayingTime = (alarmType == KAAlarm::AT_LOGIN_ALARM) ? repeatAtLoginTime : al.dateTime();
01653 switch (al.type())
01654 {
01655 case KAAlarm::AT_LOGIN__ALARM: mDisplayingFlags = REPEAT_AT_LOGIN; break;
01656 case KAAlarm::REMINDER__ALARM: mDisplayingFlags = REMINDER; break;
01657 case KAAlarm::DEFERRED_REMINDER_TIME__ALARM: mDisplayingFlags = REMINDER | TIME_DEFERRAL; break;
01658 case KAAlarm::DEFERRED_REMINDER_DATE__ALARM: mDisplayingFlags = REMINDER | DATE_DEFERRAL; break;
01659 case KAAlarm::DEFERRED_TIME__ALARM: mDisplayingFlags = TIME_DEFERRAL; break;
01660 case KAAlarm::DEFERRED_DATE__ALARM: mDisplayingFlags = DATE_DEFERRAL; break;
01661 default: mDisplayingFlags = 0; break;
01662 }
01663 ++mAlarmCount;
01664 mUpdated = true;
01665 return true;
01666 }
01667 }
01668 return false;
01669 }
01670
01671
01672
01673
01674 KAAlarm KAEvent::convertDisplayingAlarm() const
01675 {
01676 KAAlarm al;
01677 if (mDisplaying)
01678 {
01679 al = alarm(KAAlarm::DISPLAYING_ALARM);
01680 if (mDisplayingFlags & REPEAT_AT_LOGIN)
01681 {
01682 al.mRepeatAtLogin = true;
01683 al.mType = KAAlarm::AT_LOGIN__ALARM;
01684 }
01685 else if (mDisplayingFlags & DEFERRAL)
01686 {
01687 al.mDeferred = true;
01688 al.mType = (mDisplayingFlags == (REMINDER | DATE_DEFERRAL)) ? KAAlarm::DEFERRED_REMINDER_DATE__ALARM
01689 : (mDisplayingFlags == (REMINDER | TIME_DEFERRAL)) ? KAAlarm::DEFERRED_REMINDER_TIME__ALARM
01690 : (mDisplayingFlags == DATE_DEFERRAL) ? KAAlarm::DEFERRED_DATE__ALARM
01691 : KAAlarm::DEFERRED_TIME__ALARM;
01692 }
01693 else if (mDisplayingFlags & REMINDER)
01694 al.mType = KAAlarm::REMINDER__ALARM;
01695 else
01696 al.mType = KAAlarm::MAIN__ALARM;
01697 }
01698 return al;
01699 }
01700
01701
01702
01703
01704 void KAEvent::reinstateFromDisplaying(const KAEvent& dispEvent)
01705 {
01706 if (dispEvent.mDisplaying)
01707 {
01708 *this = dispEvent;
01709 setUid(ACTIVE);
01710 mDisplaying = false;
01711 --mAlarmCount;
01712 mUpdated = true;
01713 }
01714 }
01715
01716
01717
01718
01719
01720
01721 bool KAEvent::occursAfter(const QDateTime& preDateTime, bool includeRepetitions) const
01722 {
01723 QDateTime dt;
01724 if (checkRecur() != KARecurrence::NO_RECUR)
01725 {
01726 if (mRecurrence->duration() < 0)
01727 return true;
01728 dt = mRecurrence->endDateTime();
01729 }
01730 else
01731 dt = mNextMainDateTime.dateTime();
01732 if (mStartDateTime.isDateOnly())
01733 {
01734 QDate pre = preDateTime.date();
01735 if (preDateTime.time() < Preferences::startOfDay())
01736 pre = pre.addDays(-1);
01737 if (pre < dt.date())
01738 return true;
01739 }
01740 else if (preDateTime < dt)
01741 return true;
01742
01743 if (includeRepetitions && mRepeatCount)
01744 {
01745 dt.addSecs(mRepeatCount * mRepeatInterval * 60);
01746 if (preDateTime < dt)
01747 return true;
01748 }
01749 return false;
01750 }
01751
01752
01753
01754
01755
01756
01757 KAEvent::OccurType KAEvent::nextOccurrence(const QDateTime& preDateTime, DateTime& result,
01758 KAEvent::OccurOption includeRepetitions) const
01759 {
01760 int repeatSecs = 0;
01761 QDateTime pre = preDateTime;
01762 if (includeRepetitions != IGNORE_REPETITION)
01763 {
01764 if (!mRepeatCount)
01765 includeRepetitions = IGNORE_REPETITION;
01766 else
01767 {
01768 repeatSecs = mRepeatInterval * 60;
01769 pre = preDateTime.addSecs(-mRepeatCount * repeatSecs);
01770 }
01771 }
01772
01773 OccurType type;
01774 bool recurs = (checkRecur() != KARecurrence::NO_RECUR);
01775 if (recurs)
01776 {
01777 int remainingCount;
01778 type = nextRecurrence(pre, result, remainingCount);
01779 }
01780 else if (pre < mNextMainDateTime.dateTime())
01781 {
01782 result = mNextMainDateTime;
01783 type = FIRST_OR_ONLY_OCCURRENCE;
01784 }
01785 else
01786 {
01787 result = DateTime();
01788 type = NO_OCCURRENCE;
01789 }
01790
01791 if (type != NO_OCCURRENCE && result <= preDateTime)
01792 {
01793
01794 int repetition = result.secsTo(preDateTime) / repeatSecs + 1;
01795 DateTime repeatDT = result.addSecs(repetition * repeatSecs);
01796 if (recurs)
01797 {
01798
01799
01800
01801
01802 DateTime dt;
01803 OccurType newType = previousOccurrence(repeatDT.dateTime(), dt, false);
01804 if (dt > result)
01805 {
01806 type = newType;
01807 result = dt;
01808 if (includeRepetitions == RETURN_REPETITION && result <= preDateTime)
01809 {
01810
01811 int repetition = result.secsTo(preDateTime) / repeatSecs + 1;
01812 result = result.addSecs(repetition * repeatSecs);
01813 type = static_cast<OccurType>(type | OCCURRENCE_REPEAT);
01814 }
01815 return type;
01816 }
01817 }
01818 if (includeRepetitions == RETURN_REPETITION)
01819 {
01820
01821 result = repeatDT;
01822 type = static_cast<OccurType>(type | OCCURRENCE_REPEAT);
01823 }
01824 }
01825 return type;
01826 }
01827
01828
01829
01830
01831
01832
01833
01834
01835 KAEvent::OccurType KAEvent::previousOccurrence(const QDateTime& afterDateTime, DateTime& result, bool includeRepetitions) const
01836 {
01837 if (mStartDateTime >= afterDateTime)
01838 {
01839 result = QDateTime();
01840 return NO_OCCURRENCE;
01841 }
01842
01843
01844 OccurType type;
01845 if (checkRecur() == KARecurrence::NO_RECUR)
01846 {
01847 result = mStartDateTime;
01848 type = FIRST_OR_ONLY_OCCURRENCE;
01849 }
01850 else
01851 {
01852 QDateTime recurStart = mRecurrence->startDateTime();
01853 QDateTime after = afterDateTime;
01854 if (mStartDateTime.isDateOnly() && afterDateTime.time() > Preferences::startOfDay())
01855 after = after.addDays(1);
01856 QDateTime dt = mRecurrence->getPreviousDateTime(after);
01857 result.set(dt, mStartDateTime.isDateOnly());
01858 if (!dt.isValid())
01859 return NO_OCCURRENCE;
01860 if (dt == recurStart)
01861 type = FIRST_OR_ONLY_OCCURRENCE;
01862 else if (mRecurrence->getNextDateTime(dt).isValid())
01863 type = result.isDateOnly() ? RECURRENCE_DATE : RECURRENCE_DATE_TIME;
01864 else
01865 type = LAST_RECURRENCE;
01866 }
01867
01868 if (includeRepetitions && mRepeatCount)
01869 {
01870
01871
01872
01873 int repeatSecs = mRepeatInterval * 60;
01874 DateTime lastRepetition = result.addSecs(mRepeatCount * repeatSecs);
01875 if (lastRepetition < afterDateTime)
01876 {
01877 result = lastRepetition;
01878 return static_cast<OccurType>(type | OCCURRENCE_REPEAT);
01879 }
01880 int repetition = (result.dateTime().secsTo(afterDateTime) - 1) / repeatSecs;
01881 if (repetition > 0)
01882 {
01883 result = result.addSecs(repetition * repeatSecs);
01884 return static_cast<OccurType>(type | OCCURRENCE_REPEAT);
01885 }
01886 }
01887 return type;
01888 }
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898 KAEvent::OccurType KAEvent::setNextOccurrence(const QDateTime& preDateTime, bool includeRepetitions)
01899 {
01900 if (preDateTime < mNextMainDateTime.dateTime())
01901 return FIRST_OR_ONLY_OCCURRENCE;
01902 QDateTime pre = preDateTime;
01903 if (includeRepetitions)
01904 {
01905 if (!mRepeatCount)
01906 includeRepetitions = false;
01907 else
01908 pre = preDateTime.addSecs(-mRepeatCount * mRepeatInterval * 60);
01909 }
01910
01911 DateTime dt;
01912 OccurType type;
01913 if (pre < mNextMainDateTime.dateTime())
01914 {
01915 dt = mNextMainDateTime;
01916 type = FIRST_OR_ONLY_OCCURRENCE;
01917 }
01918 else if (checkRecur() != KARecurrence::NO_RECUR)
01919 {
01920 int remainingCount;
01921 type = nextRecurrence(pre, dt, remainingCount);
01922 if (type == NO_OCCURRENCE)
01923 return NO_OCCURRENCE;
01924 if (type != FIRST_OR_ONLY_OCCURRENCE && dt != mNextMainDateTime)
01925 {
01926
01927 mNextMainDateTime = dt;
01928 if (mRecurrence->duration() > 0)
01929 mRemainingRecurrences = remainingCount;
01930
01931 if (mDeferral == REMINDER_DEFERRAL || mArchiveReminderMinutes)
01932 {
01933 if (mReminderOnceOnly)
01934 {
01935 if (mReminderMinutes)
01936 set_archiveReminder();
01937 }
01938 else
01939 set_reminder(mArchiveReminderMinutes);
01940 }
01941 if (mDeferral == REMINDER_DEFERRAL)
01942 set_deferral(NO_DEFERRAL);
01943 mUpdated = true;
01944 }
01945 }
01946 else
01947 return NO_OCCURRENCE;
01948
01949 if (includeRepetitions && dt.dateTime() <= preDateTime)
01950 {
01951
01952 type = static_cast<OccurType>(type | OCCURRENCE_REPEAT);
01953
01954 if (mReminderMinutes)
01955 set_archiveReminder();
01956 if (mDeferral == REMINDER_DEFERRAL)
01957 set_deferral(NO_DEFERRAL);
01958 mUpdated = true;
01959 }
01960 return type;
01961 }
01962
01963
01964
01965
01966
01967
01968
01969 KAEvent::OccurType KAEvent::nextRecurrence(const QDateTime& preDateTime, DateTime& result, int& remainingCount) const
01970 {
01971 QDateTime recurStart = mRecurrence->startDateTime();
01972 QDateTime pre = preDateTime;
01973 if (mStartDateTime.isDateOnly() && preDateTime.time() < Preferences::startOfDay())
01974 pre = pre.addDays(-1);
01975 remainingCount = 0;
01976 QDateTime dt = mRecurrence->getNextDateTime(pre);
01977 result.set(dt, mStartDateTime.isDateOnly());
01978 if (!dt.isValid())
01979 return NO_OCCURRENCE;
01980 if (dt == recurStart)
01981 {
01982 remainingCount = mRecurrence->duration();
01983 return FIRST_OR_ONLY_OCCURRENCE;
01984 }
01985 remainingCount = mRecurrence->duration() - mRecurrence->durationTo(dt) + 1;
01986 if (remainingCount == 1)
01987 return LAST_RECURRENCE;
01988 return result.isDateOnly() ? RECURRENCE_DATE : RECURRENCE_DATE_TIME;
01989 }
01990
01991
01992
01993
01994 QString KAEvent::recurrenceText(bool brief) const
01995 {
01996 if (mRepeatAtLogin)
01997 return brief ? i18n("Brief form of 'At Login'", "Login") : i18n("At login");
01998 if (mRecurrence)
01999 {
02000 int frequency = mRecurrence->frequency();
02001 switch (mRecurrence->defaultRRuleConst()->recurrenceType())
02002 {
02003 case RecurrenceRule::rMinutely:
02004 if (frequency < 60)
02005 return i18n("1 Minute", "%n Minutes", frequency);
02006 else if (frequency % 60 == 0)
02007 return i18n("1 Hour", "%n Hours", frequency/60);
02008 else
02009 {
02010 QString mins;
02011 return i18n("Hours and Minutes", "%1H %2M").arg(QString::number(frequency/60)).arg(mins.sprintf("%02d", frequency%60));
02012 }
02013 case RecurrenceRule::rDaily:
02014 return i18n("1 Day", "%n Days", frequency);
02015 case RecurrenceRule::rWeekly:
02016 return i18n("1 Week", "%n Weeks", frequency);
02017 case RecurrenceRule::rMonthly:
02018 return i18n("1 Month", "%n Months", frequency);
02019 case RecurrenceRule::rYearly:
02020 return i18n("1 Year", "%n Years", frequency);
02021 case RecurrenceRule::rNone:
02022 default:
02023 break;
02024 }
02025 }
02026 return brief ? QString::null : i18n("None");
02027 }
02028
02029
02030
02031
02032 QString KAEvent::repetitionText(bool brief) const
02033 {
02034 if (mRepeatCount)
02035 {
02036 if (mRepeatInterval % 1440)
02037 {
02038 if (mRepeatInterval < 60)
02039 return i18n("1 Minute", "%n Minutes", mRepeatInterval);
02040 if (mRepeatInterval % 60 == 0)
02041 return i18n("1 Hour", "%n Hours", mRepeatInterval/60);
02042 QString mins;
02043 return i18n("Hours and Minutes", "%1H %2M").arg(QString::number(mRepeatInterval/60)).arg(mins.sprintf("%02d", mRepeatInterval%60));
02044 }
02045 if (mRepeatInterval % (7*1440))
02046 return i18n("1 Day", "%n Days", mRepeatInterval/1440);
02047 return i18n("1 Week", "%n Weeks", mRepeatInterval/(7*1440));
02048 }
02049 return brief ? QString::null : i18n("None");
02050 }
02051
02052
02053
02054
02055
02056
02057 void KAEvent::setFirstRecurrence()
02058 {
02059 switch (checkRecur())
02060 {
02061 case KARecurrence::NO_RECUR:
02062 case KARecurrence::MINUTELY:
02063 return;
02064 case KARecurrence::ANNUAL_DATE:
02065 case KARecurrence::ANNUAL_POS:
02066 if (mRecurrence->yearMonths().isEmpty())
02067 return;
02068 break;
02069 case KARecurrence::DAILY:
02070 case KARecurrence::WEEKLY:
02071 case KARecurrence::MONTHLY_POS:
02072 case KARecurrence::MONTHLY_DAY:
02073 break;
02074 }
02075 QDateTime recurStart = mRecurrence->startDateTime();
02076 if (mRecurrence->recursOn(recurStart.date()))
02077 return;
02078
02079
02080 int frequency = mRecurrence->frequency();
02081 mRecurrence->setFrequency(1);
02082 int remainingCount;
02083 DateTime next;
02084 nextRecurrence(mNextMainDateTime.dateTime(), next, remainingCount);
02085 if (!next.isValid())
02086 mRecurrence->setStartDateTime(recurStart);
02087 else
02088 {
02089 mRecurrence->setStartDateTime(next.dateTime());
02090 mStartDateTime = mNextMainDateTime = next;
02091 mUpdated = true;
02092 }
02093 mRecurrence->setFrequency(frequency);
02094 }
02095
02096
02097
02098
02099
02100 void KAEvent::setRecurrence(const KARecurrence& recurrence)
02101 {
02102 mUpdated = true;
02103 delete mRecurrence;
02104 if (recurrence.doesRecur())
02105 {
02106 mRecurrence = new KARecurrence(recurrence);
02107 mRecurrence->setStartDateTime(mStartDateTime.dateTime());
02108 mRecurrence->setFloats(mStartDateTime.isDateOnly());
02109 mRemainingRecurrences = mRecurrence->duration();
02110 if (mRemainingRecurrences > 0 && !isTemplate())
02111 mRemainingRecurrences -= mRecurrence->durationTo(mNextMainDateTime.dateTime()) - 1;
02112 }
02113 else
02114 {
02115 mRecurrence = 0;
02116 mRemainingRecurrences = 0;
02117 }
02118
02119
02120 setRepetition(mRepeatInterval, mRepeatCount);
02121 }
02122
02123
02124
02125
02126
02127
02128 bool KAEvent::setRepetition(int interval, int count)
02129 {
02130 mUpdated = true;
02131 mRepeatInterval = 0;
02132 mRepeatCount = 0;
02133 if (interval > 0 && count > 0 && !mRepeatAtLogin)
02134 {
02135 if (interval % 1440 && mStartDateTime.isDateOnly())
02136 return false;
02137 if (checkRecur() != KARecurrence::NO_RECUR)
02138 {
02139 int longestInterval = mRecurrence->longestInterval() - 1;
02140 if (interval * count > longestInterval)
02141 count = longestInterval / interval;
02142 }
02143 mRepeatInterval = interval;
02144 mRepeatCount = count;
02145 }
02146 return true;
02147 }
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159 bool KAEvent::setRecurMinutely(int freq, int count, const QDateTime& end)
02160 {
02161 return setRecur(RecurrenceRule::rMinutely, freq, count, end);
02162 }
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175 bool KAEvent::setRecurDaily(int freq, const QBitArray& days, int count, const QDate& end)
02176 {
02177 if (!setRecur(RecurrenceRule::rDaily, freq, count, end))
02178 return false;
02179 int n = 0;
02180 for (int i = 0; i < 7; ++i)
02181 {
02182 if (days.testBit(i))
02183 ++n;
02184 }
02185 if (n < 7)
02186 mRecurrence->addWeeklyDays(days);
02187 return true;
02188 }
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201 bool KAEvent::setRecurWeekly(int freq, const QBitArray& days, int count, const QDate& end)
02202 {
02203 if (!setRecur(RecurrenceRule::rWeekly, freq, count, end))
02204 return false;
02205 mRecurrence->addWeeklyDays(days);
02206 return true;
02207 }
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220 bool KAEvent::setRecurMonthlyByDate(int freq, const QValueList<int>& days, int count, const QDate& end)
02221 {
02222 if (!setRecur(RecurrenceRule::rMonthly, freq, count, end))
02223 return false;
02224 for (QValueListConstIterator<int> it = days.begin(); it != days.end(); ++it)
02225 mRecurrence->addMonthlyDate(*it);
02226 return true;
02227 }
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241 bool KAEvent::setRecurMonthlyByPos(int freq, const QValueList<MonthPos>& posns, int count, const QDate& end)
02242 {
02243 if (!setRecur(RecurrenceRule::rMonthly, freq, count, end))
02244 return false;
02245 for (QValueListConstIterator<MonthPos> it = posns.begin(); it != posns.end(); ++it)
02246 mRecurrence->addMonthlyPos((*it).weeknum, (*it).days);
02247 return true;
02248 }
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264 bool KAEvent::setRecurAnnualByDate(int freq, const QValueList<int>& months, int day, KARecurrence::Feb29Type feb29, int count, const QDate& end)
02265 {
02266 if (!setRecur(RecurrenceRule::rYearly, freq, count, end, feb29))
02267 return false;
02268 for (QValueListConstIterator<int> it = months.begin(); it != months.end(); ++it)
02269 mRecurrence->addYearlyMonth(*it);
02270 if (day)
02271 mRecurrence->addMonthlyDate(day);
02272 return true;
02273 }
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288 bool KAEvent::setRecurAnnualByPos(int freq, const QValueList<MonthPos>& posns, const QValueList<int>& months, int count, const QDate& end)
02289 {
02290 if (!setRecur(RecurrenceRule::rYearly, freq, count, end))
02291 return false;
02292 for (QValueListConstIterator<int> it = months.begin(); it != months.end(); ++it)
02293 mRecurrence->addYearlyMonth(*it);
02294 for (QValueListConstIterator<MonthPos> it = posns.begin(); it != posns.end(); ++it)
02295 mRecurrence->addYearlyPos((*it).weeknum, (*it).days);
02296 return true;
02297 }
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309 bool KAEvent::setRecur(RecurrenceRule::PeriodType recurType, int freq, int count, const QDateTime& end, KARecurrence::Feb29Type feb29)
02310 {
02311 if (count >= -1 && (count || end.date().isValid()))
02312 {
02313 if (!mRecurrence)
02314 mRecurrence = new KARecurrence;
02315 if (mRecurrence->init(recurType, freq, count, mNextMainDateTime, end, feb29))
02316 {
02317 mUpdated = true;
02318 mRemainingRecurrences = count;
02319 return true;
02320 }
02321 }
02322 clearRecur();
02323 return false;
02324 }
02325
02326
02327
02328
02329 void KAEvent::clearRecur()
02330 {
02331 mUpdated = true;
02332 delete mRecurrence;
02333 mRecurrence = 0;
02334 mRemainingRecurrences = 0;
02335 }
02336
02337
02338
02339
02340
02341
02342 KARecurrence::Type KAEvent::checkRecur() const
02343 {
02344 if (mRecurrence)
02345 {
02346 KARecurrence::Type type = mRecurrence->type();
02347 switch (type)
02348 {
02349 case KARecurrence::MINUTELY:
02350 case KARecurrence::DAILY:
02351 case KARecurrence::WEEKLY:
02352 case KARecurrence::MONTHLY_DAY:
02353 case KARecurrence::MONTHLY_POS:
02354 case KARecurrence::ANNUAL_DATE:
02355 case KARecurrence::ANNUAL_POS:
02356 return type;
02357 default:
02358 if (mRecurrence)
02359 {
02360 delete mRecurrence;
02361 const_cast<KAEvent*>(this)->mRecurrence = 0;
02362 }
02363 break;
02364 }
02365 }
02366 return KARecurrence::NO_RECUR;
02367 }
02368
02369
02370
02371
02372
02373 int KAEvent::recurInterval() const
02374 {
02375 if (mRecurrence)
02376 {
02377 switch (mRecurrence->type())
02378 {
02379 case KARecurrence::MINUTELY:
02380 case KARecurrence::DAILY:
02381 case KARecurrence::WEEKLY:
02382 case KARecurrence::MONTHLY_DAY:
02383 case KARecurrence::MONTHLY_POS:
02384 case KARecurrence::ANNUAL_DATE:
02385 case KARecurrence::ANNUAL_POS:
02386 return mRecurrence->frequency();
02387 default:
02388 break;
02389 }
02390 }
02391 return 0;
02392 }
02393
02394 #if 0
02395
02396
02397
02398 QValueList<KAEvent::MonthPos> KAEvent::convRecurPos(const QValueList<KCal::RecurrenceRule::WDayPos>& wdaypos)
02399 {
02400 QValueList<MonthPos> mposns;
02401 for (QValueList<KCal::RecurrenceRule::WDayPos>::ConstIterator it = wdaypos.begin(); it != wdaypos.end(); ++it)
02402 {
02403 int daybit = (*it).day() - 1;
02404 int weeknum = (*it).pos();
02405 bool found = false;
02406 for (QValueList<MonthPos>::Iterator mit = mposns.begin(); mit != mposns.end(); ++mit)
02407 {
02408 if ((*mit).weeknum == weeknum)
02409 {
02410 (*mit).days.setBit(daybit);
02411 found = true;
02412 break;
02413 }
02414 }
02415 if (!found)
02416 {
02417 MonthPos mpos;
02418 mpos.days.fill(false);
02419 mpos.days.setBit(daybit);
02420 mpos.weeknum = weeknum;
02421 mposns.append(mpos);
02422 }
02423 }
02424 return mposns;
02425 }
02426 #endif
02427
02428
02429
02430
02431
02432 KAEvent KAEvent::findTemplateName(AlarmCalendar& calendar, const QString& name)
02433 {
02434 KAEvent event;
02435 Event::List events = calendar.events();
02436 for (Event::List::ConstIterator evit = events.begin(); evit != events.end(); ++evit)
02437 {
02438 Event* ev = *evit;
02439 if (ev->summary() == name)
02440 {
02441 event.set(*ev);
02442 if (!event.isTemplate())
02443 return KAEvent();
02444 break;
02445 }
02446 }
02447 return event;
02448 }
02449
02450
02451
02452
02453
02454
02455
02456 bool KAEvent::adjustStartOfDay(const Event::List& events)
02457 {
02458 bool changed = false;
02459 QTime startOfDay = Preferences::startOfDay();
02460 for (Event::List::ConstIterator evit = events.begin(); evit != events.end(); ++evit)
02461 {
02462 Event* event = *evit;
02463 const QStringList& cats = event->categories();
02464 if (cats.find(DATE_ONLY_CATEGORY) != cats.end())
02465 {
02466
02467 QTime oldTime = event->dtStart().time();
02468 int adjustment = oldTime.secsTo(startOfDay);
02469 if (adjustment)
02470 {
02471 event->setDtStart(QDateTime(event->dtStart().date(), startOfDay));
02472 Alarm::List alarms = event->alarms();
02473 int deferralOffset = 0;
02474 for (Alarm::List::ConstIterator alit = alarms.begin(); alit != alarms.end(); ++alit)
02475 {
02476
02477 Alarm& alarm = **alit;
02478 AlarmData data;
02479 readAlarm(alarm, data);
02480 if (data.type & KAAlarm::TIMED_DEFERRAL_FLAG)
02481 {
02482
02483 deferralOffset = alarm.startOffset().asSeconds();
02484 alarm.setStartOffset(deferralOffset - adjustment);
02485 }
02486 else if (data.type == KAAlarm::AUDIO__ALARM
02487 && alarm.startOffset().asSeconds() == deferralOffset)
02488 {
02489
02490 alarm.setStartOffset(deferralOffset - adjustment);
02491 }
02492 }
02493 changed = true;
02494 }
02495 }
02496 else
02497 {
02498
02499 int deferralOffset = 0;
02500 int newDeferralOffset = 0;
02501 AlarmMap alarmMap;
02502 readAlarms(*event, &alarmMap);
02503 for (AlarmMap::Iterator it = alarmMap.begin(); it != alarmMap.end(); ++it)
02504 {
02505 const AlarmData& data = it.data();
02506 if ((data.type & KAAlarm::DEFERRED_ALARM)
02507 && !(data.type & KAAlarm::TIMED_DEFERRAL_FLAG))
02508 {
02509
02510 QDateTime altime = data.alarm->time();
02511 altime.setTime(startOfDay);
02512 deferralOffset = data.alarm->startOffset().asSeconds();
02513 newDeferralOffset = event->dtStart().secsTo(altime);
02514 const_cast<Alarm*>(data.alarm)->setStartOffset(newDeferralOffset);
02515 changed = true;
02516 }
02517 else if (data.type == KAAlarm::AUDIO__ALARM
02518 && data.alarm->startOffset().asSeconds() == deferralOffset)
02519 {
02520
02521 const_cast<Alarm*>(data.alarm)->setStartOffset(newDeferralOffset);
02522 changed = true;
02523 }
02524 }
02525 }
02526 }
02527 return changed;
02528 }
02529
02530
02531
02532
02533
02534
02535 void KAEvent::convertKCalEvents(KCal::Calendar& calendar, int version, bool adjustSummerTime)
02536 {
02537
02538 static const QChar SEPARATOR = ';';
02539 static const QChar LATE_CANCEL_CODE = 'C';
02540 static const QChar AT_LOGIN_CODE = 'L';
02541 static const QChar DEFERRAL_CODE = 'D';
02542 static const QString TEXT_PREFIX = QString::fromLatin1("TEXT:");
02543 static const QString FILE_PREFIX = QString::fromLatin1("FILE:");
02544 static const QString COMMAND_PREFIX = QString::fromLatin1("CMD:");
02545
02546
02547 static const QString BEEP_CATEGORY = QString::fromLatin1("BEEP");
02548
02549
02550 static const QString LATE_CANCEL_CAT = QString::fromLatin1("LATECANCEL");
02551
02552
02553 static const QString TEMPL_DEF_TIME_CAT = QString::fromLatin1("TMPLDEFTIME");
02554
02555
02556 static const QString EXEC_IN_XTERM_CAT = QString::fromLatin1("XTERM");
02557
02558 if (version >= calVersion())
02559 return;
02560
02561 kdDebug(5950) << "KAEvent::convertKCalEvents(): adjusting version " << version << endl;
02562 bool pre_0_7 = (version < KAlarm::Version(0,7,0));
02563 bool pre_0_9 = (version < KAlarm::Version(0,9,0));
02564 bool pre_0_9_2 = (version < KAlarm::Version(0,9,2));
02565 bool pre_1_1_1 = (version < KAlarm::Version(1,1,1));
02566 bool pre_1_2_1 = (version < KAlarm::Version(1,2,1));
02567 bool pre_1_3_0 = (version < KAlarm::Version(1,3,0));
02568 bool pre_1_3_1 = (version < KAlarm::Version(1,3,1));
02569 Q_ASSERT(calVersion() == KAlarm::Version(1,3,1));
02570
02571 QDateTime dt0(QDate(1970,1,1), QTime(0,0,0));
02572 QTime startOfDay = Preferences::startOfDay();
02573
02574 Event::List events = calendar.rawEvents();
02575 for (Event::List::ConstIterator evit = events.begin(); evit != events.end(); ++evit)
02576 {
02577 Event* event = *evit;
02578 Alarm::List alarms = event->alarms();
02579 if (alarms.isEmpty())
02580 continue;
02581 QStringList cats = event->categories();
02582 bool addLateCancel = false;
02583
02584 if (pre_0_7 && event->doesFloat())
02585 {
02586
02587
02588 event->setFloats(false);
02589 }
02590
02591 if (pre_0_9)
02592 {
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605 for (Alarm::List::ConstIterator alit = alarms.begin(); alit != alarms.end(); ++alit)
02606 {
02607 Alarm* alarm = *alit;
02608 bool atLogin = false;
02609 bool deferral = false;
02610 bool lateCancel = false;
02611 KAAlarmEventBase::Type action = T_MESSAGE;
02612 QString txt = alarm->text();
02613 int length = txt.length();
02614 int i = 0;
02615 if (txt[0].isDigit())
02616 {
02617 while (++i < length && txt[i].isDigit()) ;
02618 if (i < length && txt[i++] == SEPARATOR)
02619 {
02620 while (i < length)
02621 {
02622 QChar ch = txt[i++];
02623 if (ch == SEPARATOR)
02624 break;
02625 if (ch == LATE_CANCEL_CODE)
02626 lateCancel = true;
02627 else if (ch == AT_LOGIN_CODE)
02628 atLogin = true;
02629 else if (ch == DEFERRAL_CODE)
02630 deferral = true;
02631 }
02632 }
02633 else
02634 i = 0;
02635 }
02636 if (txt.find(TEXT_PREFIX, i) == i)
02637 i += TEXT_PREFIX.length();
02638 else if (txt.find(FILE_PREFIX, i) == i)
02639 {
02640 action = T_FILE;
02641 i += FILE_PREFIX.length();
02642 }
02643 else if (txt.find(COMMAND_PREFIX, i) == i)
02644 {
02645 action = T_COMMAND;
02646 i += COMMAND_PREFIX.length();
02647 }
02648 else
02649 i = 0;
02650 txt = txt.mid(i);
02651
02652 QStringList types;
02653 switch (action)
02654 {
02655 case T_FILE:
02656 types += FILE_TYPE;
02657
02658 case T_MESSAGE:
02659 alarm->setDisplayAlarm(txt);
02660 break;
02661 case T_COMMAND:
02662 setProcedureAlarm(alarm, txt);
02663 break;
02664 case T_EMAIL:
02665 case T_AUDIO:
02666 break;
02667 }
02668 if (atLogin)
02669 {
02670 types += AT_LOGIN_TYPE;
02671 lateCancel = false;
02672 }
02673 else if (deferral)
02674 types += TIME_DEFERRAL_TYPE;
02675 if (lateCancel)
02676 addLateCancel = true;
02677 if (types.count() > 0)
02678 alarm->setCustomProperty(APPNAME, TYPE_PROPERTY, types.join(","));
02679
02680 if (pre_0_7 && alarm->repeatCount() > 0 && alarm->snoozeTime() > 0)
02681 {
02682
02683
02684 Recurrence* recur = event->recurrence();
02685 if (recur && recur->doesRecur())
02686 {
02687 recur->setMinutely(alarm->snoozeTime());
02688 recur->setDuration(alarm->repeatCount() + 1);
02689 alarm->setRepeatCount(0);
02690 alarm->setSnoozeTime(0);
02691 }
02692 }
02693
02694 if (adjustSummerTime)
02695 {
02696
02697
02698 QDateTime dt = alarm->time();
02699 time_t t = dt0.secsTo(dt);
02700 struct tm* dtm = localtime(&t);
02701 if (dtm->tm_isdst)
02702 {
02703 dt = dt.addSecs(-3600);
02704 alarm->setTime(dt);
02705 }
02706 }
02707 }
02708 }
02709
02710 if (pre_0_9_2)
02711 {
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722 if (uidStatus(event->uid()) == EXPIRED)
02723 event->setCreated(event->dtEnd());
02724 QDateTime start = event->dtStart();
02725 if (event->doesFloat())
02726 {
02727 event->setFloats(false);
02728 start.setTime(startOfDay);
02729 cats.append(DATE_ONLY_CATEGORY);
02730 }
02731 event->setHasEndDate(false);
02732
02733 Alarm::List::ConstIterator alit;
02734 for (alit = alarms.begin(); alit != alarms.end(); ++alit)
02735 {
02736 Alarm* alarm = *alit;
02737 QDateTime dt = alarm->time();
02738 alarm->setStartOffset(start.secsTo(dt));
02739 }
02740
02741 if (cats.count() > 0)
02742 {
02743 for (alit = alarms.begin(); alit != alarms.end(); ++alit)
02744 {
02745 Alarm* alarm = *alit;
02746 if (alarm->type() == Alarm::Display)
02747 alarm->setCustomProperty(APPNAME, FONT_COLOUR_PROPERTY,
02748 QString::fromLatin1("%1;;").arg(cats[0]));
02749 }
02750 cats.remove(cats.begin());
02751 }
02752
02753 for (QStringList::Iterator it = cats.begin(); it != cats.end(); ++it)
02754 {
02755 if (*it == BEEP_CATEGORY)
02756 {
02757 cats.remove(it);
02758
02759 Alarm* alarm = event->newAlarm();
02760 alarm->setEnabled(true);
02761 alarm->setAudioAlarm();
02762 QDateTime dt = event->dtStart();
02763
02764
02765 AlarmMap alarmMap;
02766 readAlarms(*event, &alarmMap);
02767 AlarmMap::ConstIterator it = alarmMap.begin();
02768 if (it != alarmMap.end())
02769 {
02770 dt = it.data().alarm->time();
02771 break;
02772 }
02773 alarm->setStartOffset(start.secsTo(dt));
02774 break;
02775 }
02776 }
02777
02778 }
02779
02780 if (pre_1_1_1)
02781 {
02782
02783
02784
02785
02786 QStringList::Iterator it;
02787 while ((it = cats.find(LATE_CANCEL_CAT)) != cats.end())
02788 {
02789 cats.remove(it);
02790 addLateCancel = true;
02791 }
02792 }
02793
02794 if (pre_1_2_1)
02795 {
02796
02797
02798
02799
02800 for (Alarm::List::ConstIterator alit = alarms.begin(); alit != alarms.end(); ++alit)
02801 {
02802 Alarm* alarm = *alit;
02803 if (alarm->type() == Alarm::Display)
02804 {
02805 QString oldtext = alarm->text();
02806 QString newtext = AlarmText::toCalendarText(oldtext);
02807 if (oldtext != newtext)
02808 alarm->setDisplayAlarm(newtext);
02809 }
02810 }
02811 }
02812
02813 if (pre_1_3_0)
02814 {
02815
02816
02817
02818
02819 QStringList::Iterator it;
02820 while ((it = cats.find(TEMPL_DEF_TIME_CAT)) != cats.end())
02821 {
02822 cats.remove(it);
02823 cats.append(QString("%1%2").arg(TEMPL_AFTER_TIME_CATEGORY).arg(0));
02824 }
02825 }
02826
02827 if (pre_1_3_1)
02828 {
02829
02830
02831
02832
02833 QStringList::Iterator it;
02834 while ((it = cats.find(EXEC_IN_XTERM_CAT)) != cats.end())
02835 {
02836 cats.remove(it);
02837 cats.append(LOG_CATEGORY + xtermURL);
02838 }
02839 }
02840
02841 if (addLateCancel)
02842 cats.append(QString("%1%2").arg(LATE_CANCEL_CATEGORY).arg(1));
02843
02844 event->setCategories(cats);
02845 }
02846 }
02847
02848 #ifndef NDEBUG
02849 void KAEvent::dumpDebug() const
02850 {
02851 kdDebug(5950) << "KAEvent dump:\n";
02852 KAAlarmEventBase::dumpDebug();
02853 if (!mTemplateName.isEmpty())
02854 {
02855 kdDebug(5950) << "-- mTemplateName:" << mTemplateName << ":\n";
02856 kdDebug(5950) << "-- mTemplateAfterTime:" << mTemplateAfterTime << ":\n";
02857 }
02858 if (mActionType == T_MESSAGE || mActionType == T_FILE)
02859 {
02860 kdDebug(5950) << "-- mAudioFile:" << mAudioFile << ":\n";
02861 kdDebug(5950) << "-- mPreAction:" << mPreAction << ":\n";
02862 kdDebug(5950) << "-- mPostAction:" << mPostAction << ":\n";
02863 }
02864 else if (mActionType == T_COMMAND)
02865 {
02866 kdDebug(5950) << "-- mCommandXterm:" << (mCommandXterm ? "true" : "false") << ":\n";
02867 kdDebug(5950) << "-- mLogFile:" << mLogFile << ":\n";
02868 }
02869 kdDebug(5950) << "-- mKMailSerialNumber:" << mKMailSerialNumber << ":\n";
02870 kdDebug(5950) << "-- mCopyToKOrganizer:" << (mCopyToKOrganizer ? "true" : "false") << ":\n";
02871 kdDebug(5950) << "-- mStartDateTime:" << mStartDateTime.toString() << ":\n";
02872 kdDebug(5950) << "-- mSaveDateTime:" << mSaveDateTime.toString() << ":\n";
02873 if (mRepeatAtLogin)
02874 kdDebug(5950) << "-- mAtLoginDateTime:" << mAtLoginDateTime.toString() << ":\n";
02875 kdDebug(5950) << "-- mArchiveRepeatAtLogin:" << (mArchiveRepeatAtLogin ? "true" : "false") << ":\n";
02876 kdDebug(5950) << "-- mEnabled:" << (mEnabled ? "true" : "false") << ":\n";
02877 if (mReminderMinutes)
02878 kdDebug(5950) << "-- mReminderMinutes:" << mReminderMinutes << ":\n";
02879 if (mArchiveReminderMinutes)
02880 kdDebug(5950) << "-- mArchiveReminderMinutes:" << mArchiveReminderMinutes << ":\n";
02881 if (mReminderMinutes || mArchiveReminderMinutes)
02882 kdDebug(5950) << "-- mReminderOnceOnly:" << mReminderOnceOnly << ":\n";
02883 else if (mDeferral > 0)
02884 {
02885 kdDebug(5950) << "-- mDeferral:" << (mDeferral == NORMAL_DEFERRAL ? "normal" : "reminder") << ":\n";
02886 kdDebug(5950) << "-- mDeferralTime:" << mDeferralTime.toString() << ":\n";
02887 }
02888 else if (mDeferral == CANCEL_DEFERRAL)
02889 kdDebug(5950) << "-- mDeferral:cancel:\n";
02890 kdDebug(5950) << "-- mDeferDefaultMinutes:" << mDeferDefaultMinutes << ":\n";
02891 if (mDisplaying)
02892 {
02893 kdDebug(5950) << "-- mDisplayingTime:" << mDisplayingTime.toString() << ":\n";
02894 kdDebug(5950) << "-- mDisplayingFlags:" << mDisplayingFlags << ":\n";
02895 }
02896 kdDebug(5950) << "-- mRevision:" << mRevision << ":\n";
02897 kdDebug(5950) << "-- mRecurrence:" << (mRecurrence ? "true" : "false") << ":\n";
02898 if (mRecurrence)
02899 kdDebug(5950) << "-- mRemainingRecurrences:" << mRemainingRecurrences << ":\n";
02900 kdDebug(5950) << "-- mAlarmCount:" << mAlarmCount << ":\n";
02901 kdDebug(5950) << "-- mMainExpired:" << (mMainExpired ? "true" : "false") << ":\n";
02902 kdDebug(5950) << "KAEvent dump end\n";
02903 }
02904 #endif
02905
02906
02907
02908
02909
02910
02911
02912 KAAlarm::KAAlarm(const KAAlarm& alarm)
02913 : KAAlarmEventBase(alarm),
02914 mType(alarm.mType),
02915 mRecurs(alarm.mRecurs),
02916 mDeferred(alarm.mDeferred)
02917 { }
02918
02919
02920 int KAAlarm::flags() const
02921 {
02922 return KAAlarmEventBase::flags()
02923 | (mDeferred ? KAEvent::DEFERRAL : 0);
02924
02925 }
02926
02927 #ifndef NDEBUG
02928 void KAAlarm::dumpDebug() const
02929 {
02930 kdDebug(5950) << "KAAlarm dump:\n";
02931 KAAlarmEventBase::dumpDebug();
02932 const char* altype = 0;
02933 switch (mType)
02934 {
02935 case MAIN__ALARM: altype = "MAIN"; break;
02936 case REMINDER__ALARM: altype = "REMINDER"; break;
02937 case DEFERRED_DATE__ALARM: altype = "DEFERRED(DATE)"; break;
02938 case DEFERRED_TIME__ALARM: altype = "DEFERRED(TIME)"; break;
02939 case DEFERRED_REMINDER_DATE__ALARM: altype = "DEFERRED_REMINDER(DATE)"; break;
02940 case DEFERRED_REMINDER_TIME__ALARM: altype = "DEFERRED_REMINDER(TIME)"; break;
02941 case AT_LOGIN__ALARM: altype = "LOGIN"; break;
02942 case DISPLAYING__ALARM: altype = "DISPLAYING"; break;
02943 case AUDIO__ALARM: altype = "AUDIO"; break;
02944 case PRE_ACTION__ALARM: altype = "PRE_ACTION"; break;
02945 case POST_ACTION__ALARM: altype = "POST_ACTION"; break;
02946 default: altype = "INVALID"; break;
02947 }
02948 kdDebug(5950) << "-- mType:" << altype << ":\n";
02949 kdDebug(5950) << "-- mRecurs:" << (mRecurs ? "true" : "false") << ":\n";
02950 kdDebug(5950) << "-- mDeferred:" << (mDeferred ? "true" : "false") << ":\n";
02951 kdDebug(5950) << "KAAlarm dump end\n";
02952 }
02953
02954 const char* KAAlarm::debugType(Type type)
02955 {
02956 switch (type)
02957 {
02958 case MAIN_ALARM: return "MAIN";
02959 case REMINDER_ALARM: return "REMINDER";
02960 case DEFERRED_ALARM: return "DEFERRED";
02961 case DEFERRED_REMINDER_ALARM: return "DEFERRED_REMINDER";
02962 case AT_LOGIN_ALARM: return "LOGIN";
02963 case DISPLAYING_ALARM: return "DISPLAYING";
02964 case AUDIO_ALARM: return "AUDIO";
02965 case PRE_ACTION_ALARM: return "PRE_ACTION";
02966 case POST_ACTION_ALARM: return "POST_ACTION";
02967 default: return "INVALID";
02968 }
02969 }
02970 #endif
02971
02972
02973
02974
02975
02976
02977 void KAAlarmEventBase::copy(const KAAlarmEventBase& rhs)
02978 {
02979 mEventID = rhs.mEventID;
02980 mText = rhs.mText;
02981 mNextMainDateTime = rhs.mNextMainDateTime;
02982 mBgColour = rhs.mBgColour;
02983 mFgColour = rhs.mFgColour;
02984 mFont = rhs.mFont;
02985 mEmailFromKMail = rhs.mEmailFromKMail;
02986 mEmailAddresses = rhs.mEmailAddresses;
02987 mEmailSubject = rhs.mEmailSubject;
02988 mEmailAttachments = rhs.mEmailAttachments;
02989 mSoundVolume = rhs.mSoundVolume;
02990 mFadeVolume = rhs.mFadeVolume;
02991 mFadeSeconds = rhs.mFadeSeconds;
02992 mActionType = rhs.mActionType;
02993 mCommandScript = rhs.mCommandScript;
02994 mRepeatCount = rhs.mRepeatCount;
02995 mRepeatInterval = rhs.mRepeatInterval;
02996 mBeep = rhs.mBeep;
02997 mSpeak = rhs.mSpeak;
02998 mRepeatSound = rhs.mRepeatSound;
02999 mRepeatAtLogin = rhs.mRepeatAtLogin;
03000 mDisplaying = rhs.mDisplaying;
03001 mLateCancel = rhs.mLateCancel;
03002 mAutoClose = rhs.mAutoClose;
03003 mEmailBcc = rhs.mEmailBcc;
03004 mConfirmAck = rhs.mConfirmAck;
03005 mDefaultFont = rhs.mDefaultFont;
03006 }
03007
03008 void KAAlarmEventBase::set(int flags)
03009 {
03010 mSpeak = flags & KAEvent::SPEAK;
03011 mBeep = (flags & KAEvent::BEEP) && !mSpeak;
03012 mRepeatSound = flags & KAEvent::REPEAT_SOUND;
03013 mRepeatAtLogin = flags & KAEvent::REPEAT_AT_LOGIN;
03014 mAutoClose = (flags & KAEvent::AUTO_CLOSE) && mLateCancel;
03015 mEmailBcc = flags & KAEvent::EMAIL_BCC;
03016 mConfirmAck = flags & KAEvent::CONFIRM_ACK;
03017 mDisplaying = flags & KAEvent::DISPLAYING_;
03018 mDefaultFont = flags & KAEvent::DEFAULT_FONT;
03019 mCommandScript = flags & KAEvent::SCRIPT;
03020 }
03021
03022 int KAAlarmEventBase::flags() const
03023 {
03024 return (mBeep && !mSpeak ? KAEvent::BEEP : 0)
03025 | (mSpeak ? KAEvent::SPEAK : 0)
03026 | (mRepeatSound ? KAEvent::REPEAT_SOUND : 0)
03027 | (mRepeatAtLogin ? KAEvent::REPEAT_AT_LOGIN : 0)
03028 | (mAutoClose ? KAEvent::AUTO_CLOSE : 0)
03029 | (mEmailBcc ? KAEvent::EMAIL_BCC : 0)
03030 | (mConfirmAck ? KAEvent::CONFIRM_ACK : 0)
03031 | (mDisplaying ? KAEvent::DISPLAYING_ : 0)
03032 | (mDefaultFont ? KAEvent::DEFAULT_FONT : 0)
03033 | (mCommandScript ? KAEvent::SCRIPT : 0);
03034 }
03035
03036 const QFont& KAAlarmEventBase::font() const
03037 {
03038 return mDefaultFont ? Preferences::messageFont() : mFont;
03039 }
03040
03041 #ifndef NDEBUG
03042 void KAAlarmEventBase::dumpDebug() const
03043 {
03044 kdDebug(5950) << "-- mEventID:" << mEventID << ":\n";
03045 kdDebug(5950) << "-- mActionType:" << (mActionType == T_MESSAGE ? "MESSAGE" : mActionType == T_FILE ? "FILE" : mActionType == T_COMMAND ? "COMMAND" : mActionType == T_EMAIL ? "EMAIL" : mActionType == T_AUDIO ? "AUDIO" : "??") << ":\n";
03046 kdDebug(5950) << "-- mText:" << mText << ":\n";
03047 if (mActionType == T_COMMAND)
03048 kdDebug(5950) << "-- mCommandScript:" << (mCommandScript ? "true" : "false") << ":\n";
03049 kdDebug(5950) << "-- mNextMainDateTime:" << mNextMainDateTime.toString() << ":\n";
03050 if (mActionType == T_EMAIL)
03051 {
03052 kdDebug(5950) << "-- mEmail: FromKMail:" << mEmailFromKMail << ":\n";
03053 kdDebug(5950) << "-- Addresses:" << mEmailAddresses.join(", ") << ":\n";
03054 kdDebug(5950) << "-- Subject:" << mEmailSubject << ":\n";
03055 kdDebug(5950) << "-- Attachments:" << mEmailAttachments.join(", ") << ":\n";
03056 kdDebug(5950) << "-- Bcc:" << (mEmailBcc ? "true" : "false") << ":\n";
03057 }
03058 kdDebug(5950) << "-- mBgColour:" << mBgColour.name() << ":\n";
03059 kdDebug(5950) << "-- mFgColour:" << mFgColour.name() << ":\n";
03060 kdDebug(5950) << "-- mDefaultFont:" << (mDefaultFont ? "true" : "false") << ":\n";
03061 if (!mDefaultFont)
03062 kdDebug(5950) << "-- mFont:" << mFont.toString() << ":\n";
03063 kdDebug(5950) << "-- mBeep:" << (mBeep ? "true" : "false") << ":\n";
03064 kdDebug(5950) << "-- mSpeak:" << (mSpeak ? "true" : "false") << ":\n";
03065 if (mActionType == T_AUDIO)
03066 {
03067 if (mSoundVolume >= 0)
03068 {
03069 kdDebug(5950) << "-- mSoundVolume:" << mSoundVolume << ":\n";
03070 if (mFadeVolume >= 0)
03071 {
03072 kdDebug(5950) << "-- mFadeVolume:" << mFadeVolume << ":\n";
03073 kdDebug(5950) << "-- mFadeSeconds:" << mFadeSeconds << ":\n";
03074 }
03075 else
03076 kdDebug(5950) << "-- mFadeVolume:-:\n";
03077 }
03078 else
03079 kdDebug(5950) << "-- mSoundVolume:-:\n";
03080 kdDebug(5950) << "-- mRepeatSound:" << (mRepeatSound ? "true" : "false") << ":\n";
03081 }
03082 kdDebug(5950) << "-- mConfirmAck:" << (mConfirmAck ? "true" : "false") << ":\n";
03083 kdDebug(5950) << "-- mRepeatAtLogin:" << (mRepeatAtLogin ? "true" : "false") << ":\n";
03084 kdDebug(5950) << "-- mRepeatCount:" << mRepeatCount << ":\n";
03085 kdDebug(5950) << "-- mRepeatInterval:" << mRepeatInterval << ":\n";
03086 kdDebug(5950) << "-- mDisplaying:" << (mDisplaying ? "true" : "false") << ":\n";
03087 kdDebug(5950) << "-- mLateCancel:" << mLateCancel << ":\n";
03088 kdDebug(5950) << "-- mAutoClose:" << (mAutoClose ? "true" : "false") << ":\n";
03089 }
03090 #endif
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101 EmailAddressList& EmailAddressList::operator=(const QValueList<Person>& addresses)
03102 {
03103 clear();
03104 for (QValueList<Person>::ConstIterator it = addresses.begin(); it != addresses.end(); ++it)
03105 {
03106 if (!(*it).email().isEmpty())
03107 append(*it);
03108 }
03109 return *this;
03110 }
03111
03112
03113
03114
03115
03116 QString EmailAddressList::join(const QString& separator) const
03117 {
03118 QString result;
03119 bool first = true;
03120 for (QValueList<Person>::ConstIterator it = begin(); it != end(); ++it)
03121 {
03122 if (first)
03123 first = false;
03124 else
03125 result += separator;
03126
03127 bool quote = false;
03128 QString name = (*it).name();
03129 if (!name.isEmpty())
03130 {
03131
03132 int len = name.length();
03133 for (int i = 0; i < len; ++i)
03134 {
03135 QChar ch = name[i];
03136 if (!ch.isLetterOrNumber())
03137 {
03138 quote = true;
03139 result += '\"';
03140 break;
03141 }
03142 }
03143 result += (*it).name();
03144 result += (quote ? "\" <" : " <");
03145 quote = true;
03146 }
03147
03148 result += (*it).email();
03149 if (quote)
03150 result += ">";
03151 }
03152 return result;
03153 }
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165 static void setProcedureAlarm(Alarm* alarm, const QString& commandLine)
03166 {
03167 QString command = QString::null;
03168 QString arguments = QString::null;
03169 QChar quoteChar;
03170 bool quoted = false;
03171 uint posMax = commandLine.length();
03172 uint pos;
03173 for (pos = 0; pos < posMax; ++pos)
03174 {
03175 QChar ch = commandLine[pos];
03176 if (quoted)
03177 {
03178 if (ch == quoteChar)
03179 {
03180 ++pos;
03181 break;
03182 }
03183 command += ch;
03184 }
03185 else
03186 {
03187 bool done = false;
03188 switch (ch)
03189 {
03190 case ' ':
03191 case ';':
03192 case '|':
03193 case '<':
03194 case '>':
03195 done = !command.isEmpty();
03196 break;
03197 case '\'':
03198 case '"':
03199 if (command.isEmpty())
03200 {
03201
03202 quoted = true;
03203 quoteChar = ch;
03204 break;
03205 }
03206
03207 default:
03208 command += ch;
03209 break;
03210 }
03211 if (done)
03212 break;
03213 }
03214 }
03215
03216
03217 for ( ; pos < posMax && commandLine[pos] == ' '; ++pos) ;
03218 arguments = commandLine.mid(pos);
03219
03220 alarm->setProcedureAlarm(command, arguments);
03221 }