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 );
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  if (it != il.end()) {
483  parentIncidence = this->incidence(*it);
484  parentIncidence->deleteChildIncidence(incidence->uid());
485  }
486  }
487  else {
488  // Delete all children as well
489  IncidenceList il = incidence->childIncidences();
490  IncidenceListIterator it;
491  for ( it = il.begin(); it != il.end(); ++it ) {
492  deleteIncidence( this->incidence(*it) );
493  // Avoid a crash, reset the iterator every time the list is modified
494  it = il.begin();
495  }
496  }
498  bool result = incidence->accept( v );
499  endChange( incidence );
500  return result;
501  } else
502  return false;
503 }
504 
509  bool single )
510 {
511  if ( !incidence || !incidence->doesRecur() )
512  return 0;
513 
514  Incidence *newInc = incidence->clone();
515  newInc->recreate();
516  newInc->setHasRecurrenceID(false);
517 // newInc->setRecurrenceID(TQString());
518  newInc->setRelatedTo( incidence );
519  Recurrence *recur = newInc->recurrence();
520  if ( single ) {
521  recur->clear();
522  } else {
523  // Adjust the recurrence for the future incidences. In particular
524  // adjust the "end after n occurrences" rules! "No end date" and "end by ..."
525  // don't need to be modified.
526  int duration = recur->duration();
527  if ( duration > 0 ) {
528  int doneduration = recur->durationTo( date.addDays(-1) );
529  if ( doneduration >= duration ) {
530  kdDebug(5850) << "The dissociated event already occurred more often "
531  << "than it was supposed to ever occur. ERROR!" << endl;
532  recur->clear();
533  } else {
534  recur->setDuration( duration - doneduration );
535  }
536  }
537  }
538  // Adjust the date of the incidence
539  if ( incidence->type() == "Event" ) {
540  Event *ev = static_cast<Event *>( newInc );
541  TQDateTime start( ev->dtStart() );
542  int daysTo = start.date().daysTo( date );
543  ev->setDtStart( start.addDays( daysTo ) );
544  ev->setDtEnd( ev->dtEnd().addDays( daysTo ) );
545  } else if ( incidence->type() == "Todo" ) {
546  Todo *td = static_cast<Todo *>( newInc );
547  bool haveOffset = false;
548  int daysTo = 0;
549  if ( td->hasDueDate() ) {
550  TQDateTime due( td->dtDue() );
551  daysTo = due.date().daysTo( date );
552  td->setDtDue( due.addDays( daysTo ), true );
553  haveOffset = true;
554  }
555  if ( td->hasStartDate() ) {
556  TQDateTime start( td->dtStart() );
557  if ( !haveOffset )
558  daysTo = start.date().daysTo( date );
559  td->setDtStart( start.addDays( daysTo ) );
560  haveOffset = true;
561  }
562  }
563  recur = incidence->recurrence();
564  if ( recur ) {
565  if ( single ) {
566  recur->addExDate( date );
567  } else {
568  // Make sure the recurrence of the past events ends
569  // at the corresponding day
570  recur->setEndDate( date.addDays(-1) );
571  }
572  }
573  return newInc;
574 }
575 
576 Incidence *Calendar::incidence( const TQString &uid )
577 {
578  Incidence *i = event( uid );
579  if ( i )
580  return i;
581  i = todo( uid );
582  if ( i )
583  return i;
584  i = journal( uid );
585  return i;
586 }
587 
589 {
590  Incidence::List result;
592  Incidence::List::iterator it = incidences.begin();
593  for ( ; it != incidences.end(); ++it )
594  if ( (*it)->schedulingID() == UID )
595  result.append( *it );
596  return result;
597 }
598 
600 {
602  Incidence::List::iterator it = incidences.begin();
603  for ( ; it != incidences.end(); ++it )
604  if ( (*it)->schedulingID() == UID )
605  // Touchdown, and the crowd goes wild
606  return *it;
607  // Not found
608  return 0;
609 }
610 
612  TodoSortField sortField,
613  SortDirection sortDirection )
614 {
615  Todo::List todoListSorted;
616  Todo::List tempList, t;
617  Todo::List alphaList;
618  Todo::List::Iterator sortIt;
619  Todo::List::Iterator eit;
620 
621  // Notice we alphabetically presort Summaries first.
622  // We do this so comparison "ties" stay in a nice order.
623 
624  // Note that Todos may not have Start DateTimes nor due DateTimes.
625 
626  switch( sortField ) {
627  case TodoSortUnsorted:
628  todoListSorted = *todoList;
629  break;
630 
631  case TodoSortStartDate:
632  alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
633  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
634  if ( (*eit)->hasStartDate() ) {
635  sortIt = todoListSorted.begin();
636  if ( sortDirection == SortDirectionAscending ) {
637  while ( sortIt != todoListSorted.end() &&
638  (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
639  ++sortIt;
640  }
641  } else {
642  while ( sortIt != todoListSorted.end() &&
643  (*eit)->dtStart() < (*sortIt)->dtStart() ) {
644  ++sortIt;
645  }
646  }
647  todoListSorted.insert( sortIt, *eit );
648  } else {
649  // Keep a list of the Todos without Start DateTimes
650  tempList.append( *eit );
651  }
652  }
653  if ( sortDirection == SortDirectionAscending ) {
654  // Append the list of Todos without Start DateTimes
655  todoListSorted += tempList;
656  } else {
657  // Prepend the list of Todos without Start DateTimes
658  tempList += todoListSorted;
659  todoListSorted = tempList;
660  }
661  break;
662 
663  case TodoSortDueDate:
664  alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
665  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
666  if ( (*eit)->hasDueDate() ) {
667  sortIt = todoListSorted.begin();
668  if ( sortDirection == SortDirectionAscending ) {
669  while ( sortIt != todoListSorted.end() &&
670  (*eit)->dtDue() >= (*sortIt)->dtDue() ) {
671  ++sortIt;
672  }
673  } else {
674  while ( sortIt != todoListSorted.end() &&
675  (*eit)->dtDue() < (*sortIt)->dtDue() ) {
676  ++sortIt;
677  }
678  }
679  todoListSorted.insert( sortIt, *eit );
680  } else {
681  // Keep a list of the Todos without Due DateTimes
682  tempList.append( *eit );
683  }
684  }
685  if ( sortDirection == SortDirectionAscending ) {
686  // Append the list of Todos without Due DateTimes
687  todoListSorted += tempList;
688  } else {
689  // Prepend the list of Todos without Due DateTimes
690  tempList += todoListSorted;
691  todoListSorted = tempList;
692  }
693  break;
694 
695  case TodoSortPriority:
696  alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
697  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
698  sortIt = todoListSorted.begin();
699  if ( sortDirection == SortDirectionAscending ) {
700  while ( sortIt != todoListSorted.end() &&
701  (*eit)->priority() >= (*sortIt)->priority() ) {
702  ++sortIt;
703  }
704  } else {
705  while ( sortIt != todoListSorted.end() &&
706  (*eit)->priority() < (*sortIt)->priority() ) {
707  ++sortIt;
708  }
709  }
710  todoListSorted.insert( sortIt, *eit );
711  }
712  break;
713 
715  alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
716  for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
717  sortIt = todoListSorted.begin();
718  if ( sortDirection == SortDirectionAscending ) {
719  while ( sortIt != todoListSorted.end() &&
720  (*eit)->percentComplete() >= (*sortIt)->percentComplete() ) {
721  ++sortIt;
722  }
723  } else {
724  while ( sortIt != todoListSorted.end() &&
725  (*eit)->percentComplete() < (*sortIt)->percentComplete() ) {
726  ++sortIt;
727  }
728  }
729  todoListSorted.insert( sortIt, *eit );
730  }
731  break;
732 
733  case TodoSortSummary:
734  for ( eit = todoList->begin(); eit != todoList->end(); ++eit ) {
735  sortIt = todoListSorted.begin();
736  if ( sortDirection == SortDirectionAscending ) {
737  while ( sortIt != todoListSorted.end() &&
738  (*eit)->summary() >= (*sortIt)->summary() ) {
739  ++sortIt;
740  }
741  } else {
742  while ( sortIt != todoListSorted.end() &&
743  (*eit)->summary() < (*sortIt)->summary() ) {
744  ++sortIt;
745  }
746  }
747  todoListSorted.insert( sortIt, *eit );
748  }
749  break;
750  }
751 
752  return todoListSorted;
753 }
754 
756  SortDirection sortDirection )
757 {
758  Todo::List tl = rawTodos( sortField, sortDirection );
759  mFilter->apply( &tl );
760  return tl;
761 }
762 
763 Todo::List Calendar::todos( const TQDate &date )
764 {
765  Todo::List el = rawTodosForDate( date );
766  mFilter->apply( &el );
767  return el;
768 }
769 
771  JournalSortField sortField,
772  SortDirection sortDirection )
773 {
774  Journal::List journalListSorted;
775  Journal::List::Iterator sortIt;
776  Journal::List::Iterator eit;
777 
778  switch( sortField ) {
779  case JournalSortUnsorted:
780  journalListSorted = *journalList;
781  break;
782 
783  case JournalSortDate:
784  for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
785  sortIt = journalListSorted.begin();
786  if ( sortDirection == SortDirectionAscending ) {
787  while ( sortIt != journalListSorted.end() &&
788  (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
789  ++sortIt;
790  }
791  } else {
792  while ( sortIt != journalListSorted.end() &&
793  (*eit)->dtStart() < (*sortIt)->dtStart() ) {
794  ++sortIt;
795  }
796  }
797  journalListSorted.insert( sortIt, *eit );
798  }
799  break;
800 
801  case JournalSortSummary:
802  for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
803  sortIt = journalListSorted.begin();
804  if ( sortDirection == SortDirectionAscending ) {
805  while ( sortIt != journalListSorted.end() &&
806  (*eit)->summary() >= (*sortIt)->summary() ) {
807  ++sortIt;
808  }
809  } else {
810  while ( sortIt != journalListSorted.end() &&
811  (*eit)->summary() < (*sortIt)->summary() ) {
812  ++sortIt;
813  }
814  }
815  journalListSorted.insert( sortIt, *eit );
816  }
817  break;
818  }
819 
820  return journalListSorted;
821 }
822 
824  SortDirection sortDirection )
825 {
826  Journal::List jl = rawJournals( sortField, sortDirection );
827  mFilter->apply( &jl );
828  return jl;
829 }
830 
831 Journal::List Calendar::journals( const TQDate &date )
832 {
833  Journal::List el = rawJournalsForDate( date );
834  mFilter->apply( &el );
835  return el;
836 }
837 
838 // When this is called, the todo have already been added to the calendar.
839 // This method is only about linking related todos
840 void Calendar::setupRelations( Incidence *forincidence )
841 {
842  if ( !forincidence ) return;
843 // kdDebug(5850) << "Calendar::setupRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl;
844  TQString uid = forincidence->uid();
845 
846  // First, go over the list of orphans and see if this is their parent
847  while ( Incidence* i = mOrphans[ uid ] ) {
848  mOrphans.remove( uid );
849  i->setRelatedTo( forincidence );
850  forincidence->addRelation( i );
851  mOrphanUids.remove( i->uid() );
852  }
853 
854  // Now see about this incidences parent
855  if ( !forincidence->relatedTo() && !forincidence->relatedToUid().isEmpty() ) {
856  // This incidence has a uid it is related to but is not registered to it yet
857  // Try to find it
858  Incidence* parent = incidence( forincidence->relatedToUid() );
859  if ( parent ) {
860  // Found it
861  forincidence->setRelatedTo( parent );
862  parent->addRelation( forincidence );
863  } else {
864  // Not found, put this in the mOrphans list
865  // Note that the mOrphans dict might have several entries with the same key! That are
866  // multiple children that wait for the parent incidence to be inserted.
867  mOrphans.insert( forincidence->relatedToUid(), forincidence );
868  mOrphanUids.insert( forincidence->uid(), forincidence );
869  }
870  }
871 }
872 
873 // If a task with subtasks is deleted, move it's subtasks to the orphans list
875 {
876  if( !incidence ) {
877  kdDebug(5800) << "Warning: Calendar::removeRelations( 0 )!\n";
878  return;
879  }
880 
881 // kdDebug(5850) << "Calendar::removeRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl;
882  TQString uid = incidence->uid();
883 
884  Incidence::List relations = incidence->relations();
885  Incidence::List::ConstIterator it;
886  for ( it = relations.begin(); it != relations.end(); ++it ) {
887  Incidence *i = *it;
888  if ( !mOrphanUids.find( i->uid() ) ) {
889  mOrphans.insert( uid, i );
890  mOrphanUids.insert( i->uid(), i );
891  i->setRelatedTo( 0 );
892  i->setRelatedToUid( uid );
893  }
894  }
895 
896  // If this incidence is related to something else, tell that about it
897  if ( incidence->relatedTo() )
899 
900  // Remove this one from the orphans list
901  if ( mOrphanUids.remove( uid ) ) {
902  // This incidence is located in the orphans list - it should be removed
903  // Since the mOrphans dict might contain the same key (with different
904  // child incidence pointers!) multiple times, take care that we remove
905  // the correct one. So we need to remove all items with the given
906  // parent UID, and readd those that are not for this item. Also, there
907  // might be other entries with differnet UID that point to this
908  // incidence (this might happen when the relatedTo of the item is
909  // changed before its parent is inserted. This might happen with
910  // groupware servers....). Remove them, too
911  TQStringList relatedToUids;
912  // First get the list of all keys in the mOrphans list that point to the removed item
913  relatedToUids << incidence->relatedToUid();
914  for ( TQDictIterator<Incidence> it( mOrphans ); it.current(); ++it ) {
915  if ( it.current()->uid() == uid ) {
916  relatedToUids << it.currentKey();
917  }
918  }
919 
920  // now go through all uids that have one entry that point to the incidence
921  for ( TQStringList::Iterator uidit = relatedToUids.begin();
922  uidit != relatedToUids.end(); ++uidit ) {
923  Incidence::List tempList;
924  // Remove all to get access to the remaining entries
925  while( Incidence* i = mOrphans[ *uidit ] ) {
926  mOrphans.remove( *uidit );
927  if ( i != incidence ) tempList.append( i );
928  }
929  // Readd those that point to a different orphan incidence
930  for ( Incidence::List::Iterator incit = tempList.begin();
931  incit != tempList.end(); ++incit ) {
932  mOrphans.insert( *uidit, *incit );
933  }
934  }
935  }
936 }
937 
939 {
940  if( !mObservers.contains( observer ) )
941  mObservers.append( observer );
942  mNewObserver = true;
943 }
944 
946 {
947  mObservers.remove( observer );
948 }
949 
950 void Calendar::setModified( bool modified )
951 {
952  if ( modified != mModified || mNewObserver ) {
953  mNewObserver = false;
954  Observer *observer;
955  for ( observer = mObservers.first(); observer;
956  observer = mObservers.next() ) {
957  observer->calendarModified( modified, this );
958  }
959  mModified = modified;
960  }
961 }
962 
964 {
965  incidence->setSyncStatus( Event::SYNCMOD );
966  incidence->setLastModified( TQDateTime::currentDateTime() );
967  // we should probably update the revision number here,
968  // or internally in the Event itself when certain things change.
969  // need to verify with ical documentation.
970 
971  // The static_cast is ok as the CalendarLocal only observes Incidence objects
972  notifyIncidenceChanged( static_cast<Incidence *>( incidence ) );
973 
974  setModified( true );
975 }
976 
978 {
979  if ( !mObserversEnabled )
980  return;
981 
982  Observer *observer;
983  for ( observer = mObservers.first(); observer;
984  observer = mObservers.next() ) {
985  observer->calendarIncidenceAdded( i );
986  }
987 }
988 
990 {
991  if ( !mObserversEnabled )
992  return;
993 
994  Observer *observer;
995  for ( observer = mObservers.first(); observer;
996  observer = mObservers.next() ) {
997  observer->calendarIncidenceChanged( i );
998  }
999 }
1000 
1002 {
1003  if ( !mObserversEnabled )
1004  return;
1005 
1006  Observer *observer;
1007  for ( observer = mObservers.first(); observer;
1008  observer = mObservers.next() ) {
1009  observer->calendarIncidenceDeleted( i );
1010  }
1011 }
1012 
1014 {
1015  setModified( true );
1016 }
1017 
1018 void Calendar::setProductId( const TQString &productId )
1019 {
1020  mProductId = productId;
1021 }
1022 
1024 {
1025  return mProductId;
1026 }
1027 
1029  const Todo::List &todos,
1030  const Journal::List &journals )
1031 {
1033 
1034  Event::List::ConstIterator it1;
1035  for ( it1 = events.begin(); it1 != events.end(); ++it1 )
1036  incidences.append( *it1 );
1037 
1038  Todo::List::ConstIterator it2;
1039  for ( it2 = todos.begin(); it2 != todos.end(); ++it2 )
1040  incidences.append( *it2 );
1041 
1042  Journal::List::ConstIterator it3;
1043  for ( it3 = journals.begin(); it3 != journals.end(); ++it3 )
1044  incidences.append( *it3 );
1045 
1046  return incidences;
1047 }
1048 
1050 {
1051  return true;
1052 }
1053 
1055 {
1056  return true;
1057 }
1058 
1059 void Calendar::setObserversEnabled( bool enabled )
1060 {
1061  mObserversEnabled = enabled;
1062 }
1063 
1064 #include "calendar.moc"
Provides the main "calendar" object class.
Filter for calendar objects.
Definition: calfilter.h:39
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
void setEnabled(bool)
Enable or disable filter.
Definition: calfilter.cpp:178
The Observer class.
Definition: calendar.h:869
virtual void calendarIncidenceAdded(Incidence *)
Notify the Observer that an Incidence has been inserted.
Definition: calendar.h:887
virtual void calendarIncidenceDeleted(Incidence *)
Notify the Observer that an Incidence has been removed.
Definition: calendar.h:901
virtual void calendarModified(bool, Calendar *)
Notify the Observer that a Calendar has been modified.
Definition: calendar.h:879
virtual void calendarIncidenceChanged(Incidence *)
Notify the Observer that an Incidence has been modified.
Definition: calendar.h:894
void clearException()
Clears the exception status.
Definition: calendar.cpp:74
static Todo::List sortTodos(Todo::List *todoList, TodoSortField sortField, SortDirection sortDirection)
Sort a list of Todos.
Definition: calendar.cpp:611
Calendar(const TQString &timeZoneId)
Construct Calendar object using a Time Zone.
Definition: calendar.cpp:43
void setLocalTime()
Set to store calendar Incidences without a time zone.
Definition: calendar.cpp:117
Incidence * dissociateOccurrence(Incidence *incidence, TQDate date, bool single=true)
Dissociate an Incidence from a recurring Incidence.
Definition: calendar.cpp:508
void setTimeZoneId(const TQString &timeZoneId)
Set the Time Zone Id for the Calendar.
Definition: calendar.cpp:103
virtual void doSetTimeZoneId(const TQString &)
Let Calendar subclasses set the Time Zone ID.
Definition: calendar.h:974
virtual Journal::List rawJournals(JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending)=0
Return a sorted, unfiltered list of all Journals for this Calendar.
virtual Journal::List rawJournalsForDate(const TQDate &date)=0
Return an unfiltered list of all Journals for on the specifed date.
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
virtual bool addIncidence(Incidence *incidence)
Insert an Incidence into the Calendar.
Definition: calendar.cpp:466
virtual bool beginChange(Incidence *incidence)
Flag that a change to a Calendar Incidence is starting.
Definition: calendar.cpp:1049
bool isLocalTime() const
Determine if Calendar Incidences are to be written without a time zone.
Definition: calendar.cpp:125
virtual Event::List rawEventsForDate(const TQDateTime &qdt)=0
Return an unfiltered list of all Events which occur on the given timestamp.
TQString productId()
Get the Calendar's Product ID.
Definition: calendar.cpp:1023
virtual Incidence::List rawIncidences()
Return an unfiltered list of all Incidences for this Calendar.
Definition: calendar.cpp:183
void incidenceUpdated(IncidenceBase *incidenceBase)
The Observer interface.
Definition: calendar.cpp:963
virtual Incidence::List incidences()
Return a filtered list of all Incidences for this Calendar.
Definition: calendar.cpp:178
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:1028
Incidence * incidenceFromSchedulingID(const TQString &sid)
Returns the Incidence associated with the given scheduling identifier.
Definition: calendar.cpp:599
virtual void setupRelations(Incidence *incidence)
Setup Relations for an Incidence.
Definition: calendar.cpp:840
virtual Todo * todo(const TQString &uid)=0
Returns the Todo associated with the given unique identifier.
void notifyIncidenceDeleted(Incidence *incidence)
Let Calendar subclasses notify that they removed an Incidence.
Definition: calendar.cpp:1001
void registerObserver(Observer *observer)
Register an Observer for this Calendar.
Definition: calendar.cpp:938
void setFilter(CalFilter *filter)
Set the Calendar filter.
Definition: calendar.cpp:130
virtual Event * event(const TQString &uid)=0
Returns the Event associated with the given unique identifier.
virtual bool deleteIncidence(Incidence *incidence)
Remove an Incidence from the Calendar.
Definition: calendar.cpp:473
static Event::List sortEvents(Event::List *eventList, EventSortField sortField, SortDirection sortDirection)
Sort a list of Events.
Definition: calendar.cpp:188
void notifyIncidenceChanged(Incidence *incidence)
Let Calendar subclasses notify that they modified an Incidence.
Definition: calendar.cpp:989
ErrorFormat * exception() const
Returns an exception, if there is any, containing information about the last error that occurred.
Definition: calendar.cpp:80
virtual Journal * journal(const TQString &uid)=0
Returns the Journal associated with the given unique identifier.
const Person & getOwner() const
Get the owner of the Calendar.
Definition: calendar.cpp:91
virtual void customPropertyUpdated()
Definition: calendar.cpp:1013
void unregisterObserver(Observer *observer)
Unregister an Observer for this Calendar.
Definition: calendar.cpp:945
void setModified(bool modified)
Set if the Calendar had been modified.
Definition: calendar.cpp:950
virtual void removeRelations(Incidence *incidence)
Remove all Relations from an Incidence.
Definition: calendar.cpp:874
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
CalFilter * filter()
Return the Calendar filter.
Definition: calendar.cpp:139
virtual bool endChange(Incidence *incidence)
Flag that a change to a Calendar Incidence has completed.
Definition: calendar.cpp:1054
void setProductId(const TQString &productId)
Set the Calendar Product ID.
Definition: calendar.cpp:1018
void setOwner(const Person &owner)
Set the owner of the Calendar.
Definition: calendar.cpp:96
void setObserversEnabled(bool enabled)
Let Calendar subclasses notify that they enabled an Observer.
Definition: calendar.cpp:1059
virtual Event::List rawEvents(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending)=0
Return a sorted, unfiltered list of all Events for this Calendar.
TQString timeZoneId() const
Get the Time Zone ID for the Calendar.
Definition: calendar.cpp:112
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
Incidence::List incidencesFromSchedulingID(const TQString &UID)
Searches all events and todos for (an incidence with this scheduling ID.
Definition: calendar.cpp:588
void setException(ErrorFormat *e)
Sets information about the last error occurred.
Definition: calendar.cpp:85
void notifyIncidenceAdded(Incidence *incidence)
Let Calendar subclasses notify that they inserted an Incidence.
Definition: calendar.cpp:977
virtual Journal::List journals(JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Return a sorted, filtered list of all Journals for this Calendar.
Definition: calendar.cpp:823
virtual Todo::List rawTodos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending)=0
Return a sorted, unfiltered list of all Todos for this Calendar.
void batchAddingEnds()
virtual Todo::List rawTodosForDate(const TQDate &date)=0
Return an unfiltered list of all Todos which due on the specified date.
void beginBatchAdding()
Emits the beginBatchAdding() signal.
Definition: calendar.cpp:144
void batchAddingBegins()
Incidence * incidence(const TQString &uid)
Returns the Incidence associated with the given unique identifier.
Definition: calendar.cpp:576
virtual Todo::List todos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Return a sorted, filtered list of all Todos for this Calendar.
Definition: calendar.cpp:755
static Journal::List sortJournals(Journal::List *journalList, JournalSortField sortField, SortDirection sortDirection)
Sort a list of Journals.
Definition: calendar.cpp:770
void endBatchAdding()
Emits the endBatchAdding() signal.
Definition: calendar.cpp:149
Calendar format related error class.
Definition: exceptions.h:65
This class provides an Event in the sense of RFC2445.
Definition: event.h:33
virtual TQDateTime dtEnd() const
Return end date and time.
Definition: event.cpp:85
void setDtEnd(const TQDateTime &dtEnd)
Set end date and time.
Definition: event.cpp:73
This class provides the base class common to all calendar components.
Definition: incidencebase.h:46
TQString uid() const
Return the unique id for the event.
virtual TQDateTime dtStart() const
returns an event's starting date/time as a TQDateTime.
virtual bool accept(Visitor &)
Accept IncidenceVisitor.
void setSyncStatus(int status)
Set synchronisation satus.
void setLastModified(const TQDateTime &lm)
Sets the time the incidence was last modified.
This class implements a visitor for adding an Incidence to a resource supporting addEvent(),...
Definition: incidence.h:56
This class implements a visitor for deleting an Incidence from a resource supporting deleteEvent(),...
Definition: incidence.h:104
This class provides the base class common to all calendar components.
Definition: incidence.h:48
virtual Incidence * clone()=0
Return copy of this object.
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 recreate()
Recreate event.
Definition: incidence.cpp:208
void setRelatedTo(Incidence *relatedTo)
Point at some other event to which the event relates.
Definition: incidence.cpp:345
IncidenceList childIncidences() const
Returns an EventList of all child incidences.
Definition: incidence.cpp:934
Incidence * relatedTo() const
What event does this one relate to?
Definition: incidence.cpp:360
void removeRelation(Incidence *)
Remove event that is related to this event.
Definition: incidence.cpp:377
void setRelatedToUid(const TQString &)
Point at some other event to which the event relates.
Definition: incidence.cpp:333
bool doesRecur() const
Forward to Recurrence::doesRecur().
Definition: incidence.cpp:416
virtual void setDtStart(const TQDateTime &dtStart)
Set starting date/time.
Definition: incidence.cpp:264
bool hasRecurrenceID() const
Returns true if the incidence has recurrenceID, otherwise return false.
Definition: incidence.cpp:893
Incidence::List relations() const
All events that are related to this event.
Definition: incidence.cpp:365
Recurrence * recurrence() const
Return the recurrence rule associated with this incidence.
Definition: incidence.cpp:390
void deleteChildIncidence(TQString childIncidence)
Detach a child incidence from its parent incidence.
Definition: incidence.cpp:929
void addRelation(Incidence *)
Add an event which is related to this event.
Definition: incidence.cpp:370
void setHasRecurrenceID(bool hasRecurrenceID)
Sets if the incidence has recurrenceID.
Definition: incidence.cpp:898
This class represents a person.
Definition: person.h:35
This class represents a recurrence rule for a calendar incidence.
Definition: recurrence.h:90
int durationTo(const TQDateTime &) const
Returns the number of recurrences up to and including the date/time specified.
Definition: recurrence.cpp:407
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 clear()
Removes all recurrence and exception rules and dates.
Definition: recurrence.cpp:431
void setEndDate(const TQDate &endDate)
Sets the date of the last recurrence.
Definition: recurrence.cpp:378
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
This class provides a Todo in the sense of RFC2445.
Definition: todo.h:32
bool hasDueDate() const
Returns true if the todo has a due date, otherwise return false.
Definition: todo.cpp:144
bool hasStartDate() const
Returns true if the todo has a start date, otherwise return false.
Definition: todo.cpp:157
void setDtDue(const TQDateTime &dtDue, bool first=false)
Sets due date and time.
Definition: todo.cpp:85
TQDateTime dtStart(bool first=false) const
Returns the startdate of the todo.
Definition: todo.cpp:177
void setDtStart(const TQDateTime &dtStart)
Sets the startdate of the todo.
Definition: todo.cpp:192
TQDateTime dtDue(bool first=false) const
Returns due date and time.
Definition: todo.cpp:117
Namespace KCal is for global classes, objects and/or functions in libkcal.
Definition: alarm.h:38
TodoSortField
How Todos are to be sorted.
Definition: calendar.h:91
@ TodoSortSummary
Sort Todos alphabetically, by summary.
Definition: calendar.h:103
@ TodoSortDueDate
Sort Todos chronologically, by due date.
Definition: calendar.h:97
@ TodoSortPriority
Sort Todos by priority.
Definition: calendar.h:99
@ TodoSortPercentComplete
Sort Todos by percentage completed.
Definition: calendar.h:101
@ TodoSortStartDate
Sort Todos chronologically, by start date.
Definition: calendar.h:95
@ TodoSortUnsorted
Todos are to be unsorted.
Definition: calendar.h:93
JournalSortField
How Journals are to be sorted.
Definition: calendar.h:111
@ JournalSortUnsorted
Journals are to be unsorted.
Definition: calendar.h:113
@ JournalSortDate
Sort Journals chronologically by date.
Definition: calendar.h:115
@ JournalSortSummary
Sort Journals alphabetically, by summary.
Definition: calendar.h:117
EventSortField
How Events are to be sorted.
Definition: calendar.h:75
@ EventSortUnsorted
Events are to be unsorted.
Definition: calendar.h:77
@ EventSortEndDate
Sort Events chronologically, by end date.
Definition: calendar.h:81
@ EventSortSummary
Sort Events alphabetically, by summary.
Definition: calendar.h:83
@ EventSortStartDate
Sort Events chronologically, by start date.
Definition: calendar.h:79
SortDirection
Sort direction.
Definition: calendar.h:63
@ SortDirectionAscending
Sort in ascending order (first to last)
Definition: calendar.h:65