24 #include "incidenceformatter.h"
26 #include <libkcal/attachment.h>
27 #include <libkcal/event.h>
28 #include <libkcal/todo.h>
29 #include <libkcal/journal.h>
31 #include <libkcal/calendarlocal.h>
32 #include <libkcal/icalformat.h>
33 #include <libkcal/freebusy.h>
36 #include <libemailfunctions/email.h>
38 #include <ktnef/ktnefparser.h>
39 #include <ktnef/ktnefmessage.h>
40 #include <ktnef/ktnefdefs.h>
41 #include <tdeabc/phonenumber.h>
42 #include <tdeabc/vcardconverter.h>
43 #include <tdeabc/stdaddressbook.h>
45 #include <tdeapplication.h>
46 #include <tdeemailsettings.h>
48 #include <tdelocale.h>
49 #include <tdeglobal.h>
50 #include <kiconloader.h>
51 #include <kcalendarsystem.h>
52 #include <kmimetype.h>
55 #include <tqstylesheet.h>
56 #include <tqdatetime.h>
67 static TQString htmlAddLink(
const TQString &ref,
const TQString &text,
70 TQString tmpStr(
"<a href=\"" + ref +
"\">" + text +
"</a>" );
71 if ( newline ) tmpStr +=
"\n";
75 static TQString htmlAddTag(
const TQString & tag,
const TQString & text )
77 int numLineBreaks = text.contains(
"\n" );
78 TQString str =
"<" + tag +
">";
79 TQString tmpText = text;
80 TQString tmpStr = str;
81 if( numLineBreaks >= 0 ) {
82 if ( numLineBreaks > 0) {
85 for(
int i = 0; i <= numLineBreaks; i++ ) {
86 pos = tmpText.find(
"\n" );
87 tmp = tmpText.left( pos );
88 tmpText = tmpText.right( tmpText.length() - pos - 1 );
89 tmpStr += tmp +
"<br>";
95 tmpStr +=
"</" + tag +
">";
99 static bool iamAttendee(
Attendee *attendee )
104 KEMailSettings settings;
105 TQStringList profiles = settings.profiles();
106 for( TQStringList::Iterator it=profiles.begin(); it!=profiles.end(); ++it ) {
107 settings.setProfile( *it );
108 if ( settings.getSetting( KEMailSettings::EmailAddress ) == attendee->email() ) {
116 static bool iamOrganizer(
Incidence *incidence )
125 KEMailSettings settings;
126 TQStringList profiles = settings.profiles();
127 for( TQStringList::Iterator it=profiles.begin(); it!=profiles.end(); ++it ) {
128 settings.setProfile( *it );
129 if ( settings.getSetting( KEMailSettings::EmailAddress ) == incidence->organizer().email() ) {
137 static bool senderIsOrganizer(
Incidence *incidence,
const TQString &sender )
141 if ( !incidence || sender.isEmpty() ) {
145 TQString senderName, senderEmail;
146 if ( KPIM::getNameAndMail( sender, senderName, senderEmail ) ) {
148 if ( incidence->organizer().email() != senderEmail &&
149 incidence->organizer().name() != senderName ) {
156 static TQString firstAttendeeName(
Incidence *incidence,
const TQString &defName )
164 if( attendees.count() > 0 ) {
165 Attendee *attendee = *attendees.begin();
166 name = attendee->name();
167 if ( name.isEmpty() ) {
168 name = attendee->email();
170 if ( name.isEmpty() ) {
181 static TQString displayViewLinkPerson(
const TQString& email, TQString name, TQString uid )
185 if ( !email.isEmpty() && ( name.isEmpty() || uid.isEmpty() ) ) {
186 TDEABC::AddressBook *add_book = TDEABC::StdAddressBook::self(
true );
187 TDEABC::Addressee::List addressList = add_book->findByEmail( email );
188 if ( !addressList.isEmpty() ) {
189 TDEABC::Addressee o = addressList.first();
190 if ( !o.isEmpty() && addressList.size() < 2 ) {
191 if ( name.isEmpty() ) {
193 name = o.formattedName();
205 if ( !uid.isEmpty() ) {
207 if ( name.isEmpty() ) {
209 tmpString += htmlAddLink(
"uid:" + uid, email );
211 tmpString += htmlAddLink(
"uid:" + uid, name );
215 tmpString += ( name.isEmpty() ? email : name );
219 if ( !email.isEmpty() ) {
221 mailto.setProtocol(
"mailto" );
222 mailto.setPath( email );
223 const TQString iconPath =
224 TDEGlobal::iconLoader()->iconPath(
"mail-message-new", TDEIcon::Small );
225 tmpString +=
" " +
226 htmlAddLink( mailto.url(),
227 "<img valign=\"top\" src=\"" + iconPath +
"\">" );
233 static TQString displayViewFormatAttendeeRoleList(
Incidence *incidence, Attendee::Role role )
236 Attendee::List::ConstIterator it;
239 for ( it = attendees.begin(); it != attendees.end(); ++it ) {
241 if ( a->
role() != role ) {
245 if ( a->email() == incidence->organizer().email() ) {
249 tmpStr += displayViewLinkPerson( a->email(), a->name(), a->
uid() );
251 tmpStr += i18n(
" (delegated by %1)" ).arg( a->
delegator() );
254 tmpStr += i18n(
" (delegated to %1)" ).arg( a->
delegate() );
258 if ( tmpStr.endsWith(
"<br>" ) ) {
259 tmpStr.truncate( tmpStr.length() - 4 );
264 static TQString displayViewFormatAttendees(
Incidence *incidence )
266 TQString tmpStr, str;
269 int attendeeCount = incidence->
attendees().count();
270 if ( attendeeCount > 1 ||
271 ( attendeeCount == 1 &&
272 incidence->organizer().email() != incidence->
attendees().first()->email() ) ) {
274 tmpStr +=
"<td><b>" + i18n(
"Organizer:" ) +
"</b></td>";
276 displayViewLinkPerson( incidence->organizer().email(),
277 incidence->organizer().name(),
284 str = displayViewFormatAttendeeRoleList( incidence, Attendee::Chair );
285 if ( !str.isEmpty() ) {
287 tmpStr +=
"<td><b>" + i18n(
"Chair:" ) +
"</b></td>";
288 tmpStr +=
"<td>" + str +
"</td>";
293 str = displayViewFormatAttendeeRoleList( incidence, Attendee::ReqParticipant );
294 if ( !str.isEmpty() ) {
296 tmpStr +=
"<td><b>" + i18n(
"Required Participants:" ) +
"</b></td>";
297 tmpStr +=
"<td>" + str +
"</td>";
302 str = displayViewFormatAttendeeRoleList( incidence, Attendee::OptParticipant );
303 if ( !str.isEmpty() ) {
305 tmpStr +=
"<td><b>" + i18n(
"Optional Participants:" ) +
"</b></td>";
306 tmpStr +=
"<td>" + str +
"</td>";
311 str = displayViewFormatAttendeeRoleList( incidence, Attendee::NonParticipant );
312 if ( !str.isEmpty() ) {
314 tmpStr +=
"<td><b>" + i18n(
"Observers:" ) +
"</b></td>";
315 tmpStr +=
"<td>" + str +
"</td>";
322 static TQString displayViewFormatAttachments(
Incidence *incidence )
326 Attachment::List::ConstIterator it;
328 for( it = as.begin(); it != as.end(); ++it ) {
330 if ( (*it)->isUri() ) {
332 if ( (*it)->uri().startsWith(
"kmail:" ) ) {
333 name = i18n(
"Show mail" );
335 if ( (*it)->label().isEmpty() ) {
338 name = (*it)->label();
341 tmpStr += htmlAddLink( (*it)->uri(), name );
343 tmpStr += htmlAddLink(
"ATTACH:" + incidence->
uid() +
':' + (*it)->label(),
344 (*it)->label(),
false );
346 if ( count < as.count() ) {
353 static TQString displayViewFormatCategories(
Incidence *incidence )
359 static TQString displayViewFormatCreationDate(
Incidence *incidence )
361 return i18n(
"Creation date: %1" ).
362 arg( IncidenceFormatter::dateTimeToString( incidence->
created(),
false,
true ) );
365 static TQString displayViewFormatBirthday(
Event *event )
374 TQString uid =
event->customProperty(
"KABC",
"UID-1");
375 TQString name =
event->customProperty(
"KABC",
"NAME-1");
376 TQString email=
event->customProperty(
"KABC",
"EMAIL-1");
378 TQString tmpStr = displayViewLinkPerson( email, name, uid );
381 uid =
event->customProperty(
"KABC",
"UID-2");
382 name =
event->customProperty(
"KABC",
"NAME-2");
383 email=
event->customProperty(
"KABC",
"EMAIL-2");
385 tmpStr += displayViewLinkPerson( email, name, uid );
391 static TQString displayViewFormatHeader(
Incidence *incidence )
393 TQString tmpStr =
"<table><tr>";
399 if ( incidence->type() ==
"Event" ) {
402 if ( incidence->
customProperty(
"KABC",
"ANNIVERSARY" ) ==
"YES" ) {
404 TDEGlobal::iconLoader()->iconPath(
"calendaranniversary", TDEIcon::Small );
406 iconPath = TDEGlobal::iconLoader()->iconPath(
"calendarbirthday", TDEIcon::Small );
409 iconPath = TDEGlobal::iconLoader()->iconPath(
"appointment", TDEIcon::Small );
411 tmpStr +=
"<img valign=\"top\" src=\"" + iconPath +
"\">";
413 if ( incidence->type() ==
"Todo" ) {
414 tmpStr +=
"<img valign=\"top\" src=\"" +
415 TDEGlobal::iconLoader()->iconPath(
"todo", TDEIcon::Small ) +
418 if ( incidence->type() ==
"Journal" ) {
419 tmpStr +=
"<img valign=\"top\" src=\"" +
420 TDEGlobal::iconLoader()->iconPath(
"journal", TDEIcon::Small ) +
424 tmpStr +=
"<img valign=\"top\" src=\"" +
425 TDEGlobal::iconLoader()->iconPath(
"bell", TDEIcon::Small ) +
429 tmpStr +=
"<img valign=\"top\" src=\"" +
430 TDEGlobal::iconLoader()->iconPath(
"recur", TDEIcon::Small ) +
434 tmpStr +=
"<img valign=\"top\" src=\"" +
435 TDEGlobal::iconLoader()->iconPath(
"readonlyevent", TDEIcon::Small ) +
443 tmpStr +=
"<b><u>" + incidence->
summary() +
"</u></b>";
446 tmpStr +=
"</tr></table>";
451 static TQString displayViewFormatEvent(
Calendar *calendar,
Event *event,
458 TQString tmpStr = displayViewFormatHeader( event );
461 tmpStr +=
"<col width=\"25%\"/>";
462 tmpStr +=
"<col width=\"75%\"/>";
466 if ( !calStr.isEmpty() ) {
468 tmpStr +=
"<td><b>" + i18n(
"Calendar:" ) +
"</b></td>";
469 tmpStr +=
"<td>" + calStr +
"</td>";
474 if ( !event->
location().isEmpty() ) {
476 tmpStr +=
"<td><b>" + i18n(
"Location:" ) +
"</b></td>";
477 tmpStr +=
"<td>" +
event->location() +
"</td>";
481 TQDateTime startDt =
event->dtStart();
482 TQDateTime endDt =
event->dtEnd();
484 if ( date.isValid() ) {
485 TQDateTime dt( date, TQTime( 0, 0, 0 ) );
486 int diffDays = startDt.daysTo( dt );
487 dt = dt.addSecs( -1 );
490 endDt = endDt.addDays( diffDays );
491 if ( startDt > endDt ) {
493 endDt = startDt.addDays( event->
dtStart().daysTo( event->
dtEnd() ) );
502 tmpStr +=
"<td><b>" + i18n(
"Date:" ) +
"</b></td>";
504 i18n(
"<beginDate> - <endDate>",
"%1 - %2").
505 arg( IncidenceFormatter::dateToString( startDt,
false ) ).
506 arg( IncidenceFormatter::dateToString( endDt,
false ) ) +
509 tmpStr +=
"<td><b>" + i18n(
"Date:" ) +
"</b></td>";
511 i18n(
"date as string",
"%1").
512 arg( IncidenceFormatter::dateToString( startDt,
false ) ) +
517 tmpStr +=
"<td><b>" + i18n(
"Date:" ) +
"</b></td>";
519 i18n(
"<beginDate> - <endDate>",
"%1 - %2").
520 arg( IncidenceFormatter::dateToString( startDt,
false ) ).
521 arg( IncidenceFormatter::dateToString( endDt,
false ) ) +
524 tmpStr +=
"<td><b>" + i18n(
"Date:" ) +
"</b></td>";
526 i18n(
"date as string",
"%1").
527 arg( IncidenceFormatter::dateToString( startDt,
false ) ) +
530 tmpStr +=
"</tr><tr>";
531 tmpStr +=
"<td><b>" + i18n(
"Time:" ) +
"</b></td>";
532 if ( event->
hasEndDate() && startDt != endDt ) {
534 i18n(
"<beginTime> - <endTime>",
"%1 - %2").
535 arg( IncidenceFormatter::timeToString( startDt,
true ) ).
536 arg( IncidenceFormatter::timeToString( endDt,
true ) ) +
540 IncidenceFormatter::timeToString( startDt,
true ) +
548 if ( !durStr.isEmpty() ) {
550 tmpStr +=
"<td><b>" + i18n(
"Duration:" ) +
"</b></td>";
551 tmpStr +=
"<td>" + durStr +
"</td>";
557 tmpStr +=
"<td><b>" + i18n(
"Recurrence:" ) +
"</b></td>";
559 IncidenceFormatter::recurrenceString( event ) +
567 tmpStr +=
"<td><b>" + i18n(
"Anniversary:" ) +
"</b></td>";
569 tmpStr +=
"<td><b>" + i18n(
"Birthday:" ) +
"</b></td>";
571 tmpStr +=
"<td>" + displayViewFormatBirthday( event ) +
"</td>";
573 tmpStr +=
"</table>";
578 TQString description =
event->description();
581 TQRegExp urlRegex(
"https?://[^\\s]+");
584 while ((pos = urlRegex.search(description, pos)) != -1) {
585 TQString url = urlRegex.cap(0);
586 TQString link =
"<a href=\"" + url +
"\">" + url +
"</a>";
587 description.replace(pos, url.length(), link);
588 pos += link.length();
592 tmpStr +=
"<td><b>" + i18n(
"Description:" ) +
"</b></td>";
593 tmpStr +=
"<td>" + description +
"</td>";
599 int reminderCount =
event->alarms().count();
602 tmpStr +=
"<td><b>" +
603 i18n(
"Reminder:",
"%n Reminders:", reminderCount ) +
605 tmpStr +=
"<td>" + IncidenceFormatter::reminderStringList( event ).join(
"<br>" ) +
"</td>";
609 tmpStr += displayViewFormatAttendees( event );
611 int categoryCount =
event->categories().count();
612 if ( categoryCount > 0 ) {
614 tmpStr +=
"<td><b>" +
615 i18n(
"Category:",
"%n Categories:", categoryCount ) +
617 tmpStr +=
"<td>" + displayViewFormatCategories( event ) +
"</td>";
621 int attachmentCount =
event->attachments().count();
622 if ( attachmentCount > 0 ) {
624 tmpStr +=
"<td><b>" +
625 i18n(
"Attachment:",
"%n Attachments:", attachmentCount ) +
627 tmpStr +=
"<td>" + displayViewFormatAttachments( event ) +
"</td>";
630 tmpStr +=
"</table>";
632 tmpStr +=
"<em>" + displayViewFormatCreationDate( event ) +
"</em>";
637 static TQString displayViewFormatTodo(
Calendar *calendar,
Todo *todo,
644 TQString tmpStr = displayViewFormatHeader( todo );
647 tmpStr +=
"<col width=\"25%\"/>";
648 tmpStr +=
"<col width=\"75%\"/>";
652 if ( !calStr.isEmpty() ) {
654 tmpStr +=
"<td><b>" + i18n(
"Calendar:" ) +
"</b></td>";
655 tmpStr +=
"<td>" + calStr +
"</td>";
660 if ( !todo->
location().isEmpty() ) {
662 tmpStr +=
"<td><b>" + i18n(
"Location:" ) +
"</b></td>";
663 tmpStr +=
"<td>" + todo->
location() +
"</td>";
668 TQDateTime startDt = todo->
dtStart();
670 if ( date.isValid() ) {
671 startDt.setDate( date );
675 tmpStr +=
"<td><b>" + i18n(
"Start:" ) +
"</b></td>";
677 IncidenceFormatter::dateTimeToString( startDt,
684 TQDateTime dueDt = todo->
dtDue();
686 if ( date.isValid() ) {
687 TQDateTime dt( date, TQTime( 0, 0, 0 ) );
688 dt = dt.addSecs( -1 );
693 tmpStr +=
"<td><b>" + i18n(
"Due:" ) +
"</b></td>";
695 IncidenceFormatter::dateTimeToString( dueDt,
702 if ( !durStr.isEmpty() ) {
704 tmpStr +=
"<td><b>" + i18n(
"Duration:" ) +
"</b></td>";
705 tmpStr +=
"<td>" + durStr +
"</td>";
711 tmpStr +=
"<td><b>" + i18n(
"Recurrence:" ) +
"</b></td>";
713 IncidenceFormatter::recurrenceString( todo ) +
720 tmpStr +=
"<td><b>" + i18n(
"Description:" ) +
"</b></td>";
727 int reminderCount = todo->
alarms().count();
730 tmpStr +=
"<td><b>" +
731 i18n(
"Reminder:",
"%n Reminders:", reminderCount ) +
733 tmpStr +=
"<td>" + IncidenceFormatter::reminderStringList( todo ).join(
"<br>" ) +
"</td>";
737 tmpStr += displayViewFormatAttendees( todo );
739 int categoryCount = todo->
categories().count();
740 if ( categoryCount > 0 ) {
742 tmpStr +=
"<td><b>" +
743 i18n(
"Category:",
"%n Categories:", categoryCount ) +
745 tmpStr +=
"<td>" + displayViewFormatCategories( todo ) +
"</td>";
751 tmpStr +=
"<td><b>" + i18n(
"Priority:" ) +
"</b></td>";
753 tmpStr += TQString::number( todo->
priority() );
760 tmpStr +=
"<td><b>" + i18n(
"Completed:" ) +
"</b></td>";
764 tmpStr +=
"<td><b>" + i18n(
"Percent Done:" ) +
"</b></td>";
772 if ( attachmentCount > 0 ) {
774 tmpStr +=
"<td><b>" +
775 i18n(
"Attachment:",
"Attachments:", attachmentCount ) +
777 tmpStr +=
"<td>" + displayViewFormatAttachments( todo ) +
"</td>";
781 tmpStr +=
"</table>";
783 tmpStr +=
"<em>" + displayViewFormatCreationDate( todo ) +
"</em>";
788 static TQString displayViewFormatJournal(
Calendar *calendar,
Journal *journal )
794 TQString tmpStr = displayViewFormatHeader( journal );
797 tmpStr +=
"<col width=\"25%\"/>";
798 tmpStr +=
"<col width=\"75%\"/>";
802 if ( !calStr.isEmpty() ) {
804 tmpStr +=
"<td><b>" + i18n(
"Calendar:" ) +
"</b></td>";
805 tmpStr +=
"<td>" + calStr +
"</td>";
811 tmpStr +=
"<td><b>" + i18n(
"Date:" ) +
"</b></td>";
813 IncidenceFormatter::dateToString( journal->
dtStart(),
false ) +
819 tmpStr +=
"<td><b>" + i18n(
"Description:" ) +
"</b></td>";
820 tmpStr +=
"<td>" + journal->
description() +
"</td>";
824 int categoryCount = journal->
categories().count();
825 if ( categoryCount > 0 ) {
827 tmpStr +=
"<td><b>" +
828 i18n(
"Category:",
"%n Categories:", categoryCount ) +
830 tmpStr +=
"<td>" + displayViewFormatCategories( journal ) +
"</td>";
833 tmpStr +=
"</table>";
835 tmpStr +=
"<em>" + displayViewFormatCreationDate( journal ) +
"</em>";
846 TQString tmpStr = htmlAddTag(
"h2",
848 i18n(
"Free/Busy information for %1").
849 arg( fb->organizer().fullName() ) ) );
851 tmpStr += htmlAddTag(
"h4", i18n(
"Busy times in date range %1 - %2:").
852 arg( IncidenceFormatter::dateToString( fb->
dtStart(),
true ) ).
853 arg( IncidenceFormatter::dateToString( fb->dtEnd(),
true ) ) );
855 TQValueList<Period> periods = fb->busyPeriods();
857 TQString text = htmlAddTag(
"em", htmlAddTag(
"b", i18n(
"Busy:") ) );
858 TQValueList<Period>::iterator it;
859 for ( it = periods.begin(); it != periods.end(); ++it ) {
861 if ( per.hasDuration() ) {
865 cont += i18n(
"1 hour ",
"%n hours ", dur / 3600 );
869 cont += i18n(
"1 minute ",
"%n minutes ", dur / 60);
873 cont += i18n(
"1 second",
"%n seconds", dur);
875 text += i18n(
"startDate for duration",
"%1 for %2").
876 arg( IncidenceFormatter::dateTimeToString( per.start(),
false,
true ) ).
880 if ( per.start().date() == per.end().date() ) {
881 text += i18n(
"date, fromTime - toTime ",
"%1, %2 - %3").
882 arg( IncidenceFormatter::dateToString( per.start().date(),
true ) ).
883 arg( IncidenceFormatter::timeToString( per.start(),
true ) ).
884 arg( IncidenceFormatter::timeToString( per.end(),
true ) );
886 text += i18n(
"fromDateTime - toDateTime",
"%1 - %2").
887 arg( IncidenceFormatter::dateTimeToString( per.start(),
false,
true ) ).
888 arg( IncidenceFormatter::dateTimeToString( per.end(),
false,
true ) );
893 tmpStr += htmlAddTag(
"p", text );
901 : mCalendar( 0 ), mResult(
"" ) {}
905 mCalendar = calendar;
908 return incidence->
accept( *
this );
910 TQString result()
const {
return mResult; }
913 bool visit(
Event *event )
915 mResult = displayViewFormatEvent( mCalendar, event, mDate );
916 return !mResult.isEmpty();
918 bool visit(
Todo *todo )
920 mResult = displayViewFormatTodo( mCalendar, todo, mDate );
921 return !mResult.isEmpty();
925 mResult = displayViewFormatJournal( mCalendar, journal );
926 return !mResult.isEmpty();
930 mResult = displayViewFormatFreeBusy( mCalendar, fb );
931 return !mResult.isEmpty();
940 TQString IncidenceFormatter::extensiveDisplayString(
IncidenceBase *incidence )
942 return extensiveDisplayStr( 0, incidence, TQDate() );
945 TQString IncidenceFormatter::extensiveDisplayStr(
Calendar *calendar,
953 EventViewerVisitor v;
954 if ( v.act( calendar, incidence, date ) ) {
965 static TQString string2HTML(
const TQString& str )
967 return TQStyleSheet::convertFromPlainText(str, TQStyleSheetItem::WhiteSpaceNormal);
970 static TQString cleanHtml(
const TQString &html )
972 TQRegExp rx(
"<body[^>]*>(.*)</body>" );
973 rx.setCaseSensitive(
false );
975 TQString body = rx.cap( 1 );
977 return TQStyleSheet::escape( body.remove( TQRegExp(
"<[^>]*>" ) ).stripWhiteSpace() );
980 static TQString eventStartTimeStr(
Event *event )
984 tmp = i18n(
"%1: Start Date, %2: Start Time",
"%1 %2" ).
985 arg( IncidenceFormatter::dateToString( event->
dtStart(),
true ),
986 IncidenceFormatter::timeToString( event->
dtStart(),
true ) );
988 tmp = i18n(
"%1: Start Date",
"%1 (all day)" ).
989 arg( IncidenceFormatter::dateToString( event->
dtStart(),
true ) );
994 static TQString eventEndTimeStr(
Event *event )
999 tmp = i18n(
"%1: End Date, %2: End Time",
"%1 %2" ).
1000 arg( IncidenceFormatter::dateToString( event->
dtEnd(),
true ),
1001 IncidenceFormatter::timeToString( event->
dtEnd(),
true ) );
1003 tmp = i18n(
"%1: End Date",
"%1 (all day)" ).
1004 arg( IncidenceFormatter::dateToString( event->
dtEnd(),
true ) );
1010 static TQString invitationRow(
const TQString &cell1,
const TQString &cell2 )
1012 return "<tr><td>" + cell1 +
"</td><td>" + cell2 +
"</td></tr>\n";
1024 KEMailSettings settings;
1025 TQStringList profiles = settings.profiles();
1026 for( TQStringList::Iterator it=profiles.begin(); it!=profiles.end(); ++it ) {
1027 settings.setProfile( *it );
1029 TQString delegatorName, delegatorEmail;
1031 Attendee::List::ConstIterator it2;
1032 for ( it2 = attendees.begin(); it2 != attendees.end(); ++it2 ) {
1034 KPIM::getNameAndMail( a->
delegator(), delegatorName, delegatorEmail );
1035 if ( settings.getSetting( KEMailSettings::EmailAddress ) == delegatorEmail ) {
1053 KEMailSettings settings;
1054 TQStringList profiles = settings.profiles();
1055 for( TQStringList::Iterator it=profiles.begin(); it!=profiles.end(); ++it ) {
1056 settings.setProfile( *it );
1059 Attendee::List::ConstIterator it2;
1060 for ( it2 = attendees.begin(); it2 != attendees.end(); ++it2 ) {
1062 if ( settings.getSetting( KEMailSettings::EmailAddress ) == a->email() ) {
1081 Attendee::List::ConstIterator it;
1082 for ( it = attendees.begin(); it != attendees.end(); ++it ) {
1084 if ( email == a->email() ) {
1092 static bool rsvpRequested(
Incidence *incidence )
1102 Attendee::List::ConstIterator it;
1103 for ( it = attendees.begin(); it != attendees.end(); ++it ) {
1104 if ( it == attendees.begin() ) {
1105 rsvp = (*it)->RSVP();
1107 if ( (*it)->RSVP() != rsvp ) {
1116 static TQString rsvpRequestedStr(
bool rsvpRequested,
const TQString &role )
1118 if ( rsvpRequested ) {
1119 if ( role.isEmpty() ) {
1120 return i18n(
"Your response is requested" );
1122 return i18n(
"Your response as <b>%1</b> is requested" ).arg( role );
1125 if ( role.isEmpty() ) {
1126 return i18n(
"No response is necessary" );
1128 return i18n(
"No response as <b>%1</b> is necessary" ).arg( role );
1133 static TQString myStatusStr(
Incidence *incidence )
1136 Attendee *a = findMyAttendee( incidence );
1138 a->
status() != Attendee::NeedsAction && a->
status() != Attendee::Delegated ) {
1139 ret = i18n(
"(<b>Note</b>: the Organizer preset your response to <b>%1</b>)" ).
1145 static TQString invitationPerson(
const TQString& email, TQString name, TQString uid )
1149 if ( !email.isEmpty() && ( name.isEmpty() || uid.isEmpty() ) ) {
1150 TDEABC::AddressBook *add_book = TDEABC::StdAddressBook::self(
true );
1151 TDEABC::Addressee::List addressList = add_book->findByEmail( email );
1152 if ( !addressList.isEmpty() ) {
1153 TDEABC::Addressee o = addressList.first();
1154 if ( !o.isEmpty() && addressList.size() < 2 ) {
1155 if ( name.isEmpty() ) {
1157 name = o.formattedName();
1169 if ( !uid.isEmpty() ) {
1171 if ( name.isEmpty() ) {
1173 tmpString += htmlAddLink(
"uid:" + uid, email );
1175 tmpString += htmlAddLink(
"uid:" + uid, name );
1179 tmpString += ( name.isEmpty() ? email : name );
1184 if ( !email.isEmpty() ) {
1187 mailto.setProtocol(
"mailto" );
1188 mailto.setPath( person.fullName() );
1189 const TQString iconPath =
1190 TDEGlobal::iconLoader()->iconPath(
"mail-message-new", TDEIcon::Small );
1191 tmpString +=
" " +
1192 htmlAddLink( mailto.url(),
"<img src=\"" + iconPath +
"\">" )
1200 static TQString invitationsDetailsIncidence(
Incidence *incidence,
bool noHtmlMode )
1208 TQStringList comments;
1210 if ( incidence->
comments().isEmpty() ) {
1213 if ( !TQStyleSheet::mightBeRichText( incidence->
description() ) ) {
1214 comments << string2HTML( incidence->
description() );
1218 comments[0] = cleanHtml( comments[0] );
1220 comments[0] = htmlAddTag(
"p", comments[0] );
1226 TQStringList cl = incidence->
comments();
1228 for( TQStringList::Iterator it=cl.begin(); it!=cl.end(); ++it ) {
1229 if ( !TQStyleSheet::mightBeRichText( *it ) ) {
1230 comments.append( string2HTML( *it ) );
1233 comments.append( cleanHtml(
"<body>" + (*it) +
"</body>" ) );
1235 comments.append( *it );
1242 if ( !TQStyleSheet::mightBeRichText( incidence->
description() ) ) {
1247 descr = cleanHtml( descr );
1249 descr = htmlAddTag(
"p", descr );
1254 if( !descr.isEmpty() ) {
1256 html +=
"<table border=\"0\" style=\"margin-top:4px;\">";
1257 html +=
"<tr><td><center>" +
1258 htmlAddTag(
"u", i18n(
"Description:" ) ) +
1259 "</center></td></tr>";
1260 html +=
"<tr><td>" + descr +
"</td></tr>";
1264 if ( !comments.isEmpty() ) {
1266 html +=
"<table border=\"0\" style=\"margin-top:4px;\">";
1267 html +=
"<tr><td><center>" +
1268 htmlAddTag(
"u", i18n(
"Comments:" ) ) +
1269 "</center></td></tr>";
1271 if ( comments.count() > 1 ) {
1273 for ( uint i=0; i < comments.count(); ++i ) {
1274 html +=
"<li>" + comments[i] +
"</li>";
1278 html += comments[0];
1280 html +=
"</td></tr>";
1286 static TQString invitationDetailsEvent(
Event* event,
bool noHtmlMode )
1293 TQString sSummary = i18n(
"Summary unspecified" );
1294 if ( !event->
summary().isEmpty() ) {
1295 if ( !TQStyleSheet::mightBeRichText( event->
summary() ) ) {
1296 sSummary = TQStyleSheet::escape( event->
summary() );
1298 sSummary =
event->summary();
1300 sSummary = cleanHtml( sSummary );
1305 TQString sLocation = i18n(
"Location unspecified" );
1306 if ( !event->
location().isEmpty() ) {
1307 if ( !TQStyleSheet::mightBeRichText( event->
location() ) ) {
1308 sLocation = TQStyleSheet::escape( event->
location() );
1310 sLocation =
event->location();
1312 sLocation = cleanHtml( sLocation );
1317 TQString dir = ( TQApplication::reverseLayout() ?
"rtl" :
"ltr" );
1318 TQString html = TQString(
"<div dir=\"%1\">\n").arg(dir);
1320 html +=
"<table border=\"0\" cellpadding=\"1\" cellspacing=\"1\">\n";
1323 html += invitationRow( i18n(
"What:" ), sSummary );
1324 html += invitationRow( i18n(
"Where:" ), sLocation );
1327 html += invitationRow( i18n(
"First Start Time:" ), eventStartTimeStr( event ) );
1328 html += invitationRow( i18n(
"First End Time:" ), eventEndTimeStr( event ) );
1332 if ( event->
dtStart().date() == event->
dtEnd().date() ) {
1333 html += invitationRow( i18n(
"Date:" ),
1334 IncidenceFormatter::dateToString( event->
dtStart(),
false ) );
1336 html += invitationRow( i18n(
"Time:" ),
1337 IncidenceFormatter::timeToString( event->
dtStart(),
true ) +
1339 IncidenceFormatter::timeToString( event->
dtEnd(),
true ) );
1342 html += invitationRow( i18n(
"Starting date of an event",
"From:" ),
1343 IncidenceFormatter::dateToString( event->
dtStart(),
false ) );
1345 html += invitationRow( i18n(
"Starting time of an event",
"At:" ),
1346 IncidenceFormatter::timeToString( event->
dtStart(),
true ) );
1349 html += invitationRow( i18n(
"Ending date of an event",
"To:" ),
1350 IncidenceFormatter::dateToString( event->
dtEnd(),
false ) );
1352 html += invitationRow( i18n(
"Starting time of an event",
"At:" ),
1353 IncidenceFormatter::timeToString( event->
dtEnd(),
true ) );
1356 html += invitationRow( i18n(
"Ending date of an event",
"To:" ),
1357 i18n(
"no end date specified" ) );
1364 if ( !durStr.isEmpty() ) {
1365 html += invitationRow( i18n(
"Duration:" ), durStr );
1371 html += invitationRow( i18n(
"Recurrence:" ), IncidenceFormatter::recurrenceString( event ) );
1373 DateList exceptions = recur->exDates();
1374 if (exceptions.isEmpty() ==
false) {
1376 isFirstExRow =
true;
1377 DateList::ConstIterator ex_iter;
1378 for ( ex_iter = exceptions.begin(); ex_iter != exceptions.end(); ++ex_iter ) {
1379 if (isFirstExRow ==
true) {
1380 isFirstExRow =
false;
1381 html += invitationRow( i18n(
"Cancelled on:"), TDEGlobal::locale()->formatDate(* ex_iter ) );
1384 html += invitationRow(
" ", TDEGlobal::locale()->formatDate(* ex_iter ) );
1390 html +=
"</table>\n";
1391 html += invitationsDetailsIncidence( event, noHtmlMode );
1397 static TQString invitationDetailsTodo(
Todo *todo,
bool noHtmlMode )
1404 TQString sSummary = i18n(
"Summary unspecified" );
1405 if ( !todo->
summary().isEmpty() ) {
1406 if ( !TQStyleSheet::mightBeRichText( todo->
summary() ) ) {
1407 sSummary = TQStyleSheet::escape( todo->
summary() );
1411 sSummary = cleanHtml( sSummary );
1416 TQString sLocation = i18n(
"Location unspecified" );
1417 if ( !todo->
location().isEmpty() ) {
1418 if ( !TQStyleSheet::mightBeRichText( todo->
location() ) ) {
1419 sLocation = TQStyleSheet::escape( todo->
location() );
1423 sLocation = cleanHtml( sLocation );
1428 TQString dir = ( TQApplication::reverseLayout() ?
"rtl" :
"ltr" );
1429 TQString html = TQString(
"<div dir=\"%1\">\n").arg(dir);
1430 html +=
"<table border=\"0\" cellpadding=\"1\" cellspacing=\"1\">\n";
1433 html += invitationRow( i18n(
"What:" ), sSummary );
1434 html += invitationRow( i18n(
"Where:" ), sLocation );
1437 html += invitationRow( i18n(
"Start Date:" ),
1438 IncidenceFormatter::dateToString( todo->
dtStart(),
false ) );
1440 html += invitationRow( i18n(
"Start Time:" ),
1441 IncidenceFormatter::timeToString( todo->
dtStart(),
false ) );
1445 html += invitationRow( i18n(
"Due Date:" ),
1446 IncidenceFormatter::dateToString( todo->
dtDue(),
false ) );
1448 html += invitationRow( i18n(
"Due Time:" ),
1449 IncidenceFormatter::timeToString( todo->
dtDue(),
false ) );
1453 html += invitationRow( i18n(
"Due Date:" ), i18n(
"Due Date: None",
"None" ) );
1456 html +=
"</table></div>\n";
1457 html += invitationsDetailsIncidence( todo, noHtmlMode );
1462 static TQString invitationDetailsJournal(
Journal *journal,
bool noHtmlMode )
1468 TQString sSummary = i18n(
"Summary unspecified" );
1469 TQString sDescr = i18n(
"Description unspecified" );
1470 if ( ! journal->
summary().isEmpty() ) {
1471 sSummary = journal->
summary();
1473 sSummary = cleanHtml( sSummary );
1479 sDescr = cleanHtml( sDescr );
1482 TQString html(
"<table border=\"0\" cellpadding=\"1\" cellspacing=\"1\">\n" );
1483 html += invitationRow( i18n(
"Summary:" ), sSummary );
1484 html += invitationRow( i18n(
"Date:" ),
1485 IncidenceFormatter::dateToString( journal->
dtStart(),
false ) );
1486 html += invitationRow( i18n(
"Description:" ), sDescr );
1487 html +=
"</table>\n";
1488 html += invitationsDetailsIncidence( journal, noHtmlMode );
1493 static TQString invitationDetailsFreeBusy(
FreeBusy *fb,
bool )
1497 TQString html(
"<table border=\"0\" cellpadding=\"1\" cellspacing=\"1\">\n" );
1499 html += invitationRow( i18n(
"Person:"), fb->organizer().fullName() );
1500 html += invitationRow( i18n(
"Start date:"),
1501 IncidenceFormatter::dateToString( fb->
dtStart(),
true ) );
1502 html += invitationRow( i18n(
"End date:"),
1503 TDEGlobal::locale()->formatDate( fb->dtEnd().date(),
true ) );
1504 html +=
"<tr><td colspan=2><hr></td></tr>\n";
1505 html +=
"<tr><td colspan=2>Busy periods given in this free/busy object:</td></tr>\n";
1507 TQValueList<Period> periods = fb->busyPeriods();
1509 TQValueList<Period>::iterator it;
1510 for ( it = periods.begin(); it != periods.end(); ++it ) {
1512 if ( per.hasDuration() ) {
1515 if ( dur >= 3600 ) {
1516 cont += i18n(
"1 hour ",
"%n hours ", dur / 3600);
1520 cont += i18n(
"1 minute",
"%n minutes ", dur / 60);
1524 cont += i18n(
"1 second",
"%n seconds", dur);
1526 html += invitationRow( TQString(), i18n(
"startDate for duration",
"%1 for %2")
1527 .arg( TDEGlobal::locale()->formatDateTime( per.start(),
false ) )
1531 if ( per.start().date() == per.end().date() ) {
1532 cont = i18n(
"date, fromTime - toTime ",
"%1, %2 - %3")
1533 .arg( TDEGlobal::locale()->formatDate( per.start().date() ) )
1534 .arg( TDEGlobal::locale()->formatTime( per.start().time() ) )
1535 .arg( TDEGlobal::locale()->formatTime( per.end().time() ) );
1537 cont = i18n(
"fromDateTime - toDateTime",
"%1 - %2")
1538 .arg( TDEGlobal::locale()->formatDateTime( per.start(),
false ) )
1539 .arg( TDEGlobal::locale()->formatDateTime( per.end(),
false ) );
1542 html += invitationRow( TQString(), cont );
1546 html +=
"</table>\n";
1550 static bool replyMeansCounter(
Incidence * )
1569 static TQString invitationHeaderEvent(
Event *event,
Incidence *existingIncidence,
1572 if ( !msg || !event )
1575 switch ( msg->
method() ) {
1576 case Scheduler::Publish:
1577 return i18n(
"This invitation has been published" );
1578 case Scheduler::Request:
1579 if ( existingIncidence && event->
revision() > 0 ) {
1580 return i18n(
"This invitation has been updated by the organizer %1" ).
1581 arg( event->organizer().fullName() );
1583 if ( iamOrganizer( event ) ) {
1584 return i18n(
"I created this invitation" );
1587 if ( !event->organizer().fullName().isEmpty() ) {
1588 orgStr =
event->organizer().fullName();
1589 }
else if ( !event->organizer().email().isEmpty() ) {
1590 orgStr =
event->organizer().email();
1592 if ( senderIsOrganizer( event, sender ) ) {
1593 if ( !orgStr.isEmpty() ) {
1594 return i18n(
"You received an invitation from %1" ).arg( orgStr );
1596 return i18n(
"You received an invitation" );
1599 if ( !orgStr.isEmpty() ) {
1600 return i18n(
"You received an invitation from %1 as a representative of %2" ).
1601 arg( sender, orgStr );
1603 return i18n(
"You received an invitation from %1 as the organizer's representative" ).
1608 case Scheduler::Refresh:
1609 return i18n(
"This invitation was refreshed" );
1610 case Scheduler::Cancel:
1611 return i18n(
"This invitation has been canceled" );
1612 case Scheduler::Add:
1613 return i18n(
"Addition to the invitation" );
1614 case Scheduler::Reply:
1616 if ( replyMeansCounter( event ) ) {
1617 return i18n(
"%1 makes this counter proposal" ).
1618 arg( firstAttendeeName( event, i18n(
"Sender" ) ) );
1622 if( attendees.count() == 0 ) {
1623 kdDebug(5850) <<
"No attendees in the iCal reply!" << endl;
1626 if( attendees.count() != 1 ) {
1627 kdDebug(5850) <<
"Warning: attendeecount in the reply should be 1 "
1628 <<
"but is " << attendees.count() << endl;
1630 TQString attendeeName = firstAttendeeName( event, i18n(
"Sender" ) );
1632 TQString delegatorName, dummy;
1633 Attendee* attendee = *attendees.begin();
1634 KPIM::getNameAndMail( attendee->
delegator(), delegatorName, dummy );
1635 if ( delegatorName.isEmpty() ) {
1639 switch( attendee->
status() ) {
1640 case Attendee::NeedsAction:
1641 return i18n(
"%1 indicates this invitation still needs some action" ).arg( attendeeName );
1642 case Attendee::Accepted:
1644 if ( !sender.isEmpty() ) {
1645 return i18n(
"This invitation has been updated by attendee %1" ).arg( sender );
1647 return i18n(
"This invitation has been updated by an attendee" );
1650 if ( delegatorName.isEmpty() ) {
1651 return i18n(
"%1 accepts this invitation" ).arg( attendeeName );
1653 return i18n(
"%1 accepts this invitation on behalf of %2" ).
1654 arg( attendeeName ).arg( delegatorName );
1657 case Attendee::Tentative:
1658 if ( delegatorName.isEmpty() ) {
1659 return i18n(
"%1 tentatively accepts this invitation" ).
1660 arg( attendeeName );
1662 return i18n(
"%1 tentatively accepts this invitation on behalf of %2" ).
1663 arg( attendeeName ).arg( delegatorName );
1665 case Attendee::Declined:
1666 if ( delegatorName.isEmpty() ) {
1667 return i18n(
"%1 declines this invitation" ).arg( attendeeName );
1669 return i18n(
"%1 declines this invitation on behalf of %2" ).
1670 arg( attendeeName ).arg( delegatorName );
1672 case Attendee::Delegated: {
1673 TQString delegate, dummy;
1674 KPIM::getNameAndMail( attendee->
delegate(), delegate, dummy );
1675 if ( delegate.isEmpty() ) {
1678 if ( !delegate.isEmpty() ) {
1679 return i18n(
"%1 has delegated this invitation to %2" ).
1680 arg( attendeeName ) .arg( delegate );
1682 return i18n(
"%1 has delegated this invitation" ).arg( attendeeName );
1685 case Attendee::Completed:
1686 return i18n(
"This invitation is now completed" );
1687 case Attendee::InProcess:
1688 return i18n(
"%1 is still processing the invitation" ).
1689 arg( attendeeName );
1691 return i18n(
"Unknown response to this invitation" );
1696 case Scheduler::Counter:
1697 return i18n(
"%1 makes this counter proposal" ).
1698 arg( firstAttendeeName( event, i18n(
"Sender" ) ) );
1700 case Scheduler::Declinecounter:
1701 return i18n(
"%1 declines the counter proposal" ).
1702 arg( firstAttendeeName( event, i18n(
"Sender" ) ) );
1704 case Scheduler::NoMethod:
1705 return i18n(
"Error: iMIP message with unknown method: '%1'").
1711 static TQString invitationHeaderTodo(
Todo *todo,
Incidence *existingIncidence,
1714 if ( !msg || !todo ) {
1718 switch ( msg->
method() ) {
1719 case Scheduler::Publish:
1720 return i18n(
"This task has been published");
1721 case Scheduler::Request:
1722 if ( existingIncidence && todo->
revision() > 0 ) {
1723 return i18n(
"This task has been updated by the organizer %1" ).
1724 arg( todo->organizer().fullName() );
1726 if ( iamOrganizer( todo ) ) {
1727 return i18n(
"I created this task" );
1730 if ( !todo->organizer().fullName().isEmpty() ) {
1731 orgStr = todo->organizer().fullName();
1732 }
else if ( !todo->organizer().email().isEmpty() ) {
1733 orgStr = todo->organizer().email();
1735 if ( senderIsOrganizer( todo, sender ) ) {
1736 if ( !orgStr.isEmpty() ) {
1737 return i18n(
"You have been assigned this task by %1" ).arg( orgStr );
1739 return i18n(
"You have been assigned this task" );
1742 if ( !orgStr.isEmpty() ) {
1743 return i18n(
"You have been assigned this task by %1 as a representative of %2" ).
1744 arg( sender, orgStr );
1746 return i18n(
"You have been assigned this task by %1 as the organizer's representative" ).
1752 case Scheduler::Refresh:
1753 return i18n(
"This task was refreshed" );
1754 case Scheduler::Cancel:
1755 return i18n(
"This task was canceled" );
1756 case Scheduler::Add:
1757 return i18n(
"Addition to the task" );
1758 case Scheduler::Reply:
1760 if ( replyMeansCounter( todo ) ) {
1761 return i18n(
"%1 makes this counter proposal" ).
1762 arg( firstAttendeeName( todo, i18n(
"Sender" ) ) );
1766 if( attendees.count() == 0 ) {
1767 kdDebug(5850) <<
"No attendees in the iCal reply!" << endl;
1770 if( attendees.count() != 1 ) {
1771 kdDebug(5850) <<
"Warning: attendeecount in the reply should be 1 "
1772 <<
"but is " << attendees.count() << endl;
1774 TQString attendeeName = firstAttendeeName( todo, i18n(
"Sender" ) );
1776 TQString delegatorName, dummy;
1777 Attendee* attendee = *attendees.begin();
1778 KPIM::getNameAndMail( attendee->
delegator(), delegatorName, dummy );
1779 if ( delegatorName.isEmpty() ) {
1783 switch( attendee->
status() ) {
1784 case Attendee::NeedsAction:
1785 return i18n(
"%1 indicates this task assignment still needs some action" ).arg( attendeeName );
1786 case Attendee::Accepted:
1788 if ( !sender.isEmpty() ) {
1790 return i18n(
"This task has been completed by assignee %1" ).arg( sender );
1792 return i18n(
"This task has been updated by assignee %1" ).arg( sender );
1796 return i18n(
"This task has been completed by an assignee" );
1798 return i18n(
"This task has been updated by an assignee" );
1802 if ( delegatorName.isEmpty() ) {
1803 return i18n(
"%1 accepts this task" ).arg( attendeeName );
1805 return i18n(
"%1 accepts this task on behalf of %2" ).
1806 arg( attendeeName ).arg( delegatorName );
1809 case Attendee::Tentative:
1810 if ( delegatorName.isEmpty() ) {
1811 return i18n(
"%1 tentatively accepts this task" ).
1812 arg( attendeeName );
1814 return i18n(
"%1 tentatively accepts this task on behalf of %2" ).
1815 arg( attendeeName ).arg( delegatorName );
1817 case Attendee::Declined:
1818 if ( delegatorName.isEmpty() ) {
1819 return i18n(
"%1 declines this task" ).arg( attendeeName );
1821 return i18n(
"%1 declines this task on behalf of %2" ).
1822 arg( attendeeName ).arg( delegatorName );
1824 case Attendee::Delegated: {
1825 TQString delegate, dummy;
1826 KPIM::getNameAndMail( attendee->
delegate(), delegate, dummy );
1827 if ( delegate.isEmpty() ) {
1830 if ( !delegate.isEmpty() ) {
1831 return i18n(
"%1 has delegated this request for the task to %2" ).
1832 arg( attendeeName ).arg( delegate );
1834 return i18n(
"%1 has delegated this request for the task" ).
1835 arg( attendeeName );
1838 case Attendee::Completed:
1839 return i18n(
"The request for this task is now completed" );
1840 case Attendee::InProcess:
1841 return i18n(
"%1 is still processing the task" ).
1842 arg( attendeeName );
1844 return i18n(
"Unknown response to this task" );
1849 case Scheduler::Counter:
1850 return i18n(
"%1 makes this counter proposal" ).
1851 arg( firstAttendeeName( todo, i18n(
"Sender" ) ) );
1853 case Scheduler::Declinecounter:
1854 return i18n(
"%1 declines the counter proposal" ).
1855 arg( firstAttendeeName( todo, i18n(
"Sender" ) ) );
1857 case Scheduler::NoMethod:
1858 return i18n(
"Error: iMIP message with unknown method: '%1'" ).
1866 if ( !msg || !journal ) {
1870 switch ( msg->
method() ) {
1871 case Scheduler::Publish:
1872 return i18n(
"This journal has been published");
1873 case Scheduler::Request:
1874 return i18n(
"You have been assigned this journal" );
1875 case Scheduler::Refresh:
1876 return i18n(
"This journal was refreshed" );
1877 case Scheduler::Cancel:
1878 return i18n(
"This journal was canceled" );
1879 case Scheduler::Add:
1880 return i18n(
"Addition to the journal" );
1881 case Scheduler::Reply:
1883 if ( replyMeansCounter( journal ) ) {
1884 return i18n(
"Sender makes this counter proposal" );
1888 if( attendees.count() == 0 ) {
1889 kdDebug(5850) <<
"No attendees in the iCal reply!" << endl;
1892 if( attendees.count() != 1 ) {
1893 kdDebug(5850) <<
"Warning: attendeecount in the reply should be 1 "
1894 <<
"but is " << attendees.count() << endl;
1896 Attendee* attendee = *attendees.begin();
1898 switch( attendee->
status() ) {
1899 case Attendee::NeedsAction:
1900 return i18n(
"Sender indicates this journal assignment still needs some action" );
1901 case Attendee::Accepted:
1902 return i18n(
"Sender accepts this journal" );
1903 case Attendee::Tentative:
1904 return i18n(
"Sender tentatively accepts this journal" );
1905 case Attendee::Declined:
1906 return i18n(
"Sender declines this journal" );
1907 case Attendee::Delegated:
1908 return i18n(
"Sender has delegated this request for the journal" );
1909 case Attendee::Completed:
1910 return i18n(
"The request for this journal is now completed" );
1911 case Attendee::InProcess:
1912 return i18n(
"Sender is still processing the invitation" );
1914 return i18n(
"Unknown response to this journal" );
1918 case Scheduler::Counter:
1919 return i18n(
"Sender makes this counter proposal" );
1920 case Scheduler::Declinecounter:
1921 return i18n(
"Sender declines the counter proposal" );
1922 case Scheduler::NoMethod:
1923 return i18n(
"Error: iMIP message with unknown method: '%1'").
1931 if ( !msg || !fb ) {
1935 switch ( msg->
method() ) {
1936 case Scheduler::Publish:
1937 return i18n(
"This free/busy list has been published");
1938 case Scheduler::Request:
1939 return i18n(
"The free/busy list has been requested" );
1940 case Scheduler::Refresh:
1941 return i18n(
"This free/busy list was refreshed" );
1942 case Scheduler::Cancel:
1943 return i18n(
"This free/busy list was canceled" );
1944 case Scheduler::Add:
1945 return i18n(
"Addition to the free/busy list" );
1946 case Scheduler::NoMethod:
1948 return i18n(
"Error: Free/Busy iMIP message with unknown method: '%1'").
1953 static TQString invitationAttendees(
Incidence *incidence )
1960 if ( incidence->type() ==
"Todo" ) {
1961 tmpStr += htmlAddTag(
"u", i18n(
"Assignees" ) );
1963 tmpStr += htmlAddTag(
"u", i18n(
"Attendees" ) );
1969 if ( !attendees.isEmpty() ) {
1971 Attendee::List::ConstIterator it;
1972 for( it = attendees.begin(); it != attendees.end(); ++it ) {
1974 if ( !iamAttendee( a ) ) {
1977 tmpStr +=
"<table border=\"1\" cellpadding=\"1\" cellspacing=\"0\" columns=\"2\">";
1981 tmpStr += invitationPerson( a->email(), a->name(), TQString() );
1983 tmpStr += i18n(
" (delegated by %1)" ).arg( a->
delegator() );
1986 tmpStr += i18n(
" (delegated to %1)" ).arg( a->
delegate() );
1989 tmpStr +=
"<td>" + a->
statusStr() +
"</td>";
1995 tmpStr +=
"</table>";
1997 tmpStr +=
"<i>" + i18n(
"No attendee",
"None" ) +
"</i>";
2003 static TQString invitationAttachments( InvitationFormatterHelper *helper,
Incidence *incidence )
2011 if ( !attachments.isEmpty() ) {
2012 tmpStr += i18n(
"Attached Documents:" ) +
"<ol>";
2014 Attachment::List::ConstIterator it;
2015 for( it = attachments.begin(); it != attachments.end(); ++it ) {
2019 KMimeType::Ptr mimeType = KMimeType::mimeType( a->mimeType() );
2020 const TQString iconStr = mimeType ? mimeType->icon( a->uri(),
false ) : TQString(
"application-octet-stream" );
2021 const TQString iconPath = TDEGlobal::iconLoader()->iconPath( iconStr, TDEIcon::Small );
2022 if ( !iconPath.isEmpty() ) {
2023 tmpStr +=
"<img valign=\"top\" src=\"" + iconPath +
"\">";
2025 tmpStr += helper->makeLink(
"ATTACH:" + a->label(), a->label() );
2034 class IncidenceFormatter::ScheduleMessageVisitor
2038 ScheduleMessageVisitor() : mExistingIncidence( 0 ), mMessage( 0 ) { mResult =
""; }
2040 const TQString &sender )
2042 mExistingIncidence = existingIncidence;
2045 return incidence->
accept( *
this );
2047 TQString result()
const {
return mResult; }
2056 class IncidenceFormatter::InvitationHeaderVisitor
2057 :
public IncidenceFormatter::ScheduleMessageVisitor
2060 bool visit(
Event *event )
2062 mResult = invitationHeaderEvent( event, mExistingIncidence, mMessage, mSender );
2063 return !mResult.isEmpty();
2065 bool visit(
Todo *todo )
2067 mResult = invitationHeaderTodo( todo, mExistingIncidence, mMessage, mSender );
2068 return !mResult.isEmpty();
2070 bool visit(
Journal *journal )
2072 mResult = invitationHeaderJournal( journal, mMessage );
2073 return !mResult.isEmpty();
2077 mResult = invitationHeaderFreeBusy( fb, mMessage );
2078 return !mResult.isEmpty();
2082 class IncidenceFormatter::InvitationBodyVisitor
2083 :
public IncidenceFormatter::ScheduleMessageVisitor
2086 InvitationBodyVisitor(
bool noHtmlMode )
2087 : ScheduleMessageVisitor(), mNoHtmlMode( noHtmlMode ) {}
2090 bool visit(
Event *event )
2092 mResult = invitationDetailsEvent( event, mNoHtmlMode );
2093 return !mResult.isEmpty();
2095 bool visit(
Todo *todo )
2097 mResult = invitationDetailsTodo( todo, mNoHtmlMode );
2098 return !mResult.isEmpty();
2100 bool visit(
Journal *journal )
2102 mResult = invitationDetailsJournal( journal, mNoHtmlMode );
2103 return !mResult.isEmpty();
2107 mResult = invitationDetailsFreeBusy( fb, mNoHtmlMode );
2108 return !mResult.isEmpty();
2115 class IncidenceFormatter::IncidenceCompareVisitor
2119 IncidenceCompareVisitor() : mExistingIncidence(0) {}
2123 if ( !inc || !existingIncidence || inc->
revision() <= existingIncidence->
revision() )
2125 mExistingIncidence = existingIncidence;
2127 return incidence->
accept( *
this );
2130 TQString result()
const
2132 if ( mChanges.isEmpty() ) {
2135 TQString html =
"<div align=\"left\"><ul><li>";
2136 html += mChanges.join(
"</li><li>" );
2137 html +=
"</li><ul></div>";
2142 bool visit(
Event *event )
2144 compareEvents( event,
dynamic_cast<Event*
>( mExistingIncidence ) );
2145 compareIncidences( event, mExistingIncidence, mMethod );
2146 return !mChanges.isEmpty();
2148 bool visit(
Todo *todo )
2150 compareTodos( todo,
dynamic_cast<Todo*
>( mExistingIncidence ) );
2151 compareIncidences( todo, mExistingIncidence, mMethod );
2152 return !mChanges.isEmpty();
2154 bool visit(
Journal *journal )
2156 compareIncidences( journal, mExistingIncidence, mMethod );
2157 return !mChanges.isEmpty();
2162 return !mChanges.isEmpty();
2166 void compareEvents(
Event *newEvent,
Event *oldEvent )
2168 if ( !oldEvent || !newEvent )
2171 mChanges += i18n(
"The invitation starting time has been changed from %1 to %2" )
2172 .arg( eventStartTimeStr( oldEvent ) ).arg( eventStartTimeStr( newEvent ) );
2174 mChanges += i18n(
"The invitation ending time has been changed from %1 to %2" )
2175 .arg( eventEndTimeStr( oldEvent ) ).arg( eventEndTimeStr( newEvent ) );
2178 void compareTodos(
Todo *newTodo,
Todo *oldTodo )
2180 if ( !oldTodo || !newTodo ) {
2185 mChanges += i18n(
"The task has been completed" );
2188 mChanges += i18n(
"The task is no longer completed" );
2191 const TQString oldPer = i18n(
"%1%" ).arg( oldTodo->
percentComplete() );
2192 const TQString newPer = i18n(
"%1%" ).arg( newTodo->
percentComplete() );
2193 mChanges += i18n(
"The task completed percentage has changed from %1 to %2" ).
2194 arg( oldPer, newPer );
2198 mChanges += i18n(
"A task starting time has been added" );
2201 mChanges += i18n(
"The task starting time has been removed" );
2205 mChanges += i18n(
"The task starting time has been changed from %1 to %2" ).
2211 mChanges += i18n(
"A task due time has been added" );
2214 mChanges += i18n(
"The task due time has been removed" );
2218 mChanges += i18n(
"The task due time has been changed from %1 to %2" ).
2219 arg( dateTimeToString( oldTodo->
dtDue(), oldTodo->
doesFloat(),
false ),
2220 dateTimeToString( newTodo->
dtDue(), newTodo->
doesFloat(),
false ) );
2226 if ( !oldInc || !newInc )
2229 mChanges += i18n(
"The summary has been changed to: \"%1\"" ).arg( newInc->
summary() );
2231 mChanges += i18n(
"The location has been changed to: \"%1\"" ).arg( newInc->
location() );
2233 mChanges += i18n(
"The description has been changed to: \"%1\"" ).arg( newInc->
description() );
2236 for ( Attendee::List::ConstIterator it = newAttendees.constBegin();
2237 it != newAttendees.constEnd(); ++it ) {
2240 mChanges += i18n(
"Attendee %1 has been added" ).arg( (*it)->fullName() );
2242 if ( oldAtt->
status() != (*it)->status() )
2243 mChanges += i18n(
"The status of attendee %1 has been changed to: %2" ).
2244 arg( (*it)->fullName() ).arg( (*it)->statusStr() );
2247 if ( method == Scheduler::Request ) {
2248 for ( Attendee::List::ConstIterator it = oldAttendees.constBegin();
2249 it != oldAttendees.constEnd(); ++it ) {
2250 if ( (*it)->email() != oldInc->organizer().email() ) {
2253 mChanges += i18n(
"Attendee %1 has been removed" ).arg( (*it)->fullName() );
2263 TQStringList mChanges;
2267 TQString InvitationFormatterHelper::makeLink(
const TQString &
id,
const TQString &text )
2269 if ( !
id.startsWith(
"ATTACH:" ) ) {
2270 TQString res = TQString(
"<a href=\"%1\"><b>%2</b></a>" ).
2271 arg( generateLinkURL(
id ), text );
2275 TQString res = TQString(
"<a href=\"%1\">%2</a>" ).
2276 arg( generateLinkURL(
id ), text );
2286 if ( !cal || !incidence ) {
2294 if ( !subRes.contains(
"/.INBOX.directory/" ) ) {
2301 static TQString spacer =
"<td> </td>";
2303 static TQString tdOpen =
"<td>";
2304 static TQString tdClose =
"</td>" + spacer;
2306 static TQString responseButtons(
Incidence *inc,
bool rsvpReq,
bool rsvpRec,
2307 InvitationFormatterHelper *helper )
2314 if ( !rsvpReq && ( inc && inc->
revision() == 0 ) ) {
2317 html += helper->makeLink(
"record", i18n(
"[Record]" ) );
2322 html += helper->makeLink(
"delete", i18n(
"[Move to Trash]" ) );
2329 html += helper->makeLink(
"accept", i18n(
"[Accept]" ) );
2334 html += helper->makeLink(
"accept_conditionally",
2335 i18n(
"Accept conditionally",
"[Accept cond.]" ) );
2340 html += helper->makeLink(
"counter", i18n(
"[Counter proposal]" ) );
2345 html += helper->makeLink(
"decline", i18n(
"[Decline]" ) );
2349 if ( !rsvpRec || ( inc && inc->
revision() > 0 ) ) {
2352 html += helper->makeLink(
"delegate", i18n(
"[Delegate]" ) );
2357 html += helper->makeLink(
"forward", i18n(
"[Forward]" ) );
2361 if ( inc && inc->type() ==
"Event" ) {
2363 html += helper->makeLink(
"check_calendar", i18n(
"[Check my calendar]" ) );
2370 static TQString counterButtons(
Incidence *incidence,
2371 InvitationFormatterHelper *helper )
2380 html += helper->makeLink(
"accept_counter", i18n(
"[Accept]") );
2385 html += helper->makeLink(
"decline_counter", i18n(
"[Decline]") );
2389 if ( incidence && incidence->type() ==
"Event" ) {
2391 html += helper->makeLink(
"check_calendar", i18n(
"[Check my calendar]" ) );
2397 TQString IncidenceFormatter::formatICalInvitationHelper( TQString invitation,
2399 InvitationFormatterHelper *helper,
2401 const TQString &sender )
2403 if ( invitation.isEmpty() ) {
2412 kdDebug( 5850 ) <<
"Failed to parse the scheduling message" << endl;
2422 if ( incBase && helper->calendar() ) {
2423 existingIncidence = helper->calendar()->incidence( incBase->
uid() );
2424 if ( !incidenceOwnedByMe( helper->calendar(), existingIncidence ) ) {
2425 existingIncidence = 0;
2427 if ( !existingIncidence ) {
2429 for ( Incidence::List::ConstIterator it = list.begin(), end = list.end(); it != end; ++it ) {
2430 if ( (*it)->schedulingID() == incBase->
uid() &&
2431 incidenceOwnedByMe( helper->calendar(), *it ) ) {
2432 existingIncidence = *it;
2442 TQString tableStyle = TQString::fromLatin1(
2443 "style=\"border: solid 1px; margin: 0em;\"" );
2444 TQString tableHead = TQString::fromLatin1(
2445 "<div align=\"center\">"
2446 "<table width=\"80%\" cellpadding=\"1\" cellspacing=\"0\" %1>"
2447 "<tr><td>").arg(tableStyle);
2450 InvitationHeaderVisitor headerVisitor;
2452 if ( !headerVisitor.act( incBase, existingIncidence, msg, sender ) )
2454 html +=
"<b>" + headerVisitor.result() +
"</b>";
2456 InvitationBodyVisitor bodyVisitor( noHtmlMode );
2457 if ( !bodyVisitor.act( incBase, existingIncidence, msg, sender ) )
2459 html += bodyVisitor.result();
2461 if ( msg->
method() == Scheduler::Request ) {
2462 IncidenceCompareVisitor compareVisitor;
2463 if ( compareVisitor.act( incBase, existingIncidence, msg->
method() ) ) {
2464 html +=
"<p align=\"left\">";
2465 html += i18n(
"The following changes have been made by the organizer:" );
2467 html += compareVisitor.result();
2470 if ( msg->
method() == Scheduler::Reply ) {
2471 IncidenceCompareVisitor compareVisitor;
2472 if ( compareVisitor.act( incBase, existingIncidence, msg->
method() ) ) {
2473 html +=
"<p align=\"left\">";
2474 if ( !sender.isEmpty() ) {
2475 html += i18n(
"The following changes have been made by %1:" ).arg( sender );
2477 html += i18n(
"The following changes have been made by an attendee:" );
2480 html += compareVisitor.result();
2487 bool myInc = iamOrganizer( inc );
2490 bool rsvpRec =
false;
2493 Incidence *rsvpIncidence = existingIncidence;
2494 if ( !rsvpIncidence && inc && inc->
revision() > 0 ) {
2495 rsvpIncidence = inc;
2497 if ( rsvpIncidence ) {
2498 ea = findMyAttendee( rsvpIncidence );
2501 ( ea->
status() == Attendee::Accepted ||
2502 ea->
status() == Attendee::Declined ||
2503 ea->
status() == Attendee::Tentative ) ) {
2510 bool isDelegated =
false;
2511 Attendee *a = findMyAttendee( inc );
2518 isDelegated = ( a->
status() == Attendee::Delegated );
2523 bool rsvpReq = rsvpRequested( inc );
2524 if ( !myInc && a ) {
2527 if ( rsvpRec && inc ) {
2529 html += i18n(
"Your <b>%1</b> response has already been recorded" ).
2532 html += i18n(
"Your status for this invitation is <b>%1</b>" ).
2536 }
else if ( msg->
method() == Scheduler::Cancel ) {
2537 html += i18n(
"This invitation was declined" );
2538 }
else if ( msg->
method() == Scheduler::Add ) {
2539 html += i18n(
"This invitation was accepted" );
2541 if ( !isDelegated ) {
2542 html += rsvpRequestedStr( rsvpReq, role );
2544 html += i18n(
"Awaiting delegation response" );
2552 if ( inc && inc->
revision() == 0 ) {
2553 TQString statStr = myStatusStr( inc );
2554 if ( !statStr.isEmpty() ) {
2565 html +=
"<br><table border=\"0\" cellspacing=\"0\"><tr><td> </td></tr>";
2567 switch ( msg->
method() ) {
2568 case Scheduler::Publish:
2569 case Scheduler::Request:
2570 case Scheduler::Refresh:
2571 case Scheduler::Add:
2573 if ( inc && inc->
revision() > 0 && ( existingIncidence || !helper->calendar() ) ) {
2575 if ( inc->type() ==
"Todo" ) {
2576 html +=
"<td colspan=\"9\">";
2577 html += helper->makeLink(
"reply", i18n(
"[Record invitation in my task list]" ) );
2579 html +=
"<td colspan=\"13\">";
2580 html += helper->makeLink(
"reply", i18n(
"[Record invitation in my calendar]" ) );
2582 html +=
"</td></tr>";
2585 if ( !myInc && a ) {
2586 html +=
"<tr>" + responseButtons( inc, rsvpReq, rsvpRec, helper ) +
"</tr>";
2591 case Scheduler::Cancel:
2595 if ( inc->type() ==
"Todo" ) {
2596 html +=
"<td colspan=\"9\">";
2597 html += helper->makeLink(
"cancel", i18n(
"[Remove invitation from my task list]" ) );
2599 html +=
"<td colspan=\"13\">";
2600 html += helper->makeLink(
"cancel", i18n(
"[Remove invitation from my calendar]" ) );
2602 html +=
"</td></tr>";
2606 case Scheduler::Reply:
2613 if ( replyMeansCounter( inc ) ) {
2614 html +=
"<tr>" + counterButtons( inc, helper ) +
"</tr>";
2623 a = findDelegatedFromMyAttendee( inc );
2625 if ( a->
status() != Attendee::Accepted ||
2626 a->
status() != Attendee::Tentative ) {
2627 html +=
"<tr>" + responseButtons( inc, rsvpReq, rsvpRec, helper ) +
"</tr>";
2637 ea = findAttendee( existingIncidence, a->email() );
2640 if ( ea && ( ea->
status() != Attendee::NeedsAction ) && ( ea->
status() == a->
status() ) ) {
2641 if ( inc && inc->
revision() > 0 ) {
2642 html +=
"<br><u><i>";
2643 html += i18n(
"The response has been recorded [%1]" ).arg( ea->
statusStr() );
2649 if ( inc->type() ==
"Todo" ) {
2650 html += helper->makeLink(
"reply", i18n(
"[Record response in my task list]" ) );
2652 html += helper->makeLink(
"reply", i18n(
"[Record response in my calendar]" ) );
2654 html +=
"</td></tr>";
2660 case Scheduler::Counter:
2662 html +=
"<tr>" + counterButtons( inc, helper ) +
"</tr>";
2665 case Scheduler::Declinecounter:
2666 case Scheduler::NoMethod:
2671 html +=
"</td></tr></table>";
2674 if ( myInc && helper->calendar() ) {
2675 html += invitationAttendees( helper->calendar()->incidence( inc->
uid() ) );
2679 html +=
"</td></tr></table><br></div>";
2682 html += invitationAttachments( helper, inc );
2687 TQString IncidenceFormatter::formatICalInvitation( TQString invitation,
2689 InvitationFormatterHelper *helper )
2691 return formatICalInvitationHelper( invitation, mCalendar, helper,
false, TQString() );
2694 TQString IncidenceFormatter::formatICalInvitationNoHtml( TQString invitation,
2696 InvitationFormatterHelper *helper )
2698 return formatICalInvitationHelper( invitation, mCalendar, helper,
true, TQString() );
2701 TQString IncidenceFormatter::formatICalInvitationNoHtml( TQString invitation,
2703 InvitationFormatterHelper *helper,
2704 const TQString &sender )
2706 return formatICalInvitationHelper( invitation, mCalendar, helper,
true, sender );
2717 static TQString stringProp( KTNEFMessage* tnefMsg,
const TQ_UINT32& key,
2718 const TQString& fallback = TQString())
2720 return tnefMsg->findProp( key < 0x10000 ? key & 0xFFFF : key >> 16,
2724 static TQString sNamedProp( KTNEFMessage* tnefMsg,
const TQString& name,
2725 const TQString& fallback = TQString() )
2727 return tnefMsg->findNamedProp( name, fallback );
2730 struct save_tz {
char* old_tz;
char* tz_env_str; };
2733 static struct save_tz set_tz( const char* _tc )
2735 const char *tc = _tc?_tc:
"UTC";
2745 if( getenv(
"TZ" ) ) {
2746 tz_env = strdup( getenv(
"TZ" ) );
2749 char* tmp_env = (
char*)malloc( strlen( tc ) + 4 );
2750 strcpy( tmp_env,
"TZ=" );
2751 strcpy( tmp_env+3, tc );
2754 rv.tz_env_str = tmp_env;
2765 static void unset_tz(
struct save_tz old_tz )
2767 if( old_tz.old_tz ) {
2768 char* tmp_env = (
char*)malloc( strlen( old_tz.old_tz ) + 4 );
2769 strcpy( tmp_env,
"TZ=" );
2770 strcpy( tmp_env+3, old_tz.old_tz );
2773 free( old_tz.old_tz );
2776 putenv( strdup(
"TZ") );
2781 if( old_tz.tz_env_str ) free( old_tz.tz_env_str );
2784 static TQDateTime utc2Local(
const TQDateTime& utcdt )
2788 save_tz tmp_tz = set_tz(
"UTC");
2789 time_t utc = utcdt.toTime_t();
2792 localtime_r( &utc, &tmL );
2793 return TQDateTime( TQDate( tmL.tm_year+1900, tmL.tm_mon+1, tmL.tm_mday ),
2794 TQTime( tmL.tm_hour, tmL.tm_min, tmL.tm_sec ) );
2798 static TQDateTime pureISOToLocalTQDateTime(
const TQString& dtStr,
2799 bool bDateOnly =
false )
2803 int year, month, day, hour, minute, second;
2806 year = dtStr.left( 4 ).toInt();
2807 month = dtStr.mid( 4, 2 ).toInt();
2808 day = dtStr.mid( 6, 2 ).toInt();
2813 year = dtStr.left( 4 ).toInt();
2814 month = dtStr.mid( 4, 2 ).toInt();
2815 day = dtStr.mid( 6, 2 ).toInt();
2816 hour = dtStr.mid( 9, 2 ).toInt();
2817 minute = dtStr.mid( 11, 2 ).toInt();
2818 second = dtStr.mid( 13, 2 ).toInt();
2820 tmpDate.setYMD( year, month, day );
2821 tmpTime.setHMS( hour, minute, second );
2823 if( tmpDate.isValid() && tmpTime.isValid() ) {
2824 TQDateTime dT = TQDateTime( tmpDate, tmpTime );
2828 if (dtStr.at(dtStr.length()-1) ==
'Z') {
2831 dT = utc2Local( dT );
2836 return TQDateTime();
2846 TQBuffer buf( tnef );
2848 TDEABC::Addressee addressee;
2849 TDEABC::VCardConverter cardConv;
2853 if( parser.openDevice( &buf ) ) {
2854 KTNEFMessage* tnefMsg = parser.message();
2859 TQString msgClass = tnefMsg->findProp( 0x001A, TQString(),
true )
2861 if( !msgClass.isEmpty() ) {
2864 bool bCompatClassAppointment =
false;
2865 bool bCompatMethodRequest =
false;
2866 bool bCompatMethodCancled =
false;
2867 bool bCompatMethodAccepted =
false;
2868 bool bCompatMethodAcceptedCond =
false;
2869 bool bCompatMethodDeclined =
false;
2870 if( msgClass.startsWith(
"IPM.MICROSOFT SCHEDULE." ) ) {
2871 bCompatClassAppointment =
true;
2872 if( msgClass.endsWith(
".MTGREQ" ) )
2873 bCompatMethodRequest =
true;
2874 if( msgClass.endsWith(
".MTGCNCL" ) )
2875 bCompatMethodCancled =
true;
2876 if( msgClass.endsWith(
".MTGRESPP" ) )
2877 bCompatMethodAccepted =
true;
2878 if( msgClass.endsWith(
".MTGRESPA" ) )
2879 bCompatMethodAcceptedCond =
true;
2880 if( msgClass.endsWith(
".MTGRESPN" ) )
2881 bCompatMethodDeclined =
true;
2883 bool bCompatClassNote = ( msgClass ==
"IPM.MICROSOFT MAIL.NOTE" );
2885 if( bCompatClassAppointment ||
"IPM.APPOINTMENT" == msgClass ) {
2887 bool bIsReply =
false;
2888 TQString prodID =
"-//Microsoft Corporation//Outlook ";
2889 prodID += tnefMsg->findNamedProp(
"0x8554",
"9.0" );
2890 prodID +=
"MIMEDIR/EN\n";
2891 prodID +=
"VERSION:2.0\n";
2895 if( bCompatMethodRequest )
2896 method = Scheduler::Request;
2897 else if( bCompatMethodCancled )
2898 method = Scheduler::Cancel;
2899 else if( bCompatMethodAccepted || bCompatMethodAcceptedCond ||
2900 bCompatMethodDeclined ) {
2901 method = Scheduler::Reply;
2912 if( tnefMsg->findProp(0x0c17) ==
"1" )
2914 method = Scheduler::Request;
2920 TQString sSenderSearchKeyEmail( tnefMsg->findProp( 0x0C1D ) );
2922 if( !sSenderSearchKeyEmail.isEmpty() ) {
2923 int colon = sSenderSearchKeyEmail.find(
':' );
2925 if( sSenderSearchKeyEmail.find(
':' ) == -1 )
2926 sSenderSearchKeyEmail.remove( 0, colon+1 );
2929 TQString s( tnefMsg->findProp( 0x0e04 ) );
2930 TQStringList attendees = TQStringList::split(
';', s );
2931 if( attendees.count() ) {
2932 for( TQStringList::Iterator it = attendees.begin();
2933 it != attendees.end(); ++it ) {
2936 if( (*it).find(
'@') == -1 ) {
2937 s = (*it).stripWhiteSpace();
2941 if( bCompatMethodAccepted )
2942 attendee->
setStatus( Attendee::Accepted );
2943 if( bCompatMethodDeclined )
2944 attendee->
setStatus( Attendee::Declined );
2945 if( bCompatMethodAcceptedCond )
2946 attendee->
setStatus(Attendee::Tentative);
2948 attendee->
setStatus( Attendee::NeedsAction );
2949 attendee->
setRole( Attendee::ReqParticipant );
2951 event->addAttendee(attendee);
2957 s = sSenderSearchKeyEmail;
2958 if( !s.isEmpty() ) {
2962 if( bCompatMethodAccepted )
2963 attendee->
setStatus( Attendee::Accepted );
2964 if( bCompatMethodAcceptedCond )
2965 attendee->
setStatus( Attendee::Declined );
2966 if( bCompatMethodDeclined )
2967 attendee->
setStatus( Attendee::Tentative );
2969 attendee->
setStatus(Attendee::NeedsAction);
2970 attendee->
setRole(Attendee::ReqParticipant);
2972 event->addAttendee(attendee);
2975 s = tnefMsg->findProp( 0x0c1f );
2976 if( s.isEmpty() && !bIsReply )
2977 s = sSenderSearchKeyEmail;
2980 event->setOrganizer( s );
2982 s = tnefMsg->findProp( 0x8516 ).replace( TQChar(
'-' ), TQString() )
2983 .replace( TQChar(
':' ), TQString() );
2984 event->setDtStart( TQDateTime::fromString( s ) );
2986 s = tnefMsg->findProp( 0x8517 ).replace( TQChar(
'-' ), TQString() )
2987 .replace( TQChar(
':' ), TQString() );
2988 event->setDtEnd( TQDateTime::fromString( s ) );
2990 s = tnefMsg->findProp( 0x8208 );
2991 event->setLocation( s );
2998 s = tnefMsg->findProp( 0x0023 );
3004 s = tnefMsg->findProp( 0x8202 ).replace( TQChar(
'-' ), TQString() )
3005 .replace( TQChar(
':' ), TQString() );
3009 s = tnefMsg->findNamedProp(
"Keywords" );
3010 event->setCategories( s );
3012 s = tnefMsg->findProp( 0x1000 );
3013 event->setDescription( s );
3015 s = tnefMsg->findProp( 0x0070 );
3016 event->setSummary( s );
3018 s = tnefMsg->findProp( 0x0026 );
3019 event->setPriority( s.toInt() );
3022 if(!tnefMsg->findProp(0x8503).isEmpty()) {
3024 TQDateTime highNoonTime =
3025 pureISOToLocalTQDateTime( tnefMsg->findProp( 0x8502 )
3026 .replace( TQChar(
'-' ),
"" )
3027 .replace( TQChar(
':' ),
"" ) );
3028 TQDateTime wakeMeUpTime =
3029 pureISOToLocalTQDateTime( tnefMsg->findProp( 0x8560,
"" )
3030 .replace( TQChar(
'-' ),
"" )
3031 .replace( TQChar(
':' ),
"" ) );
3034 if( highNoonTime.isValid() && wakeMeUpTime.isValid() )
3043 event->addAlarm( alarm );
3048 }
else if( bCompatClassNote ||
"IPM.CONTACT" == msgClass ) {
3049 addressee.setUid( stringProp( tnefMsg, attMSGID ) );
3050 addressee.setFormattedName( stringProp( tnefMsg, MAPI_TAG_PR_DISPLAY_NAME ) );
3051 addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL1EMAILADDRESS ),
true );
3052 addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL2EMAILADDRESS ),
false );
3053 addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL3EMAILADDRESS ),
false );
3054 addressee.insertCustom(
"KADDRESSBOOK",
"X-IMAddress", sNamedProp( tnefMsg, MAPI_TAG_CONTACT_IMADDRESS ) );
3055 addressee.insertCustom(
"KADDRESSBOOK",
"X-SpousesName", stringProp( tnefMsg, MAPI_TAG_PR_SPOUSE_NAME ) );
3056 addressee.insertCustom(
"KADDRESSBOOK",
"X-ManagersName", stringProp( tnefMsg, MAPI_TAG_PR_MANAGER_NAME ) );
3057 addressee.insertCustom(
"KADDRESSBOOK",
"X-AssistantsName", stringProp( tnefMsg, MAPI_TAG_PR_ASSISTANT ) );
3058 addressee.insertCustom(
"KADDRESSBOOK",
"X-Department", stringProp( tnefMsg, MAPI_TAG_PR_DEPARTMENT_NAME ) );
3059 addressee.insertCustom(
"KADDRESSBOOK",
"X-Office", stringProp( tnefMsg, MAPI_TAG_PR_OFFICE_LOCATION ) );
3060 addressee.insertCustom(
"KADDRESSBOOK",
"X-Profession", stringProp( tnefMsg, MAPI_TAG_PR_PROFESSION ) );
3062 TQString s = tnefMsg->findProp( MAPI_TAG_PR_WEDDING_ANNIVERSARY )
3063 .replace( TQChar(
'-' ), TQString() )
3064 .replace( TQChar(
':' ), TQString() );
3066 addressee.insertCustom(
"KADDRESSBOOK",
"X-Anniversary", s );
3068 addressee.setUrl( KURL( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_WEBPAGE ) ) );
3071 addressee.setFamilyName( stringProp( tnefMsg, MAPI_TAG_PR_SURNAME ) );
3072 addressee.setGivenName( stringProp( tnefMsg, MAPI_TAG_PR_GIVEN_NAME ) );
3073 addressee.setAdditionalName( stringProp( tnefMsg, MAPI_TAG_PR_MIDDLE_NAME ) );
3074 addressee.setPrefix( stringProp( tnefMsg, MAPI_TAG_PR_DISPLAY_NAME_PREFIX ) );
3075 addressee.setSuffix( stringProp( tnefMsg, MAPI_TAG_PR_GENERATION ) );
3077 addressee.setNickName( stringProp( tnefMsg, MAPI_TAG_PR_NICKNAME ) );
3078 addressee.setRole( stringProp( tnefMsg, MAPI_TAG_PR_TITLE ) );
3079 addressee.setOrganization( stringProp( tnefMsg, MAPI_TAG_PR_COMPANY_NAME ) );
3085 TDEABC::Address adr;
3086 adr.setPostOfficeBox( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_PO_BOX ) );
3087 adr.setStreet( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_STREET ) );
3088 adr.setLocality( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_CITY ) );
3089 adr.setRegion( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_STATE_OR_PROVINCE ) );
3090 adr.setPostalCode( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_POSTAL_CODE ) );
3091 adr.setCountry( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_COUNTRY ) );
3092 adr.setType(TDEABC::Address::Home);
3093 addressee.insertAddress(adr);
3095 adr.setPostOfficeBox( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSPOBOX ) );
3096 adr.setStreet( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSSTREET ) );
3097 adr.setLocality( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSCITY ) );
3098 adr.setRegion( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSSTATE ) );
3099 adr.setPostalCode( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSPOSTALCODE ) );
3100 adr.setCountry( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSCOUNTRY ) );
3101 adr.setType( TDEABC::Address::Work );
3102 addressee.insertAddress( adr );
3104 adr.setPostOfficeBox( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_PO_BOX ) );
3105 adr.setStreet( stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_STREET ) );
3106 adr.setLocality( stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_CITY ) );
3107 adr.setRegion( stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_STATE_OR_PROVINCE ) );
3108 adr.setPostalCode( stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_POSTAL_CODE ) );
3109 adr.setCountry( stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_COUNTRY ) );
3110 adr.setType( TDEABC::Address::Dom );
3111 addressee.insertAddress(adr);
3118 nr = stringProp( tnefMsg, MAPI_TAG_PR_HOME_TELEPHONE_NUMBER );
3119 addressee.insertPhoneNumber( TDEABC::PhoneNumber( nr, TDEABC::PhoneNumber::Home ) );
3120 nr = stringProp( tnefMsg, MAPI_TAG_PR_BUSINESS_TELEPHONE_NUMBER );
3121 addressee.insertPhoneNumber( TDEABC::PhoneNumber( nr, TDEABC::PhoneNumber::Work ) );
3122 nr = stringProp( tnefMsg, MAPI_TAG_PR_MOBILE_TELEPHONE_NUMBER );
3123 addressee.insertPhoneNumber( TDEABC::PhoneNumber( nr, TDEABC::PhoneNumber::Cell ) );
3124 nr = stringProp( tnefMsg, MAPI_TAG_PR_HOME_FAX_NUMBER );
3125 addressee.insertPhoneNumber( TDEABC::PhoneNumber( nr, TDEABC::PhoneNumber::Fax | TDEABC::PhoneNumber::Home ) );
3126 nr = stringProp( tnefMsg, MAPI_TAG_PR_BUSINESS_FAX_NUMBER );
3127 addressee.insertPhoneNumber( TDEABC::PhoneNumber( nr, TDEABC::PhoneNumber::Fax | TDEABC::PhoneNumber::Work ) );
3129 s = tnefMsg->findProp( MAPI_TAG_PR_BIRTHDAY )
3130 .replace( TQChar(
'-' ), TQString() )
3131 .replace( TQChar(
':' ), TQString() );
3133 addressee.setBirthday( TQDateTime::fromString( s ) );
3135 bOk = ( !addressee.isEmpty() );
3136 }
else if(
"IPM.NOTE" == msgClass ) {
3143 TQString iCal = calFormat.
toString( &cal );
3144 if( !iCal.isEmpty() )
3149 TDEABC::VCardConverter converter;
3150 return converter.createVCard( addressee );
3154 TQString IncidenceFormatter::formatTNEFInvitation(
const TQByteArray& tnef,
3155 Calendar *mCalendar, InvitationFormatterHelper *helper )
3158 TQString iCal = IncidenceFormatter::formatICalInvitation( vPart, mCalendar, helper );
3159 if( !iCal.isEmpty() )
3175 : mCalendar( 0 ), mRichText( true ), mResult(
"" ) {}
3178 const TQDate &date=TQDate(),
bool richText=
true )
3180 mCalendar = calendar;
3182 mRichText = richText;
3184 return incidence ? incidence->
accept( *
this ) :
false;
3186 TQString result()
const {
return mResult; }
3189 bool visit(
Event *event );
3190 bool visit(
Todo *todo );
3191 bool visit(
Journal *journal );
3194 TQString dateRangeText(
Event *event,
const TQDate &date );
3195 TQString dateRangeText(
Todo *todo,
const TQDate &date );
3196 TQString dateRangeText(
Journal *journal );
3197 TQString dateRangeText(
FreeBusy *fb );
3199 TQString generateToolTip(
Incidence* incidence, TQString dtRangeText );
3208 TQString IncidenceFormatter::ToolTipVisitor::dateRangeText(
Event *event,
const TQDate &date )
3213 TQDateTime startDt =
event->dtStart();
3214 TQDateTime endDt =
event->dtEnd();
3216 if ( date.isValid() ) {
3217 TQDateTime dt( date, TQTime( 0, 0, 0 ) );
3218 int diffDays = startDt.daysTo( dt );
3219 dt = dt.addSecs( -1 );
3222 endDt = endDt.addDays( diffDays );
3223 if ( startDt > endDt ) {
3225 endDt = startDt.addDays( event->
dtStart().daysTo( event->
dtEnd() ) );
3232 tmp =
"<br>" + i18n(
"Event start",
"<i>From:</i> %1");
3234 ret += tmp.arg( IncidenceFormatter::dateToString( startDt,
false ).replace(
" ",
" ") );
3236 ret += tmp.arg( IncidenceFormatter::dateToString( startDt ).replace(
" ",
" ") );
3238 tmp =
"<br>" + i18n(
"Event end",
"<i>To:</i> %1");
3240 ret += tmp.arg( IncidenceFormatter::dateToString( endDt,
false ).replace(
" ",
" ") );
3242 ret += tmp.arg( IncidenceFormatter::dateToString( endDt ).replace(
" ",
" ") );
3246 ret +=
"<br>"+i18n(
"<i>Date:</i> %1").
3247 arg( IncidenceFormatter::dateToString( startDt,
false ).replace(
" ",
" ") );
3249 const TQString dtStartTime =
3250 IncidenceFormatter::timeToString( startDt,
true ).replace(
" ",
" " );
3251 const TQString dtEndTime =
3252 IncidenceFormatter::timeToString( endDt,
true ).replace(
" ",
" " );
3253 if ( dtStartTime == dtEndTime ) {
3254 tmp =
"<br>" + i18n(
"time for event, to prevent ugly line breaks",
3255 "<i>Time:</i> %1").
3258 tmp =
"<br>" + i18n(
"time range for event, to prevent ugly line breaks",
3259 "<i>Time:</i> %1 - %2").
3260 arg( dtStartTime, dtEndTime );
3269 TQString IncidenceFormatter::ToolTipVisitor::dateRangeText(
Todo *todo,
const TQDate &date )
3275 TQDateTime startDt = todo->
dtStart();
3277 if ( date.isValid() ) {
3278 startDt.setDate( date );
3282 i18n(
"<i>Start:</i> %1").
3283 arg( IncidenceFormatter::dateTimeToString( startDt, floats,
false ).
3284 replace(
" ",
" " ) );
3288 TQDateTime dueDt = todo->
dtDue();
3290 if ( date.isValid() ) {
3291 TQDateTime dt( date, TQTime( 0, 0, 0 ) );
3292 dt = dt.addSecs( -1 );
3297 i18n(
"<i>Due:</i> %1").
3298 arg( IncidenceFormatter::dateTimeToString( dueDt, floats,
false ).
3299 replace(
" ",
" " ) );
3306 ret +=
"<i>" + i18n(
"Priority:" ) +
"</i>" +
" ";
3307 ret += TQString::number( todo->
priority() );
3312 ret +=
"<i>" + i18n(
"Completed:" ) +
"</i>" +
" ";
3315 ret +=
"<i>" + i18n(
"Percent Done:" ) +
"</i>" +
" ";
3322 TQString IncidenceFormatter::ToolTipVisitor::dateRangeText(
Journal*journal )
3325 if (journal->
dtStart().isValid() ) {
3327 i18n(
"<i>Date:</i> %1").
3328 arg( IncidenceFormatter::dateToString( journal->
dtStart(),
false ) );
3333 TQString IncidenceFormatter::ToolTipVisitor::dateRangeText(
FreeBusy *fb )
3335 TQString tmp(
"<br>" + i18n(
"<i>Period start:</i> %1") );
3336 TQString ret = tmp.arg( TDEGlobal::locale()->formatDateTime( fb->
dtStart() ) );
3337 tmp =
"<br>" + i18n(
"<i>Period start:</i> %1");
3338 ret += tmp.arg( TDEGlobal::locale()->formatDateTime( fb->dtEnd() ) );
3344 bool IncidenceFormatter::ToolTipVisitor::visit(
Event *event )
3346 mResult = generateToolTip( event, dateRangeText( event, mDate ) );
3347 return !mResult.isEmpty();
3350 bool IncidenceFormatter::ToolTipVisitor::visit(
Todo *todo )
3352 mResult = generateToolTip( todo, dateRangeText( todo, mDate ) );
3353 return !mResult.isEmpty();
3356 bool IncidenceFormatter::ToolTipVisitor::visit(
Journal *journal )
3358 mResult = generateToolTip( journal, dateRangeText( journal ) );
3359 return !mResult.isEmpty();
3362 bool IncidenceFormatter::ToolTipVisitor::visit(
FreeBusy *fb )
3364 mResult =
"<qt><b>" + i18n(
"Free/Busy information for %1")
3365 .arg(fb->organizer().fullName()) +
"</b>";
3366 mResult += dateRangeText( fb );
3368 return !mResult.isEmpty();
3371 static TQString tooltipPerson(
const TQString& email, TQString name )
3375 if ( name.isEmpty() && !email.isEmpty() ) {
3376 TDEABC::AddressBook *add_book = TDEABC::StdAddressBook::self(
true );
3377 TDEABC::Addressee::List addressList = add_book->findByEmail( email );
3378 if ( !addressList.isEmpty() ) {
3379 TDEABC::Addressee o = addressList.first();
3380 if ( !o.isEmpty() && addressList.size() < 2 ) {
3382 name = o.formattedName();
3388 TQString tmpString = ( name.isEmpty() ? email : name );
3393 static TQString etc = i18n(
"elipsis",
"..." );
3394 static TQString tooltipFormatAttendeeRoleList(
Incidence *incidence, Attendee::Role role )
3397 TQString sep = i18n(
"separator for lists of people names",
", " );
3398 int sepLen = sep.length();
3402 Attendee::List::ConstIterator it;
3405 for( it = attendees.begin(); it != attendees.end(); ++it ) {
3407 if ( a->
role() != role ) {
3411 if ( a->email() == incidence->organizer().email() ) {
3415 if ( i == maxNumAtts ) {
3419 tmpStr += tooltipPerson( a->email(), a->name() );
3421 tmpStr += i18n(
" (delegated by %1)" ).arg( a->
delegator() );
3424 tmpStr += i18n(
" (delegated to %1)" ).arg( a->
delegate() );
3429 if ( tmpStr.endsWith( sep ) ) {
3430 tmpStr.truncate( tmpStr.length() - sepLen );
3435 static TQString tooltipFormatAttendees(
Incidence *incidence )
3437 TQString tmpStr, str;
3440 int attendeeCount = incidence->
attendees().count();
3441 if ( attendeeCount > 1 ||
3442 ( attendeeCount == 1 &&
3443 incidence->organizer().email() != incidence->
attendees().first()->email() ) ) {
3444 tmpStr +=
"<i>" + i18n(
"Organizer:" ) +
"</i>" +
" ";
3445 tmpStr += tooltipPerson( incidence->organizer().email(),
3446 incidence->organizer().name() );
3450 str = tooltipFormatAttendeeRoleList( incidence, Attendee::Chair );
3451 if ( !str.isEmpty() ) {
3452 tmpStr +=
"<br><i>" + i18n(
"Chair:" ) +
"</i>" +
" ";
3457 str = tooltipFormatAttendeeRoleList( incidence, Attendee::ReqParticipant );
3458 if ( !str.isEmpty() ) {
3459 tmpStr +=
"<br><i>" + i18n(
"Required Participants:" ) +
"</i>" +
" ";
3464 str = tooltipFormatAttendeeRoleList( incidence, Attendee::OptParticipant );
3465 if ( !str.isEmpty() ) {
3466 tmpStr +=
"<br><i>" + i18n(
"Optional Participants:" ) +
"</i>" +
" ";
3471 str = tooltipFormatAttendeeRoleList( incidence, Attendee::NonParticipant );
3472 if ( !str.isEmpty() ) {
3473 tmpStr +=
"<br><i>" + i18n(
"Observers:" ) +
"</i>" +
" ";
3480 TQString IncidenceFormatter::ToolTipVisitor::generateToolTip(
Incidence* incidence, TQString dtRangeText )
3482 uint maxDescLen = 120;
3488 TQString tmp =
"<qt>";
3491 tmp +=
"<b>" + incidence->
summary().replace(
"\n",
"<br>" ) +
"</b>";
3493 tmp +=
"<br>----------<br>";
3497 if ( !calStr.isEmpty() ) {
3498 tmp +=
"<i>" + i18n(
"Calendar:" ) +
"</i>" +
" ";
3505 if ( !incidence->
location().isEmpty() ) {
3507 tmp +=
"<i>" + i18n(
"Location:" ) +
"</i>" +
" ";
3508 tmp += incidence->
location().replace(
"\n",
"<br>" );
3512 if ( !durStr.isEmpty() ) {
3514 tmp +=
"<i>" + i18n(
"Duration:" ) +
"</i>" +
" ";
3520 tmp +=
"<i>" + i18n(
"Recurrence:" ) +
"</i>" +
" ";
3521 tmp += IncidenceFormatter::recurrenceString( incidence );
3526 if ( desc.length() > maxDescLen ) {
3527 desc = desc.left( maxDescLen ) + etc;
3529 tmp +=
"<br>----------<br>";
3530 tmp +=
"<i>" + i18n(
"Description:" ) +
"</i>" +
"<br>";
3531 tmp += desc.replace(
"\n",
"<br>" );
3532 tmp +=
"<br>----------";
3535 int reminderCount = incidence->
alarms().count();
3538 tmp +=
"<i>" + i18n(
"Reminder:",
"%n Reminders:", reminderCount ) +
"</i>" +
" ";
3539 tmp += IncidenceFormatter::reminderStringList( incidence ).join(
", " );
3543 tmp += tooltipFormatAttendees( incidence );
3545 int categoryCount = incidence->
categories().count();
3546 if ( categoryCount > 0 ) {
3548 tmp +=
"<i>" + i18n(
"Category:",
"%n Categories:", categoryCount ) +
"</i>" +
" ";
3556 TQString IncidenceFormatter::toolTipString(
IncidenceBase *incidence,
bool richText )
3558 return toolTipStr( 0, incidence, TQDate(), richText );
3561 TQString IncidenceFormatter::toolTipStr(
Calendar *calendar,
3567 if ( v.act( calendar, incidence, date, richText ) ) {
3581 MailBodyVisitor() : mResult(
"" ) {}
3586 return incidence ? incidence->
accept( *
this ) :
false;
3588 TQString result()
const {
return mResult; }
3591 bool visit(
Event *event );
3592 bool visit(
Todo *todo );
3593 bool visit(
Journal *journal );
3594 bool visit(
FreeBusy * ) { mResult = i18n(
"This is a Free Busy Object");
return !mResult.isEmpty(); }
3600 static TQString mailBodyIncidence(
Incidence *incidence )
3603 if ( !incidence->
summary().isEmpty() ) {
3604 body += i18n(
"Summary: %1\n").arg( incidence->
summary() );
3606 if ( !incidence->organizer().isEmpty() ) {
3607 body += i18n(
"Organizer: %1\n").arg( incidence->organizer().fullName() );
3609 if ( !incidence->
location().isEmpty() ) {
3610 body += i18n(
"Location: %1\n").arg( incidence->
location() );
3615 bool IncidenceFormatter::MailBodyVisitor::visit(
Event *event )
3617 TQString recurrence[]= {i18n(
"no recurrence",
"None"),
3618 i18n(
"Minutely"), i18n(
"Hourly"), i18n(
"Daily"),
3619 i18n(
"Weekly"), i18n(
"Monthly Same Day"), i18n(
"Monthly Same Position"),
3620 i18n(
"Yearly"), i18n(
"Yearly"), i18n(
"Yearly")};
3622 mResult = mailBodyIncidence( event );
3623 mResult += i18n(
"Start Date: %1\n").
3624 arg( IncidenceFormatter::dateToString( event->
dtStart(),
true ) );
3626 mResult += i18n(
"Start Time: %1\n").
3627 arg( IncidenceFormatter::timeToString( event->
dtStart(),
true ) );
3630 mResult += i18n(
"End Date: %1\n").
3631 arg( IncidenceFormatter::dateToString( event->
dtEnd(),
true ) );
3634 mResult += i18n(
"End Time: %1\n").
3635 arg( IncidenceFormatter::timeToString( event->
dtEnd(),
true ) );
3640 mResult += i18n(
"Recurs: %1\n")
3642 mResult += i18n(
"Frequency: %1\n")
3646 mResult += i18n (
"Repeats once",
"Repeats %n times", recur->
duration());
3653 endstr = TDEGlobal::locale()->formatDate( recur->
endDate() );
3655 endstr = TDEGlobal::locale()->formatDateTime( recur->
endDateTime() );
3657 mResult += i18n(
"Repeat until: %1\n").arg( endstr );
3659 mResult += i18n(
"Repeats forever\n");
3663 DateList exceptions = recur->exDates();
3664 if (exceptions.isEmpty() ==
false) {
3665 mResult += i18n(
"This recurring meeting has been cancelled on the following days:\n");
3666 DateList::ConstIterator ex_iter;
3667 for ( ex_iter = exceptions.begin(); ex_iter != exceptions.end(); ++ex_iter ) {
3668 mResult += i18n(
" %1\n").arg( TDEGlobal::locale()->formatDate(* ex_iter ) );
3672 TQString details =
event->description();
3673 if ( !details.isEmpty() ) {
3674 mResult += i18n(
"Details:\n%1\n").arg( details );
3676 return !mResult.isEmpty();
3679 bool IncidenceFormatter::MailBodyVisitor::visit(
Todo *todo )
3681 mResult = mailBodyIncidence( todo );
3684 mResult += i18n(
"Start Date: %1\n").
3685 arg( IncidenceFormatter::dateToString( todo->
dtStart(
false ),
true ) );
3687 mResult += i18n(
"Start Time: %1\n").
3688 arg( IncidenceFormatter::timeToString( todo->
dtStart(
false ),
true ) );
3692 mResult += i18n(
"Due Date: %1\n").
3693 arg( IncidenceFormatter::dateToString( todo->
dtDue(),
true ) );
3695 mResult += i18n(
"Due Time: %1\n").
3696 arg( IncidenceFormatter::timeToString( todo->
dtDue(),
true ) );
3700 if ( !details.isEmpty() ) {
3701 mResult += i18n(
"Details:\n%1\n").arg( details );
3703 return !mResult.isEmpty();
3706 bool IncidenceFormatter::MailBodyVisitor::visit(
Journal *journal )
3708 mResult = mailBodyIncidence( journal );
3709 mResult += i18n(
"Date: %1\n").
3710 arg( IncidenceFormatter::dateToString( journal->
dtStart(),
true ) );
3712 mResult += i18n(
"Time: %1\n").
3713 arg( IncidenceFormatter::timeToString( journal->
dtStart(),
true ) );
3716 mResult += i18n(
"Text of the journal:\n%1\n").arg( journal->
description() );
3717 return !mResult.isEmpty();
3722 TQString IncidenceFormatter::mailBodyString(
IncidenceBase *incidence )
3728 if ( v.act( incidence ) ) {
3734 static TQString recurEnd(
Incidence *incidence )
3748 TQString IncidenceFormatter::recurrenceString(
Incidence *incidence )
3751 return i18n(
"No recurrence" );
3753 TQStringList dayList;
3754 dayList.append( i18n(
"31st Last" ) );
3755 dayList.append( i18n(
"30th Last" ) );
3756 dayList.append( i18n(
"29th Last" ) );
3757 dayList.append( i18n(
"28th Last" ) );
3758 dayList.append( i18n(
"27th Last" ) );
3759 dayList.append( i18n(
"26th Last" ) );
3760 dayList.append( i18n(
"25th Last" ) );
3761 dayList.append( i18n(
"24th Last" ) );
3762 dayList.append( i18n(
"23rd Last" ) );
3763 dayList.append( i18n(
"22nd Last" ) );
3764 dayList.append( i18n(
"21st Last" ) );
3765 dayList.append( i18n(
"20th Last" ) );
3766 dayList.append( i18n(
"19th Last" ) );
3767 dayList.append( i18n(
"18th Last" ) );
3768 dayList.append( i18n(
"17th Last" ) );
3769 dayList.append( i18n(
"16th Last" ) );
3770 dayList.append( i18n(
"15th Last" ) );
3771 dayList.append( i18n(
"14th Last" ) );
3772 dayList.append( i18n(
"13th Last" ) );
3773 dayList.append( i18n(
"12th Last" ) );
3774 dayList.append( i18n(
"11th Last" ) );
3775 dayList.append( i18n(
"10th Last" ) );
3776 dayList.append( i18n(
"9th Last" ) );
3777 dayList.append( i18n(
"8th Last" ) );
3778 dayList.append( i18n(
"7th Last" ) );
3779 dayList.append( i18n(
"6th Last" ) );
3780 dayList.append( i18n(
"5th Last" ) );
3781 dayList.append( i18n(
"4th Last" ) );
3782 dayList.append( i18n(
"3rd Last" ) );
3783 dayList.append( i18n(
"2nd Last" ) );
3784 dayList.append( i18n(
"last day of the month",
"Last" ) );
3785 dayList.append( i18n(
"unknown day of the month",
"unknown" ) );
3786 dayList.append( i18n(
"1st" ) );
3787 dayList.append( i18n(
"2nd" ) );
3788 dayList.append( i18n(
"3rd" ) );
3789 dayList.append( i18n(
"4th" ) );
3790 dayList.append( i18n(
"5th" ) );
3791 dayList.append( i18n(
"6th" ) );
3792 dayList.append( i18n(
"7th" ) );
3793 dayList.append( i18n(
"8th" ) );
3794 dayList.append( i18n(
"9th" ) );
3795 dayList.append( i18n(
"10th" ) );
3796 dayList.append( i18n(
"11th" ) );
3797 dayList.append( i18n(
"12th" ) );
3798 dayList.append( i18n(
"13th" ) );
3799 dayList.append( i18n(
"14th" ) );
3800 dayList.append( i18n(
"15th" ) );
3801 dayList.append( i18n(
"16th" ) );
3802 dayList.append( i18n(
"17th" ) );
3803 dayList.append( i18n(
"18th" ) );
3804 dayList.append( i18n(
"19th" ) );
3805 dayList.append( i18n(
"20th" ) );
3806 dayList.append( i18n(
"21st" ) );
3807 dayList.append( i18n(
"22nd" ) );
3808 dayList.append( i18n(
"23rd" ) );
3809 dayList.append( i18n(
"24th" ) );
3810 dayList.append( i18n(
"25th" ) );
3811 dayList.append( i18n(
"26th" ) );
3812 dayList.append( i18n(
"27th" ) );
3813 dayList.append( i18n(
"28th" ) );
3814 dayList.append( i18n(
"29th" ) );
3815 dayList.append( i18n(
"30th" ) );
3816 dayList.append( i18n(
"31st" ) );
3817 int weekStart = TDEGlobal::locale()->weekStartDay();
3819 TQString recurStr, txt;
3820 const KCalendarSystem *calSys = TDEGlobal::locale()->calendar();
3823 case Recurrence::rNone:
3824 return i18n(
"No recurrence" );
3826 case Recurrence::rMinutely:
3827 recurStr = i18n(
"Recurs every minute",
"Recurs every %n minutes", recur->
frequency() );
3829 txt = i18n(
"%1 until %2" ).arg( recurStr ).arg( recurEnd( incidence ) );
3831 txt += i18n(
" (%1 occurrences)" ).arg( recur->
duration() );
3837 case Recurrence::rHourly:
3838 recurStr = i18n(
"Recurs hourly",
"Recurs every %n hours", recur->
frequency() );
3840 txt = i18n(
"%1 until %2" ).arg( recurStr ).arg( recurEnd( incidence ) );
3842 txt += i18n(
" (%1 occurrences)" ).arg( recur->
duration() );
3848 case Recurrence::rDaily:
3849 recurStr = i18n(
"Recurs daily",
"Recurs every %n days", recur->
frequency() );
3852 txt = i18n(
"%1 until %2" ).arg( recurStr ).arg( recurEnd( incidence ) );
3854 txt += i18n(
" (%1 occurrences)" ).arg( recur->
duration() );
3860 case Recurrence::rWeekly:
3862 recurStr = i18n(
"Recurs weekly",
"Recurs every %n weeks", recur->
frequency() );
3864 bool addSpace =
false;
3865 for (
int i = 0; i < 7; ++i ) {
3866 if ( recur->
days().testBit( ( i + weekStart + 6 ) % 7 ) ) {
3868 dayNames.append( i18n(
"separator for list of days",
", " ) );
3870 dayNames.append( calSys->weekDayName( ( ( i + weekStart + 6 ) % 7 ) + 1,
true ) );
3874 if ( dayNames.isEmpty() ) {
3875 dayNames = i18n(
"Recurs weekly on no days",
"no days" );
3878 txt = i18n(
"%1 on %2 until %3" ).
3879 arg( recurStr ).arg( dayNames ).arg( recurEnd( incidence ) );
3881 txt += i18n(
" (%1 occurrences)" ).arg( recur->
duration() );
3885 txt = i18n(
"%1 on %2" ).arg( recurStr ).arg( dayNames );
3888 case Recurrence::rMonthlyPos:
3890 recurStr = i18n(
"Recurs monthly",
"Recurs every %n months", recur->
frequency() );
3895 txt = i18n(
"%1 on the %2 %3 until %4" ).
3897 arg( dayList[rule.pos() + 31] ).
3898 arg( calSys->weekDayName( rule.day(),
false ) ).
3899 arg( recurEnd( incidence ) );
3901 txt += i18n(
" (%1 occurrences)" ).arg( recur->
duration() );
3905 txt = i18n(
"%1 on the %2 %3" ).
3907 arg( dayList[rule.pos() + 31] ).
3908 arg( calSys->weekDayName( rule.day(),
false ) );
3915 case Recurrence::rMonthlyDay:
3917 recurStr = i18n(
"Recurs monthly",
"Recurs every %n months", recur->
frequency() );
3922 txt = i18n(
"%1 on the %2 day until %3" ).
3924 arg( dayList[days + 31] ).
3925 arg( recurEnd( incidence ) );
3927 txt += i18n(
" (%1 occurrences)" ).arg( recur->
duration() );
3931 txt = i18n(
"%1 on the %2 day" ).arg( recurStr ).arg( dayList[days + 31] );
3938 case Recurrence::rYearlyMonth:
3940 recurStr = i18n(
"Recurs yearly",
"Recurs every %n years", recur->
frequency() );
3944 txt = i18n(
"%1 on %2 %3 until %4" ).
3947 arg( dayList[ recur->
yearDates()[0] + 31 ] ).
3948 arg( recurEnd( incidence ) );
3950 txt += i18n(
" (%1 occurrences)" ).arg( recur->
duration() );
3956 txt = i18n(
"%1 on %2 %3" ).
3959 arg( dayList[ recur->
yearDates()[0] + 31 ] );
3963 txt = i18n(
"Recurs yearly on %1 %2" ).
3964 arg( calSys->monthName( recur->
yearMonths()[0],
3966 arg( dayList[ recur->
startDate().day() + 31 ] );
3968 txt = i18n(
"Recurs yearly on %1 %2" ).
3969 arg( calSys->monthName( recur->
startDate().month(),
3971 arg( dayList[ recur->
startDate().day() + 31 ] );
3977 case Recurrence::rYearlyDay:
3979 recurStr = i18n(
"Recurs yearly",
"Recurs every %n years", recur->
frequency() );
3980 if ( !recur->
yearDays().isEmpty() ) {
3982 txt = i18n(
"%1 on day %2 until %3" ).
3985 arg( recurEnd( incidence ) );
3987 txt += i18n(
" (%1 occurrences)" ).arg( recur->
duration() );
3991 txt = i18n(
"%1 on day %2" ).arg( recurStr ).arg( recur->
yearDays()[0] );
3998 case Recurrence::rYearlyPos:
4000 recurStr = i18n(
"Every year",
"Every %n years", recur->
frequency() );
4004 txt = i18n(
"%1 on the %2 %3 of %4 until %5" ).
4006 arg( dayList[rule.pos() + 31] ).
4007 arg( calSys->weekDayName( rule.day(),
false ) ).
4009 arg( recurEnd( incidence ) );
4011 txt += i18n(
" (%1 occurrences)" ).arg( recur->
duration() );
4015 txt = i18n(
"%1 on the %2 %3 of %4" ).
4017 arg( dayList[rule.pos() + 31] ).
4018 arg( calSys->weekDayName( rule.day(),
false ) ).
4028 return i18n(
"Incidence recurs" );
4031 TQString IncidenceFormatter::timeToString(
const TQDateTime &date,
bool shortfmt )
4033 return TDEGlobal::locale()->formatTime( date.time(), !shortfmt );
4036 TQString IncidenceFormatter::dateToString(
const TQDateTime &date,
bool shortfmt )
4039 TDEGlobal::locale()->formatDate( date.date(), shortfmt );
4042 TQString IncidenceFormatter::dateTimeToString(
const TQDateTime &date,
4043 bool allDay,
bool shortfmt )
4046 return dateToString( date, shortfmt );
4049 return TDEGlobal::locale()->formatDateTime( date, shortfmt );
4054 if ( !calendar || !incidence ) {
4059 if ( !calendarResource ) {
4064 if ( resourceCalendar ) {
4067 if ( subRes.isEmpty() ) {
4068 return resourceCalendar->resourceName();
4073 return resourceCalendar->resourceName();
4079 static TQString secs2Duration(
int secs )
4082 int days = secs / 86400;
4084 tmp += i18n(
"1 day",
"%n days", days );
4086 secs -= ( days * 86400 );
4088 int hours = secs / 3600;
4090 tmp += i18n(
"1 hour",
"%n hours", hours );
4092 secs -= ( hours * 3600 );
4094 int mins = secs / 60;
4096 tmp += i18n(
"1 minute",
"%n minutes", mins );
4104 if ( incidence->type() ==
"Event" ) {
4105 Event *
event =
static_cast<Event *
>( incidence );
4108 tmp = secs2Duration( event->
dtStart().secsTo( event->
dtEnd() ) );
4110 tmp = i18n(
"1 day",
"%n days",
4111 event->
dtStart().date().daysTo( event->
dtEnd().date() ) + 1 );
4114 tmp = i18n(
"forever" );
4116 }
else if ( incidence->type() ==
"Todo" ) {
4117 Todo *todo =
static_cast<Todo *
>( incidence );
4121 tmp = secs2Duration( todo->
dtStart().secsTo( todo->
dtDue() ) );
4123 tmp = i18n(
"1 day",
"%n days",
4124 todo->
dtStart().date().daysTo( todo->
dtDue().date() ) + 1 );
4132 TQStringList IncidenceFormatter::reminderStringList(
Incidence *incidence,
bool shortfmt )
4135 Q_UNUSED( shortfmt );
4137 TQStringList reminderStringList;
4141 Alarm::List::ConstIterator it;
4142 for ( it = alarms.begin(); it != alarms.end(); ++it ) {
4145 TQString remStr, atStr, offsetStr;
4148 if ( alarm->
time().isValid() ) {
4149 atStr = TDEGlobal::locale()->formatDateTime( alarm->
time() );
4155 offsetStr = i18n(
"N days/hours/minutes before the start datetime",
4156 "%1 before the start" );
4157 }
else if ( offset > 0 ) {
4158 offsetStr = i18n(
"N days/hours/minutes after the start datetime",
4159 "%1 after the start" );
4161 if ( incidence->
dtStart().isValid() ) {
4162 atStr = TDEGlobal::locale()->formatDateTime( incidence->
dtStart() );
4169 if ( incidence->type() ==
"Todo" ) {
4170 offsetStr = i18n(
"N days/hours/minutes before the due datetime",
4171 "%1 before the to-do is due" );
4173 offsetStr = i18n(
"N days/hours/minutes before the end datetime",
4174 "%1 before the end" );
4176 }
else if ( offset > 0 ) {
4177 if ( incidence->type() ==
"Todo" ) {
4178 offsetStr = i18n(
"N days/hours/minutes after the due datetime",
4179 "%1 after the to-do is due" );
4181 offsetStr = i18n(
"N days/hours/minutes after the end datetime",
4182 "%1 after the end" );
4185 if ( incidence->type() ==
"Todo" ) {
4186 Todo *t =
static_cast<Todo *
>( incidence );
4187 if ( t->
dtDue().isValid() ) {
4188 atStr = TDEGlobal::locale()->formatDateTime( t->
dtDue() );
4191 Event *e =
static_cast<Event *
>( incidence );
4192 if ( e->
dtEnd().isValid() ) {
4193 atStr = TDEGlobal::locale()->formatDateTime( e->
dtEnd() );
4198 if ( offset == 0 ) {
4199 if ( !atStr.isEmpty() ) {
4200 remStr = i18n(
"reminder occurs at datetime",
"at %1" ).arg( atStr );
4203 remStr = offsetStr.arg( secs2Duration( offset ) );
4207 TQString countStr = i18n(
"repeats once",
"repeats %n times", alarm->
repeatCount() );
4208 TQString intervalStr = i18n(
"interval is N days/hours/minutes",
"interval is %1" ).
4210 TQString repeatStr = i18n(
"(repeat string, interval string)",
"(%1, %2)" ).
4211 arg( countStr, intervalStr );
4212 remStr = remStr +
' ' + repeatStr;
4215 reminderStringList << remStr;
4219 return reminderStringList;
Provides the main "calendar" object class.
Provides a Calendar composed of several Calendar Resources.
This class represents an alarm notification.
bool hasStartOffset() const
Return whether the alarm is defined in terms of an offset relative to the start of the event.
Duration snoozeTime() const
Get how long the alarm snooze interval is.
TQDateTime time() const
Return the date/time when an alarm goes off.
Duration endOffset() const
Return offset of alarm in time relative to the end of the event.
bool hasEndOffset() const
Return whether the alarm is defined in terms of an offset relative to the end of the event.
void setDisplayAlarm(const TQString &text=TQString())
Set the alarm to be a display alarm.
Duration startOffset() const
Return offset of alarm in time relative to the start of the event.
bool hasTime() const
Return true, if the alarm has an explicit date/time.
void setStartOffset(const Duration &)
Set offset of alarm in time relative to the start of the event.
void setTime(const TQDateTime &alarmTime)
Set the time to trigger an alarm.
int repeatCount() const
Get how many times an alarm repeats, after its initial occurrence.
This class represents information related to an attachment.
This class represents information related to an attendee of an event.
void setRole(Role)
Set role of Attendee.
TQString uid() const
Return unique id of the attendee.
TQString delegate() const
Returns the delegate.
Role role() const
Return role of Attendee.
static TQString roleName(Role)
Return string represenation of role.
TQString delegator() const
Returns the delegator.
void setStatus(PartStat s)
Set status.
static TQString statusName(PartStat)
Return string representation of attendee status.
PartStat status() const
Return status.
TQString statusStr() const
Return status as human-readable string.
This class provides a calendar stored as a local file.
bool addEvent(Event *event)
Add Event to calendar.
This class provides a Calendar which is composed of other Calendars known as "Resources".
ResourceCalendar * resource(Incidence *incidence)
Get the Resource associated with a specified Incidence.
This is the main "calendar" object class.
TQString customProperty(const TQCString &app, const TQCString &key) const
Return the value of a custom calendar property.
This class represents a duration.
int asSeconds() const
Returns the length of the duration in seconds.
This class provides an Event in the sense of RFC2445.
virtual TQDateTime dtEnd() const
Return end date and time.
bool isMultiDay() const
Return true if the event spans multiple days, otherwise return false.
bool hasEndDate() const
Return whether the event has an end date/time.
This class provides information about free/busy time of a calendar user.
This class provides the interface for a visitor of calendar components.
This class provides the base class common to all calendar components.
TQStringList comments() const
Return all comments associated with this incidence.
bool doesFloat() const
Return true or false depending on whether the incidence "floats," i.e.
const Attendee::List & attendees() const
Return list of attendees.
TQString uid() const
Return the unique id for the event.
Attendee * attendeeByMail(const TQString &) const
Return the Attendee with this email address.
virtual TQDateTime dtStart() const
returns an event's starting date/time as a TQDateTime.
virtual bool accept(Visitor &)
Accept IncidenceVisitor.
bool isReadOnly() const
Return if the object is read-only.
This class provides the base class common to all calendar components.
const Alarm::List & alarms() const
All alarms that are associated with this incidence.
TQDateTime created() const
Return time and date of creation.
int revision() const
Return the number of revisions this event has seen.
TQString description() const
Return long description.
TQStringList categories() const
Return categories as a list of strings.
int priority() const
Return priority.
bool doesRecur() const
Forward to Recurrence::doesRecur().
bool isAlarmEnabled() const
Return whether any alarm associated with this incidence is enabled.
TQString location() const
Return the event's/todo's location.
Attachment::List attachments() const
Return list of all associated attachments.
TQString summary() const
Return short summary.
Recurrence * recurrence() const
Return the recurrence rule associated with this incidence.
This class provides a Journal in the sense of RFC2445.
This class represents a period of time.
This class represents a person.
structure for describing the n-th weekday of the month/year.
This class represents a recurrence rule for a calendar incidence.
ushort recurrenceType() const
Returns the event's recurrence status.
TQDateTime endDateTime() const
Returns the date/time of the last recurrence.
int frequency() const
Returns frequency of recurrence, in terms of the recurrence time period type.
TQValueList< RecurrenceRule::WDayPos > yearPositions() const
Returns the positions within a yearly recurrence.
TQBitArray days() const
Returns week day mask (bit 0 = Monday).
TQDate startDate() const
Return the start date/time of the recurrence.
TQValueList< int > monthDays() const
Returns list of day numbers of a month.
TQDateTime getPreviousDateTime(const TQDateTime &afterDateTime) const
Returns the date and time of the last previous recurrence, before the specified date/time.
int duration() const
Returns -1 if the event recurs infinitely, 0 if the end date is set, otherwise the total number of re...
TQDate endDate() const
Returns the date of the last recurrence.
TQValueList< int > yearMonths() const
Returns the months within a yearly recurrence.
TQValueList< RecurrenceRule::WDayPos > monthPositions() const
Returns list of day positions in months.
TQValueList< int > yearDays() const
Returns the day numbers within a yearly recurrence.
TQValueList< int > yearDates() const
Returns the dates within a yearly recurrence.
TQDateTime getNextDateTime(const TQDateTime &preDateTime) const
Returns the date and time of the next recurrence, after the specified date/time.
This class provides the interfaces for a calendar resource.
virtual TQString subresourceIdentifier(Incidence *incidence)
Get the identifier of the subresource associated with a specified incidence.
virtual TQStringList subresources() const
If this resource has subresources, return a TQStringList of them.
virtual const TQString labelForSubresource(const TQString &resource) const
What is the label for this subresource?
This class provides an encapsulation of a scheduling message.
IncidenceBase * event()
Return event associated with this message.
int method()
Return iTIP method associated with this message.
This class provides a Todo in the sense of RFC2445.
bool hasDueDate() const
Returns true if the todo has a due date, otherwise return false.
TQString completedStr() const
Returns string contaiting date and time when the todo was completed formatted according to the users ...
bool isCompleted() const
Returns true if the todo is 100% completed, otherwise return false.
bool hasStartDate() const
Returns true if the todo has a start date, otherwise return false.
TQDateTime dtStart(bool first=false) const
Returns the startdate of the todo.
int percentComplete() const
Returns how many percent of the task are completed.
TQDateTime dtDue(bool first=false) const
Returns due date and time.
Namespace KCal is for global classes, objects and/or functions in libkcal.