Functions | Variables
extendedcalendar.cpp File Reference

This class provides a calendar cached into memory. More...

#include "extendedcalendar.h"
#include "sqlitestorage.h"
#include "logging_p.h"
#include <calfilter.h>
#include <sorting.h>
#include <kdebug.h>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <cmath>
Include dependency graph for extendedcalendar.cpp:

Functions

 if ((*iit) ->recurs())
 Private class that helps to provide binary compatibility between releases. More...
 
returnList append (ExpandedIncidence(validity, *iit))
 
bool directoryIsRW (const QString &dirPath)
 

Variables

 else
 
validity dtEnd = d->incidenceEndTime(*iit, dt.dateTime(), true)
 
 appended
 
return returnList
 

Detailed Description

This class provides a calendar cached into memory.

This file is part of the API for handling calendar data and defines the ExtendedCalendar class.

Author
Tero Aho <ext-t.nosp@m.ero..nosp@m.1.aho.nosp@m.@nok.nosp@m.ia.co.nosp@m.m>
Preston Brown <pbrow.nosp@m.n@kd.nosp@m.e.org>
Cornelius Schumacher <schum.nosp@m.ache.nosp@m.r@kde.nosp@m..org>

Function Documentation

◆ append()

returnList append ( ExpandedIncidence(validity, *iit)  )

◆ directoryIsRW()

bool directoryIsRW ( const QString &  dirPath)

◆ if()

if ( *iit->  recurs())

Private class that helps to provide binary compatibility between releases.

bool ExtendedCalendar::deleteTodo(const Todo::Ptr &todo) { Handle orphaned children removeRelations(todo);

if (d->mTodos.remove(todo->uid(), todo)) { todo->unRegisterObserver(this); setModified(true); notifyIncidenceDeleted(todo); d->mDeletedTodos.insert(todo->uid(), todo);

d->removeIncidenceFromLists(todo, timeSpec());

todo->setLastModified(KDateTime::currentUtcDateTime());

return true; } else { qCWarning(lcMkcal) << "Todo not found."; return false; } }

bool ExtendedCalendar::deleteTodoInstances(const Todo::Ptr &todo) { QList<Todo::Ptr> values = d->mTodos.values(todo->uid()); QList<Todo::Ptr>::const_iterator it; for (it = values.constBegin(); it != values.constEnd(); ++it) { if ((*it)->hasRecurrenceId()) { qCDebug(lcMkcal) << "deleting child todo" << (*it)->uid() << (*it)->dtStart() << (*it)->dtDue() << "in calendar"; deleteTodo((*it)); } }

return true; }

void ExtendedCalendar::deleteAllTodos() { QHashIterator<QString, Todo::Ptr>i(d->mTodos); while (i.hasNext()) { i.next(); notifyIncidenceDeleted(i.value()); suppress update notifications for the relation removal triggered by the following deletions i.value()->startUpdates(); } d->mTodos.clear(); d->mTodosForDate.clear(); }

Todo::Ptr ExtendedCalendar::todo(const QString &uid, const KDateTime &recurrenceId) const { QList<Todo::Ptr> values = d->mTodos.values(uid); QList<Todo::Ptr>::const_iterator it; for (it = values.constBegin(); it != values.constEnd(); ++it) { if (recurrenceId.isNull()) { if (!(*it)->hasRecurrenceId()) { return *it; } } else { if ((*it)->hasRecurrenceId() && (*it)->recurrenceId() == recurrenceId) { return *it; } } } return Todo::Ptr(); }

Todo::Ptr ExtendedCalendar::deletedTodo(const QString &uid, const KDateTime &recurrenceId) const { QList<Todo::Ptr> values = d->mDeletedTodos.values(uid); QList<Todo::Ptr>::const_iterator it; for (it = values.constBegin(); it != values.constEnd(); ++it) { if (recurrenceId.isNull()) { if (!(*it)->hasRecurrenceId()) { return *it; } } else { if ((*it)->hasRecurrenceId() && (*it)->recurrenceId() == recurrenceId) { return *it; } } } return Todo::Ptr(); }

Todo::List ExtendedCalendar::rawTodos(TodoSortField sortField, SortDirection sortDirection) const { Todo::List todoList; QHashIterator<QString, Todo::Ptr>i(d->mTodos); while (i.hasNext()) { i.next(); if (isVisible(i.value())) { todoList.append(i.value()); } } return Calendar::sortTodos(todoList, sortField, sortDirection); }

