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