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(
2135  ErrorFormat::CalVersionUnknown,
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 }
Provides the main "calendar" object class.
This class represents an alarm notification.
Definition: alarm.h:46
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
TQString audioFile() const
Return the name of the audio file for the alarm.
Definition: alarm.cpp:164
Duration snoozeTime() const
Get how long the alarm snooze interval is.
Definition: alarm.cpp:362
void setMailSubject(const TQString &mailAlarmSubject)
Set the subject line of the mail.
Definition: alarm.cpp:244
TQString programFile() const
Return the name of the program file to execute when the alarm is triggered.
Definition: alarm.cpp:185
void addMailAttachment(const TQString &mailAttachFile)
Add this filename to the list of files to attach to the email.
Definition: alarm.cpp:274
void setRepeatCount(int alarmRepeatCount)
Set how many times an alarm is to repeat itself after its initial occurrence (w/snoozes).
Definition: alarm.cpp:367
TQString mailSubject() const
Return the subject line of the mail.
Definition: alarm.cpp:252
TQDateTime time() const
Return the date/time when an alarm goes off.
Definition: alarm.cpp:329
TQString text() const
Return the text string that displays when the alarm is triggered.
Definition: alarm.cpp:316
void setEnabled(bool enable)
Set the alarm enabled status.
Definition: alarm.cpp:432
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
Duration endOffset() const
Return offset of alarm in time relative to the end of the event.
Definition: alarm.cpp:474
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
Duration startOffset() const
Return offset of alarm in time relative to the start of the event.
Definition: alarm.cpp:451
void setSnoozeTime(const Duration &alarmSnoozeTime)
Set the interval between snoozes for the alarm.
Definition: alarm.cpp:354
TQString programArguments() const
Return the arguments to the program to run when the alarm is triggered.
Definition: alarm.cpp:198
void setEndOffset(const Duration &)
Set offset of alarm in time relative to the end of the event.
Definition: alarm.cpp:466
void setText(const TQString &text)
Set the text to be displayed when the alarm is triggered.
Definition: alarm.cpp:308
void setProgramArguments(const TQString &arguments)
Set the arguments to the program to execute when the alarm is triggered.
Definition: alarm.cpp:190
TQString mailText() const
Return the email body text.
Definition: alarm.cpp:295
bool hasTime() const
Return true, if the alarm has an explicit date/time.
Definition: alarm.cpp:349
void setStartOffset(const Duration &)
Set offset of alarm in time relative to the start of the event.
Definition: alarm.cpp:443
TQValueList< Person > mailAddresses() const
Return the addresses to send mail to when an alarm goes off.
Definition: alarm.cpp:239
void setTime(const TQDateTime &alarmTime)
Set the time to trigger an alarm.
Definition: alarm.cpp:321
Type type() const
Return the type of the alarm.
Definition: alarm.cpp:144
void setAudioFile(const TQString &audioFile)
Set the file to play when the audio alarm is triggered.
Definition: alarm.cpp:156
void setMailText(const TQString &text)
Set the email body text.
Definition: alarm.cpp:287
void setType(Type type)
Set the type of the alarm.
Definition: alarm.cpp:115
void setProgramFile(const TQString &programFile)
Set the program file to execute when the alarm is triggered.
Definition: alarm.cpp:177
int repeatCount() const
Get how many times an alarm repeats, after its initial occurrence.
Definition: alarm.cpp:373
TQStringList mailAttachments() const
Return the filenames to attach to the email.
Definition: alarm.cpp:282
This class represents information related to an attachment.
Definition: attachment.h:35
This class represents information related to an attendee of an event.
Definition: attendee.h:37
void setDelegator(const TQString &delegator)
Sets the delegator.
Definition: attendee.h:140
void setDelegate(const TQString &delegate)
Sets the delegate.
Definition: attendee.h:131
TQString uid() const
Return unique id of the attendee.
Definition: attendee.cpp:137
TQString delegate() const
Returns the delegate.
Definition: attendee.h:135
Role role() const
Return role of Attendee.
Definition: attendee.cpp:122
TQString delegator() const
Returns the delegator.
Definition: attendee.h:144
bool RSVP() const
Return, if Attendee is asked to reply.
Definition: attendee.h:126
PartStat status() const
Return status.
Definition: attendee.cpp:61
This is the main "calendar" object class.
Definition: calendar.h:171
virtual bool addJournal(Journal *journal)=0
Insert a Journal into the Calendar.
virtual Todo * todo(const TQString &uid)=0
Returns the Todo associated with the given unique identifier.
virtual Event * event(const TQString &uid)=0
Returns the Event associated with the given unique identifier.
virtual bool addEvent(Event *event)=0
Insert an Event into the Calendar.
ErrorFormat * exception() const
Returns an exception, if there is any, containing information about the last error that occurred.
Definition: calendar.cpp:80
virtual Journal * journal(const TQString &uid)=0
Returns the Journal associated with the given unique identifier.
virtual bool addTodo(Todo *todo)=0
Insert a Todo into the Calendar.
Incidence * incidence(const TQString &uid)
Returns the Incidence associated with the given unique identifier.
Definition: calendar.cpp:576
void endBatchAdding()
Emits the endBatchAdding() signal.
Definition: calendar.cpp:149
This class provides compatibility to older (broken) versions of KOrganizer.
Definition: compat.h:46
This class represents custom calendar properties.
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 setCustomProperty(const TQCString &app, const TQCString &key, const TQString &value)
Create or modify a custom calendar property.
TQString customProperty(const TQCString &app, const TQCString &key) const
Return the value of a custom calendar property.
void removeCustomProperty(const TQCString &app, const TQCString &key)
Delete a custom calendar property.
This class represents a duration.
Definition: duration.h:34
int value() const
Returns the length of the duration in seconds or days.
Definition: duration.cpp:175
int asSeconds() const
Returns the length of the duration in seconds.
Definition: duration.cpp:165
Calendar format related error class.
Definition: exceptions.h:65
ErrorCodeFormat errorCode()
Return format error code.
Definition: exceptions.cpp:101
This class provides an Event in the sense of RFC2445.
Definition: event.h:33
virtual TQDateTime dtEnd() const
Return end date and time.
Definition: event.cpp:85
Transparency transparency() const
Return the event's time transparency level.
Definition: event.cpp:145
bool hasEndDate() const
Return whether the event has an end date/time.
Definition: event.cpp:121
This class provides information about free/busy time of a calendar user.
Definition: freebusy.h:41
void addPeriods(const PeriodList &)
Adds a list of periods to the freebusy object and then sorts that list.
Definition: freebusy.cpp:194
This class implements the iCalendar format.
Definition: icalformat.h:44
This class provides the interface for a visitor of calendar components.
Definition: incidencebase.h:55
virtual bool visit(Event *)
Reimplement this function in your concrete subclass of IncidenceBase::Visitor to perform actions on a...
Definition: incidencebase.h:64
This class provides the base class common to all calendar components.
Definition: incidencebase.h:46
void setOrganizer(const Person &o)
sets the organizer for the event
int attendeeCount() const
Return number of attendees.
void setPilotId(unsigned long id)
Set Pilot Id.
unsigned long pilotId() const
Return Pilot Id.
TQStringList comments() const
Return all comments associated with this incidence.
bool doesFloat() const
Return true or false depending on whether the incidence "floats," i.e.
const Attendee::List & attendees() const
Return list of attendees.
TQString uid() const
Return the unique id for the event.
void addComment(const TQString &comment)
Add a comment to this incidence.
void setUid(const TQString &)
Set the unique id for the event.
int syncStatus() const
Return synchronisation status.
virtual TQDateTime dtStart() const
returns an event's starting date/time as a TQDateTime.
virtual bool accept(Visitor &)
Accept IncidenceVisitor.
virtual void setDtStart(const TQDateTime &dtStart)
for setting the event's starting date/time with a TQDateTime.
TQDateTime lastModified() const
Return the time the incidence was last modified.
void setSyncStatus(int status)
Set synchronisation satus.
void setLastModified(const TQDateTime &lm)
Sets the time the incidence was last modified.
void addAttendee(Attendee *attendee, bool doUpdate=true)
Add Attendee to this incidence.
This class provides the base class common to all calendar components.
Definition: incidence.h:48
TQString statusStr() const
Return the event's status string.
Definition: incidence.cpp:762
void addAttachment(Attachment *attachment)
Add attachment.
Definition: incidence.cpp:674
TQString relatedToUid() const
What event does this one relate to? This function should only be used when constructing a calendar be...
Definition: incidence.cpp:340
void setLocation(const TQString &location)
Set the event's/todo's location.
Definition: incidence.cpp:868
const Alarm::List & alarms() const
All alarms that are associated with this incidence.
Definition: incidence.cpp:828
void setSummary(const TQString &summary)
Set short summary.
Definition: incidence.cpp:286
void setCustomStatus(const TQString &status)
Sets the incidence status to a non-standard status value.
Definition: incidence.cpp:749
void setSchedulingID(const TQString &sid)
Set the event's/todo's scheduling ID.
Definition: incidence.cpp:880
Alarm * newAlarm()
Create a new alarm which is associated with this incidence.
Definition: incidence.cpp:833
TQDateTime created() const
Return time and date of creation.
Definition: incidence.cpp:246
int revision() const
Return the number of revisions this event has seen.
Definition: incidence.cpp:259
void setPriority(int priority)
Set the incidences priority.
Definition: incidence.cpp:729
void setSecrecy(int)
Sets secrecy status.
Definition: incidence.cpp:786
int secrecy() const
Return the event's secrecy.
Definition: incidence.cpp:793
IncidenceList childIncidences() const
Returns an EventList of all child incidences.
Definition: incidence.cpp:934
TQString description() const
Return long description.
Definition: incidence.cpp:280
Status
Enumeration for describing an event's status.
Definition: incidence.h:117
TQStringList categories() const
Return categories as a list of strings.
Definition: incidence.cpp:323
void setStatus(Status status)
Sets the incidence status to a standard status value.
Definition: incidence.cpp:741
void setDescription(const TQString &description)
Set the long description.
Definition: incidence.cpp:273
int priority() const
Return priority.
Definition: incidence.cpp:736
Status status() const
Return the event's status.
Definition: incidence.cpp:757
void setFloats(bool f)
Set whether the incidence floats, i.e.
Definition: incidence.cpp:229
void setRelatedToUid(const TQString &)
Point at some other event to which the event relates.
Definition: incidence.cpp:333
bool doesRecur() const
Forward to Recurrence::doesRecur().
Definition: incidence.cpp:416
virtual void setDtStart(const TQDateTime &dtStart)
Set starting date/time.
Definition: incidence.cpp:264
TQString schedulingID() const
Return the event's/todo's scheduling ID.
Definition: incidence.cpp:885
bool hasRecurrenceID() const
Returns true if the incidence has recurrenceID, otherwise return false.
Definition: incidence.cpp:893
TQDateTime recurrenceID() const
Returns the incidence recurrenceID.
Definition: incidence.cpp:908
void setCategories(const TQStringList &categories)
Set categories.
Definition: incidence.cpp:298
TQString location() const
Return the event's/todo's location.
Definition: incidence.cpp:875
Attachment::List attachments() const
Return list of all associated attachments.
Definition: incidence.cpp:695
TQString summary() const
Return short summary.
Definition: incidence.cpp:293
Recurrence * recurrence() const
Return the recurrence rule associated with this incidence.
Definition: incidence.cpp:390
void setRevision(int rev)
Set the number of revisions this event has seen.
Definition: incidence.cpp:251
void addChildIncidence(TQString childIncidence)
Attach a child incidence to a parent incidence.
Definition: incidence.cpp:924
void setCreated(const TQDateTime &)
Set creation date.
Definition: incidence.cpp:237
void setHasRecurrenceID(bool hasRecurrenceID)
Sets if the incidence has recurrenceID.
Definition: incidence.cpp:898
void setRecurrenceID(const TQDateTime &recurrenceID)
Set the incidences recurrenceID.
Definition: incidence.cpp:913
This class provides a Journal in the sense of RFC2445.
Definition: journal.h:34
This class represents a period of time.
Definition: period.h:36
This class represents a person.
Definition: person.h:35
structure for describing the n-th weekday of the month/year.
This class represents a recurrence rule for a calendar incidence.
TQDateTime endDt(bool *result=0) const
Returns the date and time of the last recurrence.
void setDuration(int duration)
Sets the total number of times the event is to occur, including both the first and last.
void setFrequency(int freq)
Sets the frequency of recurrence, in terms of the recurrence time period type.
void setEndDt(const TQDateTime &endDateTime)
Sets the date and time of the last recurrence.
uint frequency() const
Returns frequency of recurrence, in terms of the recurrence time period type.
int duration() const
Returns -1 if the event recurs infinitely, 0 if the end date is set, otherwise the total number of re...
bool doesFloat() const
Returns whether the start date has no time associated.
void setStartDt(const TQDateTime &start)
Set start of recurrence, as a date and time.
This class represents a recurrence rule for a calendar incidence.
Definition: recurrence.h:90
Method
iTIP methods.
Definition: scheduler.h:103
This class provides a Todo in the sense of RFC2445.
Definition: todo.h:32
bool hasDueDate() const
Returns true if the todo has a due date, otherwise return false.
Definition: todo.cpp:144
bool isCompleted() const
Returns true if the todo is 100% completed, otherwise return false.
Definition: todo.cpp:217
void setDtRecurrence(const TQDateTime &dt)
Sets the due date/time of the current occurrence if recurrent.
Definition: todo.cpp:279
bool hasStartDate() const
Returns true if the todo has a start date, otherwise return false.
Definition: todo.cpp:157
void setDtDue(const TQDateTime &dtDue, bool first=false)
Sets due date and time.
Definition: todo.cpp:85
void setCompleted(bool completed)
Set completed state.
Definition: todo.cpp:223
TQDateTime dtStart(bool first=false) const
Returns the startdate of the todo.
Definition: todo.cpp:177
TQDateTime completed() const
Returns date and time when todo was completed.
Definition: todo.cpp:235
void setHasStartDate(bool hasStartDate)
Set if the todo has a start date.
Definition: todo.cpp:162
int percentComplete() const
Returns how many percent of the task are completed.
Definition: todo.cpp:263
bool hasCompletedDate() const
Returns true, if todo has a date associated with completion, otherwise return false.
Definition: todo.cpp:258
TQDateTime dtDue(bool first=false) const
Returns due date and time.
Definition: todo.cpp:117
void setHasDueDate(bool hasDueDate)
Set if the todo has a due date.
Definition: todo.cpp:149
void setPercentComplete(int)
Set how many percent of the task are completed.
Definition: todo.cpp:268
Namespace KCal is for global classes, objects and/or functions in libkcal.
Definition: alarm.h:38