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