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 #include <unistd.h>
00023 #include <time.h>
00024
00025 #include <qfile.h>
00026 #include <qtextstream.h>
00027 #include <qregexp.h>
00028 #include <qtimer.h>
00029
00030 #include <klocale.h>
00031 #include <kmessagebox.h>
00032 #include <kstandarddirs.h>
00033 #include <kstaticdeleter.h>
00034 #include <kconfig.h>
00035 #include <kaboutdata.h>
00036 #include <kio/netaccess.h>
00037 #include <kfileitem.h>
00038 #include <ktempfile.h>
00039 #include <kfiledialog.h>
00040 #include <dcopclient.h>
00041 #include <kdebug.h>
00042
00043 extern "C" {
00044 #include <libical/ical.h>
00045 }
00046
00047 #include <libkcal/vcaldrag.h>
00048 #include <libkcal/vcalformat.h>
00049 #include <libkcal/icalformat.h>
00050
00051 #include "calendarcompat.h"
00052 #include "daemon.h"
00053 #include "functions.h"
00054 #include "kalarmapp.h"
00055 #include "mainwindow.h"
00056 #include "preferences.h"
00057 #include "startdaytimer.h"
00058 #include "alarmcalendar.moc"
00059
00060 using namespace KCal;
00061
00062 QString AlarmCalendar::icalProductId()
00063 {
00064 return QString::fromLatin1("-//K Desktop Environment//NONSGML " KALARM_NAME " %1//EN").arg(KAlarm::currentCalendarVersionString());
00065 }
00066
00067 static const KAEvent::Status eventTypes[AlarmCalendar::NCALS] = {
00068 KAEvent::ACTIVE, KAEvent::EXPIRED, KAEvent::DISPLAYING, KAEvent::TEMPLATE
00069 };
00070 static const QString calendarNames[AlarmCalendar::NCALS] = {
00071 QString::fromLatin1("calendar.ics"),
00072 QString::fromLatin1("expired.ics"),
00073 QString::fromLatin1("displaying.ics"),
00074 QString::fromLatin1("template.ics")
00075 };
00076 static KStaticDeleter<AlarmCalendar> calendarDeleter[AlarmCalendar::NCALS];
00077
00078 AlarmCalendar* AlarmCalendar::mCalendars[NCALS] = { 0, 0, 0, 0 };
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 bool AlarmCalendar::initialiseCalendars()
00092 {
00093 KConfig* config = kapp->config();
00094 config->setGroup(QString::fromLatin1("General"));
00095 QString activeKey = QString::fromLatin1("Calendar");
00096 QString expiredKey = QString::fromLatin1("ExpiredCalendar");
00097 QString templateKey = QString::fromLatin1("TemplateCalendar");
00098 QString displayCal, activeCal, expiredCal, templateCal;
00099 calendarDeleter[ACTIVE].setObject(mCalendars[ACTIVE], createCalendar(ACTIVE, config, activeCal, activeKey));
00100 calendarDeleter[EXPIRED].setObject(mCalendars[EXPIRED], createCalendar(EXPIRED, config, expiredCal, expiredKey));
00101 calendarDeleter[DISPLAY].setObject(mCalendars[DISPLAY], createCalendar(DISPLAY, config, displayCal));
00102 calendarDeleter[TEMPLATE].setObject(mCalendars[TEMPLATE], createCalendar(TEMPLATE, config, templateCal, templateKey));
00103
00104 QString errorKey1, errorKey2;
00105 if (activeCal == displayCal)
00106 errorKey1 = activeKey;
00107 else if (expiredCal == displayCal)
00108 errorKey1 = expiredKey;
00109 else if (templateCal == displayCal)
00110 errorKey1 = templateKey;
00111 if (!errorKey1.isNull())
00112 {
00113 kdError(5950) << "AlarmCalendar::initialiseCalendars(): '" << errorKey1 << "' calendar name = display calendar name\n";
00114 QString file = config->readPathEntry(errorKey1);
00115 KAlarmApp::displayFatalError(i18n("%1: file name not permitted: %2").arg(errorKey1).arg(file));
00116 return false;
00117 }
00118 if (activeCal == expiredCal)
00119 {
00120 errorKey1 = activeKey;
00121 errorKey2 = expiredKey;
00122 }
00123 else if (activeCal == templateCal)
00124 {
00125 errorKey1 = activeKey;
00126 errorKey2 = templateKey;
00127 }
00128 else if (expiredCal == templateCal)
00129 {
00130 errorKey1 = expiredKey;
00131 errorKey2 = templateKey;
00132 }
00133 if (!errorKey1.isNull())
00134 {
00135 kdError(5950) << "AlarmCalendar::initialiseCalendars(): calendar names clash: " << errorKey1 << ", " << errorKey2 << endl;
00136 KAlarmApp::displayFatalError(i18n("%1, %2: file names must be different").arg(errorKey1).arg(errorKey2));
00137 return false;
00138 }
00139 if (!mCalendars[ACTIVE]->valid())
00140 {
00141 QString path = mCalendars[ACTIVE]->path();
00142 kdError(5950) << "AlarmCalendar::initialiseCalendars(): invalid name: " << path << endl;
00143 KAlarmApp::displayFatalError(i18n("Invalid calendar file name: %1").arg(path));
00144 return false;
00145 }
00146 return true;
00147 }
00148
00149
00150
00151
00152
00153 AlarmCalendar* AlarmCalendar::createCalendar(CalID type, KConfig* config, QString& writePath, const QString& configKey)
00154 {
00155 static QRegExp vcsRegExp(QString::fromLatin1("\\.vcs$"));
00156 static QString ical = QString::fromLatin1(".ics");
00157
00158 if (configKey.isNull())
00159 {
00160 writePath = locateLocal("appdata", calendarNames[type]);
00161 return new AlarmCalendar(writePath, type);
00162 }
00163 else
00164 {
00165 QString readPath = config->readPathEntry(configKey, locateLocal("appdata", calendarNames[type]));
00166 writePath = readPath;
00167 writePath.replace(vcsRegExp, ical);
00168 return new AlarmCalendar(readPath, type, writePath, configKey);
00169 }
00170 }
00171
00172
00173
00174
00175 void AlarmCalendar::terminateCalendars()
00176 {
00177 for (int i = 0; i < NCALS; ++i)
00178 {
00179 calendarDeleter[i].destructObject();
00180 mCalendars[i] = 0;
00181 }
00182 }
00183
00184
00185
00186
00187
00188
00189 AlarmCalendar* AlarmCalendar::calendarOpen(CalID id)
00190 {
00191 AlarmCalendar* cal = mCalendars[id];
00192 if (!cal->mPurgeDays)
00193 return 0;
00194 if (cal->open())
00195 return cal;
00196 kdError(5950) << "AlarmCalendar::calendarOpen(" << calendarNames[id] << "): open error\n";
00197 return 0;
00198 }
00199
00200
00201
00202
00203
00204 const KCal::Event* AlarmCalendar::getEvent(const QString& uniqueID)
00205 {
00206 if (uniqueID.isEmpty())
00207 return 0;
00208 CalID calID;
00209 switch (KAEvent::uidStatus(uniqueID))
00210 {
00211 case KAEvent::ACTIVE: calID = ACTIVE; break;
00212 case KAEvent::TEMPLATE: calID = TEMPLATE; break;
00213 case KAEvent::EXPIRED: calID = EXPIRED; break;
00214 case KAEvent::DISPLAYING: calID = DISPLAY; break;
00215 default:
00216 return 0;
00217 }
00218 AlarmCalendar* cal = calendarOpen(calID);
00219 if (!cal)
00220 return 0;
00221 return cal->event(uniqueID);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231 AlarmCalendar::AlarmCalendar(const QString& path, CalID type, const QString& icalPath,
00232 const QString& configKey)
00233 : mCalendar(0),
00234 mConfigKey(icalPath.isNull() ? QString::null : configKey),
00235 mType(eventTypes[type]),
00236 mPurgeDays(-1),
00237 mOpen(false),
00238 mPurgeDaysQueued(-1),
00239 mUpdateCount(0),
00240 mUpdateSave(false)
00241 {
00242 mUrl.setPath(path);
00243 mICalUrl.setPath(icalPath.isNull() ? path : icalPath);
00244 mVCal = (icalPath.isNull() || path != icalPath);
00245 }
00246
00247 AlarmCalendar::~AlarmCalendar()
00248 {
00249 close();
00250 }
00251
00252
00253
00254
00255 bool AlarmCalendar::open()
00256 {
00257 if (mOpen)
00258 return true;
00259 if (!mUrl.isValid())
00260 return false;
00261
00262 kdDebug(5950) << "AlarmCalendar::open(" << mUrl.prettyURL() << ")\n";
00263 if (!mCalendar)
00264 mCalendar = new CalendarLocal(QString::fromLatin1("UTC"));
00265 mCalendar->setLocalTime();
00266
00267
00268
00269 if (!KIO::NetAccess::exists(mUrl, true, MainWindow::mainMainWindow()))
00270 {
00271
00272 if (create())
00273 load();
00274 }
00275 else
00276 {
00277
00278 if (load() == 0)
00279 {
00280 if (create())
00281 load();
00282 }
00283 }
00284 if (!mOpen)
00285 {
00286 delete mCalendar;
00287 mCalendar = 0;
00288 }
00289 return mOpen;
00290 }
00291
00292
00293
00294
00295
00296 bool AlarmCalendar::create()
00297 {
00298 if (mICalUrl.isLocalFile())
00299 return saveCal(mICalUrl.path());
00300 else
00301 {
00302 KTempFile tmpFile;
00303 return saveCal(tmpFile.name());
00304 }
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314 int AlarmCalendar::load()
00315 {
00316 if (!mCalendar)
00317 return -2;
00318
00319 kdDebug(5950) << "AlarmCalendar::load(): " << mUrl.prettyURL() << endl;
00320 QString tmpFile;
00321 if (!KIO::NetAccess::download(mUrl, tmpFile, MainWindow::mainMainWindow()))
00322 {
00323 kdError(5950) << "AlarmCalendar::load(): Load failure" << endl;
00324 KMessageBox::error(0, i18n("Cannot open calendar:\n%1").arg(mUrl.prettyURL()));
00325 return -1;
00326 }
00327 kdDebug(5950) << "AlarmCalendar::load(): --- Downloaded to " << tmpFile << endl;
00328 mCalendar->setTimeZoneId(QString::null);
00329 bool loaded = mCalendar->load(tmpFile);
00330 mCalendar->setLocalTime();
00331 if (!loaded)
00332 {
00333
00334 KIO::NetAccess::removeTempFile(tmpFile);
00335 KIO::UDSEntry uds;
00336 KIO::NetAccess::stat(mUrl, uds, MainWindow::mainMainWindow());
00337 KFileItem fi(uds, mUrl);
00338 if (!fi.size())
00339 return 0;
00340 kdError(5950) << "AlarmCalendar::load(): Error loading calendar file '" << tmpFile << "'" << endl;
00341 KMessageBox::error(0, i18n("Error loading calendar:\n%1\n\nPlease fix or delete the file.").arg(mUrl.prettyURL()));
00342
00343 mCalendar->close();
00344 delete mCalendar;
00345 mCalendar = 0;
00346 return -1;
00347 }
00348 if (!mLocalFile.isEmpty())
00349 KIO::NetAccess::removeTempFile(mLocalFile);
00350 mLocalFile = tmpFile;
00351
00352 CalendarCompat::fix(*mCalendar, mLocalFile);
00353 mOpen = true;
00354 return 1;
00355 }
00356
00357
00358
00359
00360 bool AlarmCalendar::reload()
00361 {
00362 if (!mCalendar)
00363 return false;
00364 kdDebug(5950) << "AlarmCalendar::reload(): " << mUrl.prettyURL() << endl;
00365 close();
00366 bool result = open();
00367 return result;
00368 }
00369
00370
00371
00372
00373
00374 bool AlarmCalendar::saveCal(const QString& newFile)
00375 {
00376 if (!mCalendar || !mOpen && newFile.isNull())
00377 return false;
00378
00379 kdDebug(5950) << "AlarmCalendar::saveCal(\"" << newFile << "\", " << mType << ")\n";
00380 QString saveFilename = newFile.isNull() ? mLocalFile : newFile;
00381 if (mVCal && newFile.isNull() && mUrl.isLocalFile())
00382 saveFilename = mICalUrl.path();
00383 if (!mCalendar->save(saveFilename, new ICalFormat))
00384 {
00385 kdError(5950) << "AlarmCalendar::saveCal(" << saveFilename << "): failed.\n";
00386 KMessageBox::error(0, i18n("Failed to save calendar to\n'%1'").arg(mICalUrl.prettyURL()));
00387 return false;
00388 }
00389
00390 if (!mICalUrl.isLocalFile())
00391 {
00392 if (!KIO::NetAccess::upload(saveFilename, mICalUrl, MainWindow::mainMainWindow()))
00393 {
00394 kdError(5950) << "AlarmCalendar::saveCal(" << saveFilename << "): upload failed.\n";
00395 KMessageBox::error(0, i18n("Cannot upload calendar to\n'%1'").arg(mICalUrl.prettyURL()));
00396 return false;
00397 }
00398 }
00399
00400 if (mVCal)
00401 {
00402
00403
00404 if (!mConfigKey.isNull())
00405 {
00406 KConfig* config = kapp->config();
00407 config->setGroup(QString::fromLatin1("General"));
00408 config->writePathEntry(mConfigKey, mICalUrl.path());
00409 config->sync();
00410 }
00411 mUrl = mICalUrl;
00412 mVCal = false;
00413 }
00414
00415 mUpdateSave = false;
00416 emit calendarSaved(this);
00417 return true;
00418 }
00419
00420
00421
00422
00423 void AlarmCalendar::close()
00424 {
00425 if (!mLocalFile.isEmpty())
00426 {
00427 KIO::NetAccess::removeTempFile(mLocalFile);
00428 mLocalFile = "";
00429 }
00430 if (mCalendar)
00431 {
00432 mCalendar->close();
00433 delete mCalendar;
00434 mCalendar = 0;
00435 }
00436 mOpen = false;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446 bool AlarmCalendar::importAlarms(QWidget* parent)
00447 {
00448 KURL url = KFileDialog::getOpenURL(QString::fromLatin1(":importalarms"),
00449 QString::fromLatin1("*.vcs *.ics|%1").arg(i18n("Calendar Files")), parent);
00450 if (url.isEmpty())
00451 {
00452 kdError(5950) << "AlarmCalendar::importAlarms(): Empty URL" << endl;
00453 return false;
00454 }
00455 if (!url.isValid())
00456 {
00457 kdDebug(5950) << "AlarmCalendar::importAlarms(): Invalid URL" << endl;
00458 return false;
00459 }
00460 kdDebug(5950) << "AlarmCalendar::importAlarms(" << url.prettyURL() << ")" << endl;
00461
00462 bool success = true;
00463 QString filename;
00464 bool local = url.isLocalFile();
00465 if (local)
00466 {
00467 filename = url.path();
00468 if (!KStandardDirs::exists(filename))
00469 {
00470 kdDebug(5950) << "AlarmCalendar::importAlarms(): File '" << url.prettyURL() << "' not found" << endl;
00471 KMessageBox::error(parent, i18n("Could not load calendar '%1'.").arg(url.prettyURL()));
00472 return false;
00473 }
00474 }
00475 else
00476 {
00477 if (!KIO::NetAccess::download(url, filename, MainWindow::mainMainWindow()))
00478 {
00479 kdError(5950) << "AlarmCalendar::importAlarms(): Download failure" << endl;
00480 KMessageBox::error(parent, i18n("Cannot download calendar:\n%1").arg(url.prettyURL()));
00481 return false;
00482 }
00483 kdDebug(5950) << "--- Downloaded to " << filename << endl;
00484 }
00485
00486
00487 CalendarLocal cal(QString::fromLatin1("UTC"));
00488 cal.setLocalTime();
00489 success = cal.load(filename);
00490 if (!success)
00491 {
00492 kdDebug(5950) << "AlarmCalendar::importAlarms(): error loading calendar '" << filename << "'" << endl;
00493 KMessageBox::error(parent, i18n("Could not load calendar '%1'.").arg(url.prettyURL()));
00494 }
00495 else
00496 {
00497 CalendarCompat::fix(cal, filename);
00498 bool saveActive = false;
00499 bool saveExpired = false;
00500 bool saveTemplate = false;
00501 AlarmCalendar* active = activeCalendar();
00502 AlarmCalendar* expired = expiredCalendar();
00503 AlarmCalendar* templat = 0;
00504 AlarmCalendar* acal;
00505 Event::List events = cal.rawEvents();
00506 for (Event::List::ConstIterator it = events.begin(); it != events.end(); ++it)
00507 {
00508 const Event* event = *it;
00509 if (event->alarms().isEmpty())
00510 continue;
00511 KAEvent::Status type = KAEvent::uidStatus(event->uid());
00512 switch (type)
00513 {
00514 case KAEvent::ACTIVE:
00515 acal = active;
00516 saveActive = true;
00517 break;
00518 case KAEvent::EXPIRED:
00519 acal = expired;
00520 saveExpired = true;
00521 break;
00522 case KAEvent::TEMPLATE:
00523 if (!templat)
00524 templat = templateCalendarOpen();
00525 acal = templat;
00526 saveTemplate = true;
00527 break;
00528 default:
00529 continue;
00530 }
00531 if (!acal)
00532 continue;
00533
00534 Event* newev = new Event(*event);
00535
00536
00537
00538 if (type == KAEvent::ACTIVE && !newev->summary().isEmpty())
00539 {
00540 const Alarm::List& alarms = newev->alarms();
00541 for (Alarm::List::ConstIterator ait = alarms.begin(); ait != alarms.end(); ++ait)
00542 {
00543 Alarm* alarm = *ait;
00544 if (alarm->type() == Alarm::Display && alarm->text().isEmpty())
00545 alarm->setText(newev->summary());
00546 }
00547 newev->setSummary(QString::null);
00548 }
00549
00550 newev->setUid(KAEvent::uid(CalFormat::createUniqueId(), type));
00551 if (!acal->mCalendar->addEvent(newev))
00552 success = false;
00553 }
00554
00555
00556 if (saveActive)
00557 active->saveCal();
00558 if (saveExpired)
00559 expired->saveCal();
00560 if (saveTemplate)
00561 templat->saveCal();
00562 }
00563 if (!local)
00564 KIO::NetAccess::removeTempFile(filename);
00565 return success;
00566 }
00567
00568
00569
00570
00571
00572 void AlarmCalendar::startUpdate()
00573 {
00574 ++mUpdateCount;
00575 }
00576
00577
00578
00579
00580
00581 void AlarmCalendar::endUpdate()
00582 {
00583 if (mUpdateCount > 0)
00584 --mUpdateCount;
00585 if (!mUpdateCount)
00586 {
00587 if (mUpdateSave)
00588 saveCal();
00589 }
00590 }
00591
00592
00593
00594
00595 void AlarmCalendar::save()
00596 {
00597 if (mUpdateCount)
00598 mUpdateSave = true;
00599 else
00600 saveCal();
00601 }
00602
00603 #if 0
00604
00605
00606
00607
00608 void AlarmCalendar::convertToICal()
00609 {
00610 if (mVCal)
00611 {
00612 if (!mConfigKey.isNull())
00613 {
00614 KConfig* config = kapp->config();
00615 config->setGroup(QString::fromLatin1("General"));
00616 config->writePathEntry(mConfigKey, mICalUrl.path());
00617 config->sync();
00618 }
00619 mUrl = mICalUrl;
00620 mVCal = false;
00621 }
00622 }
00623 #endif
00624
00625
00626
00627
00628
00629 void AlarmCalendar::setPurgeDays(int days)
00630 {
00631 if (days != mPurgeDays)
00632 {
00633 int oldDays = mPurgeDays;
00634 mPurgeDays = days;
00635 if (mPurgeDays <= 0)
00636 StartOfDayTimer::disconnect(this);
00637 if (oldDays < 0 || days >= 0 && days < oldDays)
00638 {
00639
00640 if (open())
00641 slotPurge();
00642 }
00643 else if (mPurgeDays > 0)
00644 startPurgeTimer();
00645 }
00646 }
00647
00648
00649
00650
00651
00652 void AlarmCalendar::slotPurge()
00653 {
00654 purge(mPurgeDays);
00655 startPurgeTimer();
00656 }
00657
00658
00659
00660
00661
00662 void AlarmCalendar::purge(int daysToKeep)
00663 {
00664 if (mPurgeDaysQueued < 0 || daysToKeep < mPurgeDaysQueued)
00665 mPurgeDaysQueued = daysToKeep;
00666
00667
00668 theApp()->processQueue();
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 void AlarmCalendar::purgeIfQueued()
00680 {
00681 if (mPurgeDaysQueued >= 0)
00682 {
00683 if (open())
00684 {
00685 kdDebug(5950) << "AlarmCalendar::purgeIfQueued(" << mPurgeDaysQueued << ")\n";
00686 bool changed = false;
00687 QDate cutoff = QDate::currentDate().addDays(-mPurgeDaysQueued);
00688 Event::List events = mCalendar->rawEvents();
00689 for (Event::List::ConstIterator it = events.begin(); it != events.end(); ++it)
00690 {
00691 Event* kcalEvent = *it;
00692 if (!mPurgeDaysQueued || kcalEvent->created().date() < cutoff)
00693 {
00694 mCalendar->deleteEvent(kcalEvent);
00695 changed = true;
00696 }
00697 }
00698 if (changed)
00699 {
00700 saveCal();
00701 emit purged();
00702 }
00703 mPurgeDaysQueued = -1;
00704 }
00705 }
00706 }
00707
00708
00709
00710
00711
00712
00713 void AlarmCalendar::startPurgeTimer()
00714 {
00715 if (mPurgeDays > 0)
00716 StartOfDayTimer::connect(this, SLOT(slotPurge()));
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726 Event* AlarmCalendar::addEvent(KAEvent& event, bool useEventID)
00727 {
00728 if (!mOpen)
00729 return 0;
00730 QString id = event.id();
00731 Event* kcalEvent = new Event;
00732 if (mType == KAEvent::ACTIVE)
00733 {
00734 if (id.isEmpty())
00735 useEventID = false;
00736 if (!useEventID)
00737 event.setEventID(kcalEvent->uid());
00738 }
00739 else
00740 {
00741 if (id.isEmpty())
00742 id = kcalEvent->uid();
00743 useEventID = true;
00744 }
00745 if (useEventID)
00746 {
00747 id = KAEvent::uid(id, mType);
00748 event.setEventID(id);
00749 kcalEvent->setUid(id);
00750 }
00751 event.updateKCalEvent(*kcalEvent, false, (mType == KAEvent::EXPIRED), true);
00752 mCalendar->addEvent(kcalEvent);
00753 event.clearUpdated();
00754 return kcalEvent;
00755 }
00756
00757
00758
00759
00760
00761 void AlarmCalendar::updateEvent(const KAEvent& evnt)
00762 {
00763 if (mOpen)
00764 {
00765 Event* kcalEvent = event(evnt.id());
00766 if (kcalEvent)
00767 {
00768 evnt.updateKCalEvent(*kcalEvent);
00769 evnt.clearUpdated();
00770 if (mType == KAEvent::ACTIVE)
00771 Daemon::savingEvent(evnt.id());
00772 return;
00773 }
00774 }
00775 if (mType == KAEvent::ACTIVE)
00776 Daemon::eventHandled(evnt.id(), false);
00777 }
00778
00779
00780
00781
00782
00783 void AlarmCalendar::deleteEvent(const QString& eventID, bool saveit)
00784 {
00785 if (mOpen)
00786 {
00787 Event* kcalEvent = event(eventID);
00788 if (kcalEvent)
00789 {
00790 mCalendar->deleteEvent(kcalEvent);
00791 if (mType == KAEvent::ACTIVE)
00792 Daemon::savingEvent(eventID);
00793 if (saveit)
00794 save();
00795 return;
00796 }
00797 }
00798 if (mType == KAEvent::ACTIVE)
00799 Daemon::eventHandled(eventID, false);
00800 }
00801
00802
00803
00804
00805 void AlarmCalendar::emitEmptyStatus()
00806 {
00807 emit emptyStatus(events().isEmpty());
00808 }
00809
00810
00811
00812
00813 KCal::Event* AlarmCalendar::event(const QString& uniqueID)
00814 {
00815 return mCalendar ? mCalendar->event(uniqueID) : 0;
00816 }
00817
00818
00819
00820
00821 KCal::Event::List AlarmCalendar::events()
00822 {
00823 if (!mCalendar)
00824 return KCal::Event::List();
00825 KCal::Event::List list = mCalendar->rawEvents();
00826 KCal::Event::List::Iterator it = list.begin();
00827 while (it != list.end())
00828 {
00829 if ((*it)->alarms().isEmpty())
00830 it = list.remove(it);
00831 else
00832 ++it;
00833 }
00834 return list;
00835 }
00836
00837
00838
00839
00840 Event::List AlarmCalendar::eventsWithAlarms(const QDateTime& from, const QDateTime& to)
00841 {
00842 kdDebug(5950) << "AlarmCalendar::eventsWithAlarms(" << from.toString() << " - " << to.toString() << ")\n";
00843 Event::List evnts;
00844 if (!mCalendar)
00845 return evnts;
00846 QDateTime dt;
00847 Event::List allEvents = mCalendar->rawEvents();
00848 for (Event::List::ConstIterator it = allEvents.begin(); it != allEvents.end(); ++it)
00849 {
00850 Event* e = *it;
00851 bool recurs = e->doesRecur();
00852 int endOffset = 0;
00853 bool endOffsetValid = false;
00854 const Alarm::List& alarms = e->alarms();
00855 for (Alarm::List::ConstIterator ait = alarms.begin(); ait != alarms.end(); ++ait)
00856 {
00857 Alarm* alarm = *ait;
00858 if (alarm->enabled())
00859 {
00860 if (recurs)
00861 {
00862 if (alarm->hasTime())
00863 dt = alarm->time();
00864 else
00865 {
00866
00867
00868
00869 int offset = 0;
00870 if (alarm->hasStartOffset())
00871 offset = alarm->startOffset().asSeconds();
00872 else if (alarm->hasEndOffset())
00873 {
00874 if (!endOffsetValid)
00875 {
00876 endOffset = e->hasDuration() ? e->duration() : e->hasEndDate() ? e->dtStart().secsTo(e->dtEnd()) : 0;
00877 endOffsetValid = true;
00878 }
00879 offset = alarm->endOffset().asSeconds() + endOffset;
00880 }
00881
00882 QDateTime pre = from.addSecs(-offset - 1);
00883 if (e->doesFloat() && pre.time() < Preferences::startOfDay())
00884 pre = pre.addDays(-1);
00885 dt = e->recurrence()->getNextDateTime(pre);
00886 if (!dt.isValid())
00887 continue;
00888 dt = dt.addSecs(offset);
00889 }
00890 }
00891 else
00892 dt = alarm->time();
00893 if (dt >= from && dt <= to)
00894 {
00895 kdDebug(5950) << "AlarmCalendar::events() '" << e->summary()
00896 << "': " << dt.toString() << endl;
00897 evnts.append(e);
00898 break;
00899 }
00900 }
00901 }
00902 }
00903 return evnts;
00904 }