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 bool AlarmCalendar::endUpdate()
00582 {
00583 if (mUpdateCount > 0)
00584 --mUpdateCount;
00585 if (!mUpdateCount)
00586 {
00587 if (mUpdateSave)
00588 return saveCal();
00589 }
00590 return true;
00591 }
00592
00593
00594
00595
00596 bool AlarmCalendar::save()
00597 {
00598 if (mUpdateCount)
00599 {
00600 mUpdateSave = true;
00601 return true;
00602 }
00603 else
00604 return saveCal();
00605 }
00606
00607 #if 0
00608
00609
00610
00611
00612 void AlarmCalendar::convertToICal()
00613 {
00614 if (mVCal)
00615 {
00616 if (!mConfigKey.isNull())
00617 {
00618 KConfig* config = kapp->config();
00619 config->setGroup(QString::fromLatin1("General"));
00620 config->writePathEntry(mConfigKey, mICalUrl.path());
00621 config->sync();
00622 }
00623 mUrl = mICalUrl;
00624 mVCal = false;
00625 }
00626 }
00627 #endif
00628
00629
00630
00631
00632
00633 void AlarmCalendar::setPurgeDays(int days)
00634 {
00635 if (days != mPurgeDays)
00636 {
00637 int oldDays = mPurgeDays;
00638 mPurgeDays = days;
00639 if (mPurgeDays <= 0)
00640 StartOfDayTimer::disconnect(this);
00641 if (oldDays < 0 || days >= 0 && days < oldDays)
00642 {
00643
00644 if (open())
00645 slotPurge();
00646 }
00647 else if (mPurgeDays > 0)
00648 startPurgeTimer();
00649 }
00650 }
00651
00652
00653
00654
00655
00656 void AlarmCalendar::slotPurge()
00657 {
00658 purge(mPurgeDays);
00659 startPurgeTimer();
00660 }
00661
00662
00663
00664
00665
00666 void AlarmCalendar::purge(int daysToKeep)
00667 {
00668 if (mPurgeDaysQueued < 0 || daysToKeep < mPurgeDaysQueued)
00669 mPurgeDaysQueued = daysToKeep;
00670
00671
00672 theApp()->processQueue();
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 void AlarmCalendar::purgeIfQueued()
00684 {
00685 if (mPurgeDaysQueued >= 0)
00686 {
00687 if (open())
00688 {
00689 kdDebug(5950) << "AlarmCalendar::purgeIfQueued(" << mPurgeDaysQueued << ")\n";
00690 bool changed = false;
00691 QDate cutoff = QDate::currentDate().addDays(-mPurgeDaysQueued);
00692 Event::List events = mCalendar->rawEvents();
00693 for (Event::List::ConstIterator it = events.begin(); it != events.end(); ++it)
00694 {
00695 Event* kcalEvent = *it;
00696 if (!mPurgeDaysQueued || kcalEvent->created().date() < cutoff)
00697 {
00698 mCalendar->deleteEvent(kcalEvent);
00699 changed = true;
00700 }
00701 }
00702 if (changed)
00703 {
00704 saveCal();
00705 emit purged();
00706 }
00707 mPurgeDaysQueued = -1;
00708 }
00709 }
00710 }
00711
00712
00713
00714
00715
00716
00717 void AlarmCalendar::startPurgeTimer()
00718 {
00719 if (mPurgeDays > 0)
00720 StartOfDayTimer::connect(this, SLOT(slotPurge()));
00721 }
00722
00723
00724
00725
00726
00727
00728
00729
00730 Event* AlarmCalendar::addEvent(KAEvent& event, bool useEventID)
00731 {
00732 if (!mOpen)
00733 return 0;
00734 QString id = event.id();
00735 Event* kcalEvent = new Event;
00736 if (mType == KAEvent::ACTIVE)
00737 {
00738 if (id.isEmpty())
00739 useEventID = false;
00740 if (!useEventID)
00741 event.setEventID(kcalEvent->uid());
00742 }
00743 else
00744 {
00745 if (id.isEmpty())
00746 id = kcalEvent->uid();
00747 useEventID = true;
00748 }
00749 if (useEventID)
00750 {
00751 id = KAEvent::uid(id, mType);
00752 event.setEventID(id);
00753 kcalEvent->setUid(id);
00754 }
00755 event.updateKCalEvent(*kcalEvent, false, (mType == KAEvent::EXPIRED), true);
00756 mCalendar->addEvent(kcalEvent);
00757 event.clearUpdated();
00758 return kcalEvent;
00759 }
00760
00761
00762
00763
00764
00765 void AlarmCalendar::updateEvent(const KAEvent& evnt)
00766 {
00767 if (mOpen)
00768 {
00769 Event* kcalEvent = event(evnt.id());
00770 if (kcalEvent)
00771 {
00772 evnt.updateKCalEvent(*kcalEvent);
00773 evnt.clearUpdated();
00774 if (mType == KAEvent::ACTIVE)
00775 Daemon::savingEvent(evnt.id());
00776 return;
00777 }
00778 }
00779 if (mType == KAEvent::ACTIVE)
00780 Daemon::eventHandled(evnt.id(), false);
00781 }
00782
00783
00784
00785
00786
00787 bool AlarmCalendar::deleteEvent(const QString& eventID, bool saveit)
00788 {
00789 if (mOpen)
00790 {
00791 Event* kcalEvent = event(eventID);
00792 if (kcalEvent)
00793 {
00794 mCalendar->deleteEvent(kcalEvent);
00795 if (mType == KAEvent::ACTIVE)
00796 Daemon::savingEvent(eventID);
00797 if (saveit)
00798 return save();
00799 return true;
00800 }
00801 }
00802 if (mType == KAEvent::ACTIVE)
00803 Daemon::eventHandled(eventID, false);
00804 return false;
00805 }
00806
00807
00808
00809
00810 void AlarmCalendar::emitEmptyStatus()
00811 {
00812 emit emptyStatus(events().isEmpty());
00813 }
00814
00815
00816
00817
00818 KCal::Event* AlarmCalendar::event(const QString& uniqueID)
00819 {
00820 return mCalendar ? mCalendar->event(uniqueID) : 0;
00821 }
00822
00823
00824
00825
00826 KCal::Event::List AlarmCalendar::events()
00827 {
00828 if (!mCalendar)
00829 return KCal::Event::List();
00830 KCal::Event::List list = mCalendar->rawEvents();
00831 KCal::Event::List::Iterator it = list.begin();
00832 while (it != list.end())
00833 {
00834 if ((*it)->alarms().isEmpty())
00835 it = list.remove(it);
00836 else
00837 ++it;
00838 }
00839 return list;
00840 }
00841
00842
00843
00844
00845 Event::List AlarmCalendar::eventsWithAlarms(const QDateTime& from, const QDateTime& to)
00846 {
00847 kdDebug(5950) << "AlarmCalendar::eventsWithAlarms(" << from.toString() << " - " << to.toString() << ")\n";
00848 Event::List evnts;
00849 if (!mCalendar)
00850 return evnts;
00851 QDateTime dt;
00852 Event::List allEvents = mCalendar->rawEvents();
00853 for (Event::List::ConstIterator it = allEvents.begin(); it != allEvents.end(); ++it)
00854 {
00855 Event* e = *it;
00856 bool recurs = e->doesRecur();
00857 int endOffset = 0;
00858 bool endOffsetValid = false;
00859 const Alarm::List& alarms = e->alarms();
00860 for (Alarm::List::ConstIterator ait = alarms.begin(); ait != alarms.end(); ++ait)
00861 {
00862 Alarm* alarm = *ait;
00863 if (alarm->enabled())
00864 {
00865 if (recurs)
00866 {
00867 if (alarm->hasTime())
00868 dt = alarm->time();
00869 else
00870 {
00871
00872
00873
00874 int offset = 0;
00875 if (alarm->hasStartOffset())
00876 offset = alarm->startOffset().asSeconds();
00877 else if (alarm->hasEndOffset())
00878 {
00879 if (!endOffsetValid)
00880 {
00881 endOffset = e->hasDuration() ? e->duration() : e->hasEndDate() ? e->dtStart().secsTo(e->dtEnd()) : 0;
00882 endOffsetValid = true;
00883 }
00884 offset = alarm->endOffset().asSeconds() + endOffset;
00885 }
00886
00887 QDateTime pre = from.addSecs(-offset - 1);
00888 if (e->doesFloat() && pre.time() < Preferences::startOfDay())
00889 pre = pre.addDays(-1);
00890 dt = e->recurrence()->getNextDateTime(pre);
00891 if (!dt.isValid())
00892 continue;
00893 dt = dt.addSecs(offset);
00894 }
00895 }
00896 else
00897 dt = alarm->time();
00898 if (dt >= from && dt <= to)
00899 {
00900 kdDebug(5950) << "AlarmCalendar::events() '" << e->summary()
00901 << "': " << dt.toString() << endl;
00902 evnts.append(e);
00903 break;
00904 }
00905 }
00906 }
00907 }
00908 return evnts;
00909 }