Todo::List ExtendedCalendar::deletedTodos(TodoSortField sortField, SortDirection sortDirection) const { Todo::List todoList; QHashIterator<QString, Todo::Ptr>i(d->mDeletedTodos); while (i.hasNext()) { i.next(); todoList.append(i.value()); } return Calendar::sortTodos(todoList, sortField, sortDirection); }

Todo::List ExtendedCalendar::todoInstances(const Incidence::Ptr &todo, TodoSortField sortField, SortDirection sortDirection) const { Todo::List list;

QList<Todo::Ptr> values = d->mTodos.values(todo->uid()); QList<Todo::Ptr>::const_iterator it; for (it = values.constBegin(); it != values.constEnd(); ++it) { if ((*it)->hasRecurrenceId()) { list.append(*it); } } return Calendar::sortTodos(list, sortField, sortDirection); }

Todo::List ExtendedCalendar::rawTodosForDate(const QDate &date) const { Todo::List todoList; Todo::Ptr t;

KDateTime::Spec ts = timeSpec(); QString dateStr = date.toString(); QMultiHash<QString, Todo::Ptr>::const_iterator it = d->mTodosForDate.constFind(dateStr); while (it != d->mTodosForDate.constEnd() && it.key() == dateStr) { t = it.value(); if (isVisible(t)) { todoList.append(t); } ++it; }

Iterate over all todos. Look for recurring todoss that occur on this date QHashIterator<QString, Todo::Ptr>i(d->mTodos); while (i.hasNext()) { i.next(); t = i.value(); if (isVisible(t)) { if (t->recurs()) { if (t->recursOn(date, ts)) { if (!todoList.contains(t)) { todoList.append(t); } } } } }

return todoList; }

