libkcal

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