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>
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 |
This class provides a calendar cached into memory.
This file is part of the API for handling calendar data and defines the ExtendedCalendar class.
| returnList append | ( | ExpandedIncidence(validity, *iit) | ) |
| bool directoryIsRW | ( | const QString & | dirPath | ) |
| 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 ×pec, 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 ×pec, 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 ×pec) 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 ×pec, 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 ×pec) { 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 ×pec) { 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 ¬ebookUid) { 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 ×pec, 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
| appended |
| validity dtEnd = d->incidenceEndTime(*iit, dt.dateTime(), true) |
| else |
| return returnList |
1.8.17