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