libkcal

calendar.cpp
Go to the documentation of this file.
1 /*
2  This file is part of libkcal.
3 
4  Copyright (c) 1998 Preston Brown <pbrown@kde.org>
5  Copyright (c) 2000-2004 Cornelius Schumacher <schumacher@kde.org>
6  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Library General Public
10  License as published by the Free Software Foundation; either
11  version 2 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Library General Public License for more details.
17 
18  You should have received a copy of the GNU Library General Public License
19  along with this library; see the file COPYING.LIB. If not, write to
20  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  Boston, MA 02110-1301, USA.
22 */
31 #include <stdlib.h>
32 
33 #include <kdebug.h>
34 #include <tdelocale.h>
35 
36 #include "exceptions.h"
37 #include "calfilter.h"
38 
39 #include "calendar.h"
40 
41 using namespace KCal;
42 
43 Calendar::Calendar( const TQString &timeZoneId )
44 {
45  mTimeZoneId = timeZoneId;
46  mLocalTime = false;
47 
48  init();
49 }
50 
51 void Calendar::init()
52 {
53  mException = 0;
54  mNewObserver = false;
55  mObserversEnabled = true;
56 
57  mModified = false;
58 
59  // Setup default filter, which does nothing
60  mDefaultFilter = new CalFilter;
61  mFilter = mDefaultFilter;
62  mFilter->setEnabled( false );
63 
64  // user information...
65  setOwner( Person( i18n( "Unknown Name" ), i18n( "unknown@nowhere" ) ) );
66 }
67 
69 {
71  delete mDefaultFilter;
72 }
73 
75 {
76  delete mException;
77  mException = 0;
78 }
79 
81 {
82  return mException;
83 }
84 
86 {
87  delete mException;
88  mException = e;
89 }
90 
91 const Person &Calendar::getOwner() const
92 {
93  return mOwner;
94 }
95 
96 void Calendar::setOwner( const Person &owner )
97 {
98  mOwner = owner;
99 
100  setModified( true );
101 }
102 
103 void Calendar::setTimeZoneId( const TQString &timeZoneId )
104 {
105  mTimeZoneId = timeZoneId;
106  mLocalTime = false;
107 
108  setModified( true );
109  doSetTimeZoneId( timeZoneId );
110 }
111 
112 TQString Calendar::timeZoneId() const
113 {
114  return mTimeZoneId;
115 }
116 
118 {
119  mLocalTime = true;
120  mTimeZoneId = "";
121 
122  setModified( true );
123 }
124 
126 {
127  return mLocalTime;
128 }
129 
131 {
132  if ( filter ) {
133  mFilter = filter;
134  } else {
135  mFilter = mDefaultFilter;
136  }
137 }
138 
140 {
141  return mFilter;
142 }
143 
145 {
146  emit batchAddingBegins();
147 }
148 
150 {
151  emit batchAddingEnds();
152 }
153 
154 TQStringList Calendar::categories()
155 {
156  Incidence::List rawInc( rawIncidences() );
157  TQStringList cats, thisCats;
158  // @TODO: For now just iterate over all incidences. In the future,
159  // the list of categories should be built when reading the file.
160  for ( Incidence::List::ConstIterator i = rawInc.constBegin();
161  i != rawInc.constEnd(); ++i ) {
162  thisCats = (*i)->categories();
163  for ( TQStringList::ConstIterator si = thisCats.constBegin();
164  si != thisCats.constEnd(); ++si ) {
165  if ( cats.find( *si ) == cats.end() ) {
166  cats.append( *si );
167  }
168  }
169  }
170  return cats;
171 }
172 
174 {
175  return mergeIncidenceList( events( date ), todos( date ), journals( date ) );
176 }
177 
179 {
180  return mergeIncidenceList( events(), todos(), journals() );
181 }
182 
184 {
186 }
187 
189  EventSortField sortField,
190  SortDirection sortDirection )
191 {
192  Event::List eventListSorted;
193  Event::List tempList;
194  Event::List alphaList;
195  Event::List::Iterator sortIt;
196  Event::List::Iterator eit;
197 
198  // Notice we alphabetically presort Summaries first.
199  // We do this so comparison "ties" stay in a nice order.
200 
201  switch( sortField ) {
202  case EventSortUnsorted:
203  eventListSorted = *eventList;
204  break;
205 
206  case EventSortStartDate:
207  alphaList = sortEvents( eventList, EventSortSummary, sortDirection );
208  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
209  if ( (*eit)->doesFloat() ) {
210  tempList.append( *eit );
211  continue;
212  }
213  sortIt = eventListSorted.begin();
214  if ( sortDirection == SortDirectionAscending ) {
215  while ( sortIt != eventListSorted.end() &&
216  (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
217  ++sortIt;
218  }
219  } else {
220  while ( sortIt != eventListSorted.end() &&
221  (*eit)->dtStart() < (*sortIt)->dtStart() ) {
222  ++sortIt;
223  }
224  }
225  eventListSorted.insert( sortIt, *eit );
226  }
227  if ( sortDirection == SortDirectionAscending ) {
228  // Prepend the list of all-day Events
229  tempList += eventListSorted;
230  eventListSorted = tempList;
231  } else {
232  // Append the list of all-day Events
233  eventListSorted += tempList;
234  }
235  break;
236 
237  case EventSortEndDate:
238  alphaList = sortEvents( eventList, EventSortSummary, sortDirection );
239  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
240  if ( (*eit)->hasEndDate() ) {
241  sortIt = eventListSorted.begin();
242  if ( sortDirection == SortDirectionAscending ) {
243  while ( sortIt != eventListSorted.end() &&
244  (*eit)->dtEnd() >= (*sortIt)->dtEnd() ) {
245  ++sortIt;
246  }
247  } else {
248  while ( sortIt != eventListSorted.end() &&
249  (*eit)->dtEnd() < (*sortIt)->dtEnd() ) {
250  ++sortIt;
251  }
252  }
253  } else {
254  // Keep a list of the Events without End DateTimes
255  tempList.append( *eit );
256  }
257  eventListSorted.insert( sortIt, *eit );
258  }
259  if ( sortDirection == SortDirectionAscending ) {
260  // Append the list of Events without End DateTimes
261  eventListSorted += tempList;
262  } else {
263  // Prepend the list of Events without End DateTimes
264  tempList += eventListSorted;
265  eventListSorted = tempList;
266  }
267  break;
268 
269  case EventSortSummary:
270  for ( eit = eventList->begin(); eit != eventList->end(); ++eit ) {
271  sortIt = eventListSorted.begin();
272  if ( sortDirection == SortDirectionAscending ) {
273  while ( sortIt != eventListSorted.end() &&
274  (*eit)->summary() >= (*sortIt)->summary() ) {
275  ++sortIt;
276  }
277  } else {
278  while ( sortIt != eventListSorted.end() &&
279  (*eit)->summary() < (*sortIt)->summary() ) {
280  ++sortIt;
281  }
282  }
283  eventListSorted.insert( sortIt, *eit );
284  }
285  break;
286  }
287 
288  return eventListSorted;
289 }
290 
292  const TQDate &date,
293  EventSortField sortField,
294  SortDirection sortDirection )
295 {
296  Event::List eventListSorted;
297  Event::List tempList;
298  Event::List alphaList;
299  Event::List::Iterator sortIt;
300  Event::List::Iterator eit;
301 
302  switch( sortField ) {
303  case EventSortStartDate:
304  alphaList = sortEvents( eventList, EventSortSummary, sortDirection );
305  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
306  if ( (*eit)->doesFloat() ) {
307  tempList.append( *eit );
308  continue;
309  }
310  sortIt = eventListSorted.begin();
311  if ( sortDirection == SortDirectionAscending ) {
312  while ( sortIt != eventListSorted.end() ) {
313  if ( !(*eit)->doesRecur() ) {
314  if ( (*eit)->dtStart().time() >= (*sortIt)->dtStart().time() ) {
315  ++sortIt;
316  } else {
317  break;
318  }
319  } else {
320  if ( (*eit)->recursOn( date ) ) {
321  if ( (*eit)->dtStart().time() >= (*sortIt)->dtStart().time() ) {
322  ++sortIt;
323  } else {
324  break;
325  }
326  } else {
327  ++sortIt;
328  }
329  }
330  }
331  } else { // descending
332  while ( sortIt != eventListSorted.end() ) {
333  if ( !(*eit)->doesRecur() ) {
334  if ( (*eit)->dtStart().time() < (*sortIt)->dtStart().time() ) {
335  ++sortIt;
336  } else {
337  break;
338  }
339  } else {
340  if ( (*eit)->recursOn( date ) ) {
341  if ( (*eit)->dtStart().time() < (*sortIt)->dtStart().time() ) {
342  ++sortIt;
343  } else {
344  break;
345  }
346  } else {
347  ++sortIt;
348  }
349  }
350  }
351  }
352  eventListSorted.insert( sortIt, *eit );
353  }
354  if ( sortDirection == SortDirectionAscending ) {
355  // Prepend the list of all-day Events
356  tempList += eventListSorted;
357  eventListSorted = tempList;
358  } else {
359  // Append the list of all-day Events
360  eventListSorted += tempList;
361  }
362  break;
363 
364  case EventSortEndDate:
365  alphaList = sortEvents( eventList, EventSortSummary, sortDirection );
366  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
367  if ( (*eit)->hasEndDate() ) {
368  sortIt = eventListSorted.begin();
369  if ( sortDirection == SortDirectionAscending ) {
370  while ( sortIt != eventListSorted.end() ) {
371  if ( !(*eit)->doesRecur() ) {
372  if ( (*eit)->dtEnd().time() >= (*sortIt)->dtEnd().time() ) {
373  ++sortIt;
374  } else {
375  break;
376  }
377  } else {
378  if ( (*eit)->recursOn( date ) ) {
379  if ( (*eit)->dtEnd().time() >= (*sortIt)->dtEnd().time() ) {
380  ++sortIt;
381  } else {
382  break;
383  }
384  } else {
385  ++sortIt;
386  }
387  }
388  }
389  } else { // descending
390  while ( sortIt != eventListSorted.end() ) {
391  if ( !(*eit)->doesRecur() ) {
392  if ( (*eit)->dtEnd().time() < (*sortIt)->dtEnd().time() ) {
393  ++sortIt;
394  } else {
395  break;
396  }
397  } else {
398  if ( (*eit)->recursOn( date ) ) {
399  if ( (*eit)->dtEnd().time() < (*sortIt)->dtEnd().time() ) {
400  ++sortIt;
401  } else {
402  break;
403  }
404  } else {
405  ++sortIt;
406  }
407  }
408  }
409  }
410  } else {
411  // Keep a list of the Events without End DateTimes
412  tempList.append( *eit );
413  }
414  eventListSorted.insert( sortIt, *eit );
415  }
416  if ( sortDirection == SortDirectionAscending ) {
417  // Prepend the list of Events without End DateTimes
418  tempList += eventListSorted;
419  eventListSorted = tempList;
420  } else {
421  // Append the list of Events without End DateTimes
422  eventListSorted += tempList;
423  }
424  break;
425 
426  default:
427  eventListSorted = sortEvents( eventList, sortField, sortDirection );
428  break;
429  }
430 
431  return eventListSorted;
432 }
433 
434 Event::List Calendar::events( const TQDate &date,
435  EventSortField sortField,
436  SortDirection sortDirection )
437 {
438  Event::List el = rawEventsForDate( date, sortField, sortDirection );
439  mFilter->apply( &el );
440  return el;
441 }
442 
443 Event::List Calendar::events( const TQDateTime &qdt )
444 {
445  Event::List el = rawEventsForDate( qdt );
446  mFilter->apply( &el );
447  return el;
448 }
449 
450 Event::List Calendar::events( const TQDate &start, const TQDate &end,
451  bool inclusive)
452 {
453  Event::List el = rawEvents( start, end, inclusive );
454  mFilter->apply( &el );
455  return el;
456 }
457 
459  SortDirection sortDirection )
460 {
461  Event::List el = rawEvents( sortField, sortDirection );
462  mFilter->apply( &el );
463  return el;
464 }
465 
467 {
469 
470  return incidence->accept(v);
471 }
472 
474 {
475  if ( beginChange( incidence ) ) {
476  if (incidence->hasRecurrenceID()) {
477  // Delete this event's UID from the parent's list of children
478  Incidence *parentIncidence;
479  IncidenceList il = incidence->childIncidences();
480  IncidenceListIterator it;
481  it = il.begin();
482  parentIncidence = this->incidence(*it);
483  parentIncidence->deleteChildIncidence(incidence->uid());
484  }
485  else {
486  // Delete all children as well
487  IncidenceList il = incidence->childIncidences();
488  IncidenceListIterator it;
489  for ( it = il.begin(); it != il.end(); ++it ) {
490  deleteIncidence( this->incidence(*it) );
491  // Avoid a crash, reset the iterator every time the list is modified
492  it = il.begin();
493  }
494  }
496  bool result = incidence->accept( v );
497  endChange( incidence );
498  return result;
499  } else
500  return false;
501 }
502 
507  bool single )
508 {
509  if ( !incidence || !incidence->doesRecur() )
510  return 0;
511 
512  Incidence *newInc = incidence->clone();
513  newInc->recreate();
514  newInc->setHasRecurrenceID(false);
515 // newInc->setRecurrenceID(TQString());
516  newInc->setRelatedTo( incidence );
517  Recurrence *recur = newInc->recurrence();
518  if ( single ) {
519  recur->clear();
520  } else {
521  // Adjust the recurrence for the future incidences. In particular
522  // adjust the "end after n occurrences" rules! "No end date" and "end by ..."
523  // don't need to be modified.
524  int duration = recur->duration();
525  if ( duration > 0 ) {
526  int doneduration = recur->durationTo( date.addDays(-1) );
527  if ( doneduration >= duration ) {
528  kdDebug(5850) << "The dissociated event already occurred more often "
529  << "than it was supposed to ever occur. ERROR!" << endl;
530  recur->clear();
531  } else {
532  recur->setDuration( duration - doneduration );
533  }
534  }
535  }
536  // Adjust the date of the incidence
537  if ( incidence->type() == "Event" ) {
538  Event *ev = static_cast<Event *>( newInc );
539  TQDateTime start( ev->dtStart() );
540  int daysTo = start.date().daysTo( date );
541  ev->setDtStart( start.addDays( daysTo ) );
542  ev->setDtEnd( ev->dtEnd().addDays( daysTo ) );
543  } else if ( incidence->type() == "Todo" ) {
544  Todo *td = static_cast<Todo *>( newInc );
545  bool haveOffset = false;
546  int daysTo = 0;
547  if ( td->hasDueDate() ) {
548  TQDateTime due( td->dtDue() );
549  daysTo = due.date().daysTo( date );
550  td->setDtDue( due.addDays( daysTo ), true );
551  haveOffset = true;
552  }
553  if ( td->hasStartDate() ) {
554  TQDateTime start( td->dtStart() );
555  if ( !haveOffset )
556  daysTo = start.date().daysTo( date );
557  td->setDtStart( start.addDays( daysTo ) );
558  haveOffset = true;
559  }
560  }
561  recur = incidence->recurrence();
562  if ( recur ) {
563  if ( single ) {
564  recur->addExDate( date );
565  } else {
566  // Make sure the recurrence of the past events ends
567  // at the corresponding day
568  recur->setEndDate( date.addDays(-1) );
569  }
570  }
571  return newInc;
572 }
573 
574 Incidence *Calendar::incidence( const TQString &uid )
575 {
576  Incidence *i = event( uid );
577  if ( i )
578  return i;
579  i = todo( uid );
580  if ( i )
581  return i;
582  i = journal( uid );
583  return i;
584 }
585 
587 {
588  Incidence::List result;
590  Incidence::List::iterator it = incidences.begin();
591  for ( ; it != incidences.end(); ++it )
592  if ( (*it)->schedulingID() == UID )
593  result.append( *it );
594  return result;
595 }
596 
598 {
600  Incidence::List::iterator it = incidences.begin();
601  for ( ; it != incidences.end(); ++it )
602  if ( (*it)->schedulingID() == UID )
603  // Touchdown, and the crowd goes wild
604  return *it;
605  // Not found
606  return 0;
607 }
608 
610  TodoSortField sortField,
611  SortDirection sortDirection )
612 {
613  Todo::List todoListSorted;
614  Todo::List tempList, t;
615  Todo::List alphaList;
616  Todo::List::Iterator sortIt;
617  Todo::List::Iterator eit;
618 
619  // Notice we alphabetically presort Summaries first.
620  // We do this so comparison "ties" stay in a nice order.
621 
622  // Note that Todos may not have Start DateTimes nor due DateTimes.
623 
624  switch( sortField ) {
625  case TodoSortUnsorted:
626  todoListSorted = *todoList;
627  break;
628 
629  case TodoSortStartDate:
630  alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
631  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
632  if ( (*eit)->hasStartDate() ) {
633  sortIt = todoListSorted.begin();
634  if ( sortDirection == SortDirectionAscending ) {
635  while ( sortIt != todoListSorted.end() &&
636  (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
637  ++sortIt;
638  }
639  } else {
640  while ( sortIt != todoListSorted.end() &&
641  (*eit)->dtStart() < (*sortIt)->dtStart() ) {
642  ++sortIt;
643  }
644  }
645  todoListSorted.insert( sortIt, *eit );
646  } else {
647  // Keep a list of the Todos without Start DateTimes
648  tempList.append( *eit );
649  }
650  }
651  if ( sortDirection == SortDirectionAscending ) {
652  // Append the list of Todos without Start DateTimes
653  todoListSorted += tempList;
654  } else {
655  // Prepend the list of Todos without Start DateTimes
656  tempList += todoListSorted;
657  todoListSorted = tempList;
658  }
659  break;
660 
661  case TodoSortDueDate:
662  alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
663  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
664  if ( (*eit)->hasDueDate() ) {
665  sortIt = todoListSorted.begin();
666  if ( sortDirection == SortDirectionAscending ) {
667  while ( sortIt != todoListSorted.end() &&
668  (*eit)->dtDue() >= (*sortIt)->dtDue() ) {
669  ++sortIt;
670  }
671  } else {
672  while ( sortIt != todoListSorted.end() &&
673  (*eit)->dtDue() < (*sortIt)->dtDue() ) {
674  ++sortIt;
675  }
676  }
677  todoListSorted.insert( sortIt, *eit );
678  } else {
679  // Keep a list of the Todos without Due DateTimes
680  tempList.append( *eit );
681  }
682  }
683  if ( sortDirection == SortDirectionAscending ) {
684  // Append the list of Todos without Due DateTimes
685  todoListSorted += tempList;
686  } else {
687  // Prepend the list of Todos without Due DateTimes
688  tempList += todoListSorted;
689  todoListSorted = tempList;
690  }
691  break;
692 
693  case TodoSortPriority:
694  alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
695  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
696  sortIt = todoListSorted.begin();
697  if ( sortDirection == SortDirectionAscending ) {
698  while ( sortIt != todoListSorted.end() &&
699  (*eit)->priority() >= (*sortIt)->priority() ) {
700  ++sortIt;
701  }
702  } else {
703  while ( sortIt != todoListSorted.end() &&
704  (*eit)->priority() < (*sortIt)->priority() ) {
705  ++sortIt;
706  }
707  }
708  todoListSorted.insert( sortIt, *eit );
709  }
710  break;
711 
713  alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
714  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
715  sortIt = todoListSorted.begin();
716  if ( sortDirection == SortDirectionAscending ) {
717  while ( sortIt != todoListSorted.end() &&
718  (*eit)->percentComplete() >= (*sortIt)->percentComplete() ) {
719  ++sortIt;
720  }
721  } else {
722  while ( sortIt != todoListSorted.end() &&
723  (*eit)->percentComplete() < (*sortIt)->percentComplete() ) {
724  ++sortIt;
725  }
726  }
727  todoListSorted.insert( sortIt, *eit );
728  }
729  break;
730 
731  case TodoSortSummary:
732  for ( eit = todoList->begin(); eit != todoList->end(); ++eit ) {
733  sortIt = todoListSorted.begin();
734  if ( sortDirection == SortDirectionAscending ) {
735  while ( sortIt != todoListSorted.end() &&
736  (*eit)->summary() >= (*sortIt)->summary() ) {
737  ++sortIt;
738  }
739  } else {
740  while ( sortIt != todoListSorted.end() &&
741  (*eit)->summary() < (*sortIt)->summary() ) {
742  ++sortIt;
743  }
744  }
745  todoListSorted.insert( sortIt, *eit );
746  }
747  break;
748  }
749 
750  return todoListSorted;
751 }
752 
754  SortDirection sortDirection )
755 {
756  Todo::List tl = rawTodos( sortField, sortDirection );
757  mFilter->apply( &tl );
758  return tl;
759 }
760 
761 Todo::List Calendar::todos( const TQDate &date )
762 {
763  Todo::List el = rawTodosForDate( date );
764  mFilter->apply( &el );
765  return el;
766 }
767 
769  JournalSortField sortField,
770  SortDirection sortDirection )
771 {
772  Journal::List journalListSorted;
773  Journal::List::Iterator sortIt;
774  Journal::List::Iterator eit;
775 
776  switch( sortField ) {
777  case JournalSortUnsorted:
778  journalListSorted = *journalList;
779  break;
780 
781  case JournalSortDate:
782  for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
783  sortIt = journalListSorted.begin();
784  if ( sortDirection == SortDirectionAscending ) {
785  while ( sortIt != journalListSorted.end() &&
786  (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
787  ++sortIt;
788  }
789  } else {
790  while ( sortIt != journalListSorted.end() &&
791  (*eit)->dtStart() < (*sortIt)->dtStart() ) {
792  ++sortIt;
793  }
794  }
795  journalListSorted.insert( sortIt, *eit );
796  }
797  break;
798 
799  case JournalSortSummary:
800  for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
801  sortIt = journalListSorted.begin();
802  if ( sortDirection == SortDirectionAscending ) {
803  while ( sortIt != journalListSorted.end() &&
804  (*eit)->summary() >= (*sortIt)->summary() ) {
805  ++sortIt;
806  }
807  } else {
808  while ( sortIt != journalListSorted.end() &&
809  (*eit)->summary() < (*sortIt)->summary() ) {
810  ++sortIt;
811  }
812  }
813  journalListSorted.insert( sortIt, *eit );
814  }
815  break;
816  }
817 
818  return journalListSorted;
819 }
820 
822  SortDirection sortDirection )
823 {
824  Journal::List jl = rawJournals( sortField, sortDirection );
825  mFilter->apply( &jl );
826  return jl;
827 }
828 
829 Journal::List Calendar::journals( const TQDate &date )
830 {
831  Journal::List el = rawJournalsForDate( date );
832  mFilter->apply( &el );
833  return el;
834 }
835 
836 // When this is called, the todo have already been added to the calendar.
837 // This method is only about linking related todos
838 void Calendar::setupRelations( Incidence *forincidence )
839 {
840  if ( !forincidence ) return;
841 // kdDebug(5850) << "Calendar::setupRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl;
842  TQString uid = forincidence->uid();
843 
844  // First, go over the list of orphans and see if this is their parent
845  while ( Incidence* i = mOrphans[ uid ] ) {
846  mOrphans.remove( uid );
847  i->setRelatedTo( forincidence );
848  forincidence->addRelation( i );
849  mOrphanUids.remove( i->uid() );
850  }
851 
852  // Now see about this incidences parent
853  if ( !forincidence->relatedTo() && !forincidence->relatedToUid().isEmpty() ) {
854  // This incidence has a uid it is related to but is not registered to it yet
855  // Try to find it
856  Incidence* parent = incidence( forincidence->relatedToUid() );
857  if ( parent ) {
858  // Found it
859  forincidence->setRelatedTo( parent );
860  parent->addRelation( forincidence );
861  } else {
862  // Not found, put this in the mOrphans list
863  // Note that the mOrphans dict might have several entries with the same key! That are
864  // multiple children that wait for the parent incidence to be inserted.
865  mOrphans.insert( forincidence->relatedToUid(), forincidence );
866  mOrphanUids.insert( forincidence->uid(), forincidence );
867  }
868  }
869 }
870 
871 // If a task with subtasks is deleted, move it's subtasks to the orphans list
873 {
874  if( !incidence ) {
875  kdDebug(5800) << "Warning: Calendar::removeRelations( 0 )!\n";
876  return;
877  }
878 
879 // kdDebug(5850) << "Calendar::removeRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl;
880  TQString uid = incidence->uid();
881 
882  Incidence::List relations = incidence->relations();
883  Incidence::List::ConstIterator it;
884  for ( it = relations.begin(); it != relations.end(); ++it ) {
885  Incidence *i = *it;
886  if ( !mOrphanUids.find( i->uid() ) ) {
887  mOrphans.insert( uid, i );
888  mOrphanUids.insert( i->uid(), i );
889  i->setRelatedTo( 0 );
890  i->setRelatedToUid( uid );
891  }
892  }
893 
894  // If this incidence is related to something else, tell that about it
895  if ( incidence->relatedTo() )
896  incidence->relatedTo()->removeRelation( incidence );
897 
898  // Remove this one from the orphans list
899  if ( mOrphanUids.remove( uid ) ) {
900  // This incidence is located in the orphans list - it should be removed
901  // Since the mOrphans dict might contain the same key (with different
902  // child incidence pointers!) multiple times, take care that we remove
903  // the correct one. So we need to remove all items with the given
904  // parent UID, and readd those that are not for this item. Also, there
905  // might be other entries with differnet UID that point to this
906  // incidence (this might happen when the relatedTo of the item is
907  // changed before its parent is inserted. This might happen with
908  // groupware servers....). Remove them, too
909  TQStringList relatedToUids;
910  // First get the list of all keys in the mOrphans list that point to the removed item
911  relatedToUids << incidence->relatedToUid();
912  for ( TQDictIterator<Incidence> it( mOrphans ); it.current(); ++it ) {
913  if ( it.current()->uid() == uid ) {
914  relatedToUids << it.currentKey();
915  }
916  }
917 
918  // now go through all uids that have one entry that point to the incidence
919  for ( TQStringList::Iterator uidit = relatedToUids.begin();
920  uidit != relatedToUids.end(); ++uidit ) {
921  Incidence::List tempList;
922  // Remove all to get access to the remaining entries
923  while( Incidence* i = mOrphans[ *uidit ] ) {
924  mOrphans.remove( *uidit );
925  if ( i != incidence ) tempList.append( i );
926  }
927  // Readd those that point to a different orphan incidence
928  for ( Incidence::List::Iterator incit = tempList.begin();
929  incit != tempList.end(); ++incit ) {
930  mOrphans.insert( *uidit, *incit );
931  }
932  }
933  }
934 }
935 
937 {
938  if( !mObservers.contains( observer ) )
939  mObservers.append( observer );
940  mNewObserver = true;
941 }
942 
944 {
945  mObservers.remove( observer );
946 }
947 
948 void Calendar::setModified( bool modified )
949 {
950  if ( modified != mModified || mNewObserver ) {
951  mNewObserver = false;
952  Observer *observer;
953  for ( observer = mObservers.first(); observer;
954  observer = mObservers.next() ) {
955  observer->calendarModified( modified, this );
956  }
957  mModified = modified;
958  }
959 }
960 
962 {
963  incidence->setSyncStatus( Event::SYNCMOD );
964  incidence->setLastModified( TQDateTime::currentDateTime() );
965  // we should probably update the revision number here,
966  // or internally in the Event itself when certain things change.
967  // need to verify with ical documentation.
968 
969  // The static_cast is ok as the CalendarLocal only observes Incidence objects
970  notifyIncidenceChanged( static_cast<Incidence *>( incidence ) );
971 
972  setModified( true );
973 }
974 
976 {
977  if ( !mObserversEnabled )
978  return;
979 
980  Observer *observer;
981  for ( observer = mObservers.first(); observer;
982  observer = mObservers.next() ) {
983  observer->calendarIncidenceAdded( i );
984  }
985 }
986 
988 {
989  if ( !mObserversEnabled )
990  return;
991 
992  Observer *observer;
993  for ( observer = mObservers.first(); observer;
994  observer = mObservers.next() ) {
995  observer->calendarIncidenceChanged( i );
996  }
997 }
998 
1000 {
1001  if ( !mObserversEnabled )
1002  return;
1003 
1004  Observer *observer;
1005  for ( observer = mObservers.first(); observer;
1006  observer = mObservers.next() ) {
1007  observer->calendarIncidenceDeleted( i );
1008  }
1009 }
1010 
1012 {
1013  setModified( true );
1014 }
1015 
1016 void Calendar::setProductId( const TQString &productId )
1017 {
1018  mProductId = productId;
1019 }
1020 
1022 {
1023  return mProductId;
1024 }
1025 
1027  const Todo::List &todos,
1028  const Journal::List &journals )
1029 {
1031 
1032  Event::List::ConstIterator it1;
1033  for ( it1 = events.begin(); it1 != events.end(); ++it1 )
1034  incidences.append( *it1 );
1035 
1036  Todo::List::ConstIterator it2;
1037  for ( it2 = todos.begin(); it2 != todos.end(); ++it2 )
1038  incidences.append( *it2 );
1039 
1040  Journal::List::ConstIterator it3;
1041  for ( it3 = journals.begin(); it3 != journals.end(); ++it3 )
1042  incidences.append( *it3 );
1043 
1044  return incidences;
1045 }
1046 
1048 {
1049  return true;
1050 }
1051 
1053 {
1054  return true;
1055 }
1056 
1057 void Calendar::setObserversEnabled( bool enabled )
1058 {
1059  mObserversEnabled = enabled;
1060 }
1061 
1062 #include "calendar.moc"
static Incidence::List mergeIncidenceList(const Event::List &events, const Todo::List &todos, const Journal::List &journals)
Create a merged list of Events, Todos, and Journals.
Definition: calendar.cpp:1026
virtual Todo::List rawTodos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending)=0
Return a sorted, unfiltered list of all Todos for this Calendar.
virtual Event * event(const TQString &uid)=0
Returns the Event associated with the given unique identifier.
virtual Event::List rawEventsForDate(const TQDateTime &qdt)=0
Return an unfiltered list of all Events which occur on the given timestamp.
virtual TQDateTime dtStart() const
returns an event&#39;s starting date/time as a TQDateTime.
virtual bool accept(Visitor &)
Accept IncidenceVisitor.
JournalSortField
How Journals are to be sorted.
Definition: calendar.h:110
Journals are to be unsorted.
Definition: calendar.h:113
void setDtEnd(const TQDateTime &dtEnd)
Set end date and time.
Definition: event.cpp:73
virtual ~Calendar()
Destructor.
Definition: calendar.cpp:68
TQStringList categories()
Return a list of all categories used by Incidences in this Calendar.
Definition: calendar.cpp:154
Sort Journals alphabetically, by summary.
Definition: calendar.h:117
void setDtDue(const TQDateTime &dtDue, bool first=false)
Sets due date and time.
Definition: todo.cpp:85
static Journal::List sortJournals(Journal::List *journalList, JournalSortField sortField, SortDirection sortDirection)
Sort a list of Journals.
Definition: calendar.cpp:768
void beginBatchAdding()
Emits the beginBatchAdding() signal.
Definition: calendar.cpp:144
virtual void customPropertyUpdated()
Definition: calendar.cpp:1011
Sort Todos by percentage completed.
Definition: calendar.h:101
void setObserversEnabled(bool enabled)
Let Calendar subclasses notify that they enabled an Observer.
Definition: calendar.cpp:1057
This class provides a Todo in the sense of RFC2445.
Definition: todo.h:31
This class provides the base class common to all calendar components.
Definition: incidencebase.h:45
void setLastModified(const TQDateTime &lm)
Sets the time the incidence was last modified.
bool hasRecurrenceID() const
Returns true if the incidence has recurrenceID, otherwise return false.
Definition: incidence.cpp:893
void recreate()
Recreate event.
Definition: incidence.cpp:208
This class implements a visitor for deleting an Incidence from a resource supporting deleteEvent()...
Definition: incidence.h:103
void setModified(bool modified)
Set if the Calendar had been modified.
Definition: calendar.cpp:948
Filter for calendar objects.
Definition: calfilter.h:38
TQDateTime dtStart(bool first=false) const
Returns the startdate of the todo.
Definition: todo.cpp:177
void setRelatedToUid(const TQString &)
Point at some other event to which the event relates.
Definition: incidence.cpp:333
virtual Journal::List rawJournalsForDate(const TQDate &date)=0
Return an unfiltered list of all Journals for on the specifed date.
int durationTo(const TQDateTime &) const
Returns the number of recurrences up to and including the date/time specified.
Definition: recurrence.cpp:407
void removeRelation(Incidence *)
Remove event that is related to this event.
Definition: incidence.cpp:377
This class provides an Event in the sense of RFC2445.
Definition: event.h:32
TQString relatedToUid() const
What event does this one relate to? This function should only be used when constructing a calendar be...
Definition: incidence.cpp:340
void setOwner(const Person &owner)
Set the owner of the Calendar.
Definition: calendar.cpp:96
Incidence * dissociateOccurrence(Incidence *incidence, TQDate date, bool single=true)
Dissociate an Incidence from a recurring Incidence.
Definition: calendar.cpp:506
virtual bool beginChange(Incidence *incidence)
Flag that a change to a Calendar Incidence is starting.
Definition: calendar.cpp:1047
void batchAddingEnds()
virtual void calendarIncidenceChanged(Incidence *)
Notify the Observer that an Incidence has been modified.
Definition: calendar.h:894
virtual Event::List rawEvents(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending)=0
Return a sorted, unfiltered list of all Events for this Calendar.
bool isLocalTime() const
Determine if Calendar Incidences are to be written without a time zone.
Definition: calendar.cpp:125
TQString productId()
Get the Calendar&#39;s Product ID.
Definition: calendar.cpp:1021
Sort Todos alphabetically, by summary.
Definition: calendar.h:103
CalFilter * filter()
Return the Calendar filter.
Definition: calendar.cpp:139
void setRelatedTo(Incidence *relatedTo)
Point at some other event to which the event relates.
Definition: incidence.cpp:345
bool hasDueDate() const
Returns true if the todo has a due date, otherwise return false.
Definition: todo.cpp:144
void clear()
Removes all recurrence and exception rules and dates.
Definition: recurrence.cpp:431
TQString uid() const
Return the unique id for the event.
void setHasRecurrenceID(bool hasRecurrenceID)
Sets if the incidence has recurrenceID.
Definition: incidence.cpp:898
void setDuration(int duration)
Sets the total number of times the event is to occur, including both the first and last...
Definition: recurrence.cpp:415
bool hasStartDate() const
Returns true if the todo has a start date, otherwise return false.
Definition: todo.cpp:157
virtual Todo * todo(const TQString &uid)=0
Returns the Todo associated with the given unique identifier.
Sort Journals chronologically by date.
Definition: calendar.h:115
Recurrence * recurrence() const
Return the recurrence rule associated with this incidence.
Definition: incidence.cpp:390
void setLocalTime()
Set to store calendar Incidences without a time zone.
Definition: calendar.cpp:117
virtual Journal::List rawJournals(JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending)=0
Return a sorted, unfiltered list of all Journals for this Calendar.
void notifyIncidenceChanged(Incidence *incidence)
Let Calendar subclasses notify that they modified an Incidence.
Definition: calendar.cpp:987
void incidenceUpdated(IncidenceBase *incidenceBase)
The Observer interface.
Definition: calendar.cpp:961
void notifyIncidenceAdded(Incidence *incidence)
Let Calendar subclasses notify that they inserted an Incidence.
Definition: calendar.cpp:975
void clearException()
Clears the exception status.
Definition: calendar.cpp:74
void notifyIncidenceDeleted(Incidence *incidence)
Let Calendar subclasses notify that they removed an Incidence.
Definition: calendar.cpp:999
Sort Events chronologically, by end date.
Definition: calendar.h:81
virtual void setupRelations(Incidence *incidence)
Setup Relations for an Incidence.
Definition: calendar.cpp:838
This class represents a person.
Definition: person.h:34
void addRelation(Incidence *)
Add an event which is related to this event.
Definition: incidence.cpp:370
bool doesRecur() const
Forward to Recurrence::doesRecur().
Definition: incidence.cpp:416
Provides the main "calendar" object class.
void setException(ErrorFormat *e)
Sets information about the last error occurred.
Definition: calendar.cpp:85
Sort in ascending order (first to last)
Definition: calendar.h:65
This class implements a visitor for adding an Incidence to a resource supporting addEvent(), addTodo() and addJournal() calls.
Definition: incidence.h:55
This class provides the base class common to all calendar components.
Definition: incidence.h:47
void deleteChildIncidence(TQString childIncidence)
Detach a child incidence from its parent incidence.
Definition: incidence.cpp:929
Incidence * incidence(const TQString &uid)
Returns the Incidence associated with the given unique identifier.
Definition: calendar.cpp:574
static Todo::List sortTodos(Todo::List *todoList, TodoSortField sortField, SortDirection sortDirection)
Sort a list of Todos.
Definition: calendar.cpp:609
virtual bool endChange(Incidence *incidence)
Flag that a change to a Calendar Incidence has completed.
Definition: calendar.cpp:1052
Incidence * incidenceFromSchedulingID(const TQString &sid)
Returns the Incidence associated with the given scheduling identifier.
Definition: calendar.cpp:597
void endBatchAdding()
Emits the endBatchAdding() signal.
Definition: calendar.cpp:149
Calendar format related error class.
Definition: exceptions.h:64
Calendar(const TQString &timeZoneId)
Construct Calendar object using a Time Zone.
Definition: calendar.cpp:43
virtual void calendarIncidenceDeleted(Incidence *)
Notify the Observer that an Incidence has been removed.
Definition: calendar.h:901
Sort Todos by priority.
Definition: calendar.h:99
Todos are to be unsorted.
Definition: calendar.h:93
Sort Events alphabetically, by summary.
Definition: calendar.h:83
void setFilter(CalFilter *filter)
Set the Calendar filter.
Definition: calendar.cpp:130
void apply(Event::List *eventlist) const
Apply filter to eventlist, all events not matching filter criterias are removed from the list...
Definition: calfilter.cpp:49
ErrorFormat * exception() const
Returns an exception, if there is any, containing information about the last error that occurred...
Definition: calendar.cpp:80
static Event::List sortEventsForDate(Event::List *eventList, const TQDate &date, EventSortField sortField, SortDirection sortDirection)
Sort a list of Events that occur on a specified date.
Definition: calendar.cpp:291
virtual bool deleteIncidence(Incidence *incidence)
Remove an Incidence from the Calendar.
Definition: calendar.cpp:473
Incidence::List incidencesFromSchedulingID(const TQString &UID)
Searches all events and todos for (an incidence with this scheduling ID.
Definition: calendar.cpp:586
Sort Todos chronologically, by start date.
Definition: calendar.h:95
void setDtStart(const TQDateTime &dtStart)
Sets the startdate of the todo.
Definition: todo.cpp:192
void registerObserver(Observer *observer)
Register an Observer for this Calendar.
Definition: calendar.cpp:936
Events are to be unsorted.
Definition: calendar.h:77
TQString timeZoneId() const
Get the Time Zone ID for the Calendar.
Definition: calendar.cpp:112
Namespace KCal is for global classes, objects and/or functions in libkcal.
Definition: alarm.h:38
virtual void calendarModified(bool, Calendar *)
Notify the Observer that a Calendar has been modified.
Definition: calendar.h:879
Sort Events chronologically, by start date.
Definition: calendar.h:79
SortDirection
Sort direction.
Definition: calendar.h:62
virtual bool addIncidence(Incidence *incidence)
Insert an Incidence into the Calendar.
Definition: calendar.cpp:466
virtual void doSetTimeZoneId(const TQString &)
Let Calendar subclasses set the Time Zone ID.
Definition: calendar.h:974
const Person & getOwner() const
Get the owner of the Calendar.
Definition: calendar.cpp:91
Sort Todos chronologically, by due date.
Definition: calendar.h:97
void setEndDate(const TQDate &endDate)
Sets the date of the last recurrence.
Definition: recurrence.cpp:378
void batchAddingBegins()
virtual Journal::List journals(JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Return a sorted, filtered list of all Journals for this Calendar.
Definition: calendar.cpp:821
virtual Todo::List rawTodosForDate(const TQDate &date)=0
Return an unfiltered list of all Todos which due on the specified date.
virtual Incidence::List rawIncidences()
Return an unfiltered list of all Incidences for this Calendar.
Definition: calendar.cpp:183
void setTimeZoneId(const TQString &timeZoneId)
Set the Time Zone Id for the Calendar.
Definition: calendar.cpp:103
TodoSortField
How Todos are to be sorted.
Definition: calendar.h:90
virtual Todo::List todos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Return a sorted, filtered list of all Todos for this Calendar.
Definition: calendar.cpp:753
TQDateTime dtDue(bool first=false) const
Returns due date and time.
Definition: todo.cpp:117
int duration() const
Returns -1 if the event recurs infinitely, 0 if the end date is set, otherwise the total number of re...
Definition: recurrence.cpp:395
void setSyncStatus(int status)
Set synchronisation satus.
virtual Journal * journal(const TQString &uid)=0
Returns the Journal associated with the given unique identifier.
virtual Event::List events(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Return a sorted, filtered list of all Events for this Calendar.
Definition: calendar.cpp:458
EventSortField
How Events are to be sorted.
Definition: calendar.h:74
virtual TQDateTime dtEnd() const
Return end date and time.
Definition: event.cpp:85
void setProductId(const TQString &productId)
Set the Calendar Product ID.
Definition: calendar.cpp:1016
virtual Incidence::List incidences()
Return a filtered list of all Incidences for this Calendar.
Definition: calendar.cpp:178
static Event::List sortEvents(Event::List *eventList, EventSortField sortField, SortDirection sortDirection)
Sort a list of Events.
Definition: calendar.cpp:188
The Observer class.
Definition: calendar.h:868
Incidence::List relations() const
All events that are related to this event.
Definition: incidence.cpp:365
Incidence * relatedTo() const
What event does this one relate to?
Definition: incidence.cpp:360
void setEnabled(bool)
Enable or disable filter.
Definition: calfilter.cpp:178
IncidenceList childIncidences() const
Returns an EventList of all child incidences.
Definition: incidence.cpp:934
This class represents a recurrence rule for a calendar incidence.
Definition: recurrence.h:89
virtual Incidence * clone()=0
Return copy of this object.
virtual void setDtStart(const TQDateTime &dtStart)
Set starting date/time.
Definition: incidence.cpp:264
virtual void calendarIncidenceAdded(Incidence *)
Notify the Observer that an Incidence has been inserted.
Definition: calendar.h:887
void unregisterObserver(Observer *observer)
Unregister an Observer for this Calendar.
Definition: calendar.cpp:943
virtual void removeRelations(Incidence *incidence)
Remove all Relations from an Incidence.
Definition: calendar.cpp:872