summaryrefslogtreecommitdiffabout
path: root/libkcal/icalformatimpl.cpp
authorzautrix <zautrix>2004-06-26 19:01:18 (UTC)
committer zautrix <zautrix>2004-06-26 19:01:18 (UTC)
commitb9aad1f15dc600e4dbe4c62d3fcced6363188ba3 (patch) (unidiff)
tree2c3d4004fb21c72cba65793859f9bcd8ffd3a49c /libkcal/icalformatimpl.cpp
downloadkdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.zip
kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.gz
kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.bz2
Initial revision
Diffstat (limited to 'libkcal/icalformatimpl.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/icalformatimpl.cpp2173
1 files changed, 2173 insertions, 0 deletions
diff --git a/libkcal/icalformatimpl.cpp b/libkcal/icalformatimpl.cpp
new file mode 100644
index 0000000..e5c27a0
--- a/dev/null
+++ b/libkcal/icalformatimpl.cpp
@@ -0,0 +1,2173 @@
1/*
2 This file is part of libkcal.
3 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21#include <qdatetime.h>
22#include <qstring.h>
23#include <qptrlist.h>
24#include <qfile.h>
25
26#include <kdebug.h>
27#include <klocale.h>
28#include <kglobal.h>
29
30extern "C" {
31 #include <ical.h>
32 #include <icalss.h>
33 #include <icalparser.h>
34 #include <icalrestriction.h>
35}
36
37#include "calendar.h"
38#include "journal.h"
39#include "icalformat.h"
40#include "icalformatimpl.h"
41#include "compat.h"
42
43#define _ICAL_VERSION "2.0"
44
45using namespace KCal;
46
47const int gSecondsPerMinute = 60;
48const int gSecondsPerHour = gSecondsPerMinute * 60;
49const int gSecondsPerDay = gSecondsPerHour * 24;
50const int gSecondsPerWeek = gSecondsPerDay * 7;
51
52ICalFormatImpl::ICalFormatImpl( ICalFormat *parent ) :
53 mParent( parent ), mCalendarVersion( 0 )
54{
55 mCompat = new Compat;
56}
57
58ICalFormatImpl::~ICalFormatImpl()
59{
60 delete mCompat;
61}
62
63class ToStringVisitor : public Incidence::Visitor
64{
65 public:
66 ToStringVisitor( ICalFormatImpl *impl ) : mImpl( impl ), mComponent( 0 ) {}
67
68 bool visit( Event *e ) { mComponent = mImpl->writeEvent( e ); return true; }
69 bool visit( Todo *e ) { mComponent = mImpl->writeTodo( e ); return true; }
70 bool visit( Journal *e ) { mComponent = mImpl->writeJournal( e ); return true; }
71
72 icalcomponent *component() { return mComponent; }
73
74 private:
75 ICalFormatImpl *mImpl;
76 icalcomponent *mComponent;
77};
78
79icalcomponent *ICalFormatImpl::writeIncidence(Incidence *incidence)
80{
81 ToStringVisitor v( this );
82 incidence->accept(v);
83 return v.component();
84}
85
86icalcomponent *ICalFormatImpl::writeTodo(Todo *todo)
87{
88 QString tmpStr;
89 QStringList tmpStrList;
90
91 icalcomponent *vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
92
93 writeIncidence(vtodo,todo);
94
95 // due date
96 if (todo->hasDueDate()) {
97 icaltimetype due;
98 if (todo->doesFloat()) {
99 due = writeICalDate(todo->dtDue().date());
100 } else {
101 due = writeICalDateTime(todo->dtDue());
102 }
103 icalcomponent_add_property(vtodo,icalproperty_new_due(due));
104 }
105
106 // start time
107 if (todo->hasStartDate()) {
108 icaltimetype start;
109 if (todo->doesFloat()) {
110// kdDebug(5800) << "§§ Incidence " << todo->summary() << " floats." << endl;
111 start = writeICalDate(todo->dtStart().date());
112 } else {
113// kdDebug(5800) << "§§ incidence " << todo->summary() << " has time." << endl;
114 start = writeICalDateTime(todo->dtStart());
115 }
116 icalcomponent_add_property(vtodo,icalproperty_new_dtstart(start));
117 }
118
119 // completion date
120 if (todo->isCompleted()) {
121 if (!todo->hasCompletedDate()) {
122 // If todo was created by KOrganizer <2.2 it has no correct completion
123 // date. Set it to now.
124 todo->setCompleted(QDateTime::currentDateTime());
125 }
126 icaltimetype completed = writeICalDateTime(todo->completed());
127 icalcomponent_add_property(vtodo,icalproperty_new_completed(completed));
128 }
129
130 icalcomponent_add_property(vtodo,
131 icalproperty_new_percentcomplete(todo->percentComplete()));
132
133 return vtodo;
134}
135
136icalcomponent *ICalFormatImpl::writeEvent(Event *event)
137{
138 kdDebug(5800) << "Write Event '" << event->summary() << "' (" << event->uid()
139 << ")" << endl;
140
141 QString tmpStr;
142 QStringList tmpStrList;
143
144 icalcomponent *vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
145
146 writeIncidence(vevent,event);
147
148 // start time
149 icaltimetype start;
150 if (event->doesFloat()) {
151// kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl;
152 start = writeICalDate(event->dtStart().date());
153 } else {
154// kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl;
155 start = writeICalDateTime(event->dtStart());
156 }
157 icalcomponent_add_property(vevent,icalproperty_new_dtstart(start));
158
159 if (event->hasEndDate()) {
160 // end time
161 icaltimetype end;
162 if (event->doesFloat()) {
163// kdDebug(5800) << "§§ Event " << event->summary() << " floats." << endl;
164 // +1 day because end date is non-inclusive.
165 end = writeICalDate( event->dtEnd().date().addDays( 1 ) );
166 } else {
167// kdDebug(5800) << "§§ Event " << event->summary() << " has time." << endl;
168 end = writeICalDateTime(event->dtEnd());
169 }
170 icalcomponent_add_property(vevent,icalproperty_new_dtend(end));
171 }
172
173// TODO: attachments, resources
174#if 0
175 // attachments
176 tmpStrList = anEvent->attachments();
177 for ( QStringList::Iterator it = tmpStrList.begin();
178 it != tmpStrList.end();
179 ++it )
180 addPropValue(vevent, VCAttachProp, (*it).utf8());
181
182 // resources
183 tmpStrList = anEvent->resources();
184 tmpStr = tmpStrList.join(";");
185 if (!tmpStr.isEmpty())
186 addPropValue(vevent, VCResourcesProp, tmpStr.utf8());
187
188#endif
189
190 // Transparency
191 switch( event->transparency() ) {
192 case Event::Transparent:
193 icalcomponent_add_property(vevent, icalproperty_new_transp("TRANSPARENT"));
194 break;
195 case Event::Opaque:
196 icalcomponent_add_property(vevent, icalproperty_new_transp("OPAQUE"));
197 break;
198 }
199
200 return vevent;
201}
202
203icalcomponent *ICalFormatImpl::writeFreeBusy(FreeBusy *freebusy,
204 Scheduler::Method method)
205{
206#if QT_VERSION >= 300
207 kdDebug(5800) << "icalformatimpl: writeFreeBusy: startDate: "
208 << freebusy->dtStart().toString("ddd MMMM d yyyy: h:m:s ap") << " End Date: "
209 << freebusy->dtEnd().toString("ddd MMMM d yyyy: h:m:s ap") << endl;
210#endif
211
212 icalcomponent *vfreebusy = icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
213
214 writeIncidenceBase(vfreebusy,freebusy);
215
216 icalcomponent_add_property(vfreebusy, icalproperty_new_dtstart(
217 writeICalDateTime(freebusy->dtStart())));
218
219 icalcomponent_add_property(vfreebusy, icalproperty_new_dtend(
220 writeICalDateTime(freebusy->dtEnd())));
221
222 if (method == Scheduler::Request) {
223 icalcomponent_add_property(vfreebusy,icalproperty_new_uid(
224 freebusy->uid().utf8()));
225 }
226
227 //Loops through all the periods in the freebusy object
228 QValueList<Period> list = freebusy->busyPeriods();
229 QValueList<Period>::Iterator it;
230 icalperiodtype period;
231 for (it = list.begin(); it!= list.end(); ++it) {
232 period.start = writeICalDateTime((*it).start());
233 period.end = writeICalDateTime((*it).end());
234 icalcomponent_add_property(vfreebusy, icalproperty_new_freebusy(period) );
235 }
236
237 return vfreebusy;
238}
239
240icalcomponent *ICalFormatImpl::writeJournal(Journal *journal)
241{
242 icalcomponent *vjournal = icalcomponent_new(ICAL_VJOURNAL_COMPONENT);
243
244 writeIncidence(vjournal,journal);
245
246 // start time
247 if (journal->dtStart().isValid()) {
248 icaltimetype start;
249 if (journal->doesFloat()) {
250// kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl;
251 start = writeICalDate(journal->dtStart().date());
252 } else {
253// kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl;
254 start = writeICalDateTime(journal->dtStart());
255 }
256 icalcomponent_add_property(vjournal,icalproperty_new_dtstart(start));
257 }
258
259 return vjournal;
260}
261
262void ICalFormatImpl::writeIncidence(icalcomponent *parent,Incidence *incidence)
263{
264 // pilot sync stuff
265// TODO: move this application-specific code to kpilot
266 if (incidence->pilotId()) {
267 incidence->setNonKDECustomProperty("X-PILOTID", QString::number(incidence->pilotId()));
268 incidence->setNonKDECustomProperty("X-PILOTSTAT", QString::number(incidence->syncStatus()));
269 }
270 if (incidence->zaurusId() >= 0) {
271 incidence->setNonKDECustomProperty("X-ZAURUSID", QString::number(incidence->zaurusId()));
272 }
273
274 if (incidence->zaurusUid() > 0) {
275 incidence->setNonKDECustomProperty("X-ZAURUSUID", QString::number(incidence->zaurusUid()));
276 }
277 if (incidence->zaurusStat() > 0) {
278 incidence->setNonKDECustomProperty("X-ZAURUSSTAT", QString::number(incidence->zaurusStat()));
279 }
280
281 writeIncidenceBase(parent,incidence);
282 if (incidence->cancelled()) {
283 icalcomponent_add_property(parent,icalproperty_new_status(ICAL_STATUS_CANCELLED));
284 }
285
286 // creation date
287 icalcomponent_add_property(parent,icalproperty_new_created(
288 writeICalDateTime(incidence->created())));
289
290 // unique id
291 icalcomponent_add_property(parent,icalproperty_new_uid(
292 incidence->uid().utf8()));
293
294 // revision
295 icalcomponent_add_property(parent,icalproperty_new_sequence(
296 incidence->revision()));
297
298 // last modification date
299 icalcomponent_add_property(parent,icalproperty_new_lastmodified(
300 writeICalDateTime(incidence->lastModified())));
301
302 // description
303 if (!incidence->description().isEmpty()) {
304 icalcomponent_add_property(parent,icalproperty_new_description(
305 incidence->description().utf8()));
306 }
307
308 // summary
309 if (!incidence->summary().isEmpty()) {
310 icalcomponent_add_property(parent,icalproperty_new_summary(
311 incidence->summary().utf8()));
312 }
313
314 // location
315 if (!incidence->location().isEmpty()) {
316 icalcomponent_add_property(parent,icalproperty_new_location(
317 incidence->location().utf8()));
318 }
319
320// TODO:
321 // status
322// addPropValue(parent, VCStatusProp, incidence->getStatusStr().utf8());
323
324 // secrecy
325 const char *classStr;
326 switch (incidence->secrecy()) {
327 case Incidence::SecrecyPublic:
328 classStr = "PUBLIC";
329 break;
330 case Incidence::SecrecyConfidential:
331 classStr = "CONFIDENTIAL";
332 break;
333 case Incidence::SecrecyPrivate:
334 default:
335 classStr = "PRIVATE";
336 break;
337 }
338 icalcomponent_add_property(parent,icalproperty_new_class(classStr));
339
340 // priority
341 icalcomponent_add_property(parent,icalproperty_new_priority(
342 incidence->priority()));
343
344 // categories
345 QStringList categories = incidence->categories();
346 QStringList::Iterator it;
347 for(it = categories.begin(); it != categories.end(); ++it ) {
348 icalcomponent_add_property(parent,icalproperty_new_categories((*it).utf8()));
349 }
350// TODO: Ensure correct concatenation of categories properties.
351
352/*
353 // categories
354 tmpStrList = incidence->getCategories();
355 tmpStr = "";
356 QString catStr;
357 for ( QStringList::Iterator it = tmpStrList.begin();
358 it != tmpStrList.end();
359 ++it ) {
360 catStr = *it;
361 if (catStr[0] == ' ')
362 tmpStr += catStr.mid(1);
363 else
364 tmpStr += catStr;
365 // this must be a ';' character as the vCalendar specification requires!
366 // vcc.y has been hacked to translate the ';' to a ',' when the vcal is
367 // read in.
368 tmpStr += ";";
369 }
370 if (!tmpStr.isEmpty()) {
371 tmpStr.truncate(tmpStr.length()-1);
372 icalcomponent_add_property(parent,icalproperty_new_categories(
373 writeText(incidence->getCategories().join(";"))));
374 }
375*/
376
377 // related event
378 if (incidence->relatedTo()) {
379 icalcomponent_add_property(parent,icalproperty_new_relatedto(
380 incidence->relatedTo()->uid().utf8()));
381 }
382
383 // recurrence rule stuff
384 Recurrence *recur = incidence->recurrence();
385 if (recur->doesRecur()) {
386
387 icalcomponent_add_property(parent,writeRecurrenceRule(recur));
388 }
389
390 // recurrence excpetion dates
391 DateList dateList = incidence->exDates();
392 DateList::ConstIterator exIt;
393 for(exIt = dateList.begin(); exIt != dateList.end(); ++exIt) {
394 icalcomponent_add_property(parent,icalproperty_new_exdate(
395 writeICalDate(*exIt)));
396 }
397
398 // attachments
399 QPtrList<Attachment> attachments = incidence->attachments();
400 for (Attachment *at = attachments.first(); at; at = attachments.next())
401 icalcomponent_add_property(parent,writeAttachment(at));
402
403 // alarms
404 QPtrList<Alarm> alarms = incidence->alarms();
405 Alarm* alarm;
406 for (alarm = alarms.first(); alarm; alarm = alarms.next()) {
407 if (alarm->enabled()) {
408 kdDebug(5800) << "Write alarm for " << incidence->summary() << endl;
409 icalcomponent_add_component(parent,writeAlarm(alarm));
410 }
411 }
412
413 // duration
414
415// turned off as it always is set to PTS0 (and must not occur together with DTEND
416
417// if (incidence->hasDuration()) {
418// icaldurationtype duration;
419// duration = writeICalDuration(incidence->duration());
420// icalcomponent_add_property(parent,icalproperty_new_duration(duration));
421// }
422}
423
424void ICalFormatImpl::writeIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase)
425{
426 icalcomponent_add_property(parent,icalproperty_new_dtstamp(
427 writeICalDateTime(QDateTime::currentDateTime())));
428
429 // organizer stuff
430 icalcomponent_add_property(parent,icalproperty_new_organizer(
431 ("MAILTO:" + incidenceBase->organizer()).utf8()));
432
433 // attendees
434 if (incidenceBase->attendeeCount() != 0) {
435 QPtrList<Attendee> al = incidenceBase->attendees();
436 QPtrListIterator<Attendee> ai(al);
437 for (; ai.current(); ++ai) {
438 icalcomponent_add_property(parent,writeAttendee(ai.current()));
439 }
440 }
441
442 // custom properties
443 writeCustomProperties(parent, incidenceBase);
444}
445
446void ICalFormatImpl::writeCustomProperties(icalcomponent *parent,CustomProperties *properties)
447{
448 QMap<QCString, QString> custom = properties->customProperties();
449 for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) {
450 icalproperty *p = icalproperty_new_x(c.data().utf8());
451 icalproperty_set_x_name(p,c.key());
452 icalcomponent_add_property(parent,p);
453 }
454}
455
456icalproperty *ICalFormatImpl::writeAttendee(Attendee *attendee)
457{
458 icalproperty *p = icalproperty_new_attendee("mailto:" + attendee->email().utf8());
459
460 if (!attendee->name().isEmpty()) {
461 icalproperty_add_parameter(p,icalparameter_new_cn(attendee->name().utf8()));
462 }
463
464
465 icalproperty_add_parameter(p,icalparameter_new_rsvp(
466 attendee->RSVP() ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE ));
467
468 icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION;
469 switch (attendee->status()) {
470 default:
471 case Attendee::NeedsAction:
472 status = ICAL_PARTSTAT_NEEDSACTION;
473 break;
474 case Attendee::Accepted:
475 status = ICAL_PARTSTAT_ACCEPTED;
476 break;
477 case Attendee::Declined:
478 status = ICAL_PARTSTAT_DECLINED;
479 break;
480 case Attendee::Tentative:
481 status = ICAL_PARTSTAT_TENTATIVE;
482 break;
483 case Attendee::Delegated:
484 status = ICAL_PARTSTAT_DELEGATED;
485 break;
486 case Attendee::Completed:
487 status = ICAL_PARTSTAT_COMPLETED;
488 break;
489 case Attendee::InProcess:
490 status = ICAL_PARTSTAT_INPROCESS;
491 break;
492 }
493 icalproperty_add_parameter(p,icalparameter_new_partstat(status));
494
495 icalparameter_role role = ICAL_ROLE_REQPARTICIPANT;
496 switch (attendee->role()) {
497 case Attendee::Chair:
498 role = ICAL_ROLE_CHAIR;
499 break;
500 default:
501 case Attendee::ReqParticipant:
502 role = ICAL_ROLE_REQPARTICIPANT;
503 break;
504 case Attendee::OptParticipant:
505 role = ICAL_ROLE_OPTPARTICIPANT;
506 break;
507 case Attendee::NonParticipant:
508 role = ICAL_ROLE_NONPARTICIPANT;
509 break;
510 }
511 icalproperty_add_parameter(p,icalparameter_new_role(role));
512
513 if (!attendee->uid().isEmpty()) {
514 icalparameter* icalparameter_uid = icalparameter_new_x(attendee->uid().utf8());
515 icalparameter_set_xname(icalparameter_uid,"X-UID");
516 icalproperty_add_parameter(p,icalparameter_uid);
517 }
518
519 return p;
520}
521
522icalproperty *ICalFormatImpl::writeAttachment(Attachment *att)
523{
524 icalattachtype* attach = icalattachtype_new();
525 if (att->isURI())
526 icalattachtype_set_url(attach, att->uri().utf8().data());
527 else
528 icalattachtype_set_base64(attach, att->data(), 0);
529
530 icalproperty *p = icalproperty_new_attach(attach);
531
532 if (!att->mimeType().isEmpty())
533 icalproperty_add_parameter(p,icalparameter_new_fmttype(att->mimeType().utf8().data()));
534
535 if (att->isBinary()) {
536 icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY));
537 icalproperty_add_parameter(p,icalparameter_new_encoding(ICAL_ENCODING_BASE64));
538 }
539 return p;
540}
541
542icalproperty *ICalFormatImpl::writeRecurrenceRule(Recurrence *recur)
543{
544// kdDebug(5800) << "ICalFormatImpl::writeRecurrenceRule()" << endl;
545
546 icalrecurrencetype r;
547
548 icalrecurrencetype_clear(&r);
549
550 int index = 0;
551 int index2 = 0;
552
553 QPtrList<Recurrence::rMonthPos> tmpPositions;
554 QPtrList<int> tmpDays;
555 int *tmpDay;
556 Recurrence::rMonthPos *tmpPos;
557 bool datetime = false;
558 int day;
559 int i;
560
561 switch(recur->doesRecur()) {
562 case Recurrence::rMinutely:
563 r.freq = ICAL_MINUTELY_RECURRENCE;
564 datetime = true;
565 break;
566 case Recurrence::rHourly:
567 r.freq = ICAL_HOURLY_RECURRENCE;
568 datetime = true;
569 break;
570 case Recurrence::rDaily:
571 r.freq = ICAL_DAILY_RECURRENCE;
572 break;
573 case Recurrence::rWeekly:
574 r.freq = ICAL_WEEKLY_RECURRENCE;
575 r.week_start = static_cast<icalrecurrencetype_weekday>(recur->weekStart()%7 + 1);
576 for (i = 0; i < 7; i++) {
577 if (recur->days().testBit(i)) {
578 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1
579 r.by_day[index++] = icalrecurrencetype_day_day_of_week(day);
580 }
581 }
582// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
583 break;
584 case Recurrence::rMonthlyPos:
585 r.freq = ICAL_MONTHLY_RECURRENCE;
586
587 tmpPositions = recur->monthPositions();
588 for (tmpPos = tmpPositions.first();
589 tmpPos;
590 tmpPos = tmpPositions.next()) {
591 for (i = 0; i < 7; i++) {
592 if (tmpPos->rDays.testBit(i)) {
593 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1
594 day += tmpPos->rPos*8;
595 if (tmpPos->negative) day = -day;
596 r.by_day[index++] = day;
597 }
598 }
599 }
600// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
601 break;
602 case Recurrence::rMonthlyDay:
603 r.freq = ICAL_MONTHLY_RECURRENCE;
604
605 tmpDays = recur->monthDays();
606 for (tmpDay = tmpDays.first();
607 tmpDay;
608 tmpDay = tmpDays.next()) {
609 r.by_month_day[index++] = icalrecurrencetype_day_position(*tmpDay*8);//*tmpDay);
610 }
611// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
612 break;
613 case Recurrence::rYearlyMonth:
614 case Recurrence::rYearlyPos:
615 r.freq = ICAL_YEARLY_RECURRENCE;
616
617 tmpDays = recur->yearNums();
618 for (tmpDay = tmpDays.first();
619 tmpDay;
620 tmpDay = tmpDays.next()) {
621 r.by_month[index++] = *tmpDay;
622 }
623// r.by_set_pos[index] = ICAL_RECURRENCE_ARRAY_MAX;
624 if (recur->doesRecur() == Recurrence::rYearlyPos) {
625 tmpPositions = recur->monthPositions();
626 for (tmpPos = tmpPositions.first();
627 tmpPos;
628 tmpPos = tmpPositions.next()) {
629 for (i = 0; i < 7; i++) {
630 if (tmpPos->rDays.testBit(i)) {
631 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1
632 day += tmpPos->rPos*8;
633 if (tmpPos->negative) day = -day;
634 r.by_day[index2++] = day;
635 }
636 }
637 }
638// r.by_day[index2] = ICAL_RECURRENCE_ARRAY_MAX;
639 }
640 break;
641 case Recurrence::rYearlyDay:
642 r.freq = ICAL_YEARLY_RECURRENCE;
643
644 tmpDays = recur->yearNums();
645 for (tmpDay = tmpDays.first();
646 tmpDay;
647 tmpDay = tmpDays.next()) {
648 r.by_year_day[index++] = *tmpDay;
649 }
650// r.by_year_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
651 break;
652 default:
653 r.freq = ICAL_NO_RECURRENCE;
654 kdDebug(5800) << "ICalFormatImpl::writeRecurrence(): no recurrence" << endl;
655 break;
656 }
657
658 r.interval = recur->frequency();
659
660 if (recur->duration() > 0) {
661 r.count = recur->duration();
662 } else if (recur->duration() == -1) {
663 r.count = 0;
664 } else {
665 if (datetime)
666 r.until = writeICalDateTime(recur->endDateTime());
667 else
668 r.until = writeICalDate(recur->endDate());
669 }
670
671// Debug output
672#if 0
673 const char *str = icalrecurrencetype_as_string(&r);
674 if (str) {
675 kdDebug(5800) << " String: " << str << endl;
676 } else {
677 kdDebug(5800) << " No String" << endl;
678 }
679#endif
680
681 return icalproperty_new_rrule(r);
682}
683
684icalcomponent *ICalFormatImpl::writeAlarm(Alarm *alarm)
685{
686 icalcomponent *a = icalcomponent_new(ICAL_VALARM_COMPONENT);
687
688 icalproperty_action action;
689 icalattachtype *attach = 0;
690
691 switch (alarm->type()) {
692 case Alarm::Procedure:
693 action = ICAL_ACTION_PROCEDURE;
694 attach = icalattachtype_new();
695 icalattachtype_set_url(attach,QFile::encodeName(alarm->programFile()).data());
696 icalcomponent_add_property(a,icalproperty_new_attach(attach));
697 icalattachtype_free(attach);
698 if (!alarm->programArguments().isEmpty()) {
699 icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8()));
700 }
701 break;
702 case Alarm::Audio:
703 action = ICAL_ACTION_AUDIO;
704 if (!alarm->audioFile().isEmpty()) {
705 attach = icalattachtype_new();
706 icalattachtype_set_url(attach,QFile::encodeName( alarm->audioFile() ).data());
707 icalcomponent_add_property(a,icalproperty_new_attach(attach));
708 icalattachtype_free(attach);
709 }
710 break;
711 case Alarm::Email: {
712 action = ICAL_ACTION_EMAIL;
713 QValueList<Person> addresses = alarm->mailAddresses();
714 for (QValueList<Person>::Iterator ad = addresses.begin(); ad != addresses.end(); ++ad) {
715 icalproperty *p = icalproperty_new_attendee("MAILTO:" + (*ad).email().utf8());
716 if (!(*ad).name().isEmpty()) {
717 icalproperty_add_parameter(p,icalparameter_new_cn((*ad).name().utf8()));
718 }
719 icalcomponent_add_property(a,p);
720 }
721 icalcomponent_add_property(a,icalproperty_new_summary(alarm->mailSubject().utf8()));
722 icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8()));
723 QStringList attachments = alarm->mailAttachments();
724 if (attachments.count() > 0) {
725 for (QStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at) {
726 attach = icalattachtype_new();
727 icalattachtype_set_url(attach,QFile::encodeName( *at ).data());
728 icalcomponent_add_property(a,icalproperty_new_attach(attach));
729 icalattachtype_free(attach);
730 }
731 }
732 break;
733 }
734 case Alarm::Display:
735 action = ICAL_ACTION_DISPLAY;
736 icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8()));
737 break;
738 case Alarm::Invalid:
739 default:
740 kdDebug(5800) << "Unknown type of alarm" << endl;
741 action = ICAL_ACTION_NONE;
742 break;
743 }
744 icalcomponent_add_property(a,icalproperty_new_action(action));
745
746 // Trigger time
747 icaltriggertype trigger;
748 if ( alarm->hasTime() ) {
749 trigger.time = writeICalDateTime(alarm->time());
750 trigger.duration = icaldurationtype_null_duration();
751 } else {
752 trigger.time = icaltime_null_time();
753 Duration offset;
754 if ( alarm->hasStartOffset() )
755 offset = alarm->startOffset();
756 else
757 offset = alarm->endOffset();
758 trigger.duration = icaldurationtype_from_int( offset.asSeconds() );
759 }
760 icalproperty *p = icalproperty_new_trigger(trigger);
761 if ( alarm->hasEndOffset() )
762 icalproperty_add_parameter(p,icalparameter_new_related(ICAL_RELATED_END));
763 icalcomponent_add_property(a,p);
764
765 // Repeat count and duration
766 if (alarm->repeatCount()) {
767 icalcomponent_add_property(a,icalproperty_new_repeat(alarm->repeatCount()));
768 icalcomponent_add_property(a,icalproperty_new_duration(
769 icaldurationtype_from_int(alarm->snoozeTime()*60)));
770 }
771
772 // Custom properties
773 QMap<QCString, QString> custom = alarm->customProperties();
774 for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) {
775 icalproperty *p = icalproperty_new_x(c.data().utf8());
776 icalproperty_set_x_name(p,c.key());
777 icalcomponent_add_property(a,p);
778 }
779
780 return a;
781}
782
783Todo *ICalFormatImpl::readTodo(icalcomponent *vtodo)
784{
785 Todo *todo = new Todo;
786
787 readIncidence(vtodo,todo);
788
789 icalproperty *p = icalcomponent_get_first_property(vtodo,ICAL_ANY_PROPERTY);
790
791// int intvalue;
792 icaltimetype icaltime;
793
794 QStringList categories;
795
796 while (p) {
797 icalproperty_kind kind = icalproperty_isa(p);
798 switch (kind) {
799
800 case ICAL_DUE_PROPERTY: // due date
801 icaltime = icalproperty_get_due(p);
802 if (icaltime.is_date) {
803 todo->setDtDue(QDateTime(readICalDate(icaltime),QTime(0,0,0)));
804 todo->setFloats(true);
805
806 } else {
807 todo->setDtDue(readICalDateTime(icaltime));
808 todo->setFloats(false);
809 }
810 todo->setHasDueDate(true);
811 break;
812
813 case ICAL_COMPLETED_PROPERTY: // completion date
814 icaltime = icalproperty_get_completed(p);
815 todo->setCompleted(readICalDateTime(icaltime));
816 break;
817
818 case ICAL_PERCENTCOMPLETE_PROPERTY: // Percent completed
819 todo->setPercentComplete(icalproperty_get_percentcomplete(p));
820 break;
821
822 case ICAL_RELATEDTO_PROPERTY: // related todo (parent)
823 todo->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p)));
824 mTodosRelate.append(todo);
825 break;
826
827 case ICAL_DTSTART_PROPERTY:
828 // Flag that todo has start date. Value is read in by readIncidence().
829 todo->setHasStartDate(true);
830 break;
831
832 default:
833// kdDebug(5800) << "ICALFormat::readTodo(): Unknown property: " << kind
834// << endl;
835 break;
836 }
837
838 p = icalcomponent_get_next_property(vtodo,ICAL_ANY_PROPERTY);
839 }
840
841 return todo;
842}
843
844Event *ICalFormatImpl::readEvent(icalcomponent *vevent)
845{
846 Event *event = new Event;
847 event->setFloats(false);
848
849 readIncidence(vevent,event);
850
851 icalproperty *p = icalcomponent_get_first_property(vevent,ICAL_ANY_PROPERTY);
852
853// int intvalue;
854 icaltimetype icaltime;
855
856 QStringList categories;
857 QString transparency;
858
859 while (p) {
860 icalproperty_kind kind = icalproperty_isa(p);
861 switch (kind) {
862
863 case ICAL_DTEND_PROPERTY: // start date and time
864 icaltime = icalproperty_get_dtend(p);
865 if (icaltime.is_date) {
866 event->setFloats( true );
867 // End date is non-inclusive
868 QDate endDate = readICalDate( icaltime ).addDays( -1 );
869 mCompat->fixFloatingEnd( endDate );
870 if ( endDate < event->dtStart().date() ) {
871 endDate = event->dtStart().date();
872 }
873 event->setDtEnd( QDateTime( endDate, QTime( 0, 0, 0 ) ) );
874 } else {
875 event->setDtEnd(readICalDateTime(icaltime));
876 }
877 break;
878
879// TODO:
880 // at this point, there should be at least a start or end time.
881 // fix up for events that take up no time but have a time associated
882#if 0
883 if (!(vo = isAPropertyOf(vevent, VCDTstartProp)))
884 anEvent->setDtStart(anEvent->dtEnd());
885 if (!(vo = isAPropertyOf(vevent, VCDTendProp)))
886 anEvent->setDtEnd(anEvent->dtStart());
887#endif
888
889// TODO: exdates
890#if 0
891 // recurrence exceptions
892 if ((vo = isAPropertyOf(vevent, VCExDateProp)) != 0) {
893 anEvent->setExDates(s = fakeCString(vObjectUStringZValue(vo)));
894 deleteStr(s);
895 }
896#endif
897
898#if 0
899 // secrecy
900 if ((vo = isAPropertyOf(vevent, VCClassProp)) != 0) {
901 anEvent->setSecrecy(s = fakeCString(vObjectUStringZValue(vo)));
902 deleteStr(s);
903 }
904 else
905 anEvent->setSecrecy("PUBLIC");
906
907 // attachments
908 tmpStrList.clear();
909 initPropIterator(&voi, vevent);
910 while (moreIteration(&voi)) {
911 vo = nextVObject(&voi);
912 if (strcmp(vObjectName(vo), VCAttachProp) == 0) {
913 tmpStrList.append(s = fakeCString(vObjectUStringZValue(vo)));
914 deleteStr(s);
915 }
916 }
917 anEvent->setAttachments(tmpStrList);
918
919 // resources
920 if ((vo = isAPropertyOf(vevent, VCResourcesProp)) != 0) {
921 QString resources = (s = fakeCString(vObjectUStringZValue(vo)));
922 deleteStr(s);
923 tmpStrList.clear();
924 index1 = 0;
925 index2 = 0;
926 QString resource;
927 while ((index2 = resources.find(';', index1)) != -1) {
928 resource = resources.mid(index1, (index2 - index1));
929 tmpStrList.append(resource);
930 index1 = index2;
931 }
932 anEvent->setResources(tmpStrList);
933 }
934#endif
935
936 case ICAL_RELATEDTO_PROPERTY: // releated event (parent)
937 event->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p)));
938 mEventsRelate.append(event);
939 break;
940
941
942 case ICAL_TRANSP_PROPERTY: // Transparency
943 transparency = QString::fromUtf8(icalproperty_get_transp(p));
944 if( transparency == "TRANSPARENT" )
945 event->setTransparency( Event::Transparent );
946 else
947 event->setTransparency( Event::Opaque );
948 break;
949
950 default:
951// kdDebug(5800) << "ICALFormat::readEvent(): Unknown property: " << kind
952// << endl;
953 break;
954 }
955
956 p = icalcomponent_get_next_property(vevent,ICAL_ANY_PROPERTY);
957 }
958
959 QString msade = event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT");
960 if (!msade.isNull()) {
961 bool floats = (msade == QString::fromLatin1("TRUE"));
962 kdDebug(5800) << "ICALFormat::readEvent(): all day event: " << floats << endl;
963 event->setFloats(floats);
964 if (floats) {
965 QDateTime endDate = event->dtEnd();
966 event->setDtEnd(endDate.addDays(-1));
967 }
968 }
969
970 // some stupid vCal exporters ignore the standard and use Description
971 // instead of Summary for the default field. Correct for this.
972 if (event->summary().isEmpty() &&
973 !(event->description().isEmpty())) {
974 QString tmpStr = event->description().simplifyWhiteSpace();
975 event->setDescription("");
976 event->setSummary(tmpStr);
977 }
978
979 return event;
980}
981
982FreeBusy *ICalFormatImpl::readFreeBusy(icalcomponent *vfreebusy)
983{
984 FreeBusy *freebusy = new FreeBusy;
985
986 readIncidenceBase(vfreebusy,freebusy);
987
988 icalproperty *p = icalcomponent_get_first_property(vfreebusy,ICAL_ANY_PROPERTY);
989
990 icaltimetype icaltime;
991 icalperiodtype icalperiod;
992 QDateTime period_start, period_end;
993
994 while (p) {
995 icalproperty_kind kind = icalproperty_isa(p);
996 switch (kind) {
997
998 case ICAL_DTSTART_PROPERTY: // start date and time
999 icaltime = icalproperty_get_dtstart(p);
1000 freebusy->setDtStart(readICalDateTime(icaltime));
1001 break;
1002
1003 case ICAL_DTEND_PROPERTY: // start End Date and Time
1004 icaltime = icalproperty_get_dtend(p);
1005 freebusy->setDtEnd(readICalDateTime(icaltime));
1006 break;
1007
1008 case ICAL_FREEBUSY_PROPERTY: //Any FreeBusy Times
1009 icalperiod = icalproperty_get_freebusy(p);
1010 period_start = readICalDateTime(icalperiod.start);
1011 period_end = readICalDateTime(icalperiod.end);
1012 freebusy->addPeriod(period_start, period_end);
1013 break;
1014
1015 default:
1016 kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind
1017 << endl;
1018 break;
1019 }
1020 p = icalcomponent_get_next_property(vfreebusy,ICAL_ANY_PROPERTY);
1021 }
1022
1023 return freebusy;
1024}
1025
1026Journal *ICalFormatImpl::readJournal(icalcomponent *vjournal)
1027{
1028 Journal *journal = new Journal;
1029
1030 readIncidence(vjournal,journal);
1031
1032 return journal;
1033}
1034
1035Attendee *ICalFormatImpl::readAttendee(icalproperty *attendee)
1036{
1037 icalparameter *p = 0;
1038
1039 QString email = QString::fromUtf8(icalproperty_get_attendee(attendee));
1040
1041 QString name;
1042 QString uid = QString::null;
1043 p = icalproperty_get_first_parameter(attendee,ICAL_CN_PARAMETER);
1044 if (p) {
1045 name = QString::fromUtf8(icalparameter_get_cn(p));
1046 } else {
1047 }
1048
1049 bool rsvp=false;
1050 p = icalproperty_get_first_parameter(attendee,ICAL_RSVP_PARAMETER);
1051 if (p) {
1052 icalparameter_rsvp rsvpParameter = icalparameter_get_rsvp(p);
1053 if (rsvpParameter == ICAL_RSVP_TRUE) rsvp = true;
1054 }
1055
1056 Attendee::PartStat status = Attendee::NeedsAction;
1057 p = icalproperty_get_first_parameter(attendee,ICAL_PARTSTAT_PARAMETER);
1058 if (p) {
1059 icalparameter_partstat partStatParameter = icalparameter_get_partstat(p);
1060 switch(partStatParameter) {
1061 default:
1062 case ICAL_PARTSTAT_NEEDSACTION:
1063 status = Attendee::NeedsAction;
1064 break;
1065 case ICAL_PARTSTAT_ACCEPTED:
1066 status = Attendee::Accepted;
1067 break;
1068 case ICAL_PARTSTAT_DECLINED:
1069 status = Attendee::Declined;
1070 break;
1071 case ICAL_PARTSTAT_TENTATIVE:
1072 status = Attendee::Tentative;
1073 break;
1074 case ICAL_PARTSTAT_DELEGATED:
1075 status = Attendee::Delegated;
1076 break;
1077 case ICAL_PARTSTAT_COMPLETED:
1078 status = Attendee::Completed;
1079 break;
1080 case ICAL_PARTSTAT_INPROCESS:
1081 status = Attendee::InProcess;
1082 break;
1083 }
1084 }
1085
1086 Attendee::Role role = Attendee::ReqParticipant;
1087 p = icalproperty_get_first_parameter(attendee,ICAL_ROLE_PARAMETER);
1088 if (p) {
1089 icalparameter_role roleParameter = icalparameter_get_role(p);
1090 switch(roleParameter) {
1091 case ICAL_ROLE_CHAIR:
1092 role = Attendee::Chair;
1093 break;
1094 default:
1095 case ICAL_ROLE_REQPARTICIPANT:
1096 role = Attendee::ReqParticipant;
1097 break;
1098 case ICAL_ROLE_OPTPARTICIPANT:
1099 role = Attendee::OptParticipant;
1100 break;
1101 case ICAL_ROLE_NONPARTICIPANT:
1102 role = Attendee::NonParticipant;
1103 break;
1104 }
1105 }
1106
1107 p = icalproperty_get_first_parameter(attendee,ICAL_X_PARAMETER);
1108 uid = icalparameter_get_xvalue(p);
1109 // This should be added, but there seems to be a libical bug here.
1110 /*while (p) {
1111 // if (icalparameter_get_xname(p) == "X-UID") {
1112 uid = icalparameter_get_xvalue(p);
1113 p = icalproperty_get_next_parameter(attendee,ICAL_X_PARAMETER);
1114 } */
1115
1116 return new Attendee( name, email, rsvp, status, role, uid );
1117}
1118
1119Attachment *ICalFormatImpl::readAttachment(icalproperty *attach)
1120{
1121 icalattachtype *a = icalproperty_get_attach(attach);
1122 icalparameter_value v = ICAL_VALUE_NONE;
1123 icalparameter_encoding e = ICAL_ENCODING_NONE;
1124
1125 Attachment *attachment = 0;
1126
1127 icalparameter *vp = icalproperty_get_first_parameter(attach, ICAL_VALUE_PARAMETER);
1128 if (vp)
1129 v = icalparameter_get_value(vp);
1130
1131 icalparameter *ep = icalproperty_get_first_parameter(attach, ICAL_ENCODING_PARAMETER);
1132 if (ep)
1133 e = icalparameter_get_encoding(ep);
1134
1135 if (v == ICAL_VALUE_BINARY && e == ICAL_ENCODING_BASE64)
1136 attachment = new Attachment(icalattachtype_get_base64(a));
1137 else if ((v == ICAL_VALUE_NONE || v == ICAL_VALUE_URI) && (e == ICAL_ENCODING_NONE || e == ICAL_ENCODING_8BIT)) {
1138 attachment = new Attachment(QString(icalattachtype_get_url(a)));
1139 } else {
1140 kdWarning(5800) << "Unsupported attachment format, discarding it!" << endl;
1141 return 0;
1142 }
1143
1144 icalparameter *p = icalproperty_get_first_parameter(attach, ICAL_FMTTYPE_PARAMETER);
1145 if (p)
1146 attachment->setMimeType(QString(icalparameter_get_fmttype(p)));
1147
1148 return attachment;
1149}
1150#include <qtextcodec.h>
1151void ICalFormatImpl::readIncidence(icalcomponent *parent,Incidence *incidence)
1152{
1153 readIncidenceBase(parent,incidence);
1154
1155 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
1156 bool readrec = false;
1157 const char *text;
1158 int intvalue;
1159 icaltimetype icaltime;
1160 icaldurationtype icalduration;
1161 struct icalrecurrencetype rectype;
1162 QStringList categories;
1163
1164 while (p) {
1165 icalproperty_kind kind = icalproperty_isa(p);
1166 switch (kind) {
1167
1168 case ICAL_CREATED_PROPERTY:
1169 icaltime = icalproperty_get_created(p);
1170 incidence->setCreated(readICalDateTime(icaltime));
1171 break;
1172
1173 case ICAL_SEQUENCE_PROPERTY: // sequence
1174 intvalue = icalproperty_get_sequence(p);
1175 incidence->setRevision(intvalue);
1176 break;
1177
1178 case ICAL_LASTMODIFIED_PROPERTY: // last modification date
1179 icaltime = icalproperty_get_lastmodified(p);
1180 incidence->setLastModified(readICalDateTime(icaltime));
1181 break;
1182
1183 case ICAL_DTSTART_PROPERTY: // start date and time
1184 icaltime = icalproperty_get_dtstart(p);
1185 if (icaltime.is_date) {
1186 incidence->setDtStart(QDateTime(readICalDate(icaltime),QTime(0,0,0)));
1187 incidence->setFloats(true);
1188 } else {
1189 incidence->setDtStart(readICalDateTime(icaltime));
1190 }
1191 break;
1192
1193 case ICAL_DURATION_PROPERTY: // start date and time
1194 icalduration = icalproperty_get_duration(p);
1195 incidence->setDuration(readICalDuration(icalduration));
1196 break;
1197
1198 case ICAL_DESCRIPTION_PROPERTY: // description
1199 text = icalproperty_get_description(p);
1200 incidence->setDescription(QString::fromUtf8(text));
1201 break;
1202
1203 case ICAL_SUMMARY_PROPERTY: // summary
1204 {
1205 text = icalproperty_get_summary(p);
1206 incidence->setSummary(QString::fromUtf8(text));
1207 }
1208 break;
1209 case ICAL_STATUS_PROPERTY: // summary
1210 {
1211 if ( ICAL_STATUS_CANCELLED == icalproperty_get_status(p) )
1212 incidence->setCancelled( true );
1213 }
1214 break;
1215
1216 case ICAL_LOCATION_PROPERTY: // location
1217 text = icalproperty_get_location(p);
1218 incidence->setLocation(QString::fromUtf8(text));
1219 break;
1220
1221#if 0
1222 // status
1223 if ((vo = isAPropertyOf(vincidence, VCStatusProp)) != 0) {
1224 incidence->setStatus(s = fakeCString(vObjectUStringZValue(vo)));
1225 deleteStr(s);
1226 }
1227 else
1228 incidence->setStatus("NEEDS ACTION");
1229#endif
1230
1231 case ICAL_PRIORITY_PROPERTY: // priority
1232 intvalue = icalproperty_get_priority(p);
1233 incidence->setPriority(intvalue);
1234 break;
1235
1236 case ICAL_CATEGORIES_PROPERTY: // categories
1237 text = icalproperty_get_categories(p);
1238 categories.append(QString::fromUtf8(text));
1239 break;
1240 //*******************************************
1241 case ICAL_RRULE_PROPERTY:
1242 // we do need (maybe )start datetime of incidence for recurrence
1243 // such that we can read recurrence only after we read incidence completely
1244 readrec = true;
1245 rectype = icalproperty_get_rrule(p);
1246 break;
1247
1248 case ICAL_EXDATE_PROPERTY:
1249 icaltime = icalproperty_get_exdate(p);
1250 incidence->addExDate(readICalDate(icaltime));
1251 break;
1252
1253 case ICAL_CLASS_PROPERTY:
1254 text = icalproperty_get_class(p);
1255 if (strcmp(text,"PUBLIC") == 0) {
1256 incidence->setSecrecy(Incidence::SecrecyPublic);
1257 } else if (strcmp(text,"CONFIDENTIAL") == 0) {
1258 incidence->setSecrecy(Incidence::SecrecyConfidential);
1259 } else {
1260 incidence->setSecrecy(Incidence::SecrecyPrivate);
1261 }
1262 break;
1263
1264 case ICAL_ATTACH_PROPERTY: // attachments
1265 incidence->addAttachment(readAttachment(p));
1266 break;
1267
1268 default:
1269// kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind
1270// << endl;
1271 break;
1272 }
1273
1274 p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY);
1275 }
1276 if ( readrec ) {
1277 readRecurrenceRule(rectype,incidence);
1278 }
1279 // kpilot stuff
1280// TODO: move this application-specific code to kpilot
1281 QString kp = incidence->nonKDECustomProperty("X-PILOTID");
1282 if (!kp.isNull()) {
1283 incidence->setPilotId(kp.toInt());
1284 }
1285 kp = incidence->nonKDECustomProperty("X-PILOTSTAT");
1286 if (!kp.isNull()) {
1287 incidence->setSyncStatus(kp.toInt());
1288 }
1289 kp = incidence->nonKDECustomProperty("X-ZAURUSID");
1290 if (!kp.isNull()) {
1291 incidence->setZaurusId(kp.toInt());
1292 }
1293
1294 kp = incidence->nonKDECustomProperty("X-ZAURUSUID");
1295 if (!kp.isNull()) {
1296 incidence->setZaurusUid(kp.toInt());
1297 }
1298
1299 kp = incidence->nonKDECustomProperty("X-ZAURUSSTAT");
1300 if (!kp.isNull()) {
1301 incidence->setZaurusStat(kp.toInt());
1302 }
1303
1304 // Cancel backwards compatibility mode for subsequent changes by the application
1305 incidence->recurrence()->setCompatVersion();
1306
1307 // add categories
1308 incidence->setCategories(categories);
1309
1310 // iterate through all alarms
1311 for (icalcomponent *alarm = icalcomponent_get_first_component(parent,ICAL_VALARM_COMPONENT);
1312 alarm;
1313 alarm = icalcomponent_get_next_component(parent,ICAL_VALARM_COMPONENT)) {
1314 readAlarm(alarm,incidence);
1315 }
1316}
1317
1318void ICalFormatImpl::readIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase)
1319{
1320 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
1321
1322 while (p) {
1323 icalproperty_kind kind = icalproperty_isa(p);
1324 switch (kind) {
1325
1326 case ICAL_UID_PROPERTY: // unique id
1327 incidenceBase->setUid(QString::fromUtf8(icalproperty_get_uid(p)));
1328 break;
1329
1330 case ICAL_ORGANIZER_PROPERTY: // organizer
1331 incidenceBase->setOrganizer(QString::fromUtf8(icalproperty_get_organizer(p)));
1332 break;
1333
1334 case ICAL_ATTENDEE_PROPERTY: // attendee
1335 incidenceBase->addAttendee(readAttendee(p));
1336 break;
1337
1338 default:
1339 break;
1340 }
1341
1342 p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY);
1343 }
1344
1345 // custom properties
1346 readCustomProperties(parent, incidenceBase);
1347}
1348
1349void ICalFormatImpl::readCustomProperties(icalcomponent *parent,CustomProperties *properties)
1350{
1351 QMap<QCString, QString> customProperties;
1352
1353 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY);
1354
1355 while (p) {
1356
1357 QString value = QString::fromUtf8(icalproperty_get_x(p));
1358 customProperties[icalproperty_get_name(p)] = value;
1359
1360 p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY);
1361 }
1362
1363 properties->setCustomProperties(customProperties);
1364}
1365
1366void ICalFormatImpl::readRecurrenceRule(struct icalrecurrencetype rrule,Incidence *incidence)
1367{
1368// kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl;
1369
1370 Recurrence *recur = incidence->recurrence();
1371 recur->setCompatVersion(mCalendarVersion);
1372 recur->unsetRecurs();
1373
1374 struct icalrecurrencetype r = rrule;
1375
1376 dumpIcalRecurrence(r);
1377 readRecurrence( r, recur, incidence);
1378}
1379
1380void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur, Incidence *incidence)
1381{
1382 int wkst;
1383 int index = 0;
1384 short day = 0;
1385 QBitArray qba(7);
1386 int frequ = r.freq;
1387 int interv = r.interval;
1388 // preprocessing for odd recurrence definitions
1389
1390 if ( r.freq == ICAL_MONTHLY_RECURRENCE ) {
1391 if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1392 interv = 12;
1393 }
1394 }
1395 if ( r.freq == ICAL_YEARLY_RECURRENCE ) {
1396 if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX && r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX ) {
1397 frequ = ICAL_MONTHLY_RECURRENCE;
1398 interv = 12;
1399 }
1400 }
1401
1402 switch (frequ) {
1403 case ICAL_MINUTELY_RECURRENCE:
1404 if (!icaltime_is_null_time(r.until)) {
1405 recur->setMinutely(interv,readICalDateTime(r.until));
1406 } else {
1407 if (r.count == 0)
1408 recur->setMinutely(interv,-1);
1409 else
1410 recur->setMinutely(interv,r.count);
1411 }
1412 break;
1413 case ICAL_HOURLY_RECURRENCE:
1414 if (!icaltime_is_null_time(r.until)) {
1415 recur->setHourly(interv,readICalDateTime(r.until));
1416 } else {
1417 if (r.count == 0)
1418 recur->setHourly(interv,-1);
1419 else
1420 recur->setHourly(interv,r.count);
1421 }
1422 break;
1423 case ICAL_DAILY_RECURRENCE:
1424 if (!icaltime_is_null_time(r.until)) {
1425 recur->setDaily(interv,readICalDate(r.until));
1426 } else {
1427 if (r.count == 0)
1428 recur->setDaily(interv,-1);
1429 else
1430 recur->setDaily(interv,r.count);
1431 }
1432 break;
1433 case ICAL_WEEKLY_RECURRENCE:
1434 // kdDebug(5800) << "WEEKLY_RECURRENCE" << endl;
1435 wkst = (r.week_start + 5)%7 + 1;
1436 if (!icaltime_is_null_time(r.until)) {
1437 recur->setWeekly(interv,qba,readICalDate(r.until),wkst);
1438 } else {
1439 if (r.count == 0)
1440 recur->setWeekly(interv,qba,-1,wkst);
1441 else
1442 recur->setWeekly(interv,qba,r.count,wkst);
1443 }
1444 if ( r.by_day[0] == ICAL_RECURRENCE_ARRAY_MAX) {
1445 int wday = incidence->dtStart().date().dayOfWeek ()-1;
1446 //qDebug("weekly error found ");
1447 qba.setBit(wday);
1448 } else {
1449 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1450 // kdDebug(5800) << " " << day << endl;
1451 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
1452 }
1453 }
1454 break;
1455 case ICAL_MONTHLY_RECURRENCE:
1456
1457 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1458 if (!icaltime_is_null_time(r.until)) {
1459 recur->setMonthly(Recurrence::rMonthlyPos,interv,
1460 readICalDate(r.until));
1461 } else {
1462 if (r.count == 0)
1463 recur->setMonthly(Recurrence::rMonthlyPos,interv,-1);
1464 else
1465 recur->setMonthly(Recurrence::rMonthlyPos,interv,r.count);
1466 }
1467 bool useSetPos = false;
1468 short pos = 0;
1469 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1470 // kdDebug(5800) << "----a " << index << ": " << day << endl;
1471 pos = icalrecurrencetype_day_position(day);
1472 if (pos) {
1473 day = icalrecurrencetype_day_day_of_week(day);
1474 QBitArray ba(7); // don't wipe qba
1475 ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
1476 recur->addMonthlyPos(pos,ba);
1477 } else {
1478 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
1479 useSetPos = true;
1480 }
1481 }
1482 if (useSetPos) {
1483 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1484 recur->addMonthlyPos(r.by_set_pos[0],qba);
1485 }
1486 }
1487 } else if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1488 if (!icaltime_is_null_time(r.until)) {
1489 recur->setMonthly(Recurrence::rMonthlyDay,interv,
1490 readICalDate(r.until));
1491 } else {
1492 if (r.count == 0)
1493 recur->setMonthly(Recurrence::rMonthlyDay,interv,-1);
1494 else
1495 recur->setMonthly(Recurrence::rMonthlyDay,interv,r.count);
1496 }
1497 while((day = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1498 // kdDebug(5800) << "----b " << day << endl;
1499 recur->addMonthlyDay(day);
1500 }
1501 }
1502 break;
1503 case ICAL_YEARLY_RECURRENCE:
1504 if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1505 if (!icaltime_is_null_time(r.until)) {
1506 recur->setYearly(Recurrence::rYearlyDay,interv,
1507 readICalDate(r.until));
1508 } else {
1509 if (r.count == 0)
1510 recur->setYearly(Recurrence::rYearlyDay,interv,-1);
1511 else
1512 recur->setYearly(Recurrence::rYearlyDay,interv,r.count);
1513 }
1514 while((day = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1515 recur->addYearlyNum(day);
1516 }
1517 } else if ( true /*r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX*/) {
1518 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1519 if (!icaltime_is_null_time(r.until)) {
1520 recur->setYearly(Recurrence::rYearlyPos,interv,
1521 readICalDate(r.until));
1522 } else {
1523 if (r.count == 0)
1524 recur->setYearly(Recurrence::rYearlyPos,interv,-1);
1525 else
1526 recur->setYearly(Recurrence::rYearlyPos,interv,r.count);
1527 }
1528 bool useSetPos = false;
1529 short pos = 0;
1530 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1531 // kdDebug(5800) << "----a " << index << ": " << day << endl;
1532 pos = icalrecurrencetype_day_position(day);
1533 if (pos) {
1534 day = icalrecurrencetype_day_day_of_week(day);
1535 QBitArray ba(7); // don't wipe qba
1536 ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
1537 recur->addYearlyMonthPos(pos,ba);
1538 } else {
1539 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
1540 useSetPos = true;
1541 }
1542 }
1543 if (useSetPos) {
1544 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1545 recur->addYearlyMonthPos(r.by_set_pos[0],qba);
1546 }
1547 }
1548 } else {
1549 if (!icaltime_is_null_time(r.until)) {
1550 recur->setYearly(Recurrence::rYearlyMonth,interv,
1551 readICalDate(r.until));
1552 } else {
1553 if (r.count == 0)
1554 recur->setYearly(Recurrence::rYearlyMonth,interv,-1);
1555 else
1556 recur->setYearly(Recurrence::rYearlyMonth,interv,r.count);
1557 }
1558 }
1559 if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX ) {
1560 index = 0;
1561 while((day = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1562 recur->addYearlyNum(day);
1563 }
1564 } else {
1565 recur->addYearlyNum(incidence->dtStart().date().month());
1566 }
1567 }
1568 break;
1569 default:
1570 ;
1571 break;
1572 }
1573}
1574
1575void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence)
1576{
1577 //kdDebug(5800) << "Read alarm for " << incidence->summary() << endl;
1578
1579 Alarm* ialarm = incidence->newAlarm();
1580 ialarm->setRepeatCount(0);
1581 ialarm->setEnabled(true);
1582
1583 // Determine the alarm's action type
1584 icalproperty *p = icalcomponent_get_first_property(alarm,ICAL_ACTION_PROPERTY);
1585 if ( !p ) {
1586 return;
1587 }
1588
1589 icalproperty_action action = icalproperty_get_action(p);
1590 Alarm::Type type = Alarm::Display;
1591 switch ( action ) {
1592 case ICAL_ACTION_DISPLAY: type = Alarm::Display; break;
1593 case ICAL_ACTION_AUDIO: type = Alarm::Audio; break;
1594 case ICAL_ACTION_PROCEDURE: type = Alarm::Procedure; break;
1595 case ICAL_ACTION_EMAIL: type = Alarm::Email; break;
1596 default:
1597 ;
1598 return;
1599 }
1600 ialarm->setType(type);
1601
1602 p = icalcomponent_get_first_property(alarm,ICAL_ANY_PROPERTY);
1603 while (p) {
1604 icalproperty_kind kind = icalproperty_isa(p);
1605
1606 switch (kind) {
1607 case ICAL_TRIGGER_PROPERTY: {
1608 icaltriggertype trigger = icalproperty_get_trigger(p);
1609 if (icaltime_is_null_time(trigger.time)) {
1610 if (icaldurationtype_is_null_duration(trigger.duration)) {
1611 kdDebug(5800) << "ICalFormatImpl::readAlarm(): Trigger has no time and no duration." << endl;
1612 } else {
1613 Duration duration = icaldurationtype_as_int( trigger.duration );
1614 icalparameter *param = icalproperty_get_first_parameter(p,ICAL_RELATED_PARAMETER);
1615 if (param && icalparameter_get_related(param) == ICAL_RELATED_END)
1616 ialarm->setEndOffset(duration);
1617 else
1618 ialarm->setStartOffset(duration);
1619 }
1620 } else {
1621 ialarm->setTime(readICalDateTime(trigger.time));
1622 }
1623 break;
1624 }
1625 case ICAL_DURATION_PROPERTY: {
1626 icaldurationtype duration = icalproperty_get_duration(p);
1627 ialarm->setSnoozeTime(icaldurationtype_as_int(duration)/60);
1628 break;
1629 }
1630 case ICAL_REPEAT_PROPERTY:
1631 ialarm->setRepeatCount(icalproperty_get_repeat(p));
1632 break;
1633
1634 // Only in DISPLAY and EMAIL and PROCEDURE alarms
1635 case ICAL_DESCRIPTION_PROPERTY: {
1636 QString description = QString::fromUtf8(icalproperty_get_description(p));
1637 switch ( action ) {
1638 case ICAL_ACTION_DISPLAY:
1639 ialarm->setText( description );
1640 break;
1641 case ICAL_ACTION_PROCEDURE:
1642 ialarm->setProgramArguments( description );
1643 break;
1644 case ICAL_ACTION_EMAIL:
1645 ialarm->setMailText( description );
1646 break;
1647 default:
1648 break;
1649 }
1650 break;
1651 }
1652 // Only in EMAIL alarm
1653 case ICAL_SUMMARY_PROPERTY:
1654 ialarm->setMailSubject(QString::fromUtf8(icalproperty_get_summary(p)));
1655 break;
1656
1657 // Only in EMAIL alarm
1658 case ICAL_ATTENDEE_PROPERTY: {
1659 QString email = QString::fromUtf8(icalproperty_get_attendee(p));
1660 QString name;
1661 icalparameter *param = icalproperty_get_first_parameter(p,ICAL_CN_PARAMETER);
1662 if (param) {
1663 name = QString::fromUtf8(icalparameter_get_cn(param));
1664 }
1665 ialarm->addMailAddress(Person(name, email));
1666 break;
1667 }
1668 // Only in AUDIO and EMAIL and PROCEDURE alarms
1669 case ICAL_ATTACH_PROPERTY: {
1670 icalattachtype *attach = icalproperty_get_attach(p);
1671 QString url = QFile::decodeName(icalattachtype_get_url(attach));
1672 switch ( action ) {
1673 case ICAL_ACTION_AUDIO:
1674 ialarm->setAudioFile( url );
1675 break;
1676 case ICAL_ACTION_PROCEDURE:
1677 ialarm->setProgramFile( url );
1678 break;
1679 case ICAL_ACTION_EMAIL:
1680 ialarm->addMailAttachment( url );
1681 break;
1682 default:
1683 break;
1684 }
1685 break;
1686 }
1687 default:
1688 break;
1689 }
1690
1691 p = icalcomponent_get_next_property(alarm,ICAL_ANY_PROPERTY);
1692 }
1693
1694 // custom properties
1695 readCustomProperties(alarm, ialarm);
1696
1697 // TODO: check for consistency of alarm properties
1698}
1699
1700icaltimetype ICalFormatImpl::writeICalDate(const QDate &date)
1701{
1702 icaltimetype t;
1703
1704 t.year = date.year();
1705 t.month = date.month();
1706 t.day = date.day();
1707
1708 t.hour = 0;
1709 t.minute = 0;
1710 t.second = 0;
1711
1712 t.is_date = 1;
1713
1714 t.is_utc = 0;
1715
1716 t.zone = 0;
1717
1718 return t;
1719}
1720
1721icaltimetype ICalFormatImpl::writeICalDateTime(const QDateTime &dt )
1722{
1723 icaltimetype t;
1724 t.is_date = 0;
1725 t.zone = 0;
1726 QDateTime datetime;
1727 if ( mParent->utc() ) {
1728 int offset = KGlobal::locale()->localTimeOffset( dt );
1729 datetime = dt.addSecs ( -offset*60);
1730 t.is_utc = 1;
1731 }
1732 else {
1733 datetime = dt;
1734 t.is_utc = 0;
1735
1736 }
1737 t.year = datetime.date().year();
1738 t.month = datetime.date().month();
1739 t.day = datetime.date().day();
1740
1741 t.hour = datetime.time().hour();
1742 t.minute = datetime.time().minute();
1743 t.second = datetime.time().second();
1744
1745 //qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() );
1746
1747// if ( mParent->utc() ) {
1748// datetime = KGlobal::locale()->localTime( dt );
1749// qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() );
1750// if (mParent->timeZoneId().isEmpty())
1751// t = icaltime_as_utc(t, 0);
1752// else
1753// t = icaltime_as_utc(t,mParent->timeZoneId().local8Bit());
1754// }
1755
1756 return t;
1757}
1758
1759QDateTime ICalFormatImpl::readICalDateTime(icaltimetype t)
1760{
1761 QDateTime dt (QDate(t.year,t.month,t.day),
1762 QTime(t.hour,t.minute,t.second) );
1763
1764 if (t.is_utc) {
1765 int offset = KGlobal::locale()->localTimeOffset( dt );
1766 dt = dt.addSecs ( offset*60);
1767 }
1768
1769 return dt;
1770}
1771
1772QDate ICalFormatImpl::readICalDate(icaltimetype t)
1773{
1774 return QDate(t.year,t.month,t.day);
1775}
1776
1777icaldurationtype ICalFormatImpl::writeICalDuration(int seconds)
1778{
1779 icaldurationtype d;
1780
1781 d.weeks = seconds % gSecondsPerWeek;
1782 seconds -= d.weeks * gSecondsPerWeek;
1783 d.days = seconds % gSecondsPerDay;
1784 seconds -= d.days * gSecondsPerDay;
1785 d.hours = seconds % gSecondsPerHour;
1786 seconds -= d.hours * gSecondsPerHour;
1787 d.minutes = seconds % gSecondsPerMinute;
1788 seconds -= d.minutes * gSecondsPerMinute;
1789 d.seconds = seconds;
1790 d.is_neg = 0;
1791
1792 return d;
1793}
1794
1795int ICalFormatImpl::readICalDuration(icaldurationtype d)
1796{
1797 int result = 0;
1798
1799 result += d.weeks * gSecondsPerWeek;
1800 result += d.days * gSecondsPerDay;
1801 result += d.hours * gSecondsPerHour;
1802 result += d.minutes * gSecondsPerMinute;
1803 result += d.seconds;
1804
1805 if (d.is_neg) result *= -1;
1806
1807 return result;
1808}
1809
1810icalcomponent *ICalFormatImpl::createCalendarComponent(Calendar *cal)
1811{
1812 icalcomponent *calendar;
1813
1814 // Root component
1815 calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
1816
1817 icalproperty *p;
1818
1819 // Product Identifier
1820 p = icalproperty_new_prodid(CalFormat::productId().utf8());
1821 icalcomponent_add_property(calendar,p);
1822
1823 // TODO: Add time zone
1824
1825 // iCalendar version (2.0)
1826 p = icalproperty_new_version(const_cast<char *>(_ICAL_VERSION));
1827 icalcomponent_add_property(calendar,p);
1828
1829 // Custom properties
1830 if( cal != 0 )
1831 writeCustomProperties(calendar, cal);
1832
1833 return calendar;
1834}
1835
1836
1837
1838// take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc.
1839// and break it down from its tree-like format into the dictionary format
1840// that is used internally in the ICalFormatImpl.
1841bool ICalFormatImpl::populate( Calendar *cal, icalcomponent *calendar)
1842{
1843 // this function will populate the caldict dictionary and other event
1844 // lists. It turns vevents into Events and then inserts them.
1845
1846 if (!calendar) return false;
1847
1848// TODO: check for METHOD
1849#if 0
1850 if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) {
1851 char *methodType = 0;
1852 methodType = fakeCString(vObjectUStringZValue(curVO));
1853 if (mEnableDialogs)
1854 KMessageBox::information(mTopWidget,
1855 i18n("This calendar is an iTIP transaction of type \"%1\".")
1856 .arg(methodType),
1857 i18n("%1: iTIP Transaction").arg(CalFormat::application()));
1858 delete methodType;
1859 }
1860#endif
1861
1862 icalproperty *p;
1863
1864 p = icalcomponent_get_first_property(calendar,ICAL_PRODID_PROPERTY);
1865 if (!p) {
1866// TODO: does no PRODID really matter?
1867// mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
1868// return false;
1869 mLoadedProductId = "";
1870 mCalendarVersion = 0;
1871 } else {
1872 mLoadedProductId = QString::fromUtf8(icalproperty_get_prodid(p));
1873 mCalendarVersion = CalFormat::calendarVersion(mLoadedProductId);
1874
1875 delete mCompat;
1876 mCompat = CompatFactory::createCompat( mLoadedProductId );
1877 }
1878
1879// TODO: check for unknown PRODID
1880#if 0
1881 if (!mCalendarVersion
1882 && CalFormat::productId() != mLoadedProductId) {
1883 // warn the user that we might have trouble reading non-known calendar.
1884 if (mEnableDialogs)
1885 KMessageBox::information(mTopWidget,
1886 i18n("This vCalendar file was not created by KOrganizer "
1887 "or any other product we support. Loading anyway..."),
1888 i18n("%1: Unknown vCalendar Vendor").arg(CalFormat::application()));
1889 }
1890#endif
1891
1892 p = icalcomponent_get_first_property(calendar,ICAL_VERSION_PROPERTY);
1893 if (!p) {
1894 mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
1895 return false;
1896 } else {
1897 const char *version = icalproperty_get_version(p);
1898
1899 if (strcmp(version,"1.0") == 0) {
1900 mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1,
1901 i18n("Expected iCalendar format")));
1902 return false;
1903 } else if (strcmp(version,"2.0") != 0) {
1904 mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
1905 return false;
1906 }
1907 }
1908
1909
1910// TODO: check for calendar format version
1911#if 0
1912 // warn the user we might have trouble reading this unknown version.
1913 if ((curVO = isAPropertyOf(vcal, VCVersionProp)) != 0) {
1914 char *s = fakeCString(vObjectUStringZValue(curVO));
1915 if (strcmp(_VCAL_VERSION, s) != 0)
1916 if (mEnableDialogs)
1917 KMessageBox::sorry(mTopWidget,
1918 i18n("This vCalendar file has version %1.\n"
1919 "We only support %2.")
1920 .arg(s).arg(_VCAL_VERSION),
1921 i18n("%1: Unknown vCalendar Version").arg(CalFormat::application()));
1922 deleteStr(s);
1923 }
1924#endif
1925
1926 // custom properties
1927 readCustomProperties(calendar, cal);
1928
1929// TODO: set time zone
1930#if 0
1931 // set the time zone
1932 if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) {
1933 char *s = fakeCString(vObjectUStringZValue(curVO));
1934 cal->setTimeZone(s);
1935 deleteStr(s);
1936 }
1937#endif
1938
1939 // Store all events with a relatedTo property in a list for post-processing
1940 mEventsRelate.clear();
1941 mTodosRelate.clear();
1942 // TODO: make sure that only actually added ecvens go to this lists.
1943
1944 icalcomponent *c;
1945
1946 // Iterate through all todos
1947 c = icalcomponent_get_first_component(calendar,ICAL_VTODO_COMPONENT);
1948 while (c) {
1949// kdDebug(5800) << "----Todo found" << endl;
1950 Todo *todo = readTodo(c);
1951 if (!cal->todo(todo->uid())) cal->addTodo(todo);
1952 c = icalcomponent_get_next_component(calendar,ICAL_VTODO_COMPONENT);
1953 }
1954
1955 // Iterate through all events
1956 c = icalcomponent_get_first_component(calendar,ICAL_VEVENT_COMPONENT);
1957 while (c) {
1958// kdDebug(5800) << "----Event found" << endl;
1959 Event *event = readEvent(c);
1960 if (!cal->event(event->uid())) cal->addEvent(event);
1961 c = icalcomponent_get_next_component(calendar,ICAL_VEVENT_COMPONENT);
1962 }
1963
1964 // Iterate through all journals
1965 c = icalcomponent_get_first_component(calendar,ICAL_VJOURNAL_COMPONENT);
1966 while (c) {
1967// kdDebug(5800) << "----Journal found" << endl;
1968 Journal *journal = readJournal(c);
1969 if (!cal->journal(journal->uid())) cal->addJournal(journal);
1970 c = icalcomponent_get_next_component(calendar,ICAL_VJOURNAL_COMPONENT);
1971 }
1972
1973#if 0
1974 initPropIterator(&i, vcal);
1975
1976 // go through all the vobjects in the vcal
1977 while (moreIteration(&i)) {
1978 curVO = nextVObject(&i);
1979
1980 /************************************************************************/
1981
1982 // now, check to see that the object is an event or todo.
1983 if (strcmp(vObjectName(curVO), VCEventProp) == 0) {
1984
1985 if ((curVOProp = isAPropertyOf(curVO, KPilotStatusProp)) != 0) {
1986 char *s;
1987 s = fakeCString(vObjectUStringZValue(curVOProp));
1988 // check to see if event was deleted by the kpilot conduit
1989 if (atoi(s) == Event::SYNCDEL) {
1990 deleteStr(s);
1991 goto SKIP;
1992 }
1993 deleteStr(s);
1994 }
1995
1996 // this code checks to see if we are trying to read in an event
1997 // that we already find to be in the calendar. If we find this
1998 // to be the case, we skip the event.
1999 if ((curVOProp = isAPropertyOf(curVO, VCUniqueStringProp)) != 0) {
2000 char *s = fakeCString(vObjectUStringZValue(curVOProp));
2001 QString tmpStr(s);
2002 deleteStr(s);
2003
2004 if (cal->event(tmpStr)) {
2005 goto SKIP;
2006 }
2007 if (cal->todo(tmpStr)) {
2008 goto SKIP;
2009 }
2010 }
2011
2012 if ((!(curVOProp = isAPropertyOf(curVO, VCDTstartProp))) &&
2013 (!(curVOProp = isAPropertyOf(curVO, VCDTendProp)))) {
2014 kdDebug(5800) << "found a VEvent with no DTSTART and no DTEND! Skipping..." << endl;
2015 goto SKIP;
2016 }
2017
2018 anEvent = VEventToEvent(curVO);
2019 // we now use addEvent instead of insertEvent so that the
2020 // signal/slot get connected.
2021 if (anEvent)
2022 cal->addEvent(anEvent);
2023 else {
2024 // some sort of error must have occurred while in translation.
2025 goto SKIP;
2026 }
2027 } else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) {
2028 anEvent = VTodoToEvent(curVO);
2029 cal->addTodo(anEvent);
2030 } else if ((strcmp(vObjectName(curVO), VCVersionProp) == 0) ||
2031 (strcmp(vObjectName(curVO), VCProdIdProp) == 0) ||
2032 (strcmp(vObjectName(curVO), VCTimeZoneProp) == 0)) {
2033 // do nothing, we know these properties and we want to skip them.
2034 // we have either already processed them or are ignoring them.
2035 ;
2036 } else {
2037 ;
2038 }
2039 SKIP:
2040 ;
2041 } // while
2042#endif
2043
2044 // Post-Process list of events with relations, put Event objects in relation
2045 Event *ev;
2046 for ( ev=mEventsRelate.first(); ev != 0; ev=mEventsRelate.next() ) {
2047 ev->setRelatedTo(cal->event(ev->relatedToUid()));
2048 }
2049 Todo *todo;
2050 for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) {
2051 todo->setRelatedTo(cal->todo(todo->relatedToUid()));
2052 }
2053
2054 return true;
2055}
2056
2057QString ICalFormatImpl::extractErrorProperty(icalcomponent *c)
2058{
2059// kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: "
2060// << icalcomponent_as_ical_string(c) << endl;
2061
2062 QString errorMessage;
2063
2064 icalproperty *error;
2065 error = icalcomponent_get_first_property(c,ICAL_XLICERROR_PROPERTY);
2066 while(error) {
2067 errorMessage += icalproperty_get_xlicerror(error);
2068 errorMessage += "\n";
2069 error = icalcomponent_get_next_property(c,ICAL_XLICERROR_PROPERTY);
2070 }
2071
2072// kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " << errorMessage << endl;
2073
2074 return errorMessage;
2075}
2076
2077void ICalFormatImpl::dumpIcalRecurrence(icalrecurrencetype r)
2078{
2079 int i;
2080
2081
2082 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2083 int index = 0;
2084 QString out = " By Day: ";
2085 while((i = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2086 out.append(QString::number(i) + " ");
2087 }
2088 }
2089 if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2090 int index = 0;
2091 QString out = " By Month Day: ";
2092 while((i = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2093 out.append(QString::number(i) + " ");
2094 }
2095 }
2096 if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2097 int index = 0;
2098 QString out = " By Year Day: ";
2099 while((i = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2100 out.append(QString::number(i) + " ");
2101 }
2102 }
2103 if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2104 int index = 0;
2105 QString out = " By Month: ";
2106 while((i = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2107 out.append(QString::number(i) + " ");
2108 }
2109 }
2110 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2111 int index = 0;
2112 QString out = " By Set Pos: ";
2113 while((i = r.by_set_pos[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2114 out.append(QString::number(i) + " ");
2115 }
2116 }
2117}
2118
2119icalcomponent *ICalFormatImpl::createScheduleComponent(IncidenceBase *incidence,
2120 Scheduler::Method method)
2121{
2122 icalcomponent *message = createCalendarComponent();
2123
2124 icalproperty_method icalmethod = ICAL_METHOD_NONE;
2125
2126 switch (method) {
2127 case Scheduler::Publish:
2128 icalmethod = ICAL_METHOD_PUBLISH;
2129 break;
2130 case Scheduler::Request:
2131 icalmethod = ICAL_METHOD_REQUEST;
2132 break;
2133 case Scheduler::Refresh:
2134 icalmethod = ICAL_METHOD_REFRESH;
2135 break;
2136 case Scheduler::Cancel:
2137 icalmethod = ICAL_METHOD_CANCEL;
2138 break;
2139 case Scheduler::Add:
2140 icalmethod = ICAL_METHOD_ADD;
2141 break;
2142 case Scheduler::Reply:
2143 icalmethod = ICAL_METHOD_REPLY;
2144 break;
2145 case Scheduler::Counter:
2146 icalmethod = ICAL_METHOD_COUNTER;
2147 break;
2148 case Scheduler::Declinecounter:
2149 icalmethod = ICAL_METHOD_DECLINECOUNTER;
2150 break;
2151 default:
2152
2153 return message;
2154 }
2155
2156 icalcomponent_add_property(message,icalproperty_new_method(icalmethod));
2157
2158 // TODO: check, if dynamic cast is required
2159 if(incidence->type() == "Todo") {
2160 Todo *todo = static_cast<Todo *>(incidence);
2161 icalcomponent_add_component(message,writeTodo(todo));
2162 }
2163 if(incidence->type() == "Event") {
2164 Event *event = static_cast<Event *>(incidence);
2165 icalcomponent_add_component(message,writeEvent(event));
2166 }
2167 if(incidence->type() == "FreeBusy") {
2168 FreeBusy *freebusy = static_cast<FreeBusy *>(incidence);
2169 icalcomponent_add_component(message,writeFreeBusy(freebusy, method));
2170 }
2171
2172 return message;
2173}