Todo::List ExtendedCalendar::rawTodos(const QDate &start, const QDate &end, const KDateTime::Spec &timespec, bool inclusive) const { Q_UNUSED(inclusive); // use only exact dtDue/dtStart, not dtStart and dtEnd

Todo::List todoList; KDateTime::Spec ts = timespec.isValid() ? timespec : timeSpec(); KDateTime st(start, ts); KDateTime nd(end, ts);

Get todos QHashIterator<QString, Todo::Ptr>i(d->mTodos); Todo::Ptr todo; while (i.hasNext()) { i.next(); todo = i.value(); if (!isVisible(todo)) { continue; }

KDateTime rStart = todo->hasDueDate() ? todo->dtDue() : todo->hasStartDate() ? todo->dtStart() : KDateTime(); if (!rStart.isValid()) { continue; }

if (!todo->recurs()) { // non-recurring todos if (nd.isValid() && nd < rStart) { continue; } if (st.isValid() && rStart < st) { continue; } } else { // recurring events switch (todo->recurrence()->duration()) { case -1: // infinite break; case 0: // end date given default: // count given KDateTime rEnd(todo->recurrence()->endDate(), ts); if (!rEnd.isValid()) { continue; } if (st.isValid() && rEnd < st) { continue; } break; } // switch(duration) } //if(recurs)

todoList.append(todo); }

return todoList; }

Alarm::List ExtendedCalendar::alarmsTo(const KDateTime &to) const { return alarms(KDateTime(QDate(1900, 1, 1)), to); }

Alarm::List ExtendedCalendar::alarms(const KDateTime &from, const KDateTime &to) const { Alarm::List alarmList; QHashIterator<QString, Event::Ptr>ie(d->mEvents); Event::Ptr e; while (ie.hasNext()) { ie.next(); e = ie.value(); if (e->recurs()) { appendRecurringAlarms(alarmList, e, from, to); } else { appendAlarms(alarmList, e, from, to); } }

QHashIterator<QString, Todo::Ptr>it(d->mTodos); Todo::Ptr t; while (it.hasNext()) { it.next(); t = it.value(); if (!t->isCompleted()) { appendAlarms(alarmList, t, from, to); } }

return alarmList; }

void ExtendedCalendar::incidenceUpdate(const QString &uid, const KDateTime &recurrenceId) { The static_cast is ok as the ExtendedCalendar only observes Incidence objects Incidence::Ptr incidence = this->incidence(uid, recurrenceId);

if (!incidence) { return; }

d->removeIncidenceFromLists(incidence, timeSpec()); }

void ExtendedCalendar::incidenceUpdated(const QString &uid, const KDateTime &recurrenceId) { Incidence::Ptr incidence = this->incidence(uid, recurrenceId);

if (!incidence) { return; }

incidence->setLastModified(KDateTime::currentUtcDateTime()); we should probably update the revision number here, or internally in the Event itself when certain things change. need to verify with ical documentation.

d->addIncidenceToLists(incidence, timeSpec());

notifyIncidenceChanged(incidence);

setModified(true);

}

Event::List ExtendedCalendar::rawEventsForDate(const QDate &date, const KDateTime::Spec &timespec, EventSortField sortField, SortDirection sortDirection) const { Event::List eventList; Event::Ptr ev;

Find the hash for the specified date QString dateStr = date.toString(); QMultiHash<QString, Event::Ptr>::const_iterator it = d->mEventsForDate.constFind(dateStr); Iterate over all non-recurring, single-day events that start on this date KDateTime::Spec ts = timespec.isValid() ? timespec : timeSpec(); KDateTime kdt(date, ts); while (it != d->mEventsForDate.constEnd() && it.key() == dateStr) { ev = it.value(); if (isVisible(ev)) { KDateTime end(ev->dtEnd().toTimeSpec(ev->dtStart())); if (ev->allDay()) { end.setDateOnly(true); } qCDebug(lcMkcal) << dateStr << kdt << ev->summary() << ev->dtStart() << end; if (end >= kdt) { eventList.append(ev); } } ++it; }

Iterate over all events. Look for recurring events that occur on this date QHashIterator<QString, Event::Ptr>i(d->mEvents); while (i.hasNext()) { i.next(); ev = i.value(); if (isVisible(ev)) { if (ev->recurs()) { if (ev->isMultiDay()) { int extraDays = ev->dtStart().date().daysTo(ev->dtEnd().date()); for (int i = 0; i <= extraDays; ++i) { if (ev->recursOn(date.addDays(-i), ts)) { eventList.append(ev); break; } } } else { if (ev->recursOn(date, ts)) { eventList.append(ev); } } } else { if (ev->isMultiDay()) { if (ev->dtStart().date() <= date && ev->dtEnd().date() >= date) { eventList.append(ev); } } } } }

return Calendar::sortEvents(eventList, sortField, sortDirection); }

ExtendedCalendar::ExpandedIncidenceList ExtendedCalendar::rawExpandedEvents(const QDate &start, const QDate &end, bool startInclusive, bool endInclusive, const KDateTime::Spec &timespec) const { ExpandedIncidenceList eventList;

Event::Ptr ev;

KDateTime::Spec ts = timespec.isValid() ? timespec : timeSpec(); KDateTime ksdt(start, ts); KDateTime kedt = KDateTime(end.addDays(1), QTime(0, 0, 0), ts);

Iterate over all events. Look for recurring events that occur on this date QHashIterator<QString, Event::Ptr>i(d->mEvents); while (i.hasNext()) { i.next(); ev = i.value(); if (isVisible(ev)) { const bool asClockTime = ev->dtStart().isClockTime() || ts.type() == KDateTime::ClockTime; const KDateTime startTime = ev->dtStart(); const KDateTime endTime = ev->dtEnd(); const KDateTime rangeStartTime = (ev->allDay() && asClockTime) ? KDateTime(ksdt.date(), QTime(), KDateTime::ClockTime) : ev->allDay() ? ksdt : KDateTime(ksdt.date(), QTime(0,0,0), ksdt.timeSpec()); const KDateTime rangeEndTime = (ev->allDay() && asClockTime) ? KDateTime(kedt.date(), QTime(), KDateTime::ClockTime) : kedt; const KDateTime tsRangeStartTime = kdatetimeAsTimeSpec(rangeStartTime, ts); const KDateTime tsRangeEndTime = kdatetimeAsTimeSpec(rangeEndTime, ts); if (ev->recurs()) { int extraDays = (ev->isMultiDay() && !startInclusive) ? startTime.date().daysTo(endTime.date()) : (ev->allDay() ? 1 : 0); const KDateTime tsAdjustedRangeStartTime(tsRangeStartTime.addDays(-extraDays)); const DateTimeList times = ev->recurrence()->timesInInterval(tsAdjustedRangeStartTime, tsRangeEndTime); for (const KDateTime &timeInInterval : times) { const KDateTime tsStartTime = kdatetimeAsTimeSpec(timeInInterval, ts); const KDateTime tsEndTime = Duration(startTime, endTime).end(tsStartTime); if (tsStartTime >= tsRangeEndTime || tsEndTime <= tsAdjustedRangeStartTime || (endInclusive && (tsEndTime > tsRangeEndTime))) { continue; } ExpandedIncidenceValidity eiv = { tsStartTime.dateTime(), tsEndTime.dateTime() }; eventList.append(qMakePair(eiv, ev.dynamicCast<Incidence>())); } } else { const KDateTime tsStartTime = kdatetimeAsTimeSpec(startTime, ts); const KDateTime tsEndTime = kdatetimeAsTimeSpec(endTime, ts); if (ev->isMultiDay()) { if ((startInclusive == false || tsStartTime >= tsRangeStartTime) && tsStartTime <= tsRangeEndTime && tsEndTime >= tsRangeStartTime && (endInclusive == false || tsEndTime <= tsRangeEndTime)) { ExpandedIncidenceValidity eiv = { tsStartTime.dateTime(), tsEndTime.dateTime() }; eventList.append(qMakePair(eiv, ev.dynamicCast<Incidence>())); } } else { if (tsStartTime >= tsRangeStartTime && tsStartTime <= tsRangeEndTime) { ExpandedIncidenceValidity eiv = { tsStartTime.dateTime(), tsEndTime.dateTime() }; eventList.append(qMakePair(eiv, ev.dynamicCast<Incidence>())); } } } } }

return eventList; }

Event::List ExtendedCalendar::rawEvents(const QDate &start, const QDate &end, const KDateTime::Spec &timespec, bool inclusive) const { Event::List eventList; KDateTime::Spec ts = timespec.isValid() ? timespec : timeSpec(); KDateTime st(start, ts); KDateTime nd(end, ts);

Get non-recurring events QHashIterator<QString, Event::Ptr>i(d->mEvents); Event::Ptr event; while (i.hasNext()) { i.next(); event = i.value(); if (!isVisible(event)) { continue; }

KDateTime rStart = event->dtStart(); if (nd.isValid() && nd < rStart) { continue; } if (inclusive && st.isValid() && rStart < st) { continue; }

if (!event->recurs()) { // non-recurring events KDateTime rEnd = event->dtEnd(); if (st.isValid() && rEnd < st) { continue; } if (inclusive && nd.isValid() && nd < rEnd) { continue; } } else { // recurring events switch (event->recurrence()->duration()) { case -1: // infinite if (inclusive) { continue; } break; case 0: // end date given default: // count given KDateTime rEnd(event->recurrence()->endDate(), ts); if (!rEnd.isValid()) { continue; } if (st.isValid() && rEnd < st) { continue; } if (inclusive && nd.isValid() && nd < rEnd) { continue; } break; } // switch(duration) } //if(recurs)

eventList.append(event); }

return eventList; }

Event::List ExtendedCalendar::rawEventsForDate(const KDateTime &kdt) const { return rawEventsForDate(kdt.date(), kdt.timeSpec()); }

Event::List ExtendedCalendar::rawEvents(EventSortField sortField, SortDirection sortDirection) const { Event::List eventList; QHashIterator<QString, Event::Ptr>i(d->mEvents); while (i.hasNext()) { i.next(); if (isVisible(i.value())) { eventList.append(i.value()); } } return Calendar::sortEvents(eventList, sortField, sortDirection); }

Event::List ExtendedCalendar::deletedEvents(EventSortField sortField, SortDirection sortDirection) const { Event::List eventList; QHashIterator<QString, Event::Ptr>i(d->mDeletedEvents); while (i.hasNext()) { i.next(); eventList.append(i.value()); } return Calendar::sortEvents(eventList, sortField, sortDirection); }

Event::List ExtendedCalendar::eventInstances(const Incidence::Ptr &event, EventSortField sortField, SortDirection sortDirection) const { Event::List list;

QList<Event::Ptr> values = d->mEvents.values(event->uid()); QList<Event::Ptr>::const_iterator it; for (it = values.constBegin(); it != values.constEnd(); ++it) { if ((*it)->hasRecurrenceId()) { list.append(*it); } }

return Calendar::sortEvents(list, sortField, sortDirection); }

QDate ExtendedCalendar::nextEventsDate(const QDate &date, const KDateTime::Spec &timespec) { Event::Ptr ev;

KDateTime::Spec ts = timespec.isValid() ? timespec : timeSpec();

KDateTime kdt(date, ts); KDateTime tomorrow = kdt.addDays(1); KDateTime almostTomorrow = tomorrow; almostTomorrow.setDateOnly(false); almostTomorrow = almostTomorrow.addSecs(-1);

KDateTime rv;

QHashIterator<QString, Event::Ptr>i(d->mEvents); while (i.hasNext()) { i.next(); ev = i.value(); if (!isVisible(ev)) continue;

if (ev->recurs()) { if (ev->isMultiDay()) { int extraDays = ev->dtStart().date().daysTo(ev->dtEnd().date()); for (int i = 0; i <= extraDays; ++i) { if (ev->recursOn(date.addDays(1 - i), ts)) return tomorrow.toTimeSpec(ts).date(); } }

KDateTime next = ev->recurrence()->getNextDateTime(almostTomorrow); next.setDateOnly(true);

if (!rv.isValid() || next < rv) rv = next; } else if (ev->isMultiDay()) { KDateTime edate = ev->dtStart(); edate.setDateOnly(true); if (edate > kdt) { if (!rv.isValid() || edate < rv) rv = edate; } else { edate = ev->dtEnd(); edate.setDateOnly(true); if (edate > kdt) rv = tomorrow; } } else { KDateTime edate = ev->dtStart(); edate.setDateOnly(true); if (edate > kdt && (!rv.isValid() || edate < rv)) rv = edate; }

if (rv == tomorrow) break; // Bail early - you can't beat tomorrow }

if (!rv.isValid()) return QDate(); else return rv.toTimeSpec(ts).date(); }

QDate ExtendedCalendar::previousEventsDate(const QDate &date, const KDateTime::Spec &timespec) { Event::Ptr ev;

KDateTime::Spec ts = timespec.isValid() ? timespec : timeSpec();

KDateTime kdt(date, ts); KDateTime yesterday = kdt.addDays(-1);

KDateTime rv;

QHashIterator<QString, Event::Ptr>i(d->mEvents); while (i.hasNext()) { i.next(); ev = i.value(); if (!isVisible(ev)) continue;

if (ev->recurs()) { KDateTime prev = ev->recurrence()->getPreviousDateTime(kdt); prev.setDateOnly(true);

if (ev->isMultiDay()) { prev = prev.addDays(ev->dtStart().date().daysTo(ev->dtEnd().date())); if (prev >= kdt) return yesterday.toTimeSpec(ts).date(); }

if (!rv.isValid() || prev > rv) rv = prev; } else if (ev->isMultiDay()) { KDateTime edate = ev->dtEnd(); edate.setDateOnly(true); if (edate < kdt) { if (!rv.isValid() || edate > rv) rv = edate; } else { edate = ev->dtStart(); edate.setDateOnly(true); if (edate < kdt) rv = yesterday; } } else { KDateTime edate = ev->dtStart(); edate.setDateOnly(true); if (edate < kdt && (!rv.isValid() || edate > rv)) rv = edate; }

if (rv == yesterday) break; // Bail early - you can't beat tomorrow }

if (!rv.isValid()) return QDate(); else return rv.toTimeSpec(ts).date(); }

bool ExtendedCalendar::addJournal(const Journal::Ptr &aJournal) { return addJournal(aJournal, defaultNotebook()); }

bool ExtendedCalendar::addJournal(const Journal::Ptr &aJournal, const QString &notebookUid) { if (!aJournal) { return false; }

if (notebookUid.isEmpty()) { qCWarning(lcMkcal) << "ExtendedCalendar::addJournal(): NotebookUid empty"; return false; }

if (d->mJournals.contains(aJournal->uid())) {
    Journal::Ptr old;
    if (!aJournal->hasRecurrenceId()) {
        old = journal(aJournal->uid());
    } else {
        old = journal(aJournal->uid(), aJournal->recurrenceId());
    }
    if (old) {
        if (aJournal->revision() > old->revision()) {
            deleteJournal(old);   // move old to deleted
        } else {
            qCDebug(lcMkcal) << "Duplicate found, journal was not added";
            return false;
        }
    }
}

notifyIncidenceAdded(aJournal);
d->mJournals.insert(aJournal->uid(), aJournal);
d->addIncidenceToLists(aJournal, timeSpec());
aJournal->registerObserver(this);

setModified(true);

return setNotebook(aJournal, notebookUid);;

}

bool ExtendedCalendar::deleteJournal(const Journal::Ptr &journal) { if (d->mJournals.remove(journal->uid(), journal)) { journal->unRegisterObserver(this); setModified(true); notifyIncidenceDeleted(journal); d->mDeletedJournals.insert(journal->uid(), journal);

d->removeIncidenceFromLists(journal, timeSpec());

journal->setLastModified(KDateTime::currentUtcDateTime());

return true; } else { qCWarning(lcMkcal) << "Journal not found."; return false; } }

bool ExtendedCalendar::deleteJournalInstances(const Journal::Ptr &journal) { QList<Journal::Ptr> values = d->mJournals.values(journal->uid()); QList<Journal::Ptr>::const_iterator it; for (it = values.constBegin(); it != values.constEnd(); ++it) { if ((*it)->hasRecurrenceId()) { qCDebug(lcMkcal) << "deleting child journal" << (*it)->uid() << (*it)->dtStart() << "in calendar"; deleteJournal((*it)); } }

return true; }

void ExtendedCalendar::deleteAllJournals() { QHashIterator<QString, Journal::Ptr>i(d->mJournals); while (i.hasNext()) { i.next(); notifyIncidenceDeleted(i.value()); suppress update notifications for the relation removal triggered by the following deletions i.value()->startUpdates(); } d->mJournals.clear(); d->mJournalsForDate.clear(); }

Journal::Ptr ExtendedCalendar::journal(const QString &uid, const KDateTime &recurrenceId) const { QList<Journal::Ptr> values = d->mJournals.values(uid); QList<Journal::Ptr>::const_iterator it; for (it = values.constBegin(); it != values.constEnd(); ++it) { if (recurrenceId.isNull()) { if (!(*it)->hasRecurrenceId()) { return *it; } } else { if ((*it)->hasRecurrenceId() && (*it)->recurrenceId() == recurrenceId) { return *it; } } } return Journal::Ptr(); }

Journal::Ptr ExtendedCalendar::deletedJournal(const QString &uid, const KDateTime &recurrenceId) const { QList<Journal::Ptr> values = d->mDeletedJournals.values(uid); QList<Journal::Ptr>::const_iterator it; for (it = values.constBegin(); it != values.constEnd(); ++it) { if (recurrenceId.isNull()) { if (!(*it)->hasRecurrenceId()) { return *it; } } else { if ((*it)->hasRecurrenceId() && (*it)->recurrenceId() == recurrenceId) { return *it; } } } return Journal::Ptr(); }

Journal::List ExtendedCalendar::rawJournals(JournalSortField sortField, SortDirection sortDirection) const { Journal::List journalList; QHashIterator<QString, Journal::Ptr>i(d->mJournals); while (i.hasNext()) { i.next(); if (isVisible(i.value())) { journalList.append(i.value()); } } return Calendar::sortJournals(journalList, sortField, sortDirection); }

Journal::List ExtendedCalendar::deletedJournals(JournalSortField sortField, SortDirection sortDirection) const { Journal::List journalList; QHashIterator<QString, Journal::Ptr>i(d->mDeletedJournals); while (i.hasNext()) { i.next(); journalList.append(i.value()); } return Calendar::sortJournals(journalList, sortField, sortDirection); }

Journal::List ExtendedCalendar::journalInstances(const Incidence::Ptr &journal, JournalSortField sortField, SortDirection sortDirection) const { Journal::List list;

QList<Journal::Ptr> values = d->mJournals.values(journal->uid()); QList<Journal::Ptr>::const_iterator it; for (it = values.constBegin(); it != values.constEnd(); ++it) { if ((*it)->hasRecurrenceId()) { list.append(*it); } } return Calendar::sortJournals(list, sortField, sortDirection); }

Journal::List ExtendedCalendar::rawJournalsForDate(const QDate &date) const { Journal::List journalList; Journal::Ptr j;

QString dateStr = date.toString(); QMultiHash<QString, Journal::Ptr>::const_iterator it = d->mJournalsForDate.constFind(dateStr);

while (it != d->mJournalsForDate.constEnd() && it.key() == dateStr) { j = it.value(); if (isVisible(j)) { journalList.append(j); } ++it; } return journalList; }

Journal::List ExtendedCalendar::rawJournals(const QDate &start, const QDate &end, const KDateTime::Spec &timespec, bool inclusive) const { Q_UNUSED(inclusive); Journal::List journalList; KDateTime::Spec ts = timespec.isValid() ? timespec : timeSpec(); KDateTime st(start, ts); KDateTime nd(end, ts);

Get journals QHashIterator<QString, Journal::Ptr>i(d->mJournals); Journal::Ptr journal; while (i.hasNext()) { i.next(); journal = i.value(); if (!isVisible(journal)) { continue; }

KDateTime rStart = journal->dtStart(); if (nd.isValid() && nd < rStart) { continue; } if (inclusive && st.isValid() && rStart < st) { continue; }

if (!journal->recurs()) { // non-recurring journals TODO_ALVARO: journals don't have endDt, bug? KDateTime rEnd = journal->dateTime(Incidence::RoleEnd); if (st.isValid() && rEnd < st) { continue; } if (inclusive && nd.isValid() && nd < rEnd) { continue; } } else { // recurring journals switch (journal->recurrence()->duration()) { case -1: // infinite if (inclusive) { continue; } break; case 0: // end date given default: // count given KDateTime rEnd(journal->recurrence()->endDate(), ts); if (!rEnd.isValid()) { continue; } if (st.isValid() && rEnd < st) { continue; } if (inclusive && nd.isValid() && nd < rEnd) { continue; } break; } // switch(duration) } //if(recurs)

journalList.append(journal); }

return journalList; }

QStringList ExtendedCalendar::attendees() { return d->mAttendeeIncidences.uniqueKeys(); }

Incidence::List ExtendedCalendar::attendeeIncidences(const QString &email) { return values(d->mAttendeeIncidences, email); }

Incidence::List ExtendedCalendar::geoIncidences() { return d->mGeoIncidences; }

Incidence::List ExtendedCalendar::geoIncidences(float geoLatitude, float geoLongitude, float diffLatitude, float diffLongitude) { Incidence::List list;

Incidence::List values = incidences(QString()); Incidence::List::const_iterator it; for (it = values.begin(); it != values.end(); ++it) { float lat = (*it)->geoLatitude(); float lon = (*it)->geoLongitude();

if (fabs(lat - geoLatitude) <= diffLatitude && fabs(lon - geoLongitude) <= diffLongitude) { list.append(*it); } } return list; }

Incidence::List ExtendedCalendar::incidences(const QDate &date, const QList<KCalCore::Incidence::IncidenceType> &types) { Event::List elist; Todo::List tlist; Journal::List jlist;

if (types.contains(Incidence::TypeEvent)) { elist = events(date); }

if (types.contains(Incidence::TypeTodo)) { tlist = todos(date); }

if (types.contains(Incidence::TypeJournal)) { jlist = journals(date); }

return mergeIncidenceList(elist, tlist, jlist); }

bool ExtendedCalendar::deleteIncidenceInstances(const Incidence::Ptr &incidence) { if (!incidence) { return false; }

if (incidence->type() == Incidence::TypeEvent) { return deleteEventInstances(incidence.staticCast<Event>()); } else if (incidence->type() == Incidence::TypeTodo) { return deleteTodoInstances(incidence.staticCast<Todo>()); } else if (incidence->type() == Incidence::TypeJournal) { return deleteJournalInstances(incidence.staticCast<Journal>()); }

return false; }

void ExtendedCalendar::deleteAllIncidences() { deleteAllEvents(); deleteAllTodos(); deleteAllJournals(); }

Incidence::List ExtendedCalendar::sortIncidences(Incidence::List *incidenceList, IncidenceSortField sortField, SortDirection sortDirection) { Incidence::List incidenceListSorted; Incidence::List tempList; Incidence::List::Iterator sortIt; Incidence::List::Iterator iit;

switch (sortField) {
case IncidenceSortUnsorted:
    incidenceListSorted = *incidenceList;
    break;

case IncidenceSortDate:
    incidenceListSorted = *incidenceList;
    if (sortDirection == SortDirectionAscending) {
        qSort(incidenceListSorted.begin(), incidenceListSorted.end(), Incidences::dateLessThan);
    } else {
        qSort(incidenceListSorted.begin(), incidenceListSorted.end(), Incidences::dateMoreThan);
    }
    break;

case IncidenceSortCreated:
    incidenceListSorted = *incidenceList;
    if (sortDirection == SortDirectionAscending) {
        qSort(incidenceListSorted.begin(), incidenceListSorted.end(), Incidences::createdLessThan);
    } else {
        qSort(incidenceListSorted.begin(), incidenceListSorted.end(), Incidences::createdMoreThan);
    }
    break;

}
return incidenceListSorted;

}

static bool expandedIncidenceSortLessThan(const ExtendedCalendar::ExpandedIncidence &e1, const ExtendedCalendar::ExpandedIncidence &e2) { if (e1.first.dtStart < e2.first.dtStart) { return true; } if (e1.first.dtStart > e2.first.dtStart) { return false; } e1 == e2 => perform secondary check based on created date return e1.second->created() < e2.second->created(); }

ExtendedCalendar::ExpandedIncidenceList ExtendedCalendar::expandRecurrences( Incidence::List *incidenceList, const KDateTime &dtStart, const KDateTime &dtEnd, int maxExpand, bool *expandLimitHit) { ExtendedCalendar::ExpandedIncidenceList returnList; Incidence::List::Iterator iit; KDateTime brokenDtStart = dtStart.addSecs(-1); KDateTime::Spec ts = timeSpec(); ExpandedIncidenceValidity validity;

used for comparing with entries that have broken dtEnd => we use dtStart and compare it against this instead. As this is allocated only once per iteration, it should result in significan net savings

qCDebug(lcMkcal) << "expandRecurrences" << incidenceList->size() << dtStart.toString() << dtStart.isValid() << dtEnd.toString() << dtEnd.isValid();

if (expandLimitHit)
     expandLimitHit = false;

for (iit = incidenceList->begin(); iit != incidenceList->end(); ++iit) {
    KDateTime dt = (*iit)->dtStart().toLocalZone();
    KDateTime dte = (*iit)->dateTime(IncidenceBase::RoleEndRecurrenceBase);
    int appended = 0;
    int skipped = 0;
    bool brokenEnd = false;

    if ((*iit)->type() == Incidence::TypeTodo) {
        Todo::Ptr todo = (*iit).staticCast<Todo>();
        if (todo->hasDueDate()) {
            dt = todo->dtDue().toLocalZone();
        }
    }

    if (!dt.isValid()) {

Just leave the dateless incidences there (they will be sorted out) validity.dtStart = dt.dateTime(); validity.dtEnd = d->incidenceEndTime(*iit, dt.dateTime(), true); returnList.append(ExpandedIncidence(validity, *iit)); continue; }

Fix the non-valid dte to be dt+1 if (dte.isValid() && dte <= dt) { brokenEnd = true; }

Then insert the current; only if it (partially) fits within the [dtStart, dtEnd[ window. (note that dtEnd is not really included; similarly, the last second of events is not counted as valid. This is because (for example) all-day events in ical are typically stored as whole day+1 events (that is, the first second of next day is where it ends), and due to that otherwise date-specific queries won't work nicely.

Mandatory conditions: [1] dt < dtEnd <> start period early enough iff dtEnd specified [2] dte > dtStart <> end period late enough iff dte set

Note: This algorithm implies that events that are only partially within the desired [dtStart, dtEnd] range are also included.

    if ((!dtEnd.isValid() || dt < dtEnd)
            && (!dte.isValid()
                || (!brokenEnd && dte > dtStart)
                || (brokenEnd && dt > brokenDtStart))) {

/* DEBUG_EXPANSION

Variable Documentation

◆ appended

appended

◆ dtEnd

validity dtEnd = d->incidenceEndTime(*iit, dt.dateTime(), true)

◆ else

else
Initial value:
{
validity.dtStart = dt.dateTime()

◆ returnList

return returnList

Generated on Sat Oct 17 2020 06:54:57 for libextendedkcal by doxygen 1.8.17