41 #include "icaltimezones.h"
46 #include <icaltimezone.h>
56 class KCal::Calendar::Private
62 mNewObserver( false ),
63 mObserversEnabled( true ),
67 mFilter = mDefaultFilter;
68 mFilter->setEnabled(
false );
71 mOwner.setName( i18n(
"Unknown Name" ) );
72 mOwner.setEmail( i18n(
"unknown@nowhere" ) );
78 if ( mFilter != mDefaultFilter ) {
81 delete mDefaultFilter;
83 KDateTime::Spec timeZoneIdSpec(
const QString &timeZoneId,
bool view );
90 KDateTime::Spec mTimeSpec;
91 mutable KDateTime::Spec mViewTimeSpec;
94 bool mObserversEnabled;
95 QList<CalendarObserver*> mObservers;
101 QMultiHash<QString, Incidence*> mOrphans;
102 QMultiHash<QString, Incidence*> mOrphanUids;
152 d->mTimeSpec = d->timeZoneIdSpec( timeZoneId,
false );
153 d->mViewTimeSpec = d->mTimeSpec;
154 d->mBuiltInViewTimeZone = d->mBuiltInTimeZone;
160 KDateTime::Spec Calendar::Private::timeZoneIdSpec(
const QString &timeZoneId,
168 if ( timeZoneId == QLatin1String(
"UTC" ) ) {
169 return KDateTime::UTC;
172 if ( !tz.isValid() ) {
174 tz = tzsrc.
parse( icaltimezone_get_builtin_timezone( timeZoneId.toLatin1() ) );
176 mBuiltInViewTimeZone = tz;
178 mBuiltInTimeZone = tz;
181 if ( tz.isValid() ) {
184 return KDateTime::ClockTime;
191 KTimeZone tz = d->mTimeSpec.timeZone();
192 return tz.isValid() ? tz.name() : QString();
203 d->mViewTimeSpec = d->timeZoneIdSpec( timeZoneId,
true );
208 return d->mViewTimeSpec;
213 KTimeZone tz = d->mViewTimeSpec.timeZone();
214 return tz.isValid() ? tz.name() : QString();
219 return d->mTimeZones;
223 const KDateTime::Spec &newSpec )
229 for ( i = 0, end = ev.count(); i < end; ++i ) {
230 ev[i]->shiftTimes( oldSpec, newSpec );
234 for ( i = 0, end = to.count(); i < end; ++i ) {
235 to[i]->shiftTimes( oldSpec, newSpec );
239 for ( i = 0, end = jo.count(); i < end; ++i ) {
240 jo[i]->shiftTimes( oldSpec, newSpec );
249 d->mFilter = d->mDefaultFilter;
261 QStringList cats, thisCats;
264 for ( Incidence::List::ConstIterator i = rawInc.constBegin();
265 i != rawInc.constEnd(); ++i ) {
266 thisCats = (*i)->categories();
267 for ( QStringList::ConstIterator si = thisCats.constBegin();
268 si != thisCats.constEnd(); ++si ) {
269 if ( !cats.contains( *si ) ) {
299 Event::List::Iterator sortIt;
300 Event::List::Iterator eit;
305 switch( sortField ) {
307 eventListSorted = *eventList;
312 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
313 if ( (*eit)->dtStart().isDateOnly() ) {
314 tempList.append( *eit );
317 sortIt = eventListSorted.begin();
319 while ( sortIt != eventListSorted.end() &&
320 (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
324 while ( sortIt != eventListSorted.end() &&
325 (*eit)->dtStart() < (*sortIt)->dtStart() ) {
329 eventListSorted.insert( sortIt, *eit );
333 tempList += eventListSorted;
334 eventListSorted = tempList;
337 eventListSorted += tempList;
343 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
344 if ( (*eit)->hasEndDate() ) {
345 sortIt = eventListSorted.begin();
347 while ( sortIt != eventListSorted.end() &&
348 (*eit)->dtEnd() >= (*sortIt)->dtEnd() ) {
352 while ( sortIt != eventListSorted.end() &&
353 (*eit)->dtEnd() < (*sortIt)->dtEnd() ) {
359 tempList.append( *eit );
361 eventListSorted.insert( sortIt, *eit );
365 eventListSorted += tempList;
368 tempList += eventListSorted;
369 eventListSorted = tempList;
374 for ( eit = eventList->begin(); eit != eventList->end(); ++eit ) {
375 sortIt = eventListSorted.begin();
377 while ( sortIt != eventListSorted.end() &&
378 (*eit)->summary() >= (*sortIt)->summary() ) {
382 while ( sortIt != eventListSorted.end() &&
383 (*eit)->summary() < (*sortIt)->summary() ) {
387 eventListSorted.insert( sortIt, *eit );
392 return eventListSorted;
397 const KDateTime::Spec &timeSpec,
404 Event::List::Iterator sortIt;
405 Event::List::Iterator eit;
407 switch( sortField ) {
410 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
411 if ( (*eit)->allDay() ) {
412 tempList.append( *eit );
415 sortIt = eventListSorted.begin();
417 while ( sortIt != eventListSorted.end() ) {
418 if ( !(*eit)->recurs() ) {
419 if ( (*eit)->dtStart().time() >= (*sortIt)->dtStart().time() ) {
425 if ( (*eit)->recursOn( date, timeSpec ) ) {
426 if ( (*eit)->dtStart().time() >= (*sortIt)->dtStart().time() ) {
437 while ( sortIt != eventListSorted.end() ) {
438 if ( !(*eit)->recurs() ) {
439 if ( (*eit)->dtStart().time() < (*sortIt)->dtStart().time() ) {
445 if ( (*eit)->recursOn( date, timeSpec ) ) {
446 if ( (*eit)->dtStart().time() < (*sortIt)->dtStart().time() ) {
457 eventListSorted.insert( sortIt, *eit );
461 tempList += eventListSorted;
462 eventListSorted = tempList;
465 eventListSorted += tempList;
471 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
472 if ( (*eit)->hasEndDate() ) {
473 sortIt = eventListSorted.begin();
475 while ( sortIt != eventListSorted.end() ) {
476 if ( !(*eit)->recurs() ) {
477 if ( (*eit)->dtEnd().time() >= (*sortIt)->dtEnd().time() ) {
483 if ( (*eit)->recursOn( date, timeSpec ) ) {
484 if ( (*eit)->dtEnd().time() >= (*sortIt)->dtEnd().time() ) {
495 while ( sortIt != eventListSorted.end() ) {
496 if ( !(*eit)->recurs() ) {
497 if ( (*eit)->dtEnd().time() < (*sortIt)->dtEnd().time() ) {
503 if ( (*eit)->recursOn( date, timeSpec ) ) {
504 if ( (*eit)->dtEnd().time() < (*sortIt)->dtEnd().time() ) {
517 tempList.append( *eit );
519 eventListSorted.insert( sortIt, *eit );
523 tempList += eventListSorted;
524 eventListSorted = tempList;
527 eventListSorted += tempList;
532 eventListSorted =
sortEvents( eventList, sortField, sortDirection );
536 return eventListSorted;
540 const KDateTime::Spec &timeSpec,
545 d->mFilter->apply( &el );
552 d->mFilter->apply( &el );
557 const KDateTime::Spec &timeSpec,
561 d->mFilter->apply( &el );
569 d->mFilter->apply( &el );
575 Incidence::AddVisitor<Calendar> v(
this );
577 return incidence->
accept( v );
583 Incidence::DeleteVisitor<Calendar> v(
this );
584 bool result = incidence->
accept( v );
597 const KDateTime::Spec &spec,
600 if ( !incidence || !incidence->
recurs() ) {
619 if ( duration > 0 ) {
620 int doneduration = recur->
durationTo( date.addDays( -1 ) );
621 if ( doneduration >= duration ) {
622 kDebug() <<
"The dissociated event already occurred more often"
623 <<
"than it was supposed to ever occur. ERROR!";
631 if ( incidence->
type() ==
"Event" ) {
633 KDateTime start( ev->
dtStart() );
634 int daysTo = start.toTimeSpec( spec ).date().daysTo( date );
637 }
else if ( incidence->
type() ==
"Todo" ) {
638 Todo *td =
static_cast<Todo *
>( newInc );
639 bool haveOffset =
false;
642 KDateTime due( td->
dtDue() );
643 daysTo = due.toTimeSpec( spec ).date().daysTo( date );
644 td->
setDtDue( due.addDays( daysTo ), true );
648 KDateTime start( td->
dtStart() );
650 daysTo = start.toTimeSpec( spec ).date().daysTo( date );
659 recur->addExDate( date );
689 Incidence::List::const_iterator it = incidences.begin();
690 for ( ; it != incidences.end(); ++it ) {
691 if ( (*it)->schedulingID() == sid ) {
692 result.append( *it );
701 Incidence::List::const_iterator it = incidences.begin();
702 for ( ; it != incidences.end(); ++it ) {
703 if ( (*it)->schedulingID() == UID ) {
719 Todo::List::Iterator sortIt;
720 Todo::List::Iterator eit;
727 switch( sortField ) {
729 todoListSorted = *todoList;
734 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
735 if ( (*eit)->hasStartDate() ) {
736 sortIt = todoListSorted.begin();
738 while ( sortIt != todoListSorted.end() &&
739 (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
743 while ( sortIt != todoListSorted.end() &&
744 (*eit)->dtStart() < (*sortIt)->dtStart() ) {
748 todoListSorted.insert( sortIt, *eit );
751 tempList.append( *eit );
756 todoListSorted += tempList;
759 tempList += todoListSorted;
760 todoListSorted = tempList;
766 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
767 if ( (*eit)->hasDueDate() ) {
768 sortIt = todoListSorted.begin();
770 while ( sortIt != todoListSorted.end() &&
771 (*eit)->dtDue() >= (*sortIt)->dtDue() ) {
775 while ( sortIt != todoListSorted.end() &&
776 (*eit)->dtDue() < (*sortIt)->dtDue() ) {
780 todoListSorted.insert( sortIt, *eit );
783 tempList.append( *eit );
788 todoListSorted += tempList;
791 tempList += todoListSorted;
792 todoListSorted = tempList;
798 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
799 sortIt = todoListSorted.begin();
801 while ( sortIt != todoListSorted.end() &&
802 (*eit)->priority() >= (*sortIt)->priority() ) {
806 while ( sortIt != todoListSorted.end() &&
807 (*eit)->priority() < (*sortIt)->priority() ) {
811 todoListSorted.insert( sortIt, *eit );
817 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
818 sortIt = todoListSorted.begin();
820 while ( sortIt != todoListSorted.end() &&
821 (*eit)->percentComplete() >= (*sortIt)->percentComplete() ) {
825 while ( sortIt != todoListSorted.end() &&
826 (*eit)->percentComplete() < (*sortIt)->percentComplete() ) {
830 todoListSorted.insert( sortIt, *eit );
835 for ( eit = todoList->begin(); eit != todoList->end(); ++eit ) {
836 sortIt = todoListSorted.begin();
838 while ( sortIt != todoListSorted.end() &&
839 (*eit)->summary() >= (*sortIt)->summary() ) {
843 while ( sortIt != todoListSorted.end() &&
844 (*eit)->summary() < (*sortIt)->summary() ) {
848 todoListSorted.insert( sortIt, *eit );
853 return todoListSorted;
860 d->mFilter->apply( &tl );
867 d->mFilter->apply( &el );
876 Journal::List::Iterator sortIt;
877 Journal::List::Iterator eit;
879 switch( sortField ) {
881 journalListSorted = *journalList;
885 for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
886 sortIt = journalListSorted.begin();
888 while ( sortIt != journalListSorted.end() &&
889 (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
893 while ( sortIt != journalListSorted.end() &&
894 (*eit)->dtStart() < (*sortIt)->dtStart() ) {
898 journalListSorted.insert( sortIt, *eit );
903 for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
904 sortIt = journalListSorted.begin();
906 while ( sortIt != journalListSorted.end() &&
907 (*eit)->summary() >= (*sortIt)->summary() ) {
911 while ( sortIt != journalListSorted.end() &&
912 (*eit)->summary() < (*sortIt)->summary() ) {
916 journalListSorted.insert( sortIt, *eit );
921 return journalListSorted;
928 d->mFilter->apply( &jl );
935 d->mFilter->apply( &el );
953 if ( !forincidence ) {
957 QString uid = forincidence->
uid();
960 QList<Incidence*> l = d->mOrphans.values( uid );
961 d->mOrphans.remove( uid );
962 for (
int i = 0, end = l.count(); i < end; ++i ) {
963 l[i]->setRelatedTo( forincidence );
965 d->mOrphanUids.remove( l[i]->uid() );
979 kWarning() <<
"hierarchy loop beetween " << forincidence->
uid() <<
" and " << parent->
uid();
990 d->mOrphans.insert( forincidence->
relatedToUid(), forincidence );
991 d->mOrphanUids.insert( forincidence->
uid(), forincidence );
1000 kDebug() <<
"Warning: incidence is 0";
1004 QString uid = incidence->
uid();
1006 if ( !d->mOrphanUids.contains( i->
uid() ) ) {
1007 d->mOrphans.insert( uid, i );
1008 d->mOrphanUids.insert( i->
uid(), i );
1020 if ( d->mOrphanUids.remove( uid ) ) {
1030 QStringList relatedToUids;
1035 for ( QMultiHash<QString, Incidence*>::Iterator it = d->mOrphans.begin();
1036 it != d->mOrphans.end(); ++it ) {
1037 if ( it.value()->uid() == uid ) {
1038 relatedToUids << it.key();
1043 for ( QStringList::const_iterator uidit = relatedToUids.constBegin();
1044 uidit != relatedToUids.constEnd(); ++uidit ) {
1047 QList<Incidence*> l = d->mOrphans.values( *uidit );
1048 d->mOrphans.remove( *uidit );
1050 if ( i != incidence ) {
1051 tempList.append( i );
1055 for ( Incidence::List::Iterator incit = tempList.begin();
1056 incit != tempList.end(); ++incit ) {
1057 d->mOrphans.insert( *uidit, *incit );
1077 if ( !incidence || incidence->
relatedToUid().isEmpty() ) {
1088 Q_UNUSED( modified );
1089 Q_UNUSED( calendar );
1094 Q_UNUSED( incidence );
1099 Q_UNUSED( incidence );
1104 Q_UNUSED( incidence );
1109 if ( !d->mObservers.contains( observer ) ) {
1110 d->mObservers.append( observer );
1112 d->mNewObserver =
true;
1117 d->mObservers.removeAll( observer );
1127 if ( modified != d->mModified || d->mNewObserver ) {
1128 d->mNewObserver =
false;
1132 d->mModified = modified;
1138 return d->mModified;
1156 Q_UNUSED( timeSpec );
1161 if ( !d->mObserversEnabled ) {
1172 if ( !d->mObserversEnabled ) {
1183 if ( !d->mObserversEnabled ) {
1204 return d->mProductId;
1214 for ( i = 0, end = events.count(); i < end; ++i ) {
1215 incidences.append( events[i] );
1218 for ( i = 0, end = todos.count(); i < end; ++i ) {
1219 incidences.append( todos[i] );
1222 for ( i = 0, end = journals.count(); i < end; ++i ) {
1223 incidences.append( journals[i] );
1231 Q_UNUSED( incidence );
1237 Q_UNUSED( incidence );
1243 d->mObserversEnabled = enabled;
1247 const KDateTime &from,
const KDateTime &to )
1249 KDateTime preTime = from.addSecs(-1);
1252 for (
int i = 0, iend = alarmlist.count(); i < iend; ++i ) {
1253 if ( alarmlist[i]->enabled() ) {
1254 KDateTime dt = alarmlist[i]->nextRepetition( preTime );
1255 if ( dt.isValid() && dt <= to ) {
1256 kDebug() << incidence->
summary() <<
"':" << dt.toString();
1257 alarms.append( alarmlist[i] );
1265 const KDateTime &from,
1266 const KDateTime &to )
1270 bool endOffsetValid =
false;
1277 for (
int i = 0, iend = alarmlist.count(); i < iend; ++i ) {
1278 Alarm *a = alarmlist[i];
1283 if ( !dt.isValid() || dt > to ) {
1295 if ( !endOffsetValid ) {
1296 if ( incidence->
type() ==
"Event" ) {
1298 endOffsetValid =
true;
1299 }
else if ( incidence->
type() ==
"Todo" &&
1302 endOffsetValid =
true;
1308 KDateTime alarmStart;
1309 if ( incidence->
type() ==
"Event" ) {
1312 }
else if ( incidence->
type() ==
"Todo" ) {
1317 if ( alarmStart.isValid() && alarmStart > to ) {
1321 KDateTime baseStart;
1322 if ( incidence->
type() ==
"Event" ) {
1324 }
else if ( incidence->
type() ==
"Todo" ) {
1325 baseStart = t->
dtDue();
1327 if ( alarmStart.isValid() && from > alarmStart ) {
1329 baseStart = (-offset).end( (-endOffset).end( alarmStart ) );
1336 if ( !dt.isValid() ||
1337 ( dt = endOffset.
end( offset.
end( dt ) ) ) > to )
1348 for ( KDateTime base = baseStart;
1360 Duration toFromDuration( dt, base );
1361 int toFrom = toFromDuration.
asDays();
1363 ( toFromDuration.
isDaily() && toFrom % snooze == 0 ) ||
1364 ( toFrom / snooze + 1 ) * snooze <= toFrom + period.
asDays() ) {
1368 dt = offset.
end( dt ).addDays( ( ( toFrom - 1 ) / snooze + 1 ) * snooze );
1373 int toFrom = dt.secsTo( base );
1375 toFrom % snooze == 0 ||
1376 ( toFrom / snooze + 1 ) * snooze <= toFrom + period.
asSeconds() )
1381 dt = offset.
end( dt ).addSecs( ( ( toFrom - 1 ) / snooze + 1 ) * snooze );
1392 kDebug() << incidence->
summary() <<
"':" << dt.toString();