libkcal

icalformatimpl.cpp
1 /*
2  This file is part of libkcal.
3 
4  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
22 
23 #include <tqdatetime.h>
24 #include <tqstring.h>
25 #include <tqptrlist.h>
26 #include <tqfile.h>
27 #include <cstdlib>
28 
29 #include <kdebug.h>
30 #include <tdelocale.h>
31 #include <kmdcodec.h>
32 
33 extern "C" {
34  #include <libical/ical.h>
35  #include <libical/icalparser.h>
36  #include <libical/icalrestriction.h>
37 }
38 
39 #include "calendar.h"
40 #include "journal.h"
41 #include "icalformat.h"
42 #include "icalformatimpl.h"
43 #include "compat.h"
44 
45 #include "config.h"
46 
47 #define _ICAL_VERSION "2.0"
48 
49 using namespace KCal;
50 
51 /* Static helpers */
52 static TQDateTime ICalDate2TQDate(const icaltimetype& t)
53 {
54  // Outlook sends dates starting from 1601-01-01, but TQDate()
55  // can only handle dates starting 1752-09-14.
56  const int year = (t.year>=1754) ? t.year : 1754;
57  return TQDateTime(TQDate(year,t.month,t.day), TQTime(t.hour,t.minute,t.second));
58 }
59 
60 /*
61 static void _dumpIcaltime( const icaltimetype& t)
62 {
63  kdDebug(5800) << "--- Y: " << t.year << " M: " << t.month << " D: " << t.day
64  << endl;
65  kdDebug(5800) << "--- H: " << t.hour << " M: " << t.minute << " S: " << t.second
66  << endl;
67  kdDebug(5800) << "--- isUtc: " << icaltime_is_utc( t )<< endl;
68  kdDebug(5800) << "--- zoneId: " << icaltimezone_get_tzid( const_cast<icaltimezone*>( t.zone ) )<< endl;
69 }
70 */
71 
72 static TQString quoteForParam( const TQString &text )
73 {
74  TQString tmp = text;
75  tmp.remove( '"' );
76  if ( tmp.contains( ';' ) || tmp.contains( ':' ) || tmp.contains( ',' ) )
77  return tmp; // libical quotes in this case already, see icalparameter_as_ical_string()
78  return TQString::fromLatin1( "\"" ) + tmp + TQString::fromLatin1( "\"" );
79 }
80 
81 const int gSecondsPerMinute = 60;
82 const int gSecondsPerHour = gSecondsPerMinute * 60;
83 const int gSecondsPerDay = gSecondsPerHour * 24;
84 const int gSecondsPerWeek = gSecondsPerDay * 7;
85 
86 ICalFormatImpl::ICalFormatImpl( ICalFormat *parent ) :
87  mParent( parent ), mCompat( new Compat )
88 {
89 }
90 
91 ICalFormatImpl::~ICalFormatImpl()
92 {
93  delete mCompat;
94 }
95 
96 class ICalFormatImpl::ToComponentVisitor : public IncidenceBase::Visitor
97 {
98  public:
99  ToComponentVisitor( ICalFormatImpl *impl, Scheduler::Method m ) : mImpl( impl ), mComponent( 0 ), mMethod( m ) {}
100 
101  bool visit( Event *e ) { mComponent = mImpl->writeEvent( e ); return true; }
102  bool visit( Todo *e ) { mComponent = mImpl->writeTodo( e ); return true; }
103  bool visit( Journal *e ) { mComponent = mImpl->writeJournal( e ); return true; }
104  bool visit( FreeBusy *fb ) { mComponent = mImpl->writeFreeBusy( fb, mMethod ); return true; }
105 
106  icalcomponent *component() { return mComponent; }
107 
108  private:
109  ICalFormatImpl *mImpl;
110  icalcomponent *mComponent;
111  Scheduler::Method mMethod;
112 };
113 
114 icalcomponent *ICalFormatImpl::writeIncidence( IncidenceBase *incidence, Scheduler::Method method )
115 {
116  ToComponentVisitor v( this, method );
117  if ( incidence->accept(v) )
118  return v.component();
119  else return 0;
120 }
121 
122 icalcomponent *ICalFormatImpl::writeTodo(Todo *todo)
123 {
124  TQString tmpStr;
125  TQStringList tmpStrList;
126 
127  icalcomponent *vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
128 
129  writeIncidence(vtodo,todo);
130 
131  // due date
132  if (todo->hasDueDate()) {
133  icaltimetype due;
134  if (todo->doesFloat()) {
135  due = writeICalDate(todo->dtDue(true).date());
136  } else {
137  due = writeICalDateTime(todo->dtDue(true));
138  }
139  icalcomponent_add_property(vtodo,icalproperty_new_due(due));
140  }
141 
142  // start time
143  if ( todo->hasStartDate() || todo->doesRecur() ) {
144  icaltimetype start;
145  if (todo->doesFloat()) {
146 // kdDebug(5800) << " Incidence " << todo->summary() << " floats." << endl;
147  start = writeICalDate(todo->dtStart(true).date());
148  } else {
149 // kdDebug(5800) << " incidence " << todo->summary() << " has time." << endl;
150  start = writeICalDateTime(todo->dtStart(true));
151  }
152  icalcomponent_add_property(vtodo,icalproperty_new_dtstart(start));
153  }
154 
155  // completion date
156  if (todo->isCompleted()) {
157  if (!todo->hasCompletedDate()) {
158  // If todo was created by KOrganizer <2.2 it has no correct completion
159  // date. Set it to now.
160  todo->setCompleted(TQDateTime::currentDateTime());
161  }
162  icaltimetype completed = writeICalDateTime(todo->completed());
163  icalcomponent_add_property(vtodo,icalproperty_new_completed(completed));
164  }
165 
166  icalcomponent_add_property(vtodo,
167  icalproperty_new_percentcomplete(todo->percentComplete()));
168 
169  if( todo->doesRecur() ) {
170  icalcomponent_add_property(vtodo,
171  icalproperty_new_recurrenceid( writeICalDateTime( todo->dtDue())));
172  }
173 
174  return vtodo;
175 }
176 
177 icalcomponent *ICalFormatImpl::writeEvent(Event *event)
178 {
179 #if 0
180  kdDebug(5800) << "Write Event '" << event->summary() << "' (" << event->uid()
181  << ")" << endl;
182 #endif
183 
184  TQString tmpStr;
185  TQStringList tmpStrList;
186 
187  icalcomponent *vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
188 
189  writeIncidence(vevent,event);
190 
191  // start time
192  icaltimetype start;
193  if (event->doesFloat()) {
194 // kdDebug(5800) << " Incidence " << event->summary() << " floats." << endl;
195  start = writeICalDate(event->dtStart().date());
196  } else {
197 // kdDebug(5800) << " incidence " << event->summary() << " has time." << endl;
198  start = writeICalDateTime(event->dtStart());
199  }
200  icalcomponent_add_property(vevent,icalproperty_new_dtstart(start));
201 
202  if (event->hasEndDate()) {
203  // End time.
204  // RFC2445 says that if DTEND is present, it has to be greater than DTSTART.
205  icaltimetype end;
206  if (event->doesFloat()) {
207 // kdDebug(5800) << " Event " << event->summary() << " floats." << endl;
208  // +1 day because end date is non-inclusive.
209  end = writeICalDate( event->dtEnd().date().addDays( 1 ) );
210  icalcomponent_add_property(vevent,icalproperty_new_dtend(end));
211  } else {
212 // kdDebug(5800) << " Event " << event->summary() << " has time." << endl;
213  if (event->dtEnd() != event->dtStart()) {
214  end = writeICalDateTime(event->dtEnd());
215  icalcomponent_add_property(vevent,icalproperty_new_dtend(end));
216  }
217  }
218  }
219 
220 // TODO: resources
221 #if 0
222  // resources
223  tmpStrList = anEvent->resources();
224  tmpStr = tmpStrList.join(";");
225  if (!tmpStr.isEmpty())
226  addPropValue(vevent, VCResourcesProp, tmpStr.utf8());
227 
228 #endif
229 
230  // Transparency
231  switch( event->transparency() ) {
232  case Event::Transparent:
233  icalcomponent_add_property(
234  vevent,
235  icalproperty_new_transp( ICAL_TRANSP_TRANSPARENT ) );
236  break;
237  case Event::Opaque:
238  icalcomponent_add_property(
239  vevent,
240  icalproperty_new_transp( ICAL_TRANSP_OPAQUE ) );
241  break;
242  }
243 
244  return vevent;
245 }
246 
247 icalcomponent *ICalFormatImpl::writeFreeBusy(FreeBusy *freebusy,
248  Scheduler::Method method)
249 {
250  kdDebug(5800) << "icalformatimpl: writeFreeBusy: startDate: "
251  << freebusy->dtStart().toString("ddd MMMM d yyyy: h:m:s ap") << " End Date: "
252  << freebusy->dtEnd().toString("ddd MMMM d yyyy: h:m:s ap") << endl;
253 
254  icalcomponent *vfreebusy = icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
255 
256  writeIncidenceBase(vfreebusy,freebusy);
257 
258  icalcomponent_add_property(vfreebusy, icalproperty_new_dtstart(
259  writeICalDateTime(freebusy->dtStart())));
260 
261  icalcomponent_add_property(vfreebusy, icalproperty_new_dtend(
262  writeICalDateTime(freebusy->dtEnd())));
263 
264  if (method == Scheduler::Request) {
265  icalcomponent_add_property(vfreebusy,icalproperty_new_uid(
266  freebusy->uid().utf8()));
267  }
268 
269  //Loops through all the periods in the freebusy object
270  TQValueList<Period> list = freebusy->busyPeriods();
271  TQValueList<Period>::Iterator it;
272  icalperiodtype period = icalperiodtype_null_period();
273  for (it = list.begin(); it!= list.end(); ++it) {
274  period.start = writeICalDateTime((*it).start());
275  if ( (*it).hasDuration() ) {
276  period.duration = writeICalDuration( (*it).duration().asSeconds() );
277  } else {
278  period.end = writeICalDateTime((*it).end());
279  }
280  icalcomponent_add_property(vfreebusy, icalproperty_new_freebusy(period) );
281  }
282 
283  return vfreebusy;
284 }
285 
286 icalcomponent *ICalFormatImpl::writeJournal(Journal *journal)
287 {
288  icalcomponent *vjournal = icalcomponent_new(ICAL_VJOURNAL_COMPONENT);
289 
290  writeIncidence(vjournal,journal);
291 
292  // start time
293  if (journal->dtStart().isValid()) {
294  icaltimetype start;
295  if (journal->doesFloat()) {
296 // kdDebug(5800) << " Incidence " << event->summary() << " floats." << endl;
297  start = writeICalDate(journal->dtStart().date());
298  } else {
299 // kdDebug(5800) << " incidence " << event->summary() << " has time." << endl;
300  start = writeICalDateTime(journal->dtStart());
301  }
302  icalcomponent_add_property(vjournal,icalproperty_new_dtstart(start));
303  }
304 
305  return vjournal;
306 }
307 
308 void ICalFormatImpl::writeIncidence(icalcomponent *parent,Incidence *incidence)
309 {
310  // pilot sync stuff
311 // TODO: move this application-specific code to kpilot
312  if (incidence->pilotId()) {
313  // NOTE: we can't do setNonKDECustomProperty here because this changes
314  // data and triggers an updated() event...
315  // incidence->setNonKDECustomProperty("X-PILOTSTAT", TQString::number(incidence->syncStatus()));
316  // incidence->setNonKDECustomProperty("X-PILOTID", TQString::number(incidence->pilotId()));
317 
318  icalproperty *p = 0;
319  p = icalproperty_new_x(TQString::number(incidence->syncStatus()).utf8());
320  icalproperty_set_x_name(p,"X-PILOTSTAT");
321  icalcomponent_add_property(parent,p);
322 
323  p = icalproperty_new_x(TQString::number(incidence->pilotId()).utf8());
324  icalproperty_set_x_name(p,"X-PILOTID");
325  icalcomponent_add_property(parent,p);
326  }
327 
328  TQString modifiedUid;
329  if ( incidence->hasRecurrenceID() ) {
330  // Recurring incidences are special; they must match their parent's UID
331  // Each child has the parent set as the first item in the list
332  // So, get and set the UID...
333  IncidenceList il = incidence->childIncidences();
334  IncidenceListIterator it;
335  it = il.begin();
336  modifiedUid = (*it);
337  }
338  else {
339  modifiedUid = incidence->uid();
340  }
341 
342  if ( incidence->schedulingID() != modifiedUid )
343  // We need to store the UID in here. The rawSchedulingID will
344  // go into the iCal UID component
345  incidence->setCustomProperty( "LIBKCAL", "ID", modifiedUid );
346  else
347  incidence->removeCustomProperty( "LIBKCAL", "ID" );
348 
349  writeIncidenceBase(parent,incidence);
350 
351  // creation date
352  icalcomponent_add_property(parent,icalproperty_new_created(
353  writeICalDateTime(incidence->created())));
354 
355  // unique id
356  // If the scheduling ID is different from the real UID, the real
357  // one is stored on X-REALID above
358  if ( incidence->hasRecurrenceID() ) {
359  // Recurring incidences are special; they must match their parent's UID
360  icalcomponent_add_property(parent,icalproperty_new_uid(modifiedUid.utf8()));
361  }
362  else {
363  if ( !incidence->schedulingID().isEmpty() ) {
364  icalcomponent_add_property(parent,icalproperty_new_uid(
365  incidence->schedulingID().utf8()));
366  }
367  }
368 
369  // revision
370  if ( incidence->revision() > 0 ) { // 0 is default, so don't write that out
371  icalcomponent_add_property(parent,icalproperty_new_sequence(
372  incidence->revision()));
373  }
374 
375  // last modification date
376  if ( incidence->lastModified().isValid() ) {
377  icalcomponent_add_property(parent,icalproperty_new_lastmodified(
378  writeICalDateTime(incidence->lastModified())));
379  }
380 
381  // description
382  if (!incidence->description().isEmpty()) {
383  icalcomponent_add_property(parent,icalproperty_new_description(
384  incidence->description().utf8()));
385  }
386 
387  // summary
388  if (!incidence->summary().isEmpty()) {
389  icalcomponent_add_property(parent,icalproperty_new_summary(
390  incidence->summary().utf8()));
391  }
392 
393  // location
394  if (!incidence->location().isEmpty()) {
395  icalcomponent_add_property(parent,icalproperty_new_location(
396  incidence->location().utf8()));
397  }
398 
399  // status
400  icalproperty_status status = ICAL_STATUS_NONE;
401  switch (incidence->status()) {
402  case Incidence::StatusTentative: status = ICAL_STATUS_TENTATIVE; break;
403  case Incidence::StatusConfirmed: status = ICAL_STATUS_CONFIRMED; break;
404  case Incidence::StatusCompleted: status = ICAL_STATUS_COMPLETED; break;
405  case Incidence::StatusNeedsAction: status = ICAL_STATUS_NEEDSACTION; break;
406  case Incidence::StatusCanceled: status = ICAL_STATUS_CANCELLED; break;
407  case Incidence::StatusInProcess: status = ICAL_STATUS_INPROCESS; break;
408  case Incidence::StatusDraft: status = ICAL_STATUS_DRAFT; break;
409  case Incidence::StatusFinal: status = ICAL_STATUS_FINAL; break;
410  case Incidence::StatusX: {
411  icalproperty* p = icalproperty_new_status(ICAL_STATUS_X);
412  icalvalue_set_x(icalproperty_get_value(p), incidence->statusStr().utf8());
413  icalcomponent_add_property(parent, p);
414  break;
415  }
416  case Incidence::StatusNone:
417  default:
418  break;
419  }
420  if (status != ICAL_STATUS_NONE)
421  icalcomponent_add_property(parent, icalproperty_new_status(status));
422 
423  // secrecy
424  icalproperty_class secClass;
425  switch (incidence->secrecy()) {
426  case Incidence::SecrecyPublic:
427  secClass = ICAL_CLASS_PUBLIC;
428  break;
429  case Incidence::SecrecyConfidential:
430  secClass = ICAL_CLASS_CONFIDENTIAL;
431  break;
432  case Incidence::SecrecyPrivate:
433  default:
434  secClass = ICAL_CLASS_PRIVATE;
435  break;
436  }
437  if ( secClass != ICAL_CLASS_PUBLIC ) {
438  icalcomponent_add_property(parent,icalproperty_new_class(secClass));
439  }
440 
441  // priority
442  if ( incidence->priority() > 0 ) { // 0 is undefined priority
443  icalcomponent_add_property(parent,icalproperty_new_priority(
444  incidence->priority()));
445  }
446 
447  // categories
448  TQStringList categories = incidence->categories();
449  TQStringList::Iterator it;
450  for(it = categories.begin(); it != categories.end(); ++it ) {
451  icalcomponent_add_property(parent,icalproperty_new_categories((*it).utf8()));
452  }
453 
454  // related event
455  if ( !incidence->relatedToUid().isEmpty() ) {
456  icalcomponent_add_property(parent,icalproperty_new_relatedto(
457  incidence->relatedToUid().utf8()));
458  }
459 
460  // recurrenceid
461  if ( incidence->hasRecurrenceID() ) {
462  icalcomponent_add_property(parent, icalproperty_new_recurrenceid( writeICalDateTime( incidence->recurrenceID() ) ));
463  }
464 
465 // kdDebug(5800) << "Write recurrence for '" << incidence->summary() << "' (" << incidence->uid()
466 // << ")" << endl;
467 
468  RecurrenceRule::List rrules( incidence->recurrence()->rRules() );
469  RecurrenceRule::List::ConstIterator rit;
470  for ( rit = rrules.begin(); rit != rrules.end(); ++rit ) {
471  icalcomponent_add_property( parent, icalproperty_new_rrule(
472  writeRecurrenceRule( (*rit) ) ) );
473  }
474 
475  RecurrenceRule::List exrules( incidence->recurrence()->exRules() );
476  RecurrenceRule::List::ConstIterator exit;
477  for ( exit = exrules.begin(); exit != exrules.end(); ++exit ) {
478  icalcomponent_add_property( parent, icalproperty_new_rrule(
479  writeRecurrenceRule( (*exit) ) ) );
480  }
481 
482  DateList dateList = incidence->recurrence()->exDates();
483  DateList::ConstIterator exIt;
484  for(exIt = dateList.begin(); exIt != dateList.end(); ++exIt) {
485  icalcomponent_add_property(parent,icalproperty_new_exdate(
486  writeICalDate(*exIt)));
487  }
488  DateTimeList dateTimeList = incidence->recurrence()->exDateTimes();
489  DateTimeList::ConstIterator extIt;
490  for(extIt = dateTimeList.begin(); extIt != dateTimeList.end(); ++extIt) {
491  icalcomponent_add_property(parent,icalproperty_new_exdate(
492  writeICalDateTime(*extIt)));
493  }
494 
495 
496  dateList = incidence->recurrence()->rDates();
497  DateList::ConstIterator rdIt;
498  for( rdIt = dateList.begin(); rdIt != dateList.end(); ++rdIt) {
499  icalcomponent_add_property( parent, icalproperty_new_rdate(
500  writeICalDatePeriod(*rdIt) ) );
501  }
502  dateTimeList = incidence->recurrence()->rDateTimes();
503  DateTimeList::ConstIterator rdtIt;
504  for( rdtIt = dateTimeList.begin(); rdtIt != dateTimeList.end(); ++rdtIt) {
505  icalcomponent_add_property( parent, icalproperty_new_rdate(
506  writeICalDateTimePeriod(*rdtIt) ) );
507  }
508 
509  // attachments
510  Attachment::List attachments = incidence->attachments();
511  Attachment::List::ConstIterator atIt;
512  for ( atIt = attachments.begin(); atIt != attachments.end(); ++atIt ) {
513  icalcomponent_add_property( parent, writeAttachment( *atIt ) );
514  }
515 
516  // alarms
517  Alarm::List::ConstIterator alarmIt;
518  for ( alarmIt = incidence->alarms().begin();
519  alarmIt != incidence->alarms().end(); ++alarmIt ) {
520  if ( (*alarmIt)->enabled() ) {
521 // kdDebug(5800) << "Write alarm for " << incidence->summary() << endl;
522  icalcomponent_add_component( parent, writeAlarm( *alarmIt ) );
523  }
524  }
525 
526  // duration
527  if (incidence->hasDuration()) {
528  icaldurationtype duration;
529  duration = writeICalDuration( incidence->duration() );
530  icalcomponent_add_property(parent,icalproperty_new_duration(duration));
531  }
532 }
533 
534 void ICalFormatImpl::writeIncidenceBase( icalcomponent *parent,
535  IncidenceBase * incidenceBase )
536 {
537  icalcomponent_add_property( parent, icalproperty_new_dtstamp(
538  writeICalDateTime( TQDateTime::currentDateTime() ) ) );
539 
540  // organizer stuff
541  if ( !incidenceBase->organizer().isEmpty() ) {
542  icalcomponent_add_property( parent, writeOrganizer( incidenceBase->organizer() ) );
543  }
544 
545  // attendees
546  if ( incidenceBase->attendeeCount() > 0 ) {
547  Attendee::List::ConstIterator it;
548  for( it = incidenceBase->attendees().begin();
549  it != incidenceBase->attendees().end(); ++it ) {
550  icalcomponent_add_property( parent, writeAttendee( *it ) );
551  }
552  }
553 
554  // comments
555  TQStringList comments = incidenceBase->comments();
556  for (TQStringList::Iterator it=comments.begin(); it!=comments.end(); ++it) {
557  icalcomponent_add_property(parent, icalproperty_new_comment((*it).utf8()));
558  }
559 
560  // custom properties
561  writeCustomProperties( parent, incidenceBase );
562 }
563 
564 void ICalFormatImpl::writeCustomProperties(icalcomponent *parent,CustomProperties *properties)
565 {
566  TQMap<TQCString, TQString> custom = properties->customProperties();
567  for (TQMap<TQCString, TQString>::Iterator c = custom.begin(); c != custom.end(); ++c) {
568  icalproperty *p = icalproperty_new_x(c.data().utf8());
569  icalproperty_set_x_name(p,c.key());
570  icalcomponent_add_property(parent,p);
571  }
572 }
573 
574 icalproperty *ICalFormatImpl::writeOrganizer( const Person &organizer )
575 {
576  icalproperty *p = icalproperty_new_organizer("MAILTO:" + organizer.email().utf8());
577 
578  if (!organizer.name().isEmpty()) {
579  icalproperty_add_parameter( p, icalparameter_new_cn(quoteForParam(organizer.name()).utf8()) );
580  }
581  // TODO: Write dir, sent-by and language
582 
583  return p;
584 }
585 
586 
587 icalproperty *ICalFormatImpl::writeAttendee(Attendee *attendee)
588 {
589  icalproperty *p = icalproperty_new_attendee("mailto:" + attendee->email().utf8());
590 
591  if (!attendee->name().isEmpty()) {
592  icalproperty_add_parameter(p,icalparameter_new_cn(quoteForParam(attendee->name()).utf8()));
593  }
594 
595 
596  icalproperty_add_parameter(p,icalparameter_new_rsvp(
597  attendee->RSVP() ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE ));
598 
599  icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION;
600  switch (attendee->status()) {
601  default:
602  case Attendee::NeedsAction:
603  status = ICAL_PARTSTAT_NEEDSACTION;
604  break;
605  case Attendee::Accepted:
606  status = ICAL_PARTSTAT_ACCEPTED;
607  break;
608  case Attendee::Declined:
609  status = ICAL_PARTSTAT_DECLINED;
610  break;
611  case Attendee::Tentative:
612  status = ICAL_PARTSTAT_TENTATIVE;
613  break;
614  case Attendee::Delegated:
615  status = ICAL_PARTSTAT_DELEGATED;
616  break;
617  case Attendee::Completed:
618  status = ICAL_PARTSTAT_COMPLETED;
619  break;
620  case Attendee::InProcess:
621  status = ICAL_PARTSTAT_INPROCESS;
622  break;
623  }
624  icalproperty_add_parameter(p,icalparameter_new_partstat(status));
625 
626  icalparameter_role role = ICAL_ROLE_REQPARTICIPANT;
627  switch (attendee->role()) {
628  case Attendee::Chair:
629  role = ICAL_ROLE_CHAIR;
630  break;
631  default:
632  case Attendee::ReqParticipant:
633  role = ICAL_ROLE_REQPARTICIPANT;
634  break;
635  case Attendee::OptParticipant:
636  role = ICAL_ROLE_OPTPARTICIPANT;
637  break;
638  case Attendee::NonParticipant:
639  role = ICAL_ROLE_NONPARTICIPANT;
640  break;
641  }
642  icalproperty_add_parameter(p,icalparameter_new_role(role));
643 
644  if (!attendee->uid().isEmpty()) {
645  icalparameter* icalparameter_uid = icalparameter_new_x(attendee->uid().utf8());
646  icalparameter_set_xname(icalparameter_uid,"X-UID");
647  icalproperty_add_parameter(p,icalparameter_uid);
648  }
649 
650  if ( !attendee->delegate().isEmpty() ) {
651  icalparameter* icalparameter_delegate = icalparameter_new_delegatedto( attendee->delegate().utf8() );
652  icalproperty_add_parameter( p, icalparameter_delegate );
653  }
654 
655  if ( !attendee->delegator().isEmpty() ) {
656  icalparameter* icalparameter_delegator = icalparameter_new_delegatedfrom( attendee->delegator().utf8() );
657  icalproperty_add_parameter( p, icalparameter_delegator );
658  }
659 
660  return p;
661 }
662 
663 icalproperty *ICalFormatImpl::writeAttachment( Attachment *att )
664 {
665  icalattach *attach;
666  if ( att->isUri() ) {
667  attach = icalattach_new_from_url( att->uri().utf8().data() );
668  } else {
669 #ifdef USE_LIBICAL_0_46
670  attach = icalattach_new_from_data ( (const char *)att->data(), 0, 0 );
671 #else
672  attach = icalattach_new_from_data ( (unsigned char *)att->data(), 0, 0 );
673 #endif
674  }
675  icalproperty *p = icalproperty_new_attach( attach );
676 
677  if ( !att->mimeType().isEmpty() ) {
678  icalproperty_add_parameter( p,
679  icalparameter_new_fmttype( att->mimeType().utf8().data() ) );
680  }
681 
682  if ( att->isBinary() ) {
683  icalproperty_add_parameter( p,
684  icalparameter_new_value( ICAL_VALUE_BINARY ) );
685  icalproperty_add_parameter( p,
686  icalparameter_new_encoding( ICAL_ENCODING_BASE64 ) );
687  }
688 
689  if ( att->showInline() ) {
690  icalparameter* icalparameter_inline = icalparameter_new_x( "inline" );
691  icalparameter_set_xname( icalparameter_inline, "X-CONTENT-DISPOSITION" );
692  icalproperty_add_parameter( p, icalparameter_inline );
693  }
694 
695  if ( !att->label().isEmpty() ) {
696  icalparameter* icalparameter_label = icalparameter_new_x( att->label().utf8() );
697  icalparameter_set_xname( icalparameter_label, "X-LABEL" );
698  icalproperty_add_parameter( p, icalparameter_label );
699  }
700 
701  return p;
702 }
703 
704 icalrecurrencetype ICalFormatImpl::writeRecurrenceRule( RecurrenceRule *recur )
705 {
706 // kdDebug(5800) << "ICalFormatImpl::writeRecurrenceRule()" << endl;
707 
708  icalrecurrencetype r;
709  icalrecurrencetype_clear(&r);
710 
711  switch( recur->recurrenceType() ) {
712  case RecurrenceRule::rSecondly:
713  r.freq = ICAL_SECONDLY_RECURRENCE;
714  break;
715  case RecurrenceRule::rMinutely:
716  r.freq = ICAL_MINUTELY_RECURRENCE;
717  break;
718  case RecurrenceRule::rHourly:
719  r.freq = ICAL_HOURLY_RECURRENCE;
720  break;
721  case RecurrenceRule::rDaily:
722  r.freq = ICAL_DAILY_RECURRENCE;
723  break;
724  case RecurrenceRule::rWeekly:
725  r.freq = ICAL_WEEKLY_RECURRENCE;
726  break;
727  case RecurrenceRule::rMonthly:
728  r.freq = ICAL_MONTHLY_RECURRENCE;
729  break;
730  case RecurrenceRule::rYearly:
731  r.freq = ICAL_YEARLY_RECURRENCE;
732  break;
733  default:
734  r.freq = ICAL_NO_RECURRENCE;
735  kdDebug(5800) << "ICalFormatImpl::writeRecurrence(): no recurrence" << endl;
736  break;
737  }
738 
739  int index = 0;
740  TQValueList<int> bys;
741  TQValueList<int>::ConstIterator it;
742 
743  // Now write out the BY* parts:
744  bys = recur->bySeconds();
745  index = 0;
746  for ( it = bys.begin(); it != bys.end(); ++it ) {
747  r.by_second[index++] = *it;
748  }
749 
750  bys = recur->byMinutes();
751  index = 0;
752  for ( it = bys.begin(); it != bys.end(); ++it ) {
753  r.by_minute[index++] = *it;
754  }
755 
756  bys = recur->byHours();
757  index = 0;
758  for ( it = bys.begin(); it != bys.end(); ++it ) {
759  r.by_hour[index++] = *it;
760  }
761 
762  bys = recur->byMonthDays();
763  index = 0;
764  for ( it = bys.begin(); it != bys.end(); ++it ) {
765  r.by_month_day[index++] = icalrecurrencetype_day_position( (*it) * 8 );
766  }
767 
768  bys = recur->byYearDays();
769  index = 0;
770  for ( it = bys.begin(); it != bys.end(); ++it ) {
771  r.by_year_day[index++] = *it;
772  }
773 
774  bys = recur->byWeekNumbers();
775  index = 0;
776  for ( it = bys.begin(); it != bys.end(); ++it ) {
777  r.by_week_no[index++] = *it;
778  }
779 
780  bys = recur->byMonths();
781  index = 0;
782  for ( it = bys.begin(); it != bys.end(); ++it ) {
783  r.by_month[index++] = *it;
784  }
785 
786  bys = recur->bySetPos();
787  index = 0;
788  for ( it = bys.begin(); it != bys.end(); ++it ) {
789  r.by_set_pos[index++] = *it;
790  }
791 
792 
793  TQValueList<RecurrenceRule::WDayPos> byd = recur->byDays();
794  int day;
795  index = 0;
796  for ( TQValueList<RecurrenceRule::WDayPos>::ConstIterator dit = byd.begin();
797  dit != byd.end(); ++dit ) {
798  day = (*dit).day() % 7 + 1; // convert from Monday=1 to Sunday=1
799  if ( (*dit).pos() < 0 ) {
800  day += (-(*dit).pos())*8;
801  day = -day;
802  } else {
803  day += (*dit).pos()*8;
804  }
805  r.by_day[index++] = day;
806  }
807 
808  r.week_start = static_cast<icalrecurrencetype_weekday>(
809  recur->weekStart()%7 + 1);
810 
811  if ( recur->frequency() > 1 ) {
812  // Dont' write out INTERVAL=1, because that's the default anyway
813  r.interval = recur->frequency();
814  }
815 
816  if ( recur->duration() > 0 ) {
817  r.count = recur->duration();
818  } else if ( recur->duration() == -1 ) {
819  r.count = 0;
820  } else {
821  if ( recur->doesFloat() )
822  r.until = writeICalDate(recur->endDt().date());
823  else
824  r.until = writeICalDateTime(recur->endDt());
825  }
826 
827 // Debug output
828 #if 0
829  const char *str = icalrecurrencetype_as_string(&r);
830  if (str) {
831  kdDebug(5800) << " String: " << str << endl;
832  } else {
833  kdDebug(5800) << " No String" << endl;
834  }
835 #endif
836 
837  return r;
838 }
839 
840 
841 icalcomponent *ICalFormatImpl::writeAlarm(Alarm *alarm)
842 {
843 // kdDebug(5800) << " ICalFormatImpl::writeAlarm" << endl;
844  icalcomponent *a = icalcomponent_new(ICAL_VALARM_COMPONENT);
845 
846  icalproperty_action action;
847  icalattach *attach = 0;
848 
849  switch (alarm->type()) {
850  case Alarm::Procedure:
851  action = ICAL_ACTION_PROCEDURE;
852  attach = icalattach_new_from_url(TQFile::encodeName(alarm->programFile()).data());
853  icalcomponent_add_property(a,icalproperty_new_attach(attach));
854  if (!alarm->programArguments().isEmpty()) {
855  icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8()));
856  }
857  break;
858  case Alarm::Audio:
859  action = ICAL_ACTION_AUDIO;
860 // kdDebug(5800) << " It's an audio action, file: " << alarm->audioFile() << endl;
861  if (!alarm->audioFile().isEmpty()) {
862  attach = icalattach_new_from_url(TQFile::encodeName( alarm->audioFile() ).data());
863  icalcomponent_add_property(a,icalproperty_new_attach(attach));
864  }
865  break;
866  case Alarm::Email: {
867  action = ICAL_ACTION_EMAIL;
868  TQValueList<Person> addresses = alarm->mailAddresses();
869  for (TQValueList<Person>::Iterator ad = addresses.begin(); ad != addresses.end(); ++ad) {
870  icalproperty *p = icalproperty_new_attendee("MAILTO:" + (*ad).email().utf8());
871  if (!(*ad).name().isEmpty()) {
872  icalproperty_add_parameter(p,icalparameter_new_cn(quoteForParam((*ad).name()).utf8()));
873  }
874  icalcomponent_add_property(a,p);
875  }
876  icalcomponent_add_property(a,icalproperty_new_summary(alarm->mailSubject().utf8()));
877  icalcomponent_add_property(a,icalproperty_new_description(alarm->mailText().utf8()));
878  TQStringList attachments = alarm->mailAttachments();
879  if (attachments.count() > 0) {
880  for (TQStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at) {
881  attach = icalattach_new_from_url(TQFile::encodeName( *at ).data());
882  icalcomponent_add_property(a,icalproperty_new_attach(attach));
883  }
884  }
885  break;
886  }
887  case Alarm::Display:
888  action = ICAL_ACTION_DISPLAY;
889  icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8()));
890  break;
891  case Alarm::Invalid:
892  default:
893  kdDebug(5800) << "Unknown type of alarm" << endl;
894  action = ICAL_ACTION_NONE;
895  break;
896  }
897  icalcomponent_add_property(a,icalproperty_new_action(action));
898 
899  // Trigger time
900  icaltriggertype trigger;
901  if ( alarm->hasTime() ) {
902  trigger.time = writeICalDateTime(alarm->time());
903  trigger.duration = icaldurationtype_null_duration();
904  } else {
905  trigger.time = icaltime_null_time();
906  Duration offset;
907  if ( alarm->hasStartOffset() )
908  offset = alarm->startOffset();
909  else
910  offset = alarm->endOffset();
911  trigger.duration = writeICalDuration( offset.asSeconds() );
912  }
913  icalproperty *p = icalproperty_new_trigger(trigger);
914  if ( alarm->hasEndOffset() )
915  icalproperty_add_parameter(p,icalparameter_new_related(ICAL_RELATED_END));
916  icalcomponent_add_property(a,p);
917 
918  // Repeat count and duration
919  if (alarm->repeatCount()) {
920  icalcomponent_add_property(a,icalproperty_new_repeat(alarm->repeatCount()));
921  icalcomponent_add_property(a,icalproperty_new_duration(
922  writeICalDuration(alarm->snoozeTime().value())));
923  }
924 
925  // Custom properties
926  TQMap<TQCString, TQString> custom = alarm->customProperties();
927  for (TQMap<TQCString, TQString>::Iterator c = custom.begin(); c != custom.end(); ++c) {
928  icalproperty *p = icalproperty_new_x(c.data().utf8());
929  icalproperty_set_x_name(p,c.key());
930  icalcomponent_add_property(a,p);
931  }
932 
933  return a;
934 }
935 
936 Todo *ICalFormatImpl::readTodo(icalcomponent *vtodo)
937 {
938  Todo *todo = new Todo;
939 
940  readIncidence(vtodo, 0, todo); // FIXME timezone
941 
942  icalproperty *p = icalcomponent_get_first_property(vtodo,ICAL_ANY_PROPERTY);
943 
944 // int intvalue;
945  icaltimetype icaltime;
946 
947  TQStringList categories;
948 
949  while (p) {
950  icalproperty_kind kind = icalproperty_isa(p);
951  switch (kind) {
952 
953  case ICAL_DUE_PROPERTY: // due date
954  icaltime = icalproperty_get_due(p);
955  if (icaltime.is_date) {
956  todo->setDtDue(TQDateTime(readICalDate(icaltime),TQTime(0,0,0)),true);
957  } else {
958  todo->setDtDue(readICalDateTime(p, icaltime),true);
959  todo->setFloats(false);
960  }
961  todo->setHasDueDate(true);
962  break;
963 
964  case ICAL_COMPLETED_PROPERTY: // completion date
965  icaltime = icalproperty_get_completed(p);
966  todo->setCompleted(readICalDateTime(p, icaltime));
967  break;
968 
969  case ICAL_PERCENTCOMPLETE_PROPERTY: // Percent completed
970  todo->setPercentComplete(icalproperty_get_percentcomplete(p));
971  break;
972 
973  case ICAL_RELATEDTO_PROPERTY: // related todo (parent)
974  todo->setRelatedToUid(TQString::fromUtf8(icalproperty_get_relatedto(p)));
975  mTodosRelate.append(todo);
976  break;
977 
978  case ICAL_DTSTART_PROPERTY: {
979  // Flag that todo has start date. Value is read in by readIncidence().
980  if ( todo->comments().grep("NoStartDate").count() )
981  todo->setHasStartDate( false );
982  else
983  todo->setHasStartDate( true );
984  break;
985  }
986 
987  case ICAL_RECURRENCEID_PROPERTY:
988  icaltime = icalproperty_get_recurrenceid(p);
989  todo->setDtRecurrence( readICalDateTime(p, icaltime) );
990  break;
991 
992  default:
993 // kdDebug(5800) << "ICALFormat::readTodo(): Unknown property: " << kind
994 // << endl;
995  break;
996  }
997 
998  p = icalcomponent_get_next_property(vtodo,ICAL_ANY_PROPERTY);
999  }
1000 
1001  if (mCompat) mCompat->fixEmptySummary( todo );
1002 
1003  return todo;
1004 }
1005 
1006 Event *ICalFormatImpl::readEvent( icalcomponent *vevent, icalcomponent *vtimezone )
1007 {
1008  Event *event = new Event;
1009 
1010  // FIXME where is this freed?
1011  icaltimezone *tz = icaltimezone_new();
1012  if ( !icaltimezone_set_component( tz, vtimezone ) ) {
1013  icaltimezone_free( tz, 1 );
1014  tz = 0;
1015  }
1016 
1017  readIncidence( vevent, tz, event);
1018 
1019  icalproperty *p = icalcomponent_get_first_property( vevent, ICAL_ANY_PROPERTY );
1020 
1021  // int intvalue;
1022  icaltimetype icaltime;
1023 
1024  TQStringList categories;
1025  icalproperty_transp transparency;
1026 
1027  bool dtEndProcessed = false;
1028 
1029  while ( p ) {
1030  icalproperty_kind kind = icalproperty_isa( p );
1031  switch ( kind ) {
1032 
1033  case ICAL_DTEND_PROPERTY: // start date and time
1034  icaltime = icalproperty_get_dtend( p );
1035  if ( icaltime.is_date ) {
1036  // End date is non-inclusive
1037  TQDate endDate = readICalDate( icaltime ).addDays( -1 );
1038  if ( mCompat ) {
1039  mCompat->fixFloatingEnd( endDate );
1040  }
1041 
1042  if ( endDate < event->dtStart().date() ) {
1043  endDate = event->dtStart().date();
1044  }
1045  event->setDtEnd( TQDateTime( endDate, TQTime( 0, 0, 0 ) ) );
1046  } else {
1047  event->setDtEnd(readICalDateTime(p, icaltime, tz));
1048  event->setFloats( false );
1049  }
1050  dtEndProcessed = true;
1051  break;
1052 
1053  case ICAL_RELATEDTO_PROPERTY: // related event (parent)
1054  event->setRelatedToUid( TQString::fromUtf8( icalproperty_get_relatedto( p ) ) );
1055  mEventsRelate.append( event );
1056  break;
1057 
1058  case ICAL_TRANSP_PROPERTY: // Transparency
1059  transparency = icalproperty_get_transp( p );
1060  if ( transparency == ICAL_TRANSP_TRANSPARENT ) {
1061  event->setTransparency( Event::Transparent );
1062  } else {
1063  event->setTransparency( Event::Opaque );
1064  }
1065  break;
1066 
1067  default:
1068  // kdDebug(5800) << "ICALFormat::readEvent(): Unknown property: " << kind
1069  // << endl;
1070  break;
1071  }
1072 
1073  p = icalcomponent_get_next_property( vevent, ICAL_ANY_PROPERTY );
1074  }
1075 
1076  // according to rfc2445 the dtend shouldn't be written when it equals
1077  // start date. so assign one equal to start date.
1078  if ( !dtEndProcessed && !event->hasDuration() ) {
1079  event->setDtEnd( event->dtStart() );
1080  }
1081 
1082  const TQString msade = event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT");
1083  if ( !msade.isEmpty() ) {
1084  const bool floats = ( msade == TQString::fromLatin1("TRUE") );
1085  event->setFloats(floats);
1086  }
1087 
1088  if ( mCompat ) {
1089  mCompat->fixEmptySummary( event );
1090  }
1091 
1092  return event;
1093 }
1094 
1095 FreeBusy *ICalFormatImpl::readFreeBusy(icalcomponent *vfreebusy)
1096 {
1097  FreeBusy *freebusy = new FreeBusy;
1098 
1099  readIncidenceBase(vfreebusy, freebusy);
1100 
1101  icalproperty *p = icalcomponent_get_first_property(vfreebusy,ICAL_ANY_PROPERTY);
1102 
1103  icaltimetype icaltime;
1104  PeriodList periods;
1105 
1106  while (p) {
1107  icalproperty_kind kind = icalproperty_isa(p);
1108  switch (kind) {
1109 
1110  case ICAL_DTSTART_PROPERTY: // start date and time
1111  icaltime = icalproperty_get_dtstart(p);
1112  freebusy->setDtStart(readICalDateTime(p, icaltime));
1113  break;
1114 
1115  case ICAL_DTEND_PROPERTY: // end Date and Time
1116  icaltime = icalproperty_get_dtend(p);
1117  freebusy->setDtEnd(readICalDateTime(p, icaltime));
1118  break;
1119 
1120  case ICAL_FREEBUSY_PROPERTY: //Any FreeBusy Times
1121  {
1122  icalperiodtype icalperiod = icalproperty_get_freebusy(p);
1123  TQDateTime period_start = readICalDateTime(p, icalperiod.start);
1124  Period period;
1125  if ( !icaltime_is_null_time(icalperiod.end) ) {
1126  TQDateTime period_end = readICalDateTime(p, icalperiod.end);
1127  period = Period(period_start, period_end);
1128  } else {
1129  Duration duration = readICalDuration( icalperiod.duration );
1130  period = Period(period_start, duration);
1131  }
1132  icalparameter *param = icalproperty_get_first_parameter( p, ICAL_X_PARAMETER );
1133  while ( param ) {
1134  if ( strncmp( icalparameter_get_xname( param ), "X-SUMMARY", 9 ) == 0 ) {
1135  period.setSummary( TQString::fromUtf8(
1136  KCodecs::base64Decode( TQCString( icalparameter_get_xvalue( param ) ) ) ) );
1137  }
1138  if ( strncmp( icalparameter_get_xname( param ), "X-LOCATION", 10 ) == 0 ) {
1139  period.setLocation( TQString::fromUtf8(
1140  KCodecs::base64Decode( TQCString( icalparameter_get_xvalue( param ) ) ) ) );
1141  }
1142  param = icalproperty_get_next_parameter( p, ICAL_X_PARAMETER );
1143  }
1144  periods.append( period );
1145  break;
1146  }
1147 
1148  default:
1149 // kdDebug(5800) << "ICalFormatImpl::readFreeBusy(): Unknown property: "
1150 // << kind << endl;
1151  break;
1152  }
1153  p = icalcomponent_get_next_property(vfreebusy,ICAL_ANY_PROPERTY);
1154  }
1155  freebusy->addPeriods( periods );
1156 
1157  return freebusy;
1158 }
1159 
1160 Journal *ICalFormatImpl::readJournal(icalcomponent *vjournal)
1161 {
1162  Journal *journal = new Journal;
1163 
1164  readIncidence(vjournal, 0, journal); // FIXME tz?
1165 
1166  return journal;
1167 }
1168 
1169 Attendee *ICalFormatImpl::readAttendee(icalproperty *attendee)
1170 {
1171  icalparameter *p = 0;
1172 
1173  TQString email = TQString::fromUtf8(icalproperty_get_attendee(attendee));
1174  if ( email.startsWith( "mailto:", false ) ) {
1175  email = email.mid( 7 );
1176  }
1177 
1178  TQString name;
1179  TQString uid = TQString();
1180  p = icalproperty_get_first_parameter(attendee,ICAL_CN_PARAMETER);
1181  if (p) {
1182  name = TQString::fromUtf8(icalparameter_get_cn(p));
1183  } else {
1184  }
1185 
1186  bool rsvp=false;
1187  p = icalproperty_get_first_parameter(attendee,ICAL_RSVP_PARAMETER);
1188  if (p) {
1189  icalparameter_rsvp rsvpParameter = icalparameter_get_rsvp(p);
1190  if (rsvpParameter == ICAL_RSVP_TRUE) rsvp = true;
1191  }
1192 
1193  Attendee::PartStat status = Attendee::NeedsAction;
1194  p = icalproperty_get_first_parameter(attendee,ICAL_PARTSTAT_PARAMETER);
1195  if (p) {
1196  icalparameter_partstat partStatParameter = icalparameter_get_partstat(p);
1197  switch(partStatParameter) {
1198  default:
1199  case ICAL_PARTSTAT_NEEDSACTION:
1200  status = Attendee::NeedsAction;
1201  break;
1202  case ICAL_PARTSTAT_ACCEPTED:
1203  status = Attendee::Accepted;
1204  break;
1205  case ICAL_PARTSTAT_DECLINED:
1206  status = Attendee::Declined;
1207  break;
1208  case ICAL_PARTSTAT_TENTATIVE:
1209  status = Attendee::Tentative;
1210  break;
1211  case ICAL_PARTSTAT_DELEGATED:
1212  status = Attendee::Delegated;
1213  break;
1214  case ICAL_PARTSTAT_COMPLETED:
1215  status = Attendee::Completed;
1216  break;
1217  case ICAL_PARTSTAT_INPROCESS:
1218  status = Attendee::InProcess;
1219  break;
1220  }
1221  }
1222 
1223  Attendee::Role role = Attendee::ReqParticipant;
1224  p = icalproperty_get_first_parameter(attendee,ICAL_ROLE_PARAMETER);
1225  if (p) {
1226  icalparameter_role roleParameter = icalparameter_get_role(p);
1227  switch(roleParameter) {
1228  case ICAL_ROLE_CHAIR:
1229  role = Attendee::Chair;
1230  break;
1231  default:
1232  case ICAL_ROLE_REQPARTICIPANT:
1233  role = Attendee::ReqParticipant;
1234  break;
1235  case ICAL_ROLE_OPTPARTICIPANT:
1236  role = Attendee::OptParticipant;
1237  break;
1238  case ICAL_ROLE_NONPARTICIPANT:
1239  role = Attendee::NonParticipant;
1240  break;
1241  }
1242  }
1243 
1244  p = icalproperty_get_first_parameter(attendee,ICAL_X_PARAMETER);
1245  uid = icalparameter_get_xvalue(p);
1246  // This should be added, but there seems to be a libical bug here.
1247  // TODO: does this work now in libical-0.24 or greater?
1248  /*while (p) {
1249  // if (icalparameter_get_xname(p) == "X-UID") {
1250  uid = icalparameter_get_xvalue(p);
1251  p = icalproperty_get_next_parameter(attendee,ICAL_X_PARAMETER);
1252  } */
1253 
1254  Attendee *a = new Attendee( name, email, rsvp, status, role, uid );
1255 
1256  p = icalproperty_get_first_parameter( attendee, ICAL_DELEGATEDTO_PARAMETER );
1257  if ( p )
1258  a->setDelegate( icalparameter_get_delegatedto( p ) );
1259 
1260  p = icalproperty_get_first_parameter( attendee, ICAL_DELEGATEDFROM_PARAMETER );
1261  if ( p )
1262  a->setDelegator( icalparameter_get_delegatedfrom( p ) );
1263 
1264  return a;
1265 }
1266 
1267 Person ICalFormatImpl::readOrganizer( icalproperty *organizer )
1268 {
1269  TQString email = TQString::fromUtf8(icalproperty_get_organizer(organizer));
1270  if ( email.startsWith( "mailto:", false ) ) {
1271  email = email.mid( 7 );
1272  }
1273  TQString cn;
1274 
1275  icalparameter *p = icalproperty_get_first_parameter(
1276  organizer, ICAL_CN_PARAMETER );
1277 
1278  if ( p ) {
1279  cn = TQString::fromUtf8( icalparameter_get_cn( p ) );
1280  }
1281  Person org( cn, email );
1282  // TODO: Treat sent-by, dir and language here, too
1283  return org;
1284 }
1285 
1286 Attachment *ICalFormatImpl::readAttachment(icalproperty *attach)
1287 {
1288  Attachment *attachment = 0;
1289 
1290  const char *p;
1291  icalvalue *value = icalproperty_get_value( attach );
1292 
1293  switch( icalvalue_isa( value ) ) {
1294  case ICAL_ATTACH_VALUE:
1295  {
1296  icalattach *a = icalproperty_get_attach( attach );
1297  if ( !icalattach_get_is_url( a ) ) {
1298  p = (const char *)icalattach_get_data( a );
1299  if ( p ) {
1300  attachment = new Attachment( p );
1301  }
1302  } else {
1303  p = icalattach_get_url( a );
1304  if ( p ) {
1305  attachment = new Attachment( TQString::fromUtf8( p ) );
1306  }
1307  }
1308  break;
1309  }
1310  case ICAL_BINARY_VALUE:
1311  {
1312  icalattach *a = icalproperty_get_attach( attach );
1313  p = (const char *)icalattach_get_data( a );
1314  if ( p ) {
1315  attachment = new Attachment( p );
1316  }
1317  break;
1318  }
1319  case ICAL_URI_VALUE:
1320  p = icalvalue_get_uri( value );
1321  attachment = new Attachment( TQString::fromUtf8( p ) );
1322  break;
1323  default:
1324  break;
1325  }
1326 
1327  if ( attachment ) {
1328  icalparameter *p =
1329  icalproperty_get_first_parameter( attach, ICAL_FMTTYPE_PARAMETER );
1330  if ( p ) {
1331  attachment->setMimeType( TQString( icalparameter_get_fmttype( p ) ) );
1332  }
1333 
1334  p = icalproperty_get_first_parameter( attach, ICAL_X_PARAMETER );
1335  while ( p ) {
1336  TQString xname = TQString( icalparameter_get_xname( p ) ).upper();
1337  TQString xvalue = TQString::fromUtf8( icalparameter_get_xvalue( p ) );
1338  if ( xname == "X-CONTENT-DISPOSITION" ) {
1339  attachment->setShowInline( xvalue.lower() == "inline" );
1340  }
1341  if ( xname == "X-LABEL" ) {
1342  attachment->setLabel( xvalue );
1343  }
1344  p = icalproperty_get_next_parameter( attach, ICAL_X_PARAMETER );
1345  }
1346 
1347  p = icalproperty_get_first_parameter( attach, ICAL_X_PARAMETER );
1348  while ( p ) {
1349  if ( strncmp( icalparameter_get_xname( p ), "X-LABEL", 7 ) == 0 ) {
1350  attachment->setLabel( TQString::fromUtf8( icalparameter_get_xvalue( p ) ) );
1351  }
1352  p = icalproperty_get_next_parameter( attach, ICAL_X_PARAMETER );
1353  }
1354  }
1355 
1356  return attachment;
1357 }
1358 
1359 void ICalFormatImpl::readIncidence(icalcomponent *parent, icaltimezone *tz, Incidence *incidence)
1360 {
1361  readIncidenceBase(parent,incidence);
1362 
1363  icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
1364 
1365  const char *text;
1366  int intvalue, inttext;
1367  icaltimetype icaltime;
1368  icaldurationtype icalduration;
1369 
1370  TQStringList categories;
1371 
1372  while (p) {
1373  icalproperty_kind kind = icalproperty_isa(p);
1374  switch (kind) {
1375 
1376  case ICAL_CREATED_PROPERTY:
1377  icaltime = icalproperty_get_created(p);
1378  incidence->setCreated(readICalDateTime(p, icaltime, tz));
1379  break;
1380 
1381  case ICAL_SEQUENCE_PROPERTY: // sequence
1382  intvalue = icalproperty_get_sequence(p);
1383  incidence->setRevision(intvalue);
1384  break;
1385 
1386  case ICAL_LASTMODIFIED_PROPERTY: // last modification date
1387  icaltime = icalproperty_get_lastmodified(p);
1388  incidence->setLastModified(readICalDateTime(p, icaltime, tz));
1389  break;
1390 
1391  case ICAL_DTSTART_PROPERTY: // start date and time
1392  icaltime = icalproperty_get_dtstart(p);
1393  if (icaltime.is_date) {
1394  incidence->setDtStart(TQDateTime(readICalDate(icaltime),TQTime(0,0,0)));
1395  incidence->setFloats( true );
1396  } else {
1397  incidence->setDtStart(readICalDateTime(p, icaltime, tz));
1398  incidence->setFloats( false );
1399  }
1400  break;
1401 
1402  case ICAL_DURATION_PROPERTY: // start date and time
1403  icalduration = icalproperty_get_duration(p);
1404  incidence->setDuration(readICalDuration(icalduration));
1405  break;
1406 
1407  case ICAL_DESCRIPTION_PROPERTY: // description
1408  text = icalproperty_get_description(p);
1409  incidence->setDescription(TQString::fromUtf8(text));
1410  break;
1411 
1412  case ICAL_SUMMARY_PROPERTY: // summary
1413  text = icalproperty_get_summary(p);
1414  incidence->setSummary(TQString::fromUtf8(text));
1415  break;
1416 
1417  case ICAL_LOCATION_PROPERTY: // location
1418  text = icalproperty_get_location(p);
1419  incidence->setLocation(TQString::fromUtf8(text));
1420  break;
1421 
1422  case ICAL_STATUS_PROPERTY: { // status
1423  Incidence::Status stat;
1424  switch (icalproperty_get_status(p)) {
1425  case ICAL_STATUS_TENTATIVE: stat = Incidence::StatusTentative; break;
1426  case ICAL_STATUS_CONFIRMED: stat = Incidence::StatusConfirmed; break;
1427  case ICAL_STATUS_COMPLETED: stat = Incidence::StatusCompleted; break;
1428  case ICAL_STATUS_NEEDSACTION: stat = Incidence::StatusNeedsAction; break;
1429  case ICAL_STATUS_CANCELLED: stat = Incidence::StatusCanceled; break;
1430  case ICAL_STATUS_INPROCESS: stat = Incidence::StatusInProcess; break;
1431  case ICAL_STATUS_DRAFT: stat = Incidence::StatusDraft; break;
1432  case ICAL_STATUS_FINAL: stat = Incidence::StatusFinal; break;
1433  case ICAL_STATUS_X:
1434  incidence->setCustomStatus(TQString::fromUtf8(icalvalue_get_x(icalproperty_get_value(p))));
1435  stat = Incidence::StatusX;
1436  break;
1437  case ICAL_STATUS_NONE:
1438  default: stat = Incidence::StatusNone; break;
1439  }
1440  if (stat != Incidence::StatusX)
1441  incidence->setStatus(stat);
1442  break;
1443  }
1444 
1445  case ICAL_PRIORITY_PROPERTY: // priority
1446  intvalue = icalproperty_get_priority( p );
1447  if ( mCompat )
1448  intvalue = mCompat->fixPriority( intvalue );
1449  incidence->setPriority( intvalue );
1450  break;
1451 
1452  case ICAL_CATEGORIES_PROPERTY: // categories
1453  text = icalproperty_get_categories(p);
1454  categories.append(TQString::fromUtf8(text));
1455  break;
1456 
1457  case ICAL_RECURRENCEID_PROPERTY: // recurrenceID
1458  icaltime = icalproperty_get_recurrenceid(p);
1459  incidence->setRecurrenceID( readICalDateTime( p, icaltime ) );
1460  incidence->setHasRecurrenceID( true );
1461  break;
1462 
1463  case ICAL_RRULE_PROPERTY:
1464  readRecurrenceRule( p, incidence );
1465  break;
1466 
1467 // case ICAL_CONTACT_PROPERTY:
1468 // incidenceBase->addContact(
1469 // TQString::fromUtf8( icalproperty_get_contact( p ) ) );
1470 // break;
1471 
1472  case ICAL_RDATE_PROPERTY: {
1473  icaldatetimeperiodtype rd = icalproperty_get_rdate( p );
1474  if ( icaltime_is_valid_time( rd.time ) ) {
1475  if ( icaltime_is_date( rd.time ) ) {
1476  incidence->recurrence()->addRDate( readICalDate( rd.time ) );
1477  } else {
1478  incidence->recurrence()->addRDateTime( readICalDateTime(p, rd.time, tz ) );
1479  }
1480  } else {
1481  // TODO: RDates as period are not yet implemented!
1482  }
1483  break; }
1484 
1485  case ICAL_EXRULE_PROPERTY:
1486  readExceptionRule( p, incidence );
1487  break;
1488 
1489  case ICAL_EXDATE_PROPERTY:
1490  icaltime = icalproperty_get_exdate(p);
1491  if ( icaltime_is_date(icaltime) ) {
1492  incidence->recurrence()->addExDate( readICalDate(icaltime) );
1493  } else {
1494  incidence->recurrence()->addExDateTime( readICalDateTime(p, icaltime, tz) );
1495  }
1496  break;
1497 
1498  case ICAL_CLASS_PROPERTY:
1499  inttext = icalproperty_get_class(p);
1500  if (inttext == ICAL_CLASS_PUBLIC ) {
1501  incidence->setSecrecy(Incidence::SecrecyPublic);
1502  } else if (inttext == ICAL_CLASS_CONFIDENTIAL ) {
1503  incidence->setSecrecy(Incidence::SecrecyConfidential);
1504  } else {
1505  incidence->setSecrecy(Incidence::SecrecyPrivate);
1506  }
1507  break;
1508 
1509  case ICAL_ATTACH_PROPERTY: // attachments
1510  incidence->addAttachment(readAttachment(p));
1511  break;
1512 
1513  default:
1514 // kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind
1515 // << endl;
1516  break;
1517  }
1518 
1519  p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY);
1520  }
1521 
1522  // Set the scheduling ID
1523  const TQString uid = incidence->customProperty( "LIBKCAL", "ID" );
1524  if ( !uid.isNull() ) {
1525  // The UID stored in incidencebase is actually the scheduling ID
1526  // It has to be stored in the iCal UID component for compatibility
1527  // with other iCal applications
1528  incidence->setSchedulingID( incidence->uid() );
1529  incidence->setUid( uid );
1530  }
1531 
1532  // Now that recurrence and exception stuff is completely set up,
1533  // do any backwards compatibility adjustments.
1534  if ( incidence->doesRecur() && mCompat )
1535  mCompat->fixRecurrence( incidence );
1536 
1537  // add categories
1538  incidence->setCategories(categories);
1539 
1540  // iterate through all alarms
1541  for (icalcomponent *alarm = icalcomponent_get_first_component(parent,ICAL_VALARM_COMPONENT);
1542  alarm;
1543  alarm = icalcomponent_get_next_component(parent,ICAL_VALARM_COMPONENT)) {
1544  readAlarm(alarm,incidence);
1545  }
1546  // Fix incorrect alarm settings by other applications (like outloook 9)
1547  if ( mCompat ) mCompat->fixAlarms( incidence );
1548 
1549 }
1550 
1551 void ICalFormatImpl::readIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase)
1552 {
1553  icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
1554 
1555  bool uidProcessed = false;
1556 
1557  while ( p ) {
1558  icalproperty_kind kind = icalproperty_isa( p );
1559  switch (kind) {
1560 
1561  case ICAL_UID_PROPERTY: // unique id
1562  uidProcessed = true;
1563  incidenceBase->setUid( TQString::fromUtf8(icalproperty_get_uid( p ) ) );
1564  break;
1565 
1566  case ICAL_ORGANIZER_PROPERTY: // organizer
1567  incidenceBase->setOrganizer( readOrganizer( p ) );
1568  break;
1569 
1570  case ICAL_ATTENDEE_PROPERTY: // attendee
1571  incidenceBase->addAttendee( readAttendee( p ) );
1572  break;
1573 
1574  case ICAL_COMMENT_PROPERTY:
1575  incidenceBase->addComment(
1576  TQString::fromUtf8( icalproperty_get_comment( p ) ) );
1577  break;
1578 
1579  default:
1580  break;
1581  }
1582 
1583  p = icalcomponent_get_next_property( parent, ICAL_ANY_PROPERTY );
1584  }
1585 
1586  if ( !uidProcessed ) {
1587  kdWarning() << "The incidence didn't have any UID! Report a bug "
1588  << "to the application that generated this file."
1589  << endl;
1590 
1591  // Our in-memory incidence has a random uid generated in Event's ctor.
1592  // Make it empty so it matches what's in the file:
1593  incidenceBase->setUid( TQString() );
1594 
1595  // Otherwise, next time we read the file, this function will return
1596  // an event with another random uid and we will have two events in the calendar.
1597  }
1598 
1599  // kpilot stuff
1600  // TODO: move this application-specific code to kpilot
1601  // need to get X-PILOT* attributes out, set correct properties, and get
1602  // rid of them...
1603  // Pointer fun, as per libical documentation
1604  // (documented in UsingLibical.txt)
1605  icalproperty *next =0;
1606 
1607  for ( p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY);
1608  p != 0;
1609  p = next )
1610  {
1611 
1612  next = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY);
1613 
1614  TQString value = TQString::fromUtf8(icalproperty_get_x(p));
1615  TQString name = icalproperty_get_x_name(p);
1616 
1617  if (name == "X-PILOTID" && !value.isEmpty()) {
1618  incidenceBase->setPilotId(value.toInt());
1619  icalcomponent_remove_property(parent,p);
1620  } else if (name == "X-PILOTSTAT" && !value.isEmpty()) {
1621  incidenceBase->setSyncStatus(value.toInt());
1622  icalcomponent_remove_property(parent,p);
1623  }
1624  }
1625 
1626  // custom properties
1627  readCustomProperties(parent, incidenceBase);
1628 }
1629 
1630 void ICalFormatImpl::readCustomProperties(icalcomponent *parent,CustomProperties *properties)
1631 {
1632  TQMap<TQCString, TQString> customProperties;
1633  TQString lastProperty;
1634 
1635  icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY);
1636 
1637  while (p) {
1638 
1639  TQString value = TQString::fromUtf8(icalproperty_get_x(p));
1640  const char *name = icalproperty_get_x_name(p);
1641  if ( lastProperty != name ) {
1642  customProperties[name] = value;
1643  } else {
1644  customProperties[name] = customProperties[name].append( "," ).append( value );
1645  }
1646  // kdDebug(5800) << "Set custom property [" << name << '=' << value << ']' << endl;
1647  p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY);
1648  lastProperty = name;
1649  }
1650 
1651  properties->setCustomProperties(customProperties);
1652 }
1653 
1654 
1655 
1656 void ICalFormatImpl::readRecurrenceRule(icalproperty *rrule,Incidence *incidence )
1657 {
1658 // kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl;
1659 
1660  Recurrence *recur = incidence->recurrence();
1661 
1662  struct icalrecurrencetype r = icalproperty_get_rrule(rrule);
1663 // dumpIcalRecurrence(r);
1664 
1665  RecurrenceRule *recurrule = new RecurrenceRule( /*incidence*/ );
1666  recurrule->setStartDt( incidence->dtStart() );
1667  readRecurrence( r, recurrule );
1668  recur->addRRule( recurrule );
1669 }
1670 
1671 void ICalFormatImpl::readExceptionRule( icalproperty *rrule, Incidence *incidence )
1672 {
1673 // kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl;
1674 
1675  struct icalrecurrencetype r = icalproperty_get_exrule(rrule);
1676 // dumpIcalRecurrence(r);
1677 
1678  RecurrenceRule *recurrule = new RecurrenceRule( /*incidence*/ );
1679  recurrule->setStartDt( incidence->dtStart() );
1680  readRecurrence( r, recurrule );
1681 
1682  Recurrence *recur = incidence->recurrence();
1683  recur->addExRule( recurrule );
1684 }
1685 
1686 void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, RecurrenceRule* recur )
1687 {
1688  // Generate the RRULE string
1689  recur->mRRule = TQString( icalrecurrencetype_as_string( const_cast<struct icalrecurrencetype*>(&r) ) );
1690  // Period
1691  switch ( r.freq ) {
1692  case ICAL_SECONDLY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rSecondly ); break;
1693  case ICAL_MINUTELY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rMinutely ); break;
1694  case ICAL_HOURLY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rHourly ); break;
1695  case ICAL_DAILY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rDaily ); break;
1696  case ICAL_WEEKLY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rWeekly ); break;
1697  case ICAL_MONTHLY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rMonthly ); break;
1698  case ICAL_YEARLY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rYearly ); break;
1699  case ICAL_NO_RECURRENCE:
1700  default:
1701  recur->setRecurrenceType( RecurrenceRule::rNone );
1702  }
1703  // Frequency
1704  recur->setFrequency( r.interval );
1705 
1706  // Duration & End Date
1707  if ( !icaltime_is_null_time( r.until ) ) {
1708  icaltimetype t;
1709  t = r.until;
1710  // Convert to the correct time zone! it's in UTC by specification.
1711  TQDateTime endDate( readICalDateTime(0, t) );
1712  recur->setEndDt( endDate );
1713  } else {
1714  if (r.count == 0)
1715  recur->setDuration( -1 );
1716  else
1717  recur->setDuration( r.count );
1718  }
1719 
1720  // Week start setting
1721  int wkst = (r.week_start + 5)%7 + 1;
1722  recur->setWeekStart( wkst );
1723 
1724  // And now all BY*
1725  TQValueList<int> lst;
1726  int i;
1727  int index = 0;
1728 
1729 #define readSetByList(rrulecomp,setfunc) \
1730  index = 0; \
1731  lst.clear(); \
1732  while ( (i = r.rrulecomp[index++] ) != ICAL_RECURRENCE_ARRAY_MAX ) \
1733  lst.append( i ); \
1734  if ( !lst.isEmpty() ) recur->setfunc( lst );
1735 
1736  // BYSECOND, MINUTE and HOUR, MONTHDAY, YEARDAY, WEEKNUMBER, MONTH
1737  // and SETPOS are standard int lists, so we can treat them with the
1738  // same macro
1739  readSetByList( by_second, setBySeconds );
1740  readSetByList( by_minute, setByMinutes );
1741  readSetByList( by_hour, setByHours );
1742  readSetByList( by_month_day, setByMonthDays );
1743  readSetByList( by_year_day, setByYearDays );
1744  readSetByList( by_week_no, setByWeekNumbers );
1745  readSetByList( by_month, setByMonths );
1746  readSetByList( by_set_pos, setBySetPos );
1747 #undef readSetByList
1748 
1749  // BYDAY is a special case, since it's not an int list
1750  TQValueList<RecurrenceRule::WDayPos> wdlst;
1751  short day;
1752  index=0;
1753  while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1755  pos.setDay( ( icalrecurrencetype_day_day_of_week( day ) + 5 )%7 + 1 );
1756  pos.setPos( icalrecurrencetype_day_position( day ) );
1757 // kdDebug(5800)<< " o) By day, index="<<index-1<<", pos="<<pos.Pos<<", day="<<pos.Day<<endl;
1758  wdlst.append( pos );
1759  }
1760  if ( !wdlst.isEmpty() ) recur->setByDays( wdlst );
1761 
1762 
1763  // TODO Store all X- fields of the RRULE inside the recurrence (so they are
1764  // preserved
1765 }
1766 
1767 
1768 void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence)
1769 {
1770 // kdDebug(5800) << "Read alarm for " << incidence->summary() << endl;
1771 
1772  Alarm* ialarm = incidence->newAlarm();
1773  ialarm->setRepeatCount(0);
1774  ialarm->setEnabled(true);
1775 
1776  // Determine the alarm's action type
1777  icalproperty *p = icalcomponent_get_first_property(alarm,ICAL_ACTION_PROPERTY);
1778  Alarm::Type type = Alarm::Display;
1779  icalproperty_action action = ICAL_ACTION_DISPLAY;
1780  if ( !p ) {
1781  kdDebug(5800) << "Unknown type of alarm, using default" << endl;
1782 // return;
1783  } else {
1784 
1785  action = icalproperty_get_action(p);
1786  switch ( action ) {
1787  case ICAL_ACTION_DISPLAY: type = Alarm::Display; break;
1788  case ICAL_ACTION_AUDIO: type = Alarm::Audio; break;
1789  case ICAL_ACTION_PROCEDURE: type = Alarm::Procedure; break;
1790  case ICAL_ACTION_EMAIL: type = Alarm::Email; break;
1791  default:
1792  kdDebug(5800) << "Unknown type of alarm: " << action << endl;
1793 // type = Alarm::Invalid;
1794  }
1795  }
1796  ialarm->setType(type);
1797 // kdDebug(5800) << " alarm type =" << type << endl;
1798 
1799  p = icalcomponent_get_first_property(alarm,ICAL_ANY_PROPERTY);
1800  while (p) {
1801  icalproperty_kind kind = icalproperty_isa(p);
1802 
1803  switch (kind) {
1804 
1805  case ICAL_TRIGGER_PROPERTY: {
1806  icaltriggertype trigger = icalproperty_get_trigger(p);
1807  if (icaltime_is_null_time(trigger.time)) {
1808  if (icaldurationtype_is_null_duration(trigger.duration)) {
1809  kdDebug(5800) << "ICalFormatImpl::readAlarm(): Trigger has no time and no duration." << endl;
1810  } else {
1811  Duration duration = icaldurationtype_as_int( trigger.duration );
1812  icalparameter *param = icalproperty_get_first_parameter(p,ICAL_RELATED_PARAMETER);
1813  if (param && icalparameter_get_related(param) == ICAL_RELATED_END)
1814  ialarm->setEndOffset(duration);
1815  else
1816  ialarm->setStartOffset(duration);
1817  }
1818  } else {
1819  ialarm->setTime(readICalDateTime(p, trigger.time));
1820  }
1821  break;
1822  }
1823  case ICAL_DURATION_PROPERTY: {
1824  icaldurationtype duration = icalproperty_get_duration(p);
1825  ialarm->setSnoozeTime( readICalDuration( duration ) );
1826  break;
1827  }
1828  case ICAL_REPEAT_PROPERTY:
1829  ialarm->setRepeatCount(icalproperty_get_repeat(p));
1830  break;
1831 
1832  // Only in DISPLAY and EMAIL and PROCEDURE alarms
1833  case ICAL_DESCRIPTION_PROPERTY: {
1834  TQString description = TQString::fromUtf8(icalproperty_get_description(p));
1835  switch ( action ) {
1836  case ICAL_ACTION_DISPLAY:
1837  ialarm->setText( description );
1838  break;
1839  case ICAL_ACTION_PROCEDURE:
1840  ialarm->setProgramArguments( description );
1841  break;
1842  case ICAL_ACTION_EMAIL:
1843  ialarm->setMailText( description );
1844  break;
1845  default:
1846  break;
1847  }
1848  break;
1849  }
1850  // Only in EMAIL alarm
1851  case ICAL_SUMMARY_PROPERTY:
1852  ialarm->setMailSubject(TQString::fromUtf8(icalproperty_get_summary(p)));
1853  break;
1854 
1855  // Only in EMAIL alarm
1856  case ICAL_ATTENDEE_PROPERTY: {
1857  TQString email = TQString::fromUtf8(icalproperty_get_attendee(p));
1858  if ( email.startsWith("mailto:", false ) ) {
1859  email = email.mid( 7 );
1860  }
1861  TQString name;
1862  icalparameter *param = icalproperty_get_first_parameter(p,ICAL_CN_PARAMETER);
1863  if (param) {
1864  name = TQString::fromUtf8(icalparameter_get_cn(param));
1865  }
1866  ialarm->addMailAddress(Person(name, email));
1867  break;
1868  }
1869  // Only in AUDIO and EMAIL and PROCEDURE alarms
1870  case ICAL_ATTACH_PROPERTY: {
1871  Attachment *attach = readAttachment( p );
1872  if ( attach && attach->isUri() ) {
1873  switch ( action ) {
1874  case ICAL_ACTION_AUDIO:
1875  ialarm->setAudioFile( attach->uri() );
1876  break;
1877  case ICAL_ACTION_PROCEDURE:
1878  ialarm->setProgramFile( attach->uri() );
1879  break;
1880  case ICAL_ACTION_EMAIL:
1881  ialarm->addMailAttachment( attach->uri() );
1882  break;
1883  default:
1884  break;
1885  }
1886  } else {
1887  kdDebug() << "Alarm attachments currently only support URIs, but "
1888  "no binary data" << endl;
1889  }
1890  delete attach;
1891  break;
1892  }
1893  default:
1894  break;
1895  }
1896 
1897  p = icalcomponent_get_next_property(alarm,ICAL_ANY_PROPERTY);
1898  }
1899 
1900  // custom properties
1901  readCustomProperties(alarm, ialarm);
1902 
1903  // TODO: check for consistency of alarm properties
1904 }
1905 
1906 icaldatetimeperiodtype ICalFormatImpl::writeICalDatePeriod( const TQDate &date )
1907 {
1908  icaldatetimeperiodtype t;
1909  t.time = writeICalDate( date );
1910  t.period = icalperiodtype_null_period();
1911  return t;
1912 }
1913 
1914 icaldatetimeperiodtype ICalFormatImpl::writeICalDateTimePeriod( const TQDateTime &date )
1915 {
1916  icaldatetimeperiodtype t;
1917  t.time = writeICalDateTime( date );
1918  t.period = icalperiodtype_null_period();
1919  return t;
1920 }
1921 
1922 icaltimetype ICalFormatImpl::writeICalDate(const TQDate &date)
1923 {
1924  icaltimetype t = icaltime_null_time();
1925 
1926  t.year = date.year();
1927  t.month = date.month();
1928  t.day = date.day();
1929 
1930  t.hour = 0;
1931  t.minute = 0;
1932  t.second = 0;
1933 
1934  t.is_date = 1;
1935 #ifndef USE_LIBICAL_3_0
1936  t.is_utc = 0;
1937 #endif
1938  t.zone = 0;
1939 
1940  return t;
1941 }
1942 
1943 icaltimetype ICalFormatImpl::writeICalDateTime(const TQDateTime &datetime)
1944 {
1945  icaltimetype t = icaltime_null_time();
1946 
1947  t.year = datetime.date().year();
1948  t.month = datetime.date().month();
1949  t.day = datetime.date().day();
1950 
1951  t.hour = datetime.time().hour();
1952  t.minute = datetime.time().minute();
1953  t.second = datetime.time().second();
1954 
1955  t.is_date = 0;
1956  t.zone = icaltimezone_get_builtin_timezone ( mParent->timeZoneId().latin1() );
1957 #ifndef USE_LIBICAL_3_0
1958  t.is_utc = 0;
1959 #endif
1960 
1961  // _dumpIcaltime( t );
1962  /* The TQDateTime we get passed in is to be considered in the timezone of
1963  * the current calendar (mParent's), or, if there is none, to be floating.
1964  * In the later case store a floating time, in the former normalize to utc. */
1965  if (mParent->timeZoneId().isEmpty())
1966  t = icaltime_convert_to_zone( t, 0 ); //make floating timezone
1967  else {
1968  icaltimezone* tz = icaltimezone_get_builtin_timezone ( mParent->timeZoneId().latin1() );
1969  icaltimezone* utc = icaltimezone_get_utc_timezone();
1970  if ( tz != utc ) {
1971  t.zone = tz;
1972  t = icaltime_convert_to_zone( t, utc );
1973  } else {
1974 #ifndef USE_LIBICAL_3_0
1975  t.is_utc = 1;
1976 #endif
1977  t.zone = utc;
1978  }
1979  }
1980 // _dumpIcaltime( t );
1981 
1982  return t;
1983 }
1984 
1985 TQDateTime ICalFormatImpl::readICalDateTime( icalproperty *p, icaltimetype& t, icaltimezone* tz )
1986 {
1987 // kdDebug(5800) << "ICalFormatImpl::readICalDateTime()" << endl;
1988 #ifdef USE_LIBICAL_3_0
1989  bool time_is_utc = icaltime_is_utc(t);
1990 #else
1991  bool time_is_utc = t.is_utc;
1992 #endif
1993  if ( !time_is_utc ) { // Only use the TZ if time is not UTC.{
1994  // FIXME: We'll need to make sure to apply the appropriate TZ, not just
1995  // the first one found.
1996  icalparameter *param = p ? icalproperty_get_first_parameter(p, ICAL_TZID_PARAMETER) : 0;
1997  const char *tzid = param ? icalparameter_get_tzid(param) : 0;
1998  if ( tzid ) {
1999  icaltimezone* icaltz;
2000  // Try to match the ID with the libical time zone's location property
2001  icaltz = icaltimezone_get_builtin_timezone( tzid );
2002  if ( icaltz ) {
2003  //kdDebug(5800) << "ICalFormatImpl::readICalDateTime(): time zone '" << tzid << "' read from libical database" << endl;
2004  }
2005  t.zone = icaltz;
2006  }
2007  else {
2008  if (tz && tz != icaltimezone_get_utc_timezone()) {
2009 #ifndef USE_LIBICAL_3_0
2010  t.is_utc = 0;
2011 #endif
2012  t.zone = tz;
2013  }
2014  else {
2015 #ifndef USE_LIBICAL_3_0
2016  t.is_utc = 1;
2017 #endif
2018  t.zone = icaltimezone_get_utc_timezone();
2019  }
2020  }
2021  } else {
2022  t.zone = icaltimezone_get_utc_timezone();
2023  }
2024  //_dumpIcaltime( t );
2025 
2026  // Convert to view time
2027  if ( !mParent->timeZoneId().isEmpty() && t.zone ) {
2028 // kdDebug(5800) << "--- Converting time from: " << icaltimezone_get_tzid( const_cast<icaltimezone*>( t.zone ) ) << " (" << ICalDate2TQDate(t) << ")." << endl;
2029  icaltimezone* viewTimeZone = icaltimezone_get_builtin_timezone ( mParent->timeZoneId().latin1() );
2030  icaltimezone_convert_time( &t, const_cast<icaltimezone*>(t.zone), viewTimeZone );
2031 // kdDebug(5800) << "--- Converted to zone " << mParent->timeZoneId() << " (" << ICalDate2TQDate(t) << ")." << endl;
2032  }
2033 
2034  return ICalDate2TQDate(t);
2035 }
2036 
2037 TQDate ICalFormatImpl::readICalDate(icaltimetype t)
2038 {
2039  return ICalDate2TQDate(t).date();
2040 }
2041 
2042 icaldurationtype ICalFormatImpl::writeICalDuration(int seconds)
2043 {
2044  // should be able to use icaldurationtype_from_int(), except we know
2045  // that some older tools do not properly support weeks. So we never
2046  // set a week duration, only days
2047 
2048  icaldurationtype d;
2049 
2050  d.is_neg = (seconds<0)?1:0;
2051  if (seconds<0) seconds = -seconds;
2052 
2053  d.weeks = 0;
2054  d.days = seconds / gSecondsPerDay;
2055  seconds %= gSecondsPerDay;
2056  d.hours = seconds / gSecondsPerHour;
2057  seconds %= gSecondsPerHour;
2058  d.minutes = seconds / gSecondsPerMinute;
2059  seconds %= gSecondsPerMinute;
2060  d.seconds = seconds;
2061 
2062  return d;
2063 }
2064 
2065 int ICalFormatImpl::readICalDuration(icaldurationtype d)
2066 {
2067  int result = 0;
2068 
2069  result += d.weeks * gSecondsPerWeek;
2070  result += d.days * gSecondsPerDay;
2071  result += d.hours * gSecondsPerHour;
2072  result += d.minutes * gSecondsPerMinute;
2073  result += d.seconds;
2074 
2075  if (d.is_neg) result *= -1;
2076 
2077  return result;
2078 }
2079 
2080 icalcomponent *ICalFormatImpl::createCalendarComponent(Calendar *cal)
2081 {
2082  icalcomponent *calendar;
2083 
2084  // Root component
2085  calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
2086 
2087  icalproperty *p;
2088 
2089  // Product Identifier
2090  p = icalproperty_new_prodid(CalFormat::productId().utf8());
2091  icalcomponent_add_property(calendar,p);
2092 
2093  // TODO: Add time zone
2094 
2095  // iCalendar version (2.0)
2096  p = icalproperty_new_version(const_cast<char *>(_ICAL_VERSION));
2097  icalcomponent_add_property(calendar,p);
2098 
2099  // Custom properties
2100  if( cal != 0 )
2101  writeCustomProperties(calendar, cal);
2102 
2103  return calendar;
2104 }
2105 
2106 
2107 
2108 // take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc.
2109 // and break it down from its tree-like format into the dictionary format
2110 // that is used internally in the ICalFormatImpl.
2111 bool ICalFormatImpl::populate( Calendar *cal, icalcomponent *calendar )
2112 {
2113  // this function will populate the caldict dictionary and other event
2114  // lists. It turns vevents into Events and then inserts them.
2115 
2116  if (!calendar) return false;
2117 
2118 // TODO: check for METHOD
2119 
2120  icalproperty *p;
2121 
2122  p = icalcomponent_get_first_property(calendar,ICAL_PRODID_PROPERTY);
2123  if (!p) {
2124  kdDebug(5800) << "No PRODID property found" << endl;
2125  mLoadedProductId = "";
2126  } else {
2127  mLoadedProductId = TQString::fromUtf8(icalproperty_get_prodid(p));
2128 // kdDebug(5800) << "VCALENDAR prodid: '" << mLoadedProductId << "'" << endl;
2129 
2130  delete mCompat;
2131  mCompat = CompatFactory::createCompat( mLoadedProductId );
2132  }
2133 
2134  p = icalcomponent_get_first_property(calendar,ICAL_VERSION_PROPERTY);
2135  if (!p) {
2136  kdDebug(5800) << "No VERSION property found" << endl;
2137  mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
2138  return false;
2139  } else {
2140  const char *version = icalproperty_get_version(p);
2141  if ( !version ) {
2142  kdDebug(5800) << "No VERSION property found" << endl;
2143  mParent->setException( new ErrorFormat(
2145  i18n( "No VERSION property found" ) ) );
2146  return false;
2147  }
2148 
2149 // kdDebug(5800) << "VCALENDAR version: '" << version << "'" << endl;
2150 
2151  if (strcmp(version,"1.0") == 0) {
2152  kdDebug(5800) << "Expected iCalendar, got vCalendar" << endl;
2153  mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1,
2154  i18n("Expected iCalendar format")));
2155  return false;
2156  } else if (strcmp(version,"2.0") != 0) {
2157  kdDebug(5800) << "Expected iCalendar, got unknown format" << endl;
2158  mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
2159  return false;
2160  }
2161  }
2162 
2163  // custom properties
2164  readCustomProperties(calendar, cal);
2165 
2166 // TODO: set time zone
2167 
2168  // read a VTIMEZONE if there is one
2169  icalcomponent *ctz =
2170  icalcomponent_get_first_component( calendar, ICAL_VTIMEZONE_COMPONENT );
2171 
2172  // Store all events with a relatedTo property in a list for post-processing
2173  mEventsRelate.clear();
2174  mTodosRelate.clear();
2175  // TODO: make sure that only actually added events go to this lists.
2176 
2177  icalcomponent *c;
2178 
2179  // Iterate through all todos
2180  c = icalcomponent_get_first_component(calendar,ICAL_VTODO_COMPONENT);
2181  while (c) {
2182 // kdDebug(5800) << "----Todo found" << endl;
2183  Todo *todo = readTodo(c);
2184  if (todo) {
2185  if (todo->hasRecurrenceID()) {
2186  TQString originalUid = todo->uid();
2187  todo->setUid(originalUid + TQString("-recur-%1").arg(todo->recurrenceID().toTime_t()));
2188  if (!cal->todo(todo->uid())) {
2189  if ( !cal->addTodo( todo ) ) {
2190  cal->endBatchAdding();
2191  // If the user pressed cancel, return true, it's not an error.
2192  return cal->exception() && cal->exception()->errorCode() == ErrorFormat::UserCancel;
2193  }
2194  if (!cal->event(originalUid)) {
2195  printf("FIXME! [WARNING] Parent for child event does not yet exist!\n");
2196  }
2197  else {
2198  // Add this todo to its parent
2199  cal->todo(originalUid)->addChildIncidence(todo->uid());
2200  // And the parent to the child
2201  todo->addChildIncidence(cal->todo(originalUid)->uid());
2202  }
2203  }
2204  }
2205  else {
2206  if (!cal->todo(todo->uid())) {
2207  if ( !cal->addTodo( todo ) ) {
2208  cal->endBatchAdding();
2209  // If the user pressed cancel, return true, it's not an error.
2210  return cal->exception() && cal->exception()->errorCode() == ErrorFormat::UserCancel;
2211  }
2212  } else {
2213  delete todo;
2214  mTodosRelate.remove( todo );
2215  }
2216  }
2217  }
2218  c = icalcomponent_get_next_component(calendar,ICAL_VTODO_COMPONENT);
2219  }
2220 
2221  // Iterate through all events
2222  c = icalcomponent_get_first_component(calendar,ICAL_VEVENT_COMPONENT);
2223  while (c) {
2224 // kdDebug(5800) << "----Event found" << endl;
2225  Event *event = readEvent(c, ctz);
2226  if (event) {
2227  if (event->hasRecurrenceID()) {
2228  TQString originalUid = event->uid();
2229  event->setUid(originalUid + TQString("-recur-%1").arg(event->recurrenceID().toTime_t()));
2230  if (!cal->event(event->uid())) {
2231  cal->addEvent(event);
2232  if (!cal->event(originalUid)) {
2233  printf("FIXME! [WARNING] Parent for child event does not yet exist!\n");
2234  }
2235  else {
2236  // Add this event to its parent
2237  cal->event(originalUid)->addChildIncidence(event->uid());
2238  // And the parent to the child
2239  event->addChildIncidence(cal->event(originalUid)->uid());
2240  }
2241  }
2242  }
2243  else {
2244  if (!cal->event(event->uid())) {
2245  if ( !cal->addEvent( event ) ) {
2246  cal->endBatchAdding();
2247  // If the user pressed cancel, return true, it's not an error.
2248  return cal->exception() && cal->exception()->errorCode() == ErrorFormat::UserCancel;
2249  }
2250  } else {
2251  delete event;
2252  mEventsRelate.remove( event );
2253  }
2254  }
2255  }
2256  c = icalcomponent_get_next_component(calendar,ICAL_VEVENT_COMPONENT);
2257  }
2258 
2259  // Iterate through all journals
2260  c = icalcomponent_get_first_component(calendar,ICAL_VJOURNAL_COMPONENT);
2261  while (c) {
2262 // kdDebug(5800) << "----Journal found" << endl;
2263  Journal *journal = readJournal(c);
2264  if (journal) {
2265  if (journal->hasRecurrenceID()) {
2266  TQString originalUid = journal->uid();
2267  journal->setUid(originalUid + TQString("-recur-%1").arg(journal->recurrenceID().toTime_t()));
2268  if (!cal->journal(journal->uid())) {
2269  cal->addJournal(journal);
2270  if (!cal->event(originalUid)) {
2271  printf("FIXME! [WARNING] Parent for child event does not yet exist!\n");
2272  }
2273  else {
2274  // Add this journal to its parent
2275  cal->journal(originalUid)->addChildIncidence(journal->uid());
2276  // And the parent to the child
2277  journal->addChildIncidence(cal->journal(originalUid)->uid());
2278  }
2279  }
2280  }
2281  else {
2282  if (!cal->journal(journal->uid())) {
2283  if ( !cal->addJournal(journal) ) {
2284  cal->endBatchAdding();
2285  // If the user pressed cancel, return true, it's not an error.
2286  return cal->exception() && cal->exception()->errorCode() == ErrorFormat::UserCancel;
2287  }
2288  } else {
2289  delete journal;
2290  }
2291  }
2292  }
2293  c = icalcomponent_get_next_component(calendar,ICAL_VJOURNAL_COMPONENT);
2294  }
2295 
2296  cal->endBatchAdding();
2297 
2298  // Post-Process list of events with relations, put Event objects in relation
2299  Event::List::ConstIterator eIt;
2300  for ( eIt = mEventsRelate.begin(); eIt != mEventsRelate.end(); ++eIt ) {
2301  (*eIt)->setRelatedTo( cal->incidence( (*eIt)->relatedToUid() ) );
2302  }
2303  Todo::List::ConstIterator tIt;
2304  for ( tIt = mTodosRelate.begin(); tIt != mTodosRelate.end(); ++tIt ) {
2305  (*tIt)->setRelatedTo( cal->incidence( (*tIt)->relatedToUid() ) );
2306  }
2307 
2308  return true;
2309 }
2310 
2311 TQString ICalFormatImpl::extractErrorProperty(icalcomponent *c)
2312 {
2313 // kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: "
2314 // << icalcomponent_as_ical_string(c) << endl;
2315 
2316  TQString errorMessage;
2317 
2318  icalproperty *error;
2319  error = icalcomponent_get_first_property(c,ICAL_XLICERROR_PROPERTY);
2320  while(error) {
2321  errorMessage += icalproperty_get_xlicerror(error);
2322  errorMessage += "\n";
2323  error = icalcomponent_get_next_property(c,ICAL_XLICERROR_PROPERTY);
2324  }
2325 
2326 // kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " << errorMessage << endl;
2327 
2328  return errorMessage;
2329 }
2330 
2331 void ICalFormatImpl::dumpIcalRecurrence(icalrecurrencetype r)
2332 {
2333  int i;
2334 
2335  kdDebug(5800) << " Freq: " << r.freq << endl;
2336  kdDebug(5800) << " Until: " << icaltime_as_ical_string(r.until) << endl;
2337  kdDebug(5800) << " Count: " << r.count << endl;
2338  if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2339  int index = 0;
2340  TQString out = " By Day: ";
2341  while((i = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2342  out.append(TQString::number(i) + " ");
2343  }
2344  kdDebug(5800) << out << endl;
2345  }
2346  if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2347  int index = 0;
2348  TQString out = " By Month Day: ";
2349  while((i = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2350  out.append(TQString::number(i) + " ");
2351  }
2352  kdDebug(5800) << out << endl;
2353  }
2354  if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2355  int index = 0;
2356  TQString out = " By Year Day: ";
2357  while((i = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2358  out.append(TQString::number(i) + " ");
2359  }
2360  kdDebug(5800) << out << endl;
2361  }
2362  if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2363  int index = 0;
2364  TQString out = " By Month: ";
2365  while((i = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2366  out.append(TQString::number(i) + " ");
2367  }
2368  kdDebug(5800) << out << endl;
2369  }
2370  if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2371  int index = 0;
2372  TQString out = " By Set Pos: ";
2373  while((i = r.by_set_pos[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2374  kdDebug(5800) << "========= " << i << endl;
2375  out.append(TQString::number(i) + " ");
2376  }
2377  kdDebug(5800) << out << endl;
2378  }
2379 }
2380 
2381 icalcomponent *ICalFormatImpl::createScheduleComponent(IncidenceBase *incidence,
2382  Scheduler::Method method)
2383 {
2384  icalcomponent *message = createCalendarComponent();
2385 
2386  icalproperty_method icalmethod = ICAL_METHOD_NONE;
2387 
2388  switch (method) {
2389  case Scheduler::Publish:
2390  icalmethod = ICAL_METHOD_PUBLISH;
2391  break;
2392  case Scheduler::Request:
2393  icalmethod = ICAL_METHOD_REQUEST;
2394  break;
2395  case Scheduler::Refresh:
2396  icalmethod = ICAL_METHOD_REFRESH;
2397  break;
2398  case Scheduler::Cancel:
2399  icalmethod = ICAL_METHOD_CANCEL;
2400  break;
2401  case Scheduler::Add:
2402  icalmethod = ICAL_METHOD_ADD;
2403  break;
2404  case Scheduler::Reply:
2405  icalmethod = ICAL_METHOD_REPLY;
2406  break;
2407  case Scheduler::Counter:
2408  icalmethod = ICAL_METHOD_COUNTER;
2409  break;
2410  case Scheduler::Declinecounter:
2411  icalmethod = ICAL_METHOD_DECLINECOUNTER;
2412  break;
2413  default:
2414  kdDebug(5800) << "ICalFormat::createScheduleMessage(): Unknow method" << endl;
2415  return message;
2416  }
2417 
2418  icalcomponent_add_property(message,icalproperty_new_method(icalmethod));
2419 
2420  icalcomponent *inc = writeIncidence( incidence, method );
2421  /*
2422  * RFC 2446 states in section 3.4.3 ( REPLY to a VTODO ), that
2423  * a REQUEST-STATUS property has to be present. For the other two, event and
2424  * free busy, it can be there, but is optional. Until we do more
2425  * fine grained handling, assume all is well. Note that this is the
2426  * status of the _request_, not the attendee. Just to avoid confusion.
2427  * - till
2428  */
2429  if ( icalmethod == ICAL_METHOD_REPLY ) {
2430  struct icalreqstattype rst;
2431  rst.code = ICAL_2_0_SUCCESS_STATUS;
2432  rst.desc = 0;
2433  rst.debug = 0;
2434  icalcomponent_add_property( inc, icalproperty_new_requeststatus( rst ) );
2435  }
2436  icalcomponent_add_component( message, inc );
2437 
2438  return message;
2439 }
void setFloats(bool f)
Set whether the incidence floats, i.e.
Definition: incidence.cpp:229
Duration endOffset() const
Return offset of alarm in time relative to the end of the event.
Definition: alarm.cpp:474
virtual Event * event(const TQString &uid)=0
Returns the Event associated with the given unique identifier.
virtual TQDateTime dtStart() const
returns an event&#39;s starting date/time as a TQDateTime.
virtual bool accept(Visitor &)
Accept IncidenceVisitor.
void setDelegate(const TQString &delegate)
Sets the delegate.
Definition: attendee.h:131
void setUid(const TQString &)
Set the unique id for the event.
Transparency transparency() const
Return the event&#39;s time transparency level.
Definition: event.cpp:145
virtual bool addJournal(Journal *journal)=0
Insert a Journal into the Calendar.
bool RSVP() const
Return, if Attendee is asked to reply.
Definition: attendee.h:126
TQString mailText() const
Return the email body text.
Definition: alarm.cpp:295
TQString audioFile() const
Return the name of the audio file for the alarm.
Definition: alarm.cpp:164
void setMailText(const TQString &text)
Set the email body text.
Definition: alarm.cpp:287
ErrorCodeFormat errorCode()
Return format error code.
Definition: exceptions.cpp:101
void addComment(const TQString &comment)
Add a comment to this incidence.
void setType(Type type)
Set the type of the alarm.
Definition: alarm.cpp:115
void setEnabled(bool enable)
Set the alarm enabled status.
Definition: alarm.cpp:432
const Alarm::List & alarms() const
All alarms that are associated with this incidence.
Definition: incidence.cpp:828
void setSecrecy(int)
Sets secrecy status.
Definition: incidence.cpp:786
This class represents custom calendar properties.
uint frequency() const
Returns frequency of recurrence, in terms of the recurrence time period type.
void setDtDue(const TQDateTime &dtDue, bool first=false)
Sets due date and time.
Definition: todo.cpp:85
void setDuration(int duration)
Sets the total number of times the event is to occur, including both the first and last...
TQStringList comments() const
Return all comments associated with this incidence.
TQValueList< Person > mailAddresses() const
Return the addresses to send mail to when an alarm goes off.
Definition: alarm.cpp:239
int revision() const
Return the number of revisions this event has seen.
Definition: incidence.cpp:259
TQString summary() const
Return short summary.
Definition: incidence.cpp:293
This class provides a Todo in the sense of RFC2445.
Definition: todo.h:31
This is the main "calendar" object class.
Definition: calendar.h:169
bool hasEndOffset() const
Return whether the alarm is defined in terms of an offset relative to the end of the event...
Definition: alarm.cpp:461
This class provides the base class common to all calendar components.
Definition: incidencebase.h:45
vCalendar v1.0 detected
Definition: exceptions.h:76
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 setFrequency(int freq)
Sets the frequency of recurrence, in terms of the recurrence time period type.
TQString description() const
Return long description.
Definition: incidence.cpp:280
int secrecy() const
Return the event&#39;s secrecy.
Definition: incidence.cpp:793
TQString text() const
Return the text string that displays when the alarm is triggered.
Definition: alarm.cpp:316
TQString delegate() const
Returns the delegate.
Definition: attendee.h:135
void setSummary(const TQString &summary)
Set short summary.
Definition: incidence.cpp:286
TQDateTime dtStart(bool first=false) const
Returns the startdate of the todo.
Definition: todo.cpp:177
TQStringList categories() const
Return categories as a list of strings.
Definition: incidence.cpp:323
void setRelatedToUid(const TQString &)
Point at some other event to which the event relates.
Definition: incidence.cpp:333
This class represents information related to an attendee of an event.
Definition: attendee.h:36
void setEndDt(const TQDateTime &endDateTime)
Sets the date and time of the last recurrence.
This class provides an Event in the sense of RFC2445.
Definition: event.h:32
void setCustomProperty(const TQCString &app, const TQCString &key, const TQString &value)
Create or modify a custom calendar property.
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
int attendeeCount() const
Return number of attendees.
TQString statusStr() const
Return the event&#39;s status string.
Definition: incidence.cpp:762
User canceled the operation.
Definition: exceptions.h:81
bool hasTime() const
Return true, if the alarm has an explicit date/time.
Definition: alarm.cpp:349
bool hasEndDate() const
Return whether the event has an end date/time.
Definition: event.cpp:121
void setMailSubject(const TQString &mailAlarmSubject)
Set the subject line of the mail.
Definition: alarm.cpp:244
Status
Enumeration for describing an event&#39;s status.
Definition: incidence.h:117
Unknown calendar format detected.
Definition: exceptions.h:78
void setStartOffset(const Duration &)
Set offset of alarm in time relative to the start of the event.
Definition: alarm.cpp:443
Type type() const
Return the type of the alarm.
Definition: alarm.cpp:144
void setEndOffset(const Duration &)
Set offset of alarm in time relative to the end of the event.
Definition: alarm.cpp:466
virtual bool addEvent(Event *event)=0
Insert an Event into the Calendar.
TQMap< TQCString, TQString > customProperties() const
Return all custom calendar property key/value pairs.
bool hasDueDate() const
Returns true if the todo has a due date, otherwise return false.
Definition: todo.cpp:144
Alarm * newAlarm()
Create a new alarm which is associated with this incidence.
Definition: incidence.cpp:833
This class provides the interface for a visitor of calendar components.
Definition: incidencebase.h:54
TQString uid() const
Return the unique id for the event.
void setProgramArguments(const TQString &arguments)
Set the arguments to the program to execute when the alarm is triggered.
Definition: alarm.cpp:190
void setRecurrenceID(const TQDateTime &recurrenceID)
Set the incidences recurrenceID.
Definition: incidence.cpp:913
void setHasRecurrenceID(bool hasRecurrenceID)
Sets if the incidence has recurrenceID.
Definition: incidence.cpp:898
TQString programArguments() const
Return the arguments to the program to run when the alarm is triggered.
Definition: alarm.cpp:198
int repeatCount() const
Get how many times an alarm repeats, after its initial occurrence.
Definition: alarm.cpp:373
TQDateTime created() const
Return time and date of creation.
Definition: incidence.cpp:246
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.
void setOrganizer(const Person &o)
sets the organizer for the event
Recurrence * recurrence() const
Return the recurrence rule associated with this incidence.
Definition: incidence.cpp:390
void setSnoozeTime(const Duration &alarmSnoozeTime)
Set the interval between snoozes for the alarm.
Definition: alarm.cpp:354
TQDateTime time() const
Return the date/time when an alarm goes off.
Definition: alarm.cpp:329
structure for describing the n-th weekday of the month/year.
unsigned long pilotId() const
Return Pilot Id.
void setPercentComplete(int)
Set how many percent of the task are completed.
Definition: todo.cpp:268
int asSeconds() const
Returns the length of the duration in seconds.
Definition: duration.cpp:165
void setCategories(const TQStringList &categories)
Set categories.
Definition: incidence.cpp:298
This class implements the iCalendar format.
Definition: icalformat.h:43
bool isCompleted() const
Returns true if the todo is 100% completed, otherwise return false.
Definition: todo.cpp:217
This class represents a person.
Definition: person.h:34
bool doesRecur() const
Forward to Recurrence::doesRecur().
Definition: incidence.cpp:416
void setCompleted(bool completed)
Set completed state.
Definition: todo.cpp:223
Provides the main "calendar" object class.
int value() const
Returns the length of the duration in seconds or days.
Definition: duration.cpp:175
void setStatus(Status status)
Sets the incidence status to a standard status value.
Definition: incidence.cpp:741
void addMailAddress(const Person &mailAlarmAddress)
Add this address to the list of addresses to send mail to when the alarm is triggered.
Definition: alarm.cpp:231
void setHasDueDate(bool hasDueDate)
Set if the todo has a due date.
Definition: todo.cpp:149
This class provides the base class common to all calendar components.
Definition: incidence.h:47
TQDateTime recurrenceID() const
Returns the incidence recurrenceID.
Definition: incidence.cpp:908
Duration snoozeTime() const
Get how long the alarm snooze interval is.
Definition: alarm.cpp:362
Status status() const
Return the event&#39;s status.
Definition: incidence.cpp:757
Incidence * incidence(const TQString &uid)
Returns the Incidence associated with the given unique identifier.
Definition: calendar.cpp:576
TQString customProperty(const TQCString &app, const TQCString &key) const
Return the value of a custom calendar property.
TQDateTime completed() const
Returns date and time when todo was completed.
Definition: todo.cpp:235
This class represents information related to an attachment.
Definition: attachment.h:34
This class provides a Journal in the sense of RFC2445.
Definition: journal.h:33
PartStat status() const
Return status.
Definition: attendee.cpp:61
TQString uid() const
Return unique id of the attendee.
Definition: attendee.cpp:137
static const TQString & productId()
Return the PRODID string to write into calendar files.
Definition: calformat.h:87
void endBatchAdding()
Emits the endBatchAdding() signal.
Definition: calendar.cpp:149
Calendar format related error class.
Definition: exceptions.h:64
This class represents a period of time.
Definition: period.h:35
TQString mailSubject() const
Return the subject line of the mail.
Definition: alarm.cpp:252
virtual void setDtStart(const TQDateTime &dtStart)
for setting the event&#39;s starting date/time with a TQDateTime.
void addPeriods(const PeriodList &)
Adds a list of periods to the freebusy object and then sorts that list.
Definition: freebusy.cpp:194
ErrorFormat * exception() const
Returns an exception, if there is any, containing information about the last error that occurred...
Definition: calendar.cpp:80
bool hasCompletedDate() const
Returns true, if todo has a date associated with completion, otherwise return false.
Definition: todo.cpp:258
void addAttachment(Attachment *attachment)
Add attachment.
Definition: incidence.cpp:674
void addMailAttachment(const TQString &mailAttachFile)
Add this filename to the list of files to attach to the email.
Definition: alarm.cpp:274
TQString schedulingID() const
Return the event&#39;s/todo&#39;s scheduling ID.
Definition: incidence.cpp:885
TQString delegator() const
Returns the delegator.
Definition: attendee.h:144
void setSchedulingID(const TQString &sid)
Set the event&#39;s/todo&#39;s scheduling ID.
Definition: incidence.cpp:880
Namespace KCal is for global classes, objects and/or functions in libkcal.
Definition: alarm.h:38
TQStringList mailAttachments() const
Return the filenames to attach to the email.
Definition: alarm.cpp:282
void setCreated(const TQDateTime &)
Set creation date.
Definition: incidence.cpp:237
void setDelegator(const TQString &delegator)
Sets the delegator.
Definition: attendee.h:140
void setTime(const TQDateTime &alarmTime)
Set the time to trigger an alarm.
Definition: alarm.cpp:321
virtual bool addTodo(Todo *todo)=0
Insert a Todo into the Calendar.
void addChildIncidence(TQString childIncidence)
Attach a child incidence to a parent incidence.
Definition: incidence.cpp:924
int duration() const
Returns -1 if the event recurs infinitely, 0 if the end date is set, otherwise the total number of re...
const Attendee::List & attendees() const
Return list of attendees.
void addAttendee(Attendee *attendee, bool doUpdate=true)
Add Attendee to this incidence.
This class represents a duration.
Definition: duration.h:33
Role role() const
Return role of Attendee.
Definition: attendee.cpp:122
void setRevision(int rev)
Set the number of revisions this event has seen.
Definition: incidence.cpp:251
void setLocation(const TQString &location)
Set the event&#39;s/todo&#39;s location.
Definition: incidence.cpp:868
TQDateTime endDt(bool *result=0) const
Returns the date and time of the last recurrence.
int priority() const
Return priority.
Definition: incidence.cpp:736
bool utc() const
Return true if timezone used is UTC, otherwise return false.
Definition: icalformat.cpp:622
void setRepeatCount(int alarmRepeatCount)
Set how many times an alarm is to repeat itself after its initial occurrence (w/snoozes).
Definition: alarm.cpp:367
TQDateTime lastModified() const
Return the time the incidence was last modified.
void setDescription(const TQString &description)
Set the long description.
Definition: incidence.cpp:273
TQString programFile() const
Return the name of the program file to execute when the alarm is triggered.
Definition: alarm.cpp:185
int syncStatus() const
Return synchronisation status.
Method
iTIP methods.
Definition: scheduler.h:103
TQDateTime dtDue(bool first=false) const
Returns due date and time.
Definition: todo.cpp:117
Attachment::List attachments() const
Return list of all associated attachments.
Definition: incidence.cpp:695
int percentComplete() const
Returns how many percent of the task are completed.
Definition: todo.cpp:263
void setSyncStatus(int status)
Set synchronisation satus.
void removeCustomProperty(const TQCString &app, const TQCString &key)
Delete a custom calendar property.
virtual Journal * journal(const TQString &uid)=0
Returns the Journal associated with the given unique identifier.
Duration startOffset() const
Return offset of alarm in time relative to the start of the event.
Definition: alarm.cpp:451
bool hasStartOffset() const
Return whether the alarm is defined in terms of an offset relative to the start of the event...
Definition: alarm.cpp:456
void setDtRecurrence(const TQDateTime &dt)
Sets the due date/time of the current occurrence if recurrent.
Definition: todo.cpp:279
TQString location() const
Return the event&#39;s/todo&#39;s location.
Definition: incidence.cpp:875
virtual TQDateTime dtEnd() const
Return end date and time.
Definition: event.cpp:85
void setPilotId(unsigned long id)
Set Pilot Id.
void setPriority(int priority)
Set the incidences priority.
Definition: incidence.cpp:729
bool doesFloat() const
Return true or false depending on whether the incidence "floats," i.e.
void setProgramFile(const TQString &programFile)
Set the program file to execute when the alarm is triggered.
Definition: alarm.cpp:177
void setAudioFile(const TQString &audioFile)
Set the file to play when the audio alarm is triggered.
Definition: alarm.cpp:156
void setHasStartDate(bool hasStartDate)
Set if the todo has a start date.
Definition: todo.cpp:162
void setCustomProperties(const TQMap< TQCString, TQString > &properties)
Initialise the alarm&#39;s custom calendar properties to the specified key/value pairs.
This class provides information about free/busy time of a calendar user.
Definition: freebusy.h:40
This class represents an alarm notification.
Definition: alarm.h:45
void setCustomStatus(const TQString &status)
Sets the incidence status to a non-standard status value.
Definition: incidence.cpp:749
IncidenceList childIncidences() const
Returns an EventList of all child incidences.
Definition: incidence.cpp:934
This class provides compatibility to older (broken) versions of KOrganizer.
Definition: compat.h:45
bool doesFloat() const
Returns whether the start date has no time associated.
This class represents a recurrence rule for a calendar incidence.
Definition: recurrence.h:89
void setStartDt(const TQDateTime &start)
Set start of recurrence, as a date and time.
virtual void setDtStart(const TQDateTime &dtStart)
Set starting date/time.
Definition: incidence.cpp:264
void setText(const TQString &text)
Set the text to be displayed when the alarm is triggered.
Definition: alarm.cpp:308
This class represents a recurrence rule for a calendar incidence.