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