00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "incidenceformatter.h"
00025
00026 #include <libkcal/attachment.h>
00027 #include <libkcal/event.h>
00028 #include <libkcal/todo.h>
00029 #include <libkcal/journal.h>
00030 #include <libkcal/calendar.h>
00031 #include <libkcal/calendarlocal.h>
00032 #include <libkcal/icalformat.h>
00033 #include <libkcal/freebusy.h>
00034 #include <libkcal/calendarresources.h>
00035
00036 #include <libemailfunctions/email.h>
00037
00038 #include <ktnef/ktnefparser.h>
00039 #include <ktnef/ktnefmessage.h>
00040 #include <ktnef/ktnefdefs.h>
00041 #include <kabc/phonenumber.h>
00042 #include <kabc/vcardconverter.h>
00043 #include <kabc/stdaddressbook.h>
00044
00045 #include <kapplication.h>
00046 #include <kemailsettings.h>
00047
00048 #include <klocale.h>
00049 #include <kglobal.h>
00050 #include <kiconloader.h>
00051 #include <kcalendarsystem.h>
00052 #include <kmimetype.h>
00053
00054 #include <qbuffer.h>
00055 #include <qstylesheet.h>
00056 #include <qdatetime.h>
00057 #include <qregexp.h>
00058
00059 #include <time.h>
00060
00061 using namespace KCal;
00062
00063
00064
00065
00066
00067 static QString htmlAddLink( const QString &ref, const QString &text,
00068 bool newline = true )
00069 {
00070 QString tmpStr( "<a href=\"" + ref + "\">" + text + "</a>" );
00071 if ( newline ) tmpStr += "\n";
00072 return tmpStr;
00073 }
00074
00075 static QString htmlAddTag( const QString & tag, const QString & text )
00076 {
00077 int numLineBreaks = text.contains( "\n" );
00078 QString str = "<" + tag + ">";
00079 QString tmpText = text;
00080 QString tmpStr = str;
00081 if( numLineBreaks >= 0 ) {
00082 if ( numLineBreaks > 0) {
00083 int pos = 0;
00084 QString tmp;
00085 for( int i = 0; i <= numLineBreaks; i++ ) {
00086 pos = tmpText.find( "\n" );
00087 tmp = tmpText.left( pos );
00088 tmpText = tmpText.right( tmpText.length() - pos - 1 );
00089 tmpStr += tmp + "<br>";
00090 }
00091 } else {
00092 tmpStr += tmpText;
00093 }
00094 }
00095 tmpStr += "</" + tag + ">";
00096 return tmpStr;
00097 }
00098
00099 static bool iamAttendee( Attendee *attendee )
00100 {
00101
00102
00103 bool iam = false;
00104 KEMailSettings settings;
00105 QStringList profiles = settings.profiles();
00106 for( QStringList::Iterator it=profiles.begin(); it!=profiles.end(); ++it ) {
00107 settings.setProfile( *it );
00108 if ( settings.getSetting( KEMailSettings::EmailAddress ) == attendee->email() ) {
00109 iam = true;
00110 break;
00111 }
00112 }
00113 return iam;
00114 }
00115
00116 static bool iamOrganizer( Incidence *incidence )
00117 {
00118
00119
00120 if ( !incidence ) {
00121 return false;
00122 }
00123
00124 bool iam = false;
00125 KEMailSettings settings;
00126 QStringList profiles = settings.profiles();
00127 for( QStringList::Iterator it=profiles.begin(); it!=profiles.end(); ++it ) {
00128 settings.setProfile( *it );
00129 if ( settings.getSetting( KEMailSettings::EmailAddress ) == incidence->organizer().email() ) {
00130 iam = true;
00131 break;
00132 }
00133 }
00134 return iam;
00135 }
00136
00137
00138
00139
00140
00141 static QString displayViewLinkPerson( const QString& email, QString name, QString uid )
00142 {
00143
00144
00145 if ( !email.isEmpty() && ( name.isEmpty() || uid.isEmpty() ) ) {
00146 KABC::AddressBook *add_book = KABC::StdAddressBook::self( true );
00147 KABC::Addressee::List addressList = add_book->findByEmail( email );
00148 if ( !addressList.isEmpty() ) {
00149 KABC::Addressee o = addressList.first();
00150 if ( !o.isEmpty() && addressList.size() < 2 ) {
00151 if ( name.isEmpty() ) {
00152
00153 name = o.formattedName();
00154 }
00155 uid = o.uid();
00156 } else {
00157
00158 uid = QString::null;
00159 }
00160 }
00161 }
00162 kdDebug(5850) << "formatAttendees: uid = " << uid << endl;
00163
00164
00165 QString tmpString;
00166 if ( !uid.isEmpty() ) {
00167
00168 if ( name.isEmpty() ) {
00169
00170 tmpString += htmlAddLink( "uid:" + uid, email );
00171 } else {
00172 tmpString += htmlAddLink( "uid:" + uid, name );
00173 }
00174 } else {
00175
00176 tmpString += ( name.isEmpty() ? email : name );
00177 }
00178
00179
00180 if ( !email.isEmpty() ) {
00181 KURL mailto;
00182 mailto.setProtocol( "mailto" );
00183 mailto.setPath( email );
00184 const QString iconPath =
00185 KGlobal::iconLoader()->iconPath( "mail_new", KIcon::Small );
00186 tmpString += htmlAddLink( mailto.url(),
00187 "<img valign=\"top\" src=\"" + iconPath + "\">" );
00188 }
00189
00190 return tmpString;
00191 }
00192
00193 static QString displayViewFormatAttendees( Incidence *incidence )
00194 {
00195 QString tmpStr;
00196 Attendee::List attendees = incidence->attendees();
00197
00198
00199 tmpStr += "<tr>";
00200 tmpStr += "<td><b>" + i18n( "Organizer:" ) + "</b></td>";
00201 tmpStr += "<td>" +
00202 displayViewLinkPerson( incidence->organizer().email(),
00203 incidence->organizer().name(),
00204 QString::null ) +
00205 "</td>";
00206 tmpStr += "</tr>";
00207
00208
00209 tmpStr += "<tr>";
00210 tmpStr += "<td><b>" + i18n( "Attendees:" ) + "</b></td>";
00211 tmpStr += "<td>";
00212 Attendee::List::ConstIterator it;
00213 for( it = attendees.begin(); it != attendees.end(); ++it ) {
00214 Attendee *a = *it;
00215 if ( a->email() == incidence->organizer().email() ) {
00216
00217 continue;
00218 }
00219 tmpStr += displayViewLinkPerson( a->email(), a->name(), a->uid() );
00220 if ( !a->delegator().isEmpty() ) {
00221 tmpStr += i18n(" (delegated by %1)" ).arg( a->delegator() );
00222 }
00223 if ( !a->delegate().isEmpty() ) {
00224 tmpStr += i18n(" (delegated to %1)" ).arg( a->delegate() );
00225 }
00226 tmpStr += "<br>";
00227 }
00228 if ( tmpStr.endsWith( "<br>" ) ) {
00229 tmpStr.truncate( tmpStr.length() - 4 );
00230 }
00231
00232 tmpStr += "</td>";
00233 tmpStr += "</tr>";
00234 return tmpStr;
00235 }
00236
00237 static QString displayViewFormatAttachments( Incidence *incidence )
00238 {
00239 QString tmpStr;
00240 Attachment::List as = incidence->attachments();
00241 Attachment::List::ConstIterator it;
00242 uint count = 0;
00243 for( it = as.begin(); it != as.end(); ++it ) {
00244 count++;
00245 if ( (*it)->isUri() ) {
00246 QString name;
00247 if ( (*it)->uri().startsWith( "kmail:" ) ) {
00248 name = i18n( "Show mail" );
00249 } else {
00250 name = (*it)->label();
00251 }
00252 tmpStr += htmlAddLink( (*it)->uri(), name );
00253 } else {
00254 tmpStr += (*it)->label();
00255 }
00256 if ( count < as.count() ) {
00257 tmpStr += "<br>";
00258 }
00259 }
00260 return tmpStr;
00261 }
00262
00263 static QString displayViewFormatCategories( Incidence *incidence )
00264 {
00265 return incidence->categoriesStr();
00266 }
00267
00268 static QString displayViewFormatCreationDate( Incidence *incidence )
00269 {
00270 return i18n( "Creation date: %1" ).
00271 arg( IncidenceFormatter::dateTimeToString( incidence->created(), false, true ) );
00272 }
00273
00274 static QString displayViewFormatBirthday( Event *event )
00275 {
00276 if ( !event ) {
00277 return QString::null;
00278 }
00279 if ( event->customProperty("KABC","BIRTHDAY") != "YES" ) {
00280 return QString::null;
00281 }
00282
00283 QString uid = event->customProperty("KABC","UID-1");
00284 QString name = event->customProperty("KABC","NAME-1");
00285 QString email= event->customProperty("KABC","EMAIL-1");
00286
00287 QString tmpStr = displayViewLinkPerson( email, name, uid );
00288
00289 if ( event->customProperty( "KABC", "ANNIVERSARY") == "YES" ) {
00290 uid = event->customProperty("KABC","UID-2");
00291 name = event->customProperty("KABC","NAME-2");
00292 email= event->customProperty("KABC","EMAIL-2");
00293 tmpStr += "<br>";
00294 tmpStr += displayViewLinkPerson( email, name, uid );
00295 }
00296
00297 return tmpStr;
00298 }
00299
00300 static QString displayViewFormatHeader( Incidence *incidence )
00301 {
00302 QString tmpStr = "<table><tr>";
00303
00304
00305 {
00306 tmpStr += "<td>";
00307
00308 if ( incidence->type() == "Event" ) {
00309 QString iconPath;
00310 if ( incidence->customProperty( "KABC", "BIRTHDAY" ) == "YES" ) {
00311 if ( incidence->customProperty( "KABC", "ANNIVERSARY" ) == "YES" ) {
00312 iconPath =
00313 KGlobal::iconLoader()->iconPath( "calendaranniversary", KIcon::Small );
00314 } else {
00315 iconPath = KGlobal::iconLoader()->iconPath( "calendarbirthday", KIcon::Small );
00316 }
00317 } else {
00318 iconPath = KGlobal::iconLoader()->iconPath( "appointment", KIcon::Small );
00319 }
00320 tmpStr += "<img valign=\"top\" src=\"" + iconPath + "\">";
00321 }
00322 if ( incidence->type() == "Todo" ) {
00323 tmpStr += "<img valign=\"top\" src=\"" +
00324 KGlobal::iconLoader()->iconPath( "todo", KIcon::Small ) +
00325 "\">";
00326 }
00327 if ( incidence->type() == "Journal" ) {
00328 tmpStr += "<img valign=\"top\" src=\"" +
00329 KGlobal::iconLoader()->iconPath( "journal", KIcon::Small ) +
00330 "\">";
00331 }
00332 if ( incidence->isAlarmEnabled() ) {
00333 tmpStr += "<img valign=\"top\" src=\"" +
00334 KGlobal::iconLoader()->iconPath( "bell", KIcon::Small ) +
00335 "\">";
00336 }
00337 if ( incidence->doesRecur() ) {
00338 tmpStr += "<img valign=\"top\" src=\"" +
00339 KGlobal::iconLoader()->iconPath( "recur", KIcon::Small ) +
00340 "\">";
00341 }
00342 if ( incidence->isReadOnly() ) {
00343 tmpStr += "<img valign=\"top\" src=\"" +
00344 KGlobal::iconLoader()->iconPath( "readonlyevent", KIcon::Small ) +
00345 "\">";
00346 }
00347
00348 tmpStr += "</td>";
00349 }
00350
00351 tmpStr += "<td>";
00352 tmpStr += "<b><u>" + incidence->summary() + "</u></b>";
00353 tmpStr += "</td>";
00354
00355 tmpStr += "</tr></table>";
00356
00357 return tmpStr;
00358 }
00359
00360 static QString displayViewFormatEvent( Calendar *calendar, Event *event,
00361 const QDate &date )
00362 {
00363 if ( !event ) {
00364 return QString::null;
00365 }
00366
00367 QString tmpStr = displayViewFormatHeader( event );
00368
00369 tmpStr += "<table>";
00370 tmpStr += "<col width=\"25%\"/>";
00371 tmpStr += "<col width=\"75%\"/>";
00372
00373 if ( calendar ) {
00374 QString calStr = IncidenceFormatter::resourceString( calendar, event );
00375 if ( !calStr.isEmpty() ) {
00376 tmpStr += "<tr>";
00377 tmpStr += "<td><b>" + i18n( "Calendar:" ) + "</b></td>";
00378 tmpStr += "<td>" + calStr + "</td>";
00379 tmpStr += "</tr>";
00380 }
00381 }
00382
00383 if ( !event->location().isEmpty() ) {
00384 tmpStr += "<tr>";
00385 tmpStr += "<td><b>" + i18n( "Location:" ) + "</b></td>";
00386 tmpStr += "<td>" + event->location() + "</td>";
00387 tmpStr += "</tr>";
00388 }
00389
00390 tmpStr += "<tr>";
00391 QDateTime startDt = event->dtStart();
00392 QDateTime endDt = event->dtEnd();
00393 if ( event->doesRecur() ) {
00394 if ( date.isValid() ) {
00395 QDateTime dt( date, QTime( 0, 0, 0 ) );
00396 int diffDays = startDt.daysTo( dt );
00397 dt = dt.addSecs( -1 );
00398 startDt.setDate( event->recurrence()->getNextDateTime( dt ).date() );
00399 if ( event->hasEndDate() ) {
00400 endDt = endDt.addDays( diffDays );
00401 if ( startDt > endDt ) {
00402 startDt.setDate( event->recurrence()->getPreviousDateTime( dt ).date() );
00403 endDt = startDt.addDays( event->dtStart().daysTo( event->dtEnd() ) );
00404 }
00405 }
00406 }
00407 }
00408 if ( event->doesFloat() ) {
00409 if ( event->isMultiDay() ) {
00410 tmpStr += "<td><b>" + i18n( "Time:" ) + "</b></td>";
00411 tmpStr += "<td>" +
00412 i18n("<beginTime> - <endTime>","%1 - %2").
00413 arg( IncidenceFormatter::dateToString( startDt, false ) ).
00414 arg( IncidenceFormatter::dateToString( endDt, false ) ) +
00415 "</td>";
00416 } else {
00417 tmpStr += "<td><b>" + i18n( "Date:" ) + "</b></td>";
00418 tmpStr += "<td>" +
00419 i18n("date as string","%1").
00420 arg( IncidenceFormatter::dateToString( startDt, false ) ) +
00421 "</td>";
00422 }
00423 } else {
00424 if ( event->isMultiDay() ) {
00425 tmpStr += "<td><b>" + i18n( "Time:" ) + "</b></td>";
00426 tmpStr += "<td>" +
00427 i18n("<beginTime> - <endTime>","%1 - %2").
00428 arg( IncidenceFormatter::dateToString( startDt, false ) ).
00429 arg( IncidenceFormatter::dateToString( endDt, false ) ) +
00430 "</td>";
00431 } else {
00432 tmpStr += "<td><b>" + i18n( "Time:" ) + "</b></td>";
00433 if ( event->hasEndDate() && startDt != endDt ) {
00434 tmpStr += "<td>" +
00435 i18n("<beginTime> - <endTime>","%1 - %2").
00436 arg( IncidenceFormatter::timeToString( startDt, true ) ).
00437 arg( IncidenceFormatter::timeToString( endDt, true ) ) +
00438 "</td>";
00439 } else {
00440 tmpStr += "<td>" +
00441 IncidenceFormatter::timeToString( startDt, true ) +
00442 "</td>";
00443 }
00444 tmpStr += "</tr><tr>";
00445 tmpStr += "<td><b>" + i18n( "Date:" ) + "</b></td>";
00446 tmpStr += "<td>" +
00447 i18n("date as string","%1").
00448 arg( IncidenceFormatter::dateToString( startDt, false ) ) +
00449 "</td>";
00450 }
00451 }
00452 tmpStr += "</tr>";
00453
00454 if ( event->customProperty("KABC","BIRTHDAY")== "YES" ) {
00455 tmpStr += "<tr>";
00456 if ( event->customProperty( "KABC", "ANNIVERSARY" ) == "YES" ) {
00457 tmpStr += "<td><b>" + i18n( "Anniversary:" ) + "</b></td>";
00458 } else {
00459 tmpStr += "<td><b>" + i18n( "Birthday:" ) + "</b></td>";
00460 }
00461 tmpStr += "<td>" + displayViewFormatBirthday( event ) + "</td>";
00462 tmpStr += "</tr>";
00463 tmpStr += "</table>";
00464 return tmpStr;
00465 }
00466
00467 if ( !event->description().isEmpty() ) {
00468 tmpStr += "<tr>";
00469 tmpStr += "<td><b>" + i18n( "Description:" ) + "</b></td>";
00470 tmpStr += "<td>" + event->description() + "</td>";
00471 tmpStr += "</tr>";
00472 }
00473
00474 int categoryCount = event->categories().count();
00475 if ( categoryCount > 0 ) {
00476 tmpStr += "<tr>";
00477 tmpStr += "<td><b>" +
00478 i18n( "Category:", "Categories:", categoryCount ) +
00479 "</b></td>";
00480 tmpStr += "<td>" + displayViewFormatCategories( event ) + "</td>";
00481 tmpStr += "</tr>";
00482 }
00483
00484 if ( event->doesRecur() ) {
00485 QDateTime dt =
00486 event->recurrence()->getNextDateTime( QDateTime::currentDateTime() );
00487 tmpStr += "<tr>";
00488 tmpStr += "<td><b>" + i18n( "next recurrence", "Next:" ) + "</b></td>";
00489 tmpStr += "<td>" +
00490 ( dt.isValid() ?
00491 IncidenceFormatter::dateTimeToString( dt, event->doesFloat(), false ) :
00492 i18n( "no date", "none" ) ) +
00493 "</td>";
00494 tmpStr += "</tr>";
00495 }
00496
00497 if ( event->attendees().count() > 1 ) {
00498 tmpStr += displayViewFormatAttendees( event );
00499 }
00500
00501 int attachmentCount = event->attachments().count();
00502 if ( attachmentCount > 0 ) {
00503 tmpStr += "<tr>";
00504 tmpStr += "<td><b>" +
00505 i18n( "Attachment:", "Attachments:", attachmentCount ) +
00506 "</b></td>";
00507 tmpStr += "<td>" + displayViewFormatAttachments( event ) + "</td>";
00508 tmpStr += "</tr>";
00509 }
00510 tmpStr += "</table>";
00511
00512 tmpStr += "<em>" + displayViewFormatCreationDate( event ) + "</em>";
00513
00514 return tmpStr;
00515 }
00516
00517 static QString displayViewFormatTodo( Calendar *calendar, Todo *todo,
00518 const QDate &date )
00519 {
00520 if ( !todo ) {
00521 return QString::null;
00522 }
00523
00524 QString tmpStr = displayViewFormatHeader( todo );
00525
00526 tmpStr += "<table>";
00527 tmpStr += "<col width=\"25%\"/>";
00528 tmpStr += "<col width=\"75%\"/>";
00529
00530 if ( calendar ) {
00531 QString calStr = IncidenceFormatter::resourceString( calendar, todo );
00532 if ( !calStr.isEmpty() ) {
00533 tmpStr += "<tr>";
00534 tmpStr += "<td><b>" + i18n( "Calendar:" ) + "</b></td>";
00535 tmpStr += "<td>" + calStr + "</td>";
00536 tmpStr += "</tr>";
00537 }
00538 }
00539
00540 if ( !todo->location().isEmpty() ) {
00541 tmpStr += "<tr>";
00542 tmpStr += "<td><b>" + i18n( "Location:" ) + "</b></td>";
00543 tmpStr += "<td>" + todo->location() + "</td>";
00544 tmpStr += "</tr>";
00545 }
00546
00547 if ( todo->hasStartDate() && todo->dtStart().isValid() ) {
00548 QDateTime startDt = todo->dtStart();
00549 if ( todo->doesRecur() ) {
00550 if ( date.isValid() ) {
00551 startDt.setDate( date );
00552 }
00553 }
00554 tmpStr += "<tr>";
00555 tmpStr += "<td><b>" + i18n( "Start:" ) + "</b></td>";
00556 tmpStr += "<td>" +
00557 IncidenceFormatter::dateTimeToString( startDt,
00558 todo->doesFloat(), false ) +
00559 "</td>";
00560 tmpStr += "</tr>";
00561 }
00562
00563 if ( todo->hasDueDate() && todo->dtDue().isValid() ) {
00564 QDateTime dueDt = todo->dtDue();
00565 if ( todo->doesRecur() ) {
00566 if ( date.isValid() ) {
00567 dueDt.addDays( todo->dtDue().date().daysTo( date ) );
00568 }
00569 }
00570 tmpStr += "<tr>";
00571 tmpStr += "<td><b>" + i18n( "Due:" ) + "</b></td>";
00572 tmpStr += "<td>" +
00573 IncidenceFormatter::dateTimeToString( dueDt,
00574 todo->doesFloat(), false ) +
00575 "</td>";
00576 tmpStr += "</tr>";
00577 }
00578
00579 if ( !todo->description().isEmpty() ) {
00580 tmpStr += "<tr>";
00581 tmpStr += "<td><b>" + i18n( "Description:" ) + "</b></td>";
00582 tmpStr += "<td>" + todo->description() + "</td>";
00583 tmpStr += "</tr>";
00584 }
00585
00586 int categoryCount = todo->categories().count();
00587 if ( categoryCount > 0 ) {
00588 tmpStr += "<tr>";
00589 tmpStr += "<td><b>" +
00590 i18n( "Category:", "Categories:", categoryCount ) +
00591 "</b></td>";
00592 tmpStr += "<td>" + displayViewFormatCategories( todo ) + "</td>";
00593 tmpStr += "</tr>";
00594 }
00595
00596 tmpStr += "<tr>";
00597 tmpStr += "<td><b>" + i18n( "Priority:" ) + "</b></td>";
00598 tmpStr += "<td>";
00599 if ( todo->priority() > 0 ) {
00600 tmpStr += QString::number( todo->priority() );
00601 } else {
00602 tmpStr += i18n( "Unspecified" );
00603 }
00604 tmpStr += "</td>";
00605 tmpStr += "</tr>";
00606
00607 tmpStr += "<tr>";
00608 tmpStr += "<td><b>" + i18n( "Completed:" ) + "</b></td>";
00609 tmpStr += "<td>" + i18n( "%1%" ).arg( todo->percentComplete() ) + "</td>";
00610 tmpStr += "</tr>";
00611
00612 if ( todo->doesRecur() ) {
00613 QDateTime dt =
00614 todo->recurrence()->getNextDateTime( QDateTime::currentDateTime() );
00615 tmpStr += "<tr>";
00616 tmpStr += "<td><b>" +
00617 i18n( "next recurrence", "Next:" ) +
00618 "</b></td>";
00619 tmpStr += ( dt.isValid() ?
00620 IncidenceFormatter::dateTimeToString( dt, todo->doesFloat(), false ) :
00621 i18n( "no date", "none" ) ) +
00622 "</td>";
00623 tmpStr += "</tr>";
00624 }
00625
00626 if ( todo->attendees().count() > 1 ) {
00627 tmpStr += displayViewFormatAttendees( todo );
00628 }
00629
00630 int attachmentCount = todo->attachments().count();
00631 if ( attachmentCount > 0 ) {
00632 tmpStr += "<tr>";
00633 tmpStr += "<td><b>" +
00634 i18n( "Attachment:", "Attachments:", attachmentCount ) +
00635 "</b></td>";
00636 tmpStr += "<td>" + displayViewFormatAttachments( todo ) + "</td>";
00637 tmpStr += "</tr>";
00638 }
00639
00640 tmpStr += "</table>";
00641
00642 tmpStr += "<em>" + displayViewFormatCreationDate( todo ) + "</em>";
00643
00644 return tmpStr;
00645 }
00646
00647 static QString displayViewFormatJournal( Calendar *calendar, Journal *journal )
00648 {
00649 if ( !journal ) {
00650 return QString::null;
00651 }
00652
00653 QString tmpStr = displayViewFormatHeader( journal );
00654
00655 tmpStr += "<table>";
00656 tmpStr += "<col width=\"25%\"/>";
00657 tmpStr += "<col width=\"75%\"/>";
00658
00659 if ( calendar ) {
00660 QString calStr = IncidenceFormatter::resourceString( calendar, journal );
00661 if ( !calStr.isEmpty() ) {
00662 tmpStr += "<tr>";
00663 tmpStr += "<td><b>" + i18n( "Calendar:" ) + "</b></td>";
00664 tmpStr += "<td>" + calStr + "</td>";
00665 tmpStr += "</tr>";
00666 }
00667 }
00668
00669 tmpStr += "<tr>";
00670 tmpStr += "<td><b>" + i18n( "Date:" ) + "</b></td>";
00671 tmpStr += "<td>" +
00672 IncidenceFormatter::dateToString( journal->dtStart(), false ) +
00673 "</td>";
00674 tmpStr += "</tr>";
00675
00676 if ( !journal->description().isEmpty() ) {
00677 tmpStr += "<tr>";
00678 tmpStr += "<td><b>" + i18n( "Description:" ) + "</b></td>";
00679 tmpStr += "<td>" + journal->description() + "</td>";
00680 tmpStr += "</tr>";
00681 }
00682
00683 int categoryCount = journal->categories().count();
00684 if ( categoryCount > 0 ) {
00685 tmpStr += "<tr>";
00686 tmpStr += "<td><b>" +
00687 i18n( "Category:", "Categories:", categoryCount ) +
00688 "</b></td>";
00689 tmpStr += "<td>" + displayViewFormatCategories( journal ) + "</td>";
00690 tmpStr += "</tr>";
00691 }
00692 tmpStr += "</table>";
00693
00694 tmpStr += "<em>" + displayViewFormatCreationDate( journal ) + "</em>";
00695
00696 return tmpStr;
00697 }
00698
00699 static QString displayViewFormatFreeBusy( Calendar * , FreeBusy *fb )
00700 {
00701 if ( !fb ) {
00702 return QString::null;
00703 }
00704
00705 QString tmpStr = htmlAddTag( "h2",
00706 htmlAddTag( "b",
00707 i18n("Free/Busy information for %1").
00708 arg( fb->organizer().fullName() ) ) );
00709
00710 tmpStr += htmlAddTag( "h4", i18n("Busy times in date range %1 - %2:").
00711 arg( IncidenceFormatter::dateToString( fb->dtStart(), true ) ).
00712 arg( IncidenceFormatter::dateToString( fb->dtEnd(), true ) ) );
00713
00714 QValueList<Period> periods = fb->busyPeriods();
00715
00716 QString text = htmlAddTag( "em", htmlAddTag( "b", i18n("Busy:") ) );
00717 QValueList<Period>::iterator it;
00718 for ( it = periods.begin(); it != periods.end(); ++it ) {
00719 Period per = *it;
00720 if ( per.hasDuration() ) {
00721 int dur = per.duration().asSeconds();
00722 QString cont;
00723 if ( dur >= 3600 ) {
00724 cont += i18n("1 hour ", "%n hours ", dur / 3600 );
00725 dur %= 3600;
00726 }
00727 if ( dur >= 60 ) {
00728 cont += i18n("1 minute ", "%n minutes ", dur / 60);
00729 dur %= 60;
00730 }
00731 if ( dur > 0 ) {
00732 cont += i18n("1 second", "%n seconds", dur);
00733 }
00734 text += i18n("startDate for duration", "%1 for %2").
00735 arg( IncidenceFormatter::dateTimeToString( per.start(), false, true ) ).
00736 arg( cont );
00737 text += "<br>";
00738 } else {
00739 if ( per.start().date() == per.end().date() ) {
00740 text += i18n("date, fromTime - toTime ", "%1, %2 - %3").
00741 arg( IncidenceFormatter::dateToString( per.start().date(), true ) ).
00742 arg( IncidenceFormatter::timeToString( per.start(), true ) ).
00743 arg( IncidenceFormatter::timeToString( per.end(), true ) );
00744 } else {
00745 text += i18n("fromDateTime - toDateTime", "%1 - %2").
00746 arg( IncidenceFormatter::dateTimeToString( per.start(), false, true ) ).
00747 arg( IncidenceFormatter::dateTimeToString( per.end(), false, true ) );
00748 }
00749 text += "<br>";
00750 }
00751 }
00752 tmpStr += htmlAddTag( "p", text );
00753 return tmpStr;
00754 }
00755
00756 class IncidenceFormatter::EventViewerVisitor : public IncidenceBase::Visitor
00757 {
00758 public:
00759 EventViewerVisitor()
00760 : mCalendar( 0 ), mResult( "" ) {}
00761
00762 bool act( Calendar *calendar, IncidenceBase *incidence, const QDate &date )
00763 {
00764 mCalendar = calendar;
00765 mDate = date;
00766 mResult = "";
00767 return incidence->accept( *this );
00768 }
00769 QString result() const { return mResult; }
00770
00771 protected:
00772 bool visit( Event *event )
00773 {
00774 mResult = displayViewFormatEvent( mCalendar, event, mDate );
00775 return !mResult.isEmpty();
00776 }
00777 bool visit( Todo *todo )
00778 {
00779 mResult = displayViewFormatTodo( mCalendar, todo, mDate );
00780 return !mResult.isEmpty();
00781 }
00782 bool visit( Journal *journal )
00783 {
00784 mResult = displayViewFormatJournal( mCalendar, journal );
00785 return !mResult.isEmpty();
00786 }
00787 bool visit( FreeBusy *fb )
00788 {
00789 mResult = displayViewFormatFreeBusy( mCalendar, fb );
00790 return !mResult.isEmpty();
00791 }
00792
00793 protected:
00794 Calendar *mCalendar;
00795 QDate mDate;
00796 QString mResult;
00797 };
00798
00799 QString IncidenceFormatter::extensiveDisplayString( IncidenceBase *incidence )
00800 {
00801 return extensiveDisplayStr( 0, incidence, QDate() );
00802 }
00803
00804 QString IncidenceFormatter::extensiveDisplayStr( Calendar *calendar,
00805 IncidenceBase *incidence,
00806 const QDate &date )
00807 {
00808 if ( !incidence ) {
00809 return QString::null;
00810 }
00811
00812 EventViewerVisitor v;
00813 if ( v.act( calendar, incidence, date ) ) {
00814 return v.result();
00815 } else {
00816 return QString::null;
00817 }
00818 }
00819
00820
00821
00822
00823
00824 static QString string2HTML( const QString& str )
00825 {
00826 return QStyleSheet::convertFromPlainText(str, QStyleSheetItem::WhiteSpaceNormal);
00827 }
00828
00829 static QString cleanHtml( const QString &html )
00830 {
00831 QRegExp rx( "<body[^>]*>(.*)</body>" );
00832 rx.setCaseSensitive( false );
00833 rx.search( html );
00834 QString body = rx.cap( 1 );
00835
00836 return QStyleSheet::escape( body.remove( QRegExp( "<[^>]*>" ) ).stripWhiteSpace() );
00837 }
00838
00839 static QString eventStartTimeStr( Event *event )
00840 {
00841 QString tmp;
00842 if ( !event->doesFloat() ) {
00843 tmp = i18n( "%1: Start Date, %2: Start Time", "%1 %2" ).
00844 arg( IncidenceFormatter::dateToString( event->dtStart(), true ),
00845 IncidenceFormatter::timeToString( event->dtStart(), true ) );
00846 } else {
00847 tmp = i18n( "%1: Start Date", "%1 (all day)" ).
00848 arg( IncidenceFormatter::dateToString( event->dtStart(), true ) );
00849 }
00850 return tmp;
00851 }
00852
00853 static QString eventEndTimeStr( Event *event )
00854 {
00855 QString tmp;
00856 if ( event->hasEndDate() && event->dtEnd().isValid() ) {
00857 if ( !event->doesFloat() ) {
00858 tmp = i18n( "%1: End Date, %2: End Time", "%1 %2" ).
00859 arg( IncidenceFormatter::dateToString( event->dtEnd(), true ),
00860 IncidenceFormatter::timeToString( event->dtEnd(), true ) );
00861 } else {
00862 tmp = i18n( "%1: End Date", "%1 (all day)" ).
00863 arg( IncidenceFormatter::dateToString( event->dtEnd(), true ) );
00864 }
00865 }
00866 return tmp;
00867 }
00868
00869 static QString invitationRow( const QString &cell1, const QString &cell2 )
00870 {
00871 return "<tr><td>" + cell1 + "</td><td>" + cell2 + "</td></tr>\n";
00872 }
00873
00874 static Attendee *findMyAttendee( Incidence *incidence )
00875 {
00876
00877
00878 Attendee *attendee = 0;
00879 if ( !incidence ) {
00880 return attendee;
00881 }
00882
00883 KEMailSettings settings;
00884 QStringList profiles = settings.profiles();
00885 for( QStringList::Iterator it=profiles.begin(); it!=profiles.end(); ++it ) {
00886 settings.setProfile( *it );
00887
00888 Attendee::List attendees = incidence->attendees();
00889 Attendee::List::ConstIterator it2;
00890 for ( it2 = attendees.begin(); it2 != attendees.end(); ++it2 ) {
00891 Attendee *a = *it2;
00892 if ( settings.getSetting( KEMailSettings::EmailAddress ) == a->email() ) {
00893 attendee = a;
00894 break;
00895 }
00896 }
00897 }
00898 return attendee;
00899 }
00900
00901 static Attendee *findAttendee( Incidence *incidence, const QString &email )
00902 {
00903
00904
00905 Attendee *attendee = 0;
00906 if ( !incidence ) {
00907 return attendee;
00908 }
00909
00910 Attendee::List attendees = incidence->attendees();
00911 Attendee::List::ConstIterator it;
00912 for ( it = attendees.begin(); it != attendees.end(); ++it ) {
00913 Attendee *a = *it;
00914 if ( email == a->email() ) {
00915 attendee = a;
00916 break;
00917 }
00918 }
00919 return attendee;
00920 }
00921
00922 static bool rsvpRequested( Incidence *incidence )
00923 {
00924 if ( !incidence ) {
00925 return false;
00926 }
00927
00928
00929
00930 bool rsvp = true;
00931 Attendee::List attendees = incidence->attendees();
00932 Attendee::List::ConstIterator it;
00933 for ( it = attendees.begin(); it != attendees.end(); ++it ) {
00934 if ( it == attendees.begin() ) {
00935 rsvp = (*it)->RSVP();
00936 } else {
00937 if ( (*it)->RSVP() != rsvp ) {
00938 rsvp = true;
00939 break;
00940 }
00941 }
00942 }
00943 return rsvp;
00944 }
00945
00946 static QString rsvpRequestedStr( bool rsvpRequested, const QString &role )
00947 {
00948 if ( rsvpRequested ) {
00949 if ( role.isEmpty() ) {
00950 return i18n( "Your response is requested" );
00951 } else {
00952 return i18n( "Your response as <b>%1</b> is requested" ).arg( role );
00953 }
00954 } else {
00955 if ( role.isEmpty() ) {
00956 return i18n( "A response is not necessary" );
00957 } else {
00958 return i18n( "A response as <b>%1</b> is not necessary" ).arg( role );
00959 }
00960 }
00961 }
00962
00963 static QString myStatusStr( Incidence *incidence )
00964 {
00965 QString ret;
00966 Attendee *a = findMyAttendee( incidence );
00967 if ( a && a->status() != Attendee::NeedsAction ) {
00968 ret = i18n( "(<b>Note</b>: the Organizer preset your response to <b>%1</b>)" ).
00969 arg( Attendee::statusName( a->status() ) );
00970 }
00971 return ret;
00972 }
00973
00974 static QString invitationPerson( const QString& email, QString name, QString uid )
00975 {
00976
00977
00978 if ( !email.isEmpty() && ( name.isEmpty() || uid.isEmpty() ) ) {
00979 KABC::AddressBook *add_book = KABC::StdAddressBook::self( true );
00980 KABC::Addressee::List addressList = add_book->findByEmail( email );
00981 if ( !addressList.isEmpty() ) {
00982 KABC::Addressee o = addressList.first();
00983 if ( !o.isEmpty() && addressList.size() < 2 ) {
00984 if ( name.isEmpty() ) {
00985
00986 name = o.formattedName();
00987 }
00988 uid = o.uid();
00989 } else {
00990
00991 uid = QString::null;
00992 }
00993 }
00994 }
00995
00996
00997 QString tmpString;
00998 if ( !uid.isEmpty() ) {
00999
01000 if ( name.isEmpty() ) {
01001
01002 tmpString += htmlAddLink( "uid:" + uid, email );
01003 } else {
01004 tmpString += htmlAddLink( "uid:" + uid, name );
01005 }
01006 } else {
01007
01008 tmpString += ( name.isEmpty() ? email : name );
01009 }
01010 tmpString += '\n';
01011
01012
01013 if ( !email.isEmpty() ) {
01014 KCal::Person person( name, email );
01015 KURL mailto;
01016 mailto.setProtocol( "mailto" );
01017 mailto.setPath( person.fullName() );
01018 const QString iconPath =
01019 KGlobal::iconLoader()->iconPath( "mail_new", KIcon::Small );
01020 tmpString += htmlAddLink( mailto.url(), "<img src=\"" + iconPath + "\">" )
01021 ;
01022 }
01023 tmpString += "\n";
01024
01025 return tmpString;
01026 }
01027
01028 static QString invitationsDetailsIncidence( Incidence *incidence, bool noHtmlMode )
01029 {
01030
01031
01032
01033
01034 QString html;
01035 QString descr;
01036 QStringList comments;
01037
01038 if ( incidence->comments().isEmpty() ) {
01039 if ( !incidence->description().isEmpty() ) {
01040
01041 if ( !QStyleSheet::mightBeRichText( incidence->description() ) ) {
01042 comments << string2HTML( incidence->description() );
01043 } else {
01044 comments << incidence->description();
01045 if ( noHtmlMode ) {
01046 comments[0] = cleanHtml( comments[0] );
01047 }
01048 comments[0] = htmlAddTag( "p", comments[0] );
01049 }
01050 }
01051
01052 } else {
01053
01054 QStringList cl = incidence->comments();
01055 uint i = 0;
01056 for( QStringList::Iterator it=cl.begin(); it!=cl.end(); ++it ) {
01057 if ( !QStyleSheet::mightBeRichText( *it ) ) {
01058 comments.append( string2HTML( *it ) );
01059 } else {
01060 if ( noHtmlMode ) {
01061 comments.append( cleanHtml( "<body>" + (*it) + "</body>" ) );
01062 } else {
01063 comments.append( *it );
01064 }
01065 }
01066 i++;
01067 }
01068 if ( !incidence->description().isEmpty() ) {
01069
01070 if ( !QStyleSheet::mightBeRichText( incidence->description() ) ) {
01071 descr = string2HTML( incidence->description() );
01072 } else {
01073 descr = incidence->description();
01074 if ( noHtmlMode ) {
01075 descr = cleanHtml( descr );
01076 }
01077 descr = htmlAddTag( "p", descr );
01078 }
01079 }
01080 }
01081
01082 if( !descr.isEmpty() ) {
01083 html += "<p>";
01084 html += "<table border=\"0\" style=\"margin-top:4px;\">";
01085 html += "<tr><td><center>" +
01086 htmlAddTag( "u", i18n( "Description:" ) ) +
01087 "</center></td></tr>";
01088 html += "<tr><td>" + descr + "</td></tr>";
01089 html += "</table>";
01090 }
01091
01092 if ( !comments.isEmpty() ) {
01093 html += "<p>";
01094 html += "<table border=\"0\" style=\"margin-top:4px;\">";
01095 html += "<tr><td><center>" +
01096 htmlAddTag( "u", i18n( "Comments:" ) ) +
01097 "</center></td></tr>";
01098 html += "<tr><td>";
01099 if ( comments.count() > 1 ) {
01100 html += "<ul>";
01101 for ( uint i=0; i < comments.count(); ++i ) {
01102 html += "<li>" + comments[i] + "</li>";
01103 }
01104 html += "</ul>";
01105 } else {
01106 html += comments[0];
01107 }
01108 html += "</td></tr>";
01109 html += "</table>";
01110 }
01111 return html;
01112 }
01113
01114 static QString invitationDetailsEvent( Event* event, bool noHtmlMode )
01115 {
01116
01117 if ( !event ) {
01118 return QString::null;
01119 }
01120
01121 QString sSummary = i18n( "Summary unspecified" );
01122 if ( !event->summary().isEmpty() ) {
01123 if ( !QStyleSheet::mightBeRichText( event->summary() ) ) {
01124 sSummary = QStyleSheet::escape( event->summary() );
01125 } else {
01126 sSummary = event->summary();
01127 if ( noHtmlMode ) {
01128 sSummary = cleanHtml( sSummary );
01129 }
01130 }
01131 }
01132
01133 QString sLocation = i18n( "Location unspecified" );
01134 if ( !event->location().isEmpty() ) {
01135 if ( !QStyleSheet::mightBeRichText( event->location() ) ) {
01136 sLocation = QStyleSheet::escape( event->location() );
01137 } else {
01138 sLocation = event->location();
01139 if ( noHtmlMode ) {
01140 sLocation = cleanHtml( sLocation );
01141 }
01142 }
01143 }
01144
01145 QString dir = ( QApplication::reverseLayout() ? "rtl" : "ltr" );
01146 QString html = QString("<div dir=\"%1\">\n").arg(dir);
01147 html += "<table border=\"0\" cellpadding=\"1\" cellspacing=\"1\">\n";
01148
01149
01150 html += invitationRow( i18n( "What:" ), sSummary );
01151 html += invitationRow( i18n( "Where:" ), sLocation );
01152
01153
01154 if ( event->dtStart().date() == event->dtEnd().date() ) {
01155 html += invitationRow( i18n( "Date:" ),
01156 IncidenceFormatter::dateToString( event->dtStart(), false ) );
01157 if ( !event->doesFloat() ) {
01158 html += invitationRow( i18n( "Time:" ),
01159 IncidenceFormatter::timeToString( event->dtStart(), true ) +
01160 " - " +
01161 IncidenceFormatter::timeToString( event->dtEnd(), true ) );
01162 }
01163 } else {
01164 html += invitationRow( i18n( "Starting date of an event", "From:" ),
01165 IncidenceFormatter::dateToString( event->dtStart(), false ) );
01166 if ( !event->doesFloat() ) {
01167 html += invitationRow( i18n( "Starting time of an event", "At:" ),
01168 IncidenceFormatter::timeToString( event->dtStart(), true ) );
01169 }
01170 if ( event->hasEndDate() ) {
01171 html += invitationRow( i18n( "Ending date of an event", "To:" ),
01172 IncidenceFormatter::dateToString( event->dtEnd(), false ) );
01173 if ( !event->doesFloat() ) {
01174 html += invitationRow( i18n( "Starting time of an event", "At:" ),
01175 IncidenceFormatter::timeToString( event->dtEnd(), true ) );
01176 }
01177 } else {
01178 html += invitationRow( i18n( "Ending date of an event", "To:" ),
01179 i18n( "no end date specified" ) );
01180 }
01181 }
01182
01183
01184 if ( !event->doesFloat() && event->hasEndDate() ) {
01185 QString tmp;
01186 int secs = event->dtStart().secsTo( event->dtEnd() );
01187 int days = secs / 86400;
01188 if ( days > 0 ) {
01189 tmp += i18n( "1 day", "%n days", days );
01190 tmp += ' ';
01191 secs -= ( days * 86400 );
01192 }
01193 int hours = secs / 3600;
01194 if ( hours > 0 ) {
01195 tmp += i18n( "1 hour", "%n hours", hours );
01196 tmp += ' ';
01197 secs -= ( hours * 3600 );
01198 }
01199 int mins = secs / 60;
01200 if ( mins > 0 ) {
01201 tmp += i18n( "1 minute", "%n minutes", mins );
01202 tmp += ' ';
01203 }
01204 html += invitationRow( i18n( "Duration:" ), tmp );
01205 }
01206
01207 if ( event->doesRecur() )
01208 html += invitationRow( i18n( "Recurrence:" ), IncidenceFormatter::recurrenceString( event ) );
01209
01210 html += "</table>\n";
01211 html += invitationsDetailsIncidence( event, noHtmlMode );
01212 html += "</div>\n";
01213
01214 return html;
01215 }
01216
01217 static QString invitationDetailsTodo( Todo *todo, bool noHtmlMode )
01218 {
01219
01220 if ( !todo ) {
01221 return QString::null;
01222 }
01223
01224 QString sSummary = i18n( "Summary unspecified" );
01225 if ( !todo->summary().isEmpty() ) {
01226 if ( !QStyleSheet::mightBeRichText( todo->summary() ) ) {
01227 sSummary = QStyleSheet::escape( todo->summary() );
01228 } else {
01229 sSummary = todo->summary();
01230 if ( noHtmlMode ) {
01231 sSummary = cleanHtml( sSummary );
01232 }
01233 }
01234 }
01235
01236 QString sLocation = i18n( "Location unspecified" );
01237 if ( !todo->location().isEmpty() ) {
01238 if ( !QStyleSheet::mightBeRichText( todo->location() ) ) {
01239 sLocation = QStyleSheet::escape( todo->location() );
01240 } else {
01241 sLocation = todo->location();
01242 if ( noHtmlMode ) {
01243 sLocation = cleanHtml( sLocation );
01244 }
01245 }
01246 }
01247
01248 QString dir = ( QApplication::reverseLayout() ? "rtl" : "ltr" );
01249 QString html = QString("<div dir=\"%1\">\n").arg(dir);
01250 html += "<table border=\"0\" cellpadding=\"1\" cellspacing=\"1\">\n";
01251
01252
01253 html += invitationRow( i18n( "What:" ), sSummary );
01254 html += invitationRow( i18n( "Where:" ), sLocation );
01255
01256 if ( todo->hasStartDate() && todo->dtStart().isValid() ) {
01257 html += invitationRow( i18n( "Start Date:" ),
01258 IncidenceFormatter::dateToString( todo->dtStart(), false ) );
01259 }
01260 if ( todo->hasDueDate() && todo->dtDue().isValid() ) {
01261 html += invitationRow( i18n( "Due Date:" ),
01262 IncidenceFormatter::dateToString( todo->dtDue(), false ) );
01263 if ( !todo->doesFloat() ) {
01264 html += invitationRow( i18n( "Due Time:" ),
01265 KGlobal::locale()->formatTime( todo->dtDue().time() ) );
01266 }
01267
01268 } else {
01269 html += invitationRow( i18n( "Due Date:" ),
01270 i18n( "Due Date: None", "None" ) );
01271 }
01272
01273 html += "</table></div>\n";
01274 html += invitationsDetailsIncidence( todo, noHtmlMode );
01275
01276 return html;
01277 }
01278
01279 static QString invitationDetailsJournal( Journal *journal, bool noHtmlMode )
01280 {
01281 if ( !journal ) {
01282 return QString::null;
01283 }
01284
01285 QString sSummary = i18n( "Summary unspecified" );
01286 QString sDescr = i18n( "Description unspecified" );
01287 if ( ! journal->summary().isEmpty() ) {
01288 sSummary = journal->summary();
01289 if ( noHtmlMode ) {
01290 sSummary = cleanHtml( sSummary );
01291 }
01292 }
01293 if ( ! journal->description().isEmpty() ) {
01294 sDescr = journal->description();
01295 if ( noHtmlMode ) {
01296 sDescr = cleanHtml( sDescr );
01297 }
01298 }
01299 QString html( "<table border=\"0\" cellpadding=\"1\" cellspacing=\"1\">\n" );
01300 html += invitationRow( i18n( "Summary:" ), sSummary );
01301 html += invitationRow( i18n( "Date:" ),
01302 IncidenceFormatter::dateToString( journal->dtStart(), false ) );
01303 html += invitationRow( i18n( "Description:" ), sDescr );
01304 html += "</table>\n";
01305 html += invitationsDetailsIncidence( journal, noHtmlMode );
01306
01307 return html;
01308 }
01309
01310 static QString invitationDetailsFreeBusy( FreeBusy *fb, bool )
01311 {
01312 if ( !fb )
01313 return QString::null;
01314 QString html( "<table border=\"0\" cellpadding=\"1\" cellspacing=\"1\">\n" );
01315
01316 html += invitationRow( i18n("Person:"), fb->organizer().fullName() );
01317 html += invitationRow( i18n("Start date:"),
01318 IncidenceFormatter::dateToString( fb->dtStart(), true ) );
01319 html += invitationRow( i18n("End date:"),
01320 KGlobal::locale()->formatDate( fb->dtEnd().date(), true ) );
01321 html += "<tr><td colspan=2><hr></td></tr>\n";
01322 html += "<tr><td colspan=2>Busy periods given in this free/busy object:</td></tr>\n";
01323
01324 QValueList<Period> periods = fb->busyPeriods();
01325
01326 QValueList<Period>::iterator it;
01327 for ( it = periods.begin(); it != periods.end(); ++it ) {
01328 Period per = *it;
01329 if ( per.hasDuration() ) {
01330 int dur = per.duration().asSeconds();
01331 QString cont;
01332 if ( dur >= 3600 ) {
01333 cont += i18n("1 hour ", "%n hours ", dur / 3600);
01334 dur %= 3600;
01335 }
01336 if ( dur >= 60 ) {
01337 cont += i18n("1 minute", "%n minutes ", dur / 60);
01338 dur %= 60;
01339 }
01340 if ( dur > 0 ) {
01341 cont += i18n("1 second", "%n seconds", dur);
01342 }
01343 html += invitationRow( QString::null, i18n("startDate for duration", "%1 for %2")
01344 .arg( KGlobal::locale()->formatDateTime( per.start(), false ) )
01345 .arg(cont) );
01346 } else {
01347 QString cont;
01348 if ( per.start().date() == per.end().date() ) {
01349 cont = i18n("date, fromTime - toTime ", "%1, %2 - %3")
01350 .arg( KGlobal::locale()->formatDate( per.start().date() ) )
01351 .arg( KGlobal::locale()->formatTime( per.start().time() ) )
01352 .arg( KGlobal::locale()->formatTime( per.end().time() ) );
01353 } else {
01354 cont = i18n("fromDateTime - toDateTime", "%1 - %2")
01355 .arg( KGlobal::locale()->formatDateTime( per.start(), false ) )
01356 .arg( KGlobal::locale()->formatDateTime( per.end(), false ) );
01357 }
01358
01359 html += invitationRow( QString::null, cont );
01360 }
01361 }
01362
01363 html += "</table>\n";
01364 return html;
01365 }
01366
01367 static QString invitationHeaderEvent( Event *event, ScheduleMessage *msg )
01368 {
01369 if ( !msg || !event )
01370 return QString::null;
01371
01372 switch ( msg->method() ) {
01373 case Scheduler::Publish:
01374 return i18n( "This invitation has been published" );
01375 case Scheduler::Request:
01376 if ( event->revision() > 0 ) {
01377 return i18n( "This invitation has been updated" );
01378 }
01379 if ( iamOrganizer( event ) ) {
01380 return i18n( "I sent this invitation" );
01381 } else {
01382 if ( !event->organizer().fullName().isEmpty() ) {
01383 return i18n( "You received an invitation from %1" ).
01384 arg( event->organizer().fullName() );
01385 } else {
01386 return i18n( "You received an invitation" );
01387 }
01388 }
01389 case Scheduler::Refresh:
01390 return i18n( "This invitation was refreshed" );
01391 case Scheduler::Cancel:
01392 return i18n( "This invitation has been canceled" );
01393 case Scheduler::Add:
01394 return i18n( "Addition to the invitation" );
01395 case Scheduler::Reply: {
01396 Attendee::List attendees = event->attendees();
01397 if( attendees.count() == 0 ) {
01398 kdDebug(5850) << "No attendees in the iCal reply!" << endl;
01399 return QString::null;
01400 }
01401 if( attendees.count() != 1 ) {
01402 kdDebug(5850) << "Warning: attendeecount in the reply should be 1 "
01403 << "but is " << attendees.count() << endl;
01404 }
01405 Attendee* attendee = *attendees.begin();
01406 QString attendeeName = attendee->name();
01407 if ( attendeeName.isEmpty() ) {
01408 attendeeName = attendee->email();
01409 }
01410 if ( attendeeName.isEmpty() ) {
01411 attendeeName = i18n( "Sender" );
01412 }
01413
01414 QString delegatorName, dummy;
01415 KPIM::getNameAndMail( attendee->delegator(), delegatorName, dummy );
01416 if ( delegatorName.isEmpty() ) {
01417 delegatorName = attendee->delegator();
01418 }
01419
01420 switch( attendee->status() ) {
01421 case Attendee::NeedsAction:
01422 return i18n( "%1 indicates this invitation still needs some action" ).arg( attendeeName );
01423 case Attendee::Accepted:
01424 if ( delegatorName.isEmpty() ) {
01425 return i18n( "%1 accepts this invitation" ).arg( attendeeName );
01426 } else {
01427 return i18n( "%1 accepts this invitation on behalf of %2" ).
01428 arg( attendeeName ).arg( delegatorName );
01429 }
01430 case Attendee::Tentative:
01431 if ( delegatorName.isEmpty() ) {
01432 return i18n( "%1 tentatively accepts this invitation" ).
01433 arg( attendeeName );
01434 } else {
01435 return i18n( "%1 tentatively accepts this invitation on behalf of %2" ).
01436 arg( attendeeName ).arg( delegatorName );
01437 }
01438 case Attendee::Declined:
01439 if ( delegatorName.isEmpty() ) {
01440 return i18n( "%1 declines this invitation" ).arg( attendeeName );
01441 } else {
01442 return i18n( "%1 declines this invitation on behalf of %2" ).
01443 arg( attendeeName ).arg( delegatorName );
01444 }
01445 case Attendee::Delegated: {
01446 QString delegate, dummy;
01447 KPIM::getNameAndMail( attendee->delegate(), delegate, dummy );
01448 if ( delegate.isEmpty() ) {
01449 delegate = attendee->delegate();
01450 }
01451 if ( !delegate.isEmpty() ) {
01452 return i18n( "%1 has delegated this invitation to %2" ).
01453 arg( attendeeName ) .arg( delegate );
01454 } else {
01455 return i18n( "%1 has delegated this invitation" ).arg( attendeeName );
01456 }
01457 }
01458 case Attendee::Completed:
01459 return i18n( "This invitation is now completed" );
01460 case Attendee::InProcess:
01461 return i18n( "%1 is still processing the invitation" ).
01462 arg( attendeeName );
01463 default:
01464 return i18n( "Unknown response to this invitation" );
01465 }
01466 break; }
01467 case Scheduler::Counter:
01468 return i18n( "Sender makes this counter proposal" );
01469 case Scheduler::Declinecounter:
01470 return i18n( "Sender declines the counter proposal" );
01471 case Scheduler::NoMethod:
01472 return i18n("Error: iMIP message with unknown method: '%1'").
01473 arg( msg->method() );
01474 }
01475 return QString::null;
01476 }
01477
01478 static QString invitationHeaderTodo( Todo *todo, ScheduleMessage *msg )
01479 {
01480 if ( !msg || !todo ) {
01481 return QString::null;
01482 }
01483
01484 switch ( msg->method() ) {
01485 case Scheduler::Publish:
01486 return i18n("This task has been published");
01487 case Scheduler::Request:
01488 if ( todo->revision() > 0 ) {
01489 return i18n( "This task has been updated" );
01490 } else {
01491 return i18n( "You have been assigned this task" );
01492 }
01493 case Scheduler::Refresh:
01494 return i18n( "This task was refreshed" );
01495 case Scheduler::Cancel:
01496 return i18n( "This task was canceled" );
01497 case Scheduler::Add:
01498 return i18n( "Addition to the task" );
01499 case Scheduler::Reply: {
01500 Attendee::List attendees = todo->attendees();
01501 if( attendees.count() == 0 ) {
01502 kdDebug(5850) << "No attendees in the iCal reply!" << endl;
01503 return QString::null;
01504 }
01505 if( attendees.count() != 1 ) {
01506 kdDebug(5850) << "Warning: attendeecount in the reply should be 1 "
01507 << "but is " << attendees.count() << endl;
01508 }
01509 Attendee* attendee = *attendees.begin();
01510
01511 switch( attendee->status() ) {
01512 case Attendee::NeedsAction:
01513 return i18n( "Sender indicates this task assignment still needs some action" );
01514 case Attendee::Accepted:
01515 return i18n( "Sender accepts this task" );
01516 case Attendee::Tentative:
01517 return i18n( "Sender tentatively accepts this task" );
01518 case Attendee::Declined:
01519 return i18n( "Sender declines this task" );
01520 case Attendee::Delegated: {
01521 QString delegate, dummy;
01522 KPIM::getNameAndMail( attendee->delegate(), delegate, dummy );
01523 if ( delegate.isEmpty() ) {
01524 delegate = attendee->delegate();
01525 }
01526 if ( !delegate.isEmpty() ) {
01527 return i18n( "Sender has delegated this request for the task to %1" ).arg( delegate );
01528 } else {
01529 return i18n( "Sender has delegated this request for the task " );
01530 }
01531 }
01532 case Attendee::Completed:
01533 return i18n( "The request for this task is now completed" );
01534 case Attendee::InProcess:
01535 return i18n( "Sender is still processing the invitation" );
01536 default:
01537 return i18n( "Unknown response to this task" );
01538 }
01539 break; }
01540 case Scheduler::Counter:
01541 return i18n( "Sender makes this counter proposal" );
01542 case Scheduler::Declinecounter:
01543 return i18n( "Sender declines the counter proposal" );
01544 case Scheduler::NoMethod:
01545 return i18n("Error: iMIP message with unknown method: '%1'").
01546 arg( msg->method() );
01547 }
01548 return QString::null;
01549 }
01550
01551 static QString invitationHeaderJournal( Journal *journal, ScheduleMessage *msg )
01552 {
01553 if ( !msg || !journal ) {
01554 return QString::null;
01555 }
01556
01557 switch ( msg->method() ) {
01558 case Scheduler::Publish:
01559 return i18n("This journal has been published");
01560 case Scheduler::Request:
01561 return i18n( "You have been assigned this journal" );
01562 case Scheduler::Refresh:
01563 return i18n( "This journal was refreshed" );
01564 case Scheduler::Cancel:
01565 return i18n( "This journal was canceled" );
01566 case Scheduler::Add:
01567 return i18n( "Addition to the journal" );
01568 case Scheduler::Reply: {
01569 Attendee::List attendees = journal->attendees();
01570 if( attendees.count() == 0 ) {
01571 kdDebug(5850) << "No attendees in the iCal reply!" << endl;
01572 return QString::null;
01573 }
01574 if( attendees.count() != 1 ) {
01575 kdDebug(5850) << "Warning: attendeecount in the reply should be 1 "
01576 << "but is " << attendees.count() << endl;
01577 }
01578 Attendee* attendee = *attendees.begin();
01579
01580 switch( attendee->status() ) {
01581 case Attendee::NeedsAction:
01582 return i18n( "Sender indicates this journal assignment still needs some action" );
01583 case Attendee::Accepted:
01584 return i18n( "Sender accepts this journal" );
01585 case Attendee::Tentative:
01586 return i18n( "Sender tentatively accepts this journal" );
01587 case Attendee::Declined:
01588 return i18n( "Sender declines this journal" );
01589 case Attendee::Delegated:
01590 return i18n( "Sender has delegated this request for the journal" );
01591 case Attendee::Completed:
01592 return i18n( "The request for this journal is now completed" );
01593 case Attendee::InProcess:
01594 return i18n( "Sender is still processing the invitation" );
01595 default:
01596 return i18n( "Unknown response to this journal" );
01597 }
01598 break;
01599 }
01600 case Scheduler::Counter:
01601 return i18n( "Sender makes this counter proposal" );
01602 case Scheduler::Declinecounter:
01603 return i18n( "Sender declines the counter proposal" );
01604 case Scheduler::NoMethod:
01605 return i18n("Error: iMIP message with unknown method: '%1'").
01606 arg( msg->method() );
01607 }
01608 return QString::null;
01609 }
01610
01611 static QString invitationHeaderFreeBusy( FreeBusy *fb, ScheduleMessage *msg )
01612 {
01613 if ( !msg || !fb ) {
01614 return QString::null;
01615 }
01616
01617 switch ( msg->method() ) {
01618 case Scheduler::Publish:
01619 return i18n("This free/busy list has been published");
01620 case Scheduler::Request:
01621 return i18n( "The free/busy list has been requested" );
01622 case Scheduler::Refresh:
01623 return i18n( "This free/busy list was refreshed" );
01624 case Scheduler::Cancel:
01625 return i18n( "This free/busy list was canceled" );
01626 case Scheduler::Add:
01627 return i18n( "Addition to the free/busy list" );
01628 case Scheduler::NoMethod:
01629 default:
01630 return i18n("Error: Free/Busy iMIP message with unknown method: '%1'").
01631 arg( msg->method() );
01632 }
01633 }
01634
01635 static QString invitationAttendees( Incidence *incidence )
01636 {
01637 QString tmpStr;
01638 if ( !incidence ) {
01639 return tmpStr;
01640 }
01641
01642 tmpStr += htmlAddTag( "u", i18n( "Attendee List" ) );
01643 tmpStr += "<br/>";
01644
01645 int count=0;
01646 Attendee::List attendees = incidence->attendees();
01647 if ( !attendees.isEmpty() ) {
01648
01649 Attendee::List::ConstIterator it;
01650 for( it = attendees.begin(); it != attendees.end(); ++it ) {
01651 Attendee *a = *it;
01652 if ( !iamAttendee( a ) ) {
01653 count++;
01654 if ( count == 1 ) {
01655 tmpStr += "<table border=\"1\" cellpadding=\"1\" cellspacing=\"0\" columns=\"2\">";
01656 }
01657 tmpStr += "<tr>";
01658 tmpStr += "<td>";
01659 tmpStr += invitationPerson( a->email(), a->name(), QString::null );
01660 if ( !a->delegator().isEmpty() ) {
01661 tmpStr += i18n(" (delegated by %1)" ).arg( a->delegator() );
01662 }
01663 if ( !a->delegate().isEmpty() ) {
01664 tmpStr += i18n(" (delegated to %1)" ).arg( a->delegate() );
01665 }
01666 tmpStr += "</td>";
01667 tmpStr += "<td>" + a->statusStr() + "</td>";
01668 tmpStr += "</tr>";
01669 }
01670 }
01671 }
01672 if ( count ) {
01673 tmpStr += "</table>";
01674 } else {
01675 tmpStr += "<i>" + i18n( "No attendee", "None" ) + "</i>";
01676 }
01677
01678 return tmpStr;
01679 }
01680
01681 static QString invitationAttachments( InvitationFormatterHelper *helper, Incidence *incidence )
01682 {
01683 QString tmpStr;
01684 if ( !incidence ) {
01685 return tmpStr;
01686 }
01687
01688 Attachment::List attachments = incidence->attachments();
01689 if ( !attachments.isEmpty() ) {
01690 tmpStr += i18n( "Attached Documents:" ) + "<ol>";
01691
01692 Attachment::List::ConstIterator it;
01693 for( it = attachments.begin(); it != attachments.end(); ++it ) {
01694 Attachment *a = *it;
01695 tmpStr += "<li>";
01696
01697 KMimeType::Ptr mimeType = KMimeType::mimeType( a->mimeType() );
01698 const QString iconStr = mimeType ? mimeType->icon( a->uri(), false ) : QString( "application-octet-stream" );
01699 const QString iconPath = KGlobal::iconLoader()->iconPath( iconStr, KIcon::Small );
01700 if ( !iconPath.isEmpty() ) {
01701 tmpStr += "<img valign=\"top\" src=\"" + iconPath + "\">";
01702 }
01703 tmpStr += helper->makeLink( "ATTACH:" + a->label(), a->label() );
01704 tmpStr += "</li>";
01705 }
01706 tmpStr += "</ol>";
01707 }
01708
01709 return tmpStr;
01710 }
01711
01712 class IncidenceFormatter::ScheduleMessageVisitor
01713 : public IncidenceBase::Visitor
01714 {
01715 public:
01716 ScheduleMessageVisitor() : mMessage(0) { mResult = ""; }
01717 bool act( IncidenceBase *incidence, ScheduleMessage *msg )
01718 {
01719 mMessage = msg;
01720 return incidence->accept( *this );
01721 }
01722 QString result() const { return mResult; }
01723
01724 protected:
01725 QString mResult;
01726 ScheduleMessage *mMessage;
01727 };
01728
01729 class IncidenceFormatter::InvitationHeaderVisitor
01730 : public IncidenceFormatter::ScheduleMessageVisitor
01731 {
01732 protected:
01733 bool visit( Event *event )
01734 {
01735 mResult = invitationHeaderEvent( event, mMessage );
01736 return !mResult.isEmpty();
01737 }
01738 bool visit( Todo *todo )
01739 {
01740 mResult = invitationHeaderTodo( todo, mMessage );
01741 return !mResult.isEmpty();
01742 }
01743 bool visit( Journal *journal )
01744 {
01745 mResult = invitationHeaderJournal( journal, mMessage );
01746 return !mResult.isEmpty();
01747 }
01748 bool visit( FreeBusy *fb )
01749 {
01750 mResult = invitationHeaderFreeBusy( fb, mMessage );
01751 return !mResult.isEmpty();
01752 }
01753 };
01754
01755 class IncidenceFormatter::InvitationBodyVisitor
01756 : public IncidenceFormatter::ScheduleMessageVisitor
01757 {
01758 public:
01759 InvitationBodyVisitor( bool noHtmlMode )
01760 : ScheduleMessageVisitor(), mNoHtmlMode( noHtmlMode ) {}
01761
01762 protected:
01763 bool visit( Event *event )
01764 {
01765 mResult = invitationDetailsEvent( event, mNoHtmlMode );
01766 return !mResult.isEmpty();
01767 }
01768 bool visit( Todo *todo )
01769 {
01770 mResult = invitationDetailsTodo( todo, mNoHtmlMode );
01771 return !mResult.isEmpty();
01772 }
01773 bool visit( Journal *journal )
01774 {
01775 mResult = invitationDetailsJournal( journal, mNoHtmlMode );
01776 return !mResult.isEmpty();
01777 }
01778 bool visit( FreeBusy *fb )
01779 {
01780 mResult = invitationDetailsFreeBusy( fb, mNoHtmlMode );
01781 return !mResult.isEmpty();
01782 }
01783
01784 private:
01785 bool mNoHtmlMode;
01786 };
01787
01788 class IncidenceFormatter::IncidenceCompareVisitor
01789 : public IncidenceBase::Visitor
01790 {
01791 public:
01792 IncidenceCompareVisitor() : mExistingIncidence(0) {}
01793 bool act( IncidenceBase *incidence, Incidence* existingIncidence )
01794 {
01795 Incidence *inc = dynamic_cast<Incidence*>( incidence );
01796 if ( !inc || !existingIncidence || inc->revision() <= existingIncidence->revision() )
01797 return false;
01798 mExistingIncidence = existingIncidence;
01799 return incidence->accept( *this );
01800 }
01801
01802 QString result() const
01803 {
01804 if ( mChanges.isEmpty() ) {
01805 return QString::null;
01806 }
01807 QString html = "<div align=\"left\"><ul><li>";
01808 html += mChanges.join( "</li><li>" );
01809 html += "</li><ul></div>";
01810 return html;
01811 }
01812
01813 protected:
01814 bool visit( Event *event )
01815 {
01816 compareEvents( event, dynamic_cast<Event*>( mExistingIncidence ) );
01817 compareIncidences( event, mExistingIncidence );
01818 return !mChanges.isEmpty();
01819 }
01820 bool visit( Todo *todo )
01821 {
01822 compareIncidences( todo, mExistingIncidence );
01823 return !mChanges.isEmpty();
01824 }
01825 bool visit( Journal *journal )
01826 {
01827 compareIncidences( journal, mExistingIncidence );
01828 return !mChanges.isEmpty();
01829 }
01830 bool visit( FreeBusy *fb )
01831 {
01832 Q_UNUSED( fb );
01833 return !mChanges.isEmpty();
01834 }
01835
01836 private:
01837 void compareEvents( Event *newEvent, Event *oldEvent )
01838 {
01839 if ( !oldEvent || !newEvent )
01840 return;
01841 if ( oldEvent->dtStart() != newEvent->dtStart() || oldEvent->doesFloat() != newEvent->doesFloat() )
01842 mChanges += i18n( "The invitation starting time has been changed from %1 to %2" )
01843 .arg( eventStartTimeStr( oldEvent ) ).arg( eventStartTimeStr( newEvent ) );
01844 if ( oldEvent->dtEnd() != newEvent->dtEnd() || oldEvent->doesFloat() != newEvent->doesFloat() )
01845 mChanges += i18n( "The invitation ending time has been changed from %1 to %2" )
01846 .arg( eventEndTimeStr( oldEvent ) ).arg( eventEndTimeStr( newEvent ) );
01847 }
01848
01849 void compareIncidences( Incidence *newInc, Incidence *oldInc )
01850 {
01851 if ( !oldInc || !newInc )
01852 return;
01853 if ( oldInc->summary() != newInc->summary() )
01854 mChanges += i18n( "The summary has been changed to: \"%1\"" ).arg( newInc->summary() );
01855 if ( oldInc->location() != newInc->location() )
01856 mChanges += i18n( "The location has been changed to: \"%1\"" ).arg( newInc->location() );
01857 if ( oldInc->description() != newInc->description() )
01858 mChanges += i18n( "The description has been changed to: \"%1\"" ).arg( newInc->description() );
01859 Attendee::List oldAttendees = oldInc->attendees();
01860 Attendee::List newAttendees = newInc->attendees();
01861 for ( Attendee::List::ConstIterator it = newAttendees.constBegin(); it != newAttendees.constEnd(); ++it ) {
01862 Attendee *oldAtt = oldInc->attendeeByMail( (*it)->email() );
01863 if ( !oldAtt ) {
01864 mChanges += i18n( "Attendee %1 has been added" ).arg( (*it)->fullName() );
01865 } else {
01866 if ( oldAtt->status() != (*it)->status() )
01867 mChanges += i18n( "The status of attendee %1 has been changed to: %2" ).arg( (*it)->fullName() )
01868 .arg( (*it)->statusStr() );
01869 }
01870 }
01871 for ( Attendee::List::ConstIterator it = oldAttendees.constBegin(); it != oldAttendees.constEnd(); ++it ) {
01872 Attendee *newAtt = newInc->attendeeByMail( (*it)->email() );
01873 if ( !newAtt )
01874 mChanges += i18n( "Attendee %1 has been removed" ).arg( (*it)->fullName() );
01875 }
01876 }
01877
01878 private:
01879 Incidence* mExistingIncidence;
01880 QStringList mChanges;
01881 };
01882
01883
01884 QString InvitationFormatterHelper::makeLink( const QString &id, const QString &text )
01885 {
01886 if ( !id.startsWith( "ATTACH:" ) ) {
01887 QString res = QString( "<a href=\"%1\"><b>%2</b></a>" ).
01888 arg( generateLinkURL( id ), text );
01889 return res;
01890 } else {
01891
01892 QString res = QString( "<a href=\"%1\">%2</a>" ).
01893 arg( generateLinkURL( id ), text );
01894 return res;
01895 }
01896 }
01897
01898
01899
01900 static bool incidenceOwnedByMe( Calendar *calendar, Incidence *incidence )
01901 {
01902 CalendarResources *cal = dynamic_cast<CalendarResources*>( calendar );
01903 if ( !cal || !incidence ) {
01904 return true;
01905 }
01906 ResourceCalendar *res = cal->resource( incidence );
01907 if ( !res ) {
01908 return true;
01909 }
01910 const QString subRes = res->subresourceIdentifier( incidence );
01911 if ( !subRes.contains( "/.INBOX.directory/" ) ) {
01912 return false;
01913 }
01914 return true;
01915 }
01916
01917 QString IncidenceFormatter::formatICalInvitationHelper( QString invitation,
01918 Calendar *mCalendar,
01919 InvitationFormatterHelper *helper,
01920 bool noHtmlMode )
01921 {
01922 if ( invitation.isEmpty() ) {
01923 return QString::null;
01924 }
01925
01926 ICalFormat format;
01927
01928 ScheduleMessage *msg = format.parseScheduleMessage( mCalendar, invitation );
01929
01930 if( !msg ) {
01931 kdDebug( 5850 ) << "Failed to parse the scheduling message" << endl;
01932 Q_ASSERT( format.exception() );
01933 kdDebug( 5850 ) << format.exception()->message() << endl;
01934 return QString::null;
01935 }
01936
01937 IncidenceBase *incBase = msg->event();
01938
01939
01940 Incidence *existingIncidence = 0;
01941 if ( incBase && helper->calendar() ) {
01942 existingIncidence = helper->calendar()->incidence( incBase->uid() );
01943 if ( !incidenceOwnedByMe( helper->calendar(), existingIncidence ) ) {
01944 existingIncidence = 0;
01945 }
01946 if ( !existingIncidence ) {
01947 const Incidence::List list = helper->calendar()->incidences();
01948 for ( Incidence::List::ConstIterator it = list.begin(), end = list.end(); it != end; ++it ) {
01949 if ( (*it)->schedulingID() == incBase->uid() &&
01950 incidenceOwnedByMe( helper->calendar(), *it ) ) {
01951 existingIncidence = *it;
01952 break;
01953 }
01954 }
01955 }
01956 }
01957
01958
01959 QString html;
01960
01961 QString tableStyle = QString::fromLatin1(
01962 "style=\"border: solid 1px; margin: 0em;\"" );
01963 QString tableHead = QString::fromLatin1(
01964 "<div align=\"center\">"
01965 "<table width=\"80%\" cellpadding=\"1\" cellspacing=\"0\" %1>"
01966 "<tr><td>").arg(tableStyle);
01967
01968 html += tableHead;
01969 InvitationHeaderVisitor headerVisitor;
01970
01971 if ( !headerVisitor.act( incBase, msg ) )
01972 return QString::null;
01973 html += "<b>" + headerVisitor.result() + "</b>";
01974
01975 InvitationBodyVisitor bodyVisitor( noHtmlMode );
01976 if ( !bodyVisitor.act( incBase, msg ) )
01977 return QString::null;
01978 html += bodyVisitor.result();
01979
01980 if ( msg->method() == Scheduler::Request ) {
01981 IncidenceCompareVisitor compareVisitor;
01982 if ( compareVisitor.act( incBase, existingIncidence ) ) {
01983 html += i18n("<p align=\"left\">The following changes have been made by the organizer:</p>");
01984 html += compareVisitor.result();
01985 }
01986 }
01987
01988 Incidence *inc = dynamic_cast<Incidence*>( incBase );
01989
01990
01991 bool myInc = iamOrganizer( inc );
01992
01993
01994 bool rsvpRec = false;
01995 Attendee *ea = 0;
01996 if ( !myInc ) {
01997 if ( existingIncidence ) {
01998 ea = findMyAttendee( existingIncidence );
01999 }
02000 if ( ea && ( ea->status() == Attendee::Accepted || ea->status() == Attendee::Declined ) ) {
02001 rsvpRec = true;
02002 }
02003 }
02004
02005
02006 QString role;
02007 Attendee *a = findMyAttendee( inc );
02008 if ( !a && inc ) {
02009 a = inc->attendees().first();
02010 }
02011 if ( a ) {
02012 role = Attendee::roleName( a->role() );
02013 }
02014
02015
02016 bool rsvpReq = rsvpRequested( inc );
02017 if ( !myInc ) {
02018 html += "<br/>";
02019 html += "<i><u>";
02020 if ( rsvpRec && ( inc && inc->revision() == 0 ) ) {
02021 html += i18n( "Your response has already been recorded [%1]" ).
02022 arg( ea->statusStr() );
02023 rsvpReq = false;
02024 } else if ( msg->method() == Scheduler::Cancel ) {
02025 html += i18n( "This invitation was declined" );
02026 } else if ( msg->method() == Scheduler::Add ) {
02027 html += i18n( "This invitation was accepted" );
02028 } else {
02029 html += rsvpRequestedStr( rsvpReq, role );
02030 }
02031 html += "</u></i>";
02032 }
02033
02034
02035 if ( !myInc ) {
02036 QString statStr = myStatusStr( inc );
02037 if ( !statStr.isEmpty() ) {
02038 html += "<br/>";
02039 html += "<i>";
02040 html += statStr;
02041 html += "</i>";
02042 }
02043 }
02044
02045
02046
02047 html += "<br><table border=\"0\" cellspacing=\"0\"><tr><td> </td></tr><tr>";
02048
02049 switch ( msg->method() ) {
02050 case Scheduler::Publish:
02051 case Scheduler::Request:
02052 case Scheduler::Refresh:
02053 case Scheduler::Add:
02054 {
02055 if ( inc && inc->revision() > 0 && ( existingIncidence || !helper->calendar() ) ) {
02056 if ( inc->type() == "Todo" ) {
02057 html += "<td colspan=\"9\">";
02058 html += helper->makeLink( "reply", i18n( "[Record invitation in my task list]" ) );
02059 } else {
02060 html += "<td colspan=\"13\">";
02061 html += helper->makeLink( "reply", i18n( "[Record invitation in my calendar]" ) );
02062 }
02063 html += "</td></tr><tr>";
02064 }
02065 html += "<td>";
02066
02067 if ( !myInc ) {
02068 if ( !rsvpReq ) {
02069
02070 html += helper->makeLink( "record", i18n( "[Record]" ) );
02071 html += "</td><td> </td><td>";
02072 }
02073
02074 if ( rsvpReq ) {
02075
02076 html += helper->makeLink( "accept", i18n( "[Accept]" ) );
02077 html += "</td><td> </td><td>";
02078 html += helper->makeLink( "accept_conditionally",
02079 i18n( "Accept conditionally", "[Accept cond.]" ) );
02080 html += "</td><td> </td><td>";
02081 }
02082
02083 if ( rsvpReq ) {
02084
02085 html += helper->makeLink( "counter", i18n( "[Counter proposal]" ) );
02086 html += "</td><td> </td><td>";
02087 }
02088
02089 if ( rsvpReq ) {
02090
02091 html += helper->makeLink( "decline", i18n( "[Decline]" ) );
02092 html += "</td><td> </td><td>";
02093 }
02094
02095 if ( !rsvpRec || ( inc && inc->revision() > 0 ) ) {
02096
02097 html += helper->makeLink( "delegate", i18n( "[Delegate]" ) );
02098 html += "</td><td> </td><td>";
02099
02100
02101 html += helper->makeLink( "forward", i18n( "[Forward]" ) );
02102
02103
02104 if ( inc && inc->type() == "Event" ) {
02105 html += "</td><td> </td><td>";
02106 html += helper->makeLink( "check_calendar", i18n("[Check my calendar]" ) );
02107 }
02108 }
02109 }
02110 break;
02111 }
02112
02113 case Scheduler::Cancel:
02114
02115 if ( inc->type() == "Todo" ) {
02116 html += helper->makeLink( "cancel", i18n( "[Remove invitation from my task list]" ) );
02117 } else {
02118 html += helper->makeLink( "cancel", i18n( "[Remove invitation from my calendar]" ) );
02119 }
02120 break;
02121
02122 case Scheduler::Reply:
02123 {
02124
02125 Attendee *a = 0;
02126 Attendee *ea = 0;
02127 if ( inc ) {
02128 a = inc->attendees().first();
02129 if ( a ) {
02130 ea = findAttendee( existingIncidence, a->email() );
02131 }
02132 }
02133 if ( ea && ( ea->status() != Attendee::NeedsAction ) && ( ea->status() == a->status() ) ) {
02134 if ( inc && inc->revision() > 0 ) {
02135 html += "<br><u><i>";
02136 html += i18n( "The response has been recorded [%1]" ).arg( ea->statusStr() );
02137 html += "</i></u>";
02138 }
02139 } else {
02140 if ( inc ) {
02141 if ( inc->type() == "Todo" ) {
02142 html += helper->makeLink( "reply", i18n( "[Record response in my task list]" ) );
02143 } else {
02144 html += helper->makeLink( "reply", i18n( "[Record response in my calendar]" ) );
02145 }
02146 }
02147 }
02148 break;
02149 }
02150
02151 case Scheduler::Counter:
02152
02153 html += helper->makeLink( "accept_counter", i18n("[Accept]") );
02154 html += " ";
02155 html += helper->makeLink( "decline_counter", i18n("[Decline]") );
02156 html += " ";
02157 html += helper->makeLink( "check_calendar", i18n("[Check my calendar]" ) );
02158 break;
02159
02160 case Scheduler::Declinecounter:
02161 case Scheduler::NoMethod:
02162 break;
02163 }
02164
02165
02166 html += "</td></tr></table>";
02167
02168
02169 if ( myInc && helper->calendar() ) {
02170 html += invitationAttendees( helper->calendar()->incidence( inc->uid() ) );
02171 }
02172
02173
02174 html += "</td></tr></table><br></div>";
02175
02176
02177 html += invitationAttachments( helper, inc );
02178
02179 return html;
02180 }
02181
02182 QString IncidenceFormatter::formatICalInvitation( QString invitation,
02183 Calendar *mCalendar,
02184 InvitationFormatterHelper *helper )
02185 {
02186 return formatICalInvitationHelper( invitation, mCalendar, helper, false );
02187 }
02188
02189 QString IncidenceFormatter::formatICalInvitationNoHtml( QString invitation,
02190 Calendar *mCalendar,
02191 InvitationFormatterHelper *helper )
02192 {
02193 return formatICalInvitationHelper( invitation, mCalendar, helper, true );
02194 }
02195
02196
02197
02198
02199
02200
02201
02202
02203 static QString stringProp( KTNEFMessage* tnefMsg, const Q_UINT32& key,
02204 const QString& fallback = QString::null)
02205 {
02206 return tnefMsg->findProp( key < 0x10000 ? key & 0xFFFF : key >> 16,
02207 fallback );
02208 }
02209
02210 static QString sNamedProp( KTNEFMessage* tnefMsg, const QString& name,
02211 const QString& fallback = QString::null )
02212 {
02213 return tnefMsg->findNamedProp( name, fallback );
02214 }
02215
02216 struct save_tz { char* old_tz; char* tz_env_str; };
02217
02218
02219 static struct save_tz set_tz( const char* _tc )
02220 {
02221 const char *tc = _tc?_tc:"UTC";
02222
02223 struct save_tz rv;
02224
02225 rv.old_tz = 0;
02226 rv.tz_env_str = 0;
02227
02228
02229
02230 char* tz_env = 0;
02231 if( getenv( "TZ" ) ) {
02232 tz_env = strdup( getenv( "TZ" ) );
02233 rv.old_tz = tz_env;
02234 }
02235 char* tmp_env = (char*)malloc( strlen( tc ) + 4 );
02236 strcpy( tmp_env, "TZ=" );
02237 strcpy( tmp_env+3, tc );
02238 putenv( tmp_env );
02239
02240 rv.tz_env_str = tmp_env;
02241
02242
02243
02244 tzset();
02245
02246
02247 return rv;
02248 }
02249
02250
02251 static void unset_tz( struct save_tz old_tz )
02252 {
02253 if( old_tz.old_tz ) {
02254 char* tmp_env = (char*)malloc( strlen( old_tz.old_tz ) + 4 );
02255 strcpy( tmp_env, "TZ=" );
02256 strcpy( tmp_env+3, old_tz.old_tz );
02257 putenv( tmp_env );
02258
02259 free( old_tz.old_tz );
02260 } else {
02261
02262 putenv( strdup("TZ") );
02263 }
02264 tzset();
02265
02266
02267 if( old_tz.tz_env_str ) free( old_tz.tz_env_str );
02268 }
02269
02270 static QDateTime utc2Local( const QDateTime& utcdt )
02271 {
02272 struct tm tmL;
02273
02274 save_tz tmp_tz = set_tz("UTC");
02275 time_t utc = utcdt.toTime_t();
02276 unset_tz( tmp_tz );
02277
02278 localtime_r( &utc, &tmL );
02279 return QDateTime( QDate( tmL.tm_year+1900, tmL.tm_mon+1, tmL.tm_mday ),
02280 QTime( tmL.tm_hour, tmL.tm_min, tmL.tm_sec ) );
02281 }
02282
02283
02284 static QDateTime pureISOToLocalQDateTime( const QString& dtStr,
02285 bool bDateOnly = false )
02286 {
02287 QDate tmpDate;
02288 QTime tmpTime;
02289 int year, month, day, hour, minute, second;
02290
02291 if( bDateOnly ) {
02292 year = dtStr.left( 4 ).toInt();
02293 month = dtStr.mid( 4, 2 ).toInt();
02294 day = dtStr.mid( 6, 2 ).toInt();
02295 hour = 0;
02296 minute = 0;
02297 second = 0;
02298 } else {
02299 year = dtStr.left( 4 ).toInt();
02300 month = dtStr.mid( 4, 2 ).toInt();
02301 day = dtStr.mid( 6, 2 ).toInt();
02302 hour = dtStr.mid( 9, 2 ).toInt();
02303 minute = dtStr.mid( 11, 2 ).toInt();
02304 second = dtStr.mid( 13, 2 ).toInt();
02305 }
02306 tmpDate.setYMD( year, month, day );
02307 tmpTime.setHMS( hour, minute, second );
02308
02309 if( tmpDate.isValid() && tmpTime.isValid() ) {
02310 QDateTime dT = QDateTime( tmpDate, tmpTime );
02311
02312 if( !bDateOnly ) {
02313
02314 if (dtStr.at(dtStr.length()-1) == 'Z') {
02315
02316
02317 dT = utc2Local( dT );
02318 }
02319 }
02320 return dT;
02321 } else
02322 return QDateTime();
02323 }
02324
02325
02326
02327 QString IncidenceFormatter::msTNEFToVPart( const QByteArray& tnef )
02328 {
02329 bool bOk = false;
02330
02331 KTNEFParser parser;
02332 QBuffer buf( tnef );
02333 CalendarLocal cal ( QString::fromLatin1( "UTC" ) );
02334 KABC::Addressee addressee;
02335 KABC::VCardConverter cardConv;
02336 ICalFormat calFormat;
02337 Event* event = new Event();
02338
02339 if( parser.openDevice( &buf ) ) {
02340 KTNEFMessage* tnefMsg = parser.message();
02341
02342
02343
02344
02345 QString msgClass = tnefMsg->findProp( 0x001A, QString::null, true )
02346 .upper();
02347 if( !msgClass.isEmpty() ) {
02348
02349
02350 bool bCompatClassAppointment = false;
02351 bool bCompatMethodRequest = false;
02352 bool bCompatMethodCancled = false;
02353 bool bCompatMethodAccepted = false;
02354 bool bCompatMethodAcceptedCond = false;
02355 bool bCompatMethodDeclined = false;
02356 if( msgClass.startsWith( "IPM.MICROSOFT SCHEDULE." ) ) {
02357 bCompatClassAppointment = true;
02358 if( msgClass.endsWith( ".MTGREQ" ) )
02359 bCompatMethodRequest = true;
02360 if( msgClass.endsWith( ".MTGCNCL" ) )
02361 bCompatMethodCancled = true;
02362 if( msgClass.endsWith( ".MTGRESPP" ) )
02363 bCompatMethodAccepted = true;
02364 if( msgClass.endsWith( ".MTGRESPA" ) )
02365 bCompatMethodAcceptedCond = true;
02366 if( msgClass.endsWith( ".MTGRESPN" ) )
02367 bCompatMethodDeclined = true;
02368 }
02369 bool bCompatClassNote = ( msgClass == "IPM.MICROSOFT MAIL.NOTE" );
02370
02371 if( bCompatClassAppointment || "IPM.APPOINTMENT" == msgClass ) {
02372
02373 bool bIsReply = false;
02374 QString prodID = "-//Microsoft Corporation//Outlook ";
02375 prodID += tnefMsg->findNamedProp( "0x8554", "9.0" );
02376 prodID += "MIMEDIR/EN\n";
02377 prodID += "VERSION:2.0\n";
02378 calFormat.setApplication( "Outlook", prodID );
02379
02380 Scheduler::Method method;
02381 if( bCompatMethodRequest )
02382 method = Scheduler::Request;
02383 else if( bCompatMethodCancled )
02384 method = Scheduler::Cancel;
02385 else if( bCompatMethodAccepted || bCompatMethodAcceptedCond ||
02386 bCompatMethodDeclined ) {
02387 method = Scheduler::Reply;
02388 bIsReply = true;
02389 } else {
02390
02391
02392
02393
02394
02395
02396
02397
02398 if( tnefMsg->findProp(0x0c17) == "1" )
02399 bIsReply = true;
02400 method = Scheduler::Request;
02401 }
02402
02404 ScheduleMessage schedMsg(event, method, ScheduleMessage::Unknown );
02405
02406 QString sSenderSearchKeyEmail( tnefMsg->findProp( 0x0C1D ) );
02407
02408 if( !sSenderSearchKeyEmail.isEmpty() ) {
02409 int colon = sSenderSearchKeyEmail.find( ':' );
02410
02411 if( sSenderSearchKeyEmail.find( ':' ) == -1 )
02412 sSenderSearchKeyEmail.remove( 0, colon+1 );
02413 }
02414
02415 QString s( tnefMsg->findProp( 0x0e04 ) );
02416 QStringList attendees = QStringList::split( ';', s );
02417 if( attendees.count() ) {
02418 for( QStringList::Iterator it = attendees.begin();
02419 it != attendees.end(); ++it ) {
02420
02421
02422 if( (*it).find('@') == -1 ) {
02423 s = (*it).stripWhiteSpace();
02424
02425 Attendee *attendee = new Attendee( s, s, true );
02426 if( bIsReply ) {
02427 if( bCompatMethodAccepted )
02428 attendee->setStatus( Attendee::Accepted );
02429 if( bCompatMethodDeclined )
02430 attendee->setStatus( Attendee::Declined );
02431 if( bCompatMethodAcceptedCond )
02432 attendee->setStatus(Attendee::Tentative);
02433 } else {
02434 attendee->setStatus( Attendee::NeedsAction );
02435 attendee->setRole( Attendee::ReqParticipant );
02436 }
02437 event->addAttendee(attendee);
02438 }
02439 }
02440 } else {
02441
02442
02443 s = sSenderSearchKeyEmail;
02444 if( !s.isEmpty() ) {
02445 Attendee *attendee = new Attendee( QString::null, QString::null,
02446 true );
02447 if( bIsReply ) {
02448 if( bCompatMethodAccepted )
02449 attendee->setStatus( Attendee::Accepted );
02450 if( bCompatMethodAcceptedCond )
02451 attendee->setStatus( Attendee::Declined );
02452 if( bCompatMethodDeclined )
02453 attendee->setStatus( Attendee::Tentative );
02454 } else {
02455 attendee->setStatus(Attendee::NeedsAction);
02456 attendee->setRole(Attendee::ReqParticipant);
02457 }
02458 event->addAttendee(attendee);
02459 }
02460 }
02461 s = tnefMsg->findProp( 0x0c1f );
02462 if( s.isEmpty() && !bIsReply )
02463 s = sSenderSearchKeyEmail;
02464
02465 if( !s.isEmpty() )
02466 event->setOrganizer( s );
02467
02468 s = tnefMsg->findProp( 0x8516 ).replace( QChar( '-' ), QString::null )
02469 .replace( QChar( ':' ), QString::null );
02470 event->setDtStart( QDateTime::fromString( s ) );
02471
02472 s = tnefMsg->findProp( 0x8517 ).replace( QChar( '-' ), QString::null )
02473 .replace( QChar( ':' ), QString::null );
02474 event->setDtEnd( QDateTime::fromString( s ) );
02475
02476 s = tnefMsg->findProp( 0x8208 );
02477 event->setLocation( s );
02478
02479
02480
02481
02482
02483
02484 s = tnefMsg->findProp( 0x0023 );
02485 event->setUid( s );
02486
02487
02488
02489
02490 s = tnefMsg->findProp( 0x8202 ).replace( QChar( '-' ), QString::null )
02491 .replace( QChar( ':' ), QString::null );
02492
02493
02494
02495 s = tnefMsg->findNamedProp( "Keywords" );
02496 event->setCategories( s );
02497
02498 s = tnefMsg->findProp( 0x1000 );
02499 event->setDescription( s );
02500
02501 s = tnefMsg->findProp( 0x0070 );
02502 event->setSummary( s );
02503
02504 s = tnefMsg->findProp( 0x0026 );
02505 event->setPriority( s.toInt() );
02506
02507
02508 if(!tnefMsg->findProp(0x8503).isEmpty()) {
02509 Alarm *alarm = new Alarm(event);
02510 QDateTime highNoonTime =
02511 pureISOToLocalQDateTime( tnefMsg->findProp( 0x8502 )
02512 .replace( QChar( '-' ), "" )
02513 .replace( QChar( ':' ), "" ) );
02514 QDateTime wakeMeUpTime =
02515 pureISOToLocalQDateTime( tnefMsg->findProp( 0x8560, "" )
02516 .replace( QChar( '-' ), "" )
02517 .replace( QChar( ':' ), "" ) );
02518 alarm->setTime(wakeMeUpTime);
02519
02520 if( highNoonTime.isValid() && wakeMeUpTime.isValid() )
02521 alarm->setStartOffset( Duration( highNoonTime, wakeMeUpTime ) );
02522 else
02523
02524 alarm->setStartOffset( Duration( 15*60 ) );
02525 alarm->setDisplayAlarm( i18n( "Reminder" ) );
02526
02527
02528
02529 event->addAlarm( alarm );
02530 }
02531 cal.addEvent( event );
02532 bOk = true;
02533
02534 } else if( bCompatClassNote || "IPM.CONTACT" == msgClass ) {
02535 addressee.setUid( stringProp( tnefMsg, attMSGID ) );
02536 addressee.setFormattedName( stringProp( tnefMsg, MAPI_TAG_PR_DISPLAY_NAME ) );
02537 addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL1EMAILADDRESS ), true );
02538 addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL2EMAILADDRESS ), false );
02539 addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL3EMAILADDRESS ), false );
02540 addressee.insertCustom( "KADDRESSBOOK", "X-IMAddress", sNamedProp( tnefMsg, MAPI_TAG_CONTACT_IMADDRESS ) );
02541 addressee.insertCustom( "KADDRESSBOOK", "X-SpousesName", stringProp( tnefMsg, MAPI_TAG_PR_SPOUSE_NAME ) );
02542 addressee.insertCustom( "KADDRESSBOOK", "X-ManagersName", stringProp( tnefMsg, MAPI_TAG_PR_MANAGER_NAME ) );
02543 addressee.insertCustom( "KADDRESSBOOK", "X-AssistantsName", stringProp( tnefMsg, MAPI_TAG_PR_ASSISTANT ) );
02544 addressee.insertCustom( "KADDRESSBOOK", "X-Department", stringProp( tnefMsg, MAPI_TAG_PR_DEPARTMENT_NAME ) );
02545 addressee.insertCustom( "KADDRESSBOOK", "X-Office", stringProp( tnefMsg, MAPI_TAG_PR_OFFICE_LOCATION ) );
02546 addressee.insertCustom( "KADDRESSBOOK", "X-Profession", stringProp( tnefMsg, MAPI_TAG_PR_PROFESSION ) );
02547
02548 QString s = tnefMsg->findProp( MAPI_TAG_PR_WEDDING_ANNIVERSARY )
02549 .replace( QChar( '-' ), QString::null )
02550 .replace( QChar( ':' ), QString::null );
02551 if( !s.isEmpty() )
02552 addressee.insertCustom( "KADDRESSBOOK", "X-Anniversary", s );
02553
02554 addressee.setUrl( KURL( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_WEBPAGE ) ) );
02555
02556
02557 addressee.setFamilyName( stringProp( tnefMsg, MAPI_TAG_PR_SURNAME ) );
02558 addressee.setGivenName( stringProp( tnefMsg, MAPI_TAG_PR_GIVEN_NAME ) );
02559 addressee.setAdditionalName( stringProp( tnefMsg, MAPI_TAG_PR_MIDDLE_NAME ) );
02560 addressee.setPrefix( stringProp( tnefMsg, MAPI_TAG_PR_DISPLAY_NAME_PREFIX ) );
02561 addressee.setSuffix( stringProp( tnefMsg, MAPI_TAG_PR_GENERATION ) );
02562
02563 addressee.setNickName( stringProp( tnefMsg, MAPI_TAG_PR_NICKNAME ) );
02564 addressee.setRole( stringProp( tnefMsg, MAPI_TAG_PR_TITLE ) );
02565 addressee.setOrganization( stringProp( tnefMsg, MAPI_TAG_PR_COMPANY_NAME ) );
02566
02567
02568
02569
02570
02571 KABC::Address adr;
02572 adr.setPostOfficeBox( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_PO_BOX ) );
02573 adr.setStreet( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_STREET ) );
02574 adr.setLocality( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_CITY ) );
02575 adr.setRegion( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_STATE_OR_PROVINCE ) );
02576 adr.setPostalCode( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_POSTAL_CODE ) );
02577 adr.setCountry( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_COUNTRY ) );
02578 adr.setType(KABC::Address::Home);
02579 addressee.insertAddress(adr);
02580
02581 adr.setPostOfficeBox( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSPOBOX ) );
02582 adr.setStreet( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSSTREET ) );
02583 adr.setLocality( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSCITY ) );
02584 adr.setRegion( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSSTATE ) );
02585 adr.setPostalCode( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSPOSTALCODE ) );
02586 adr.setCountry( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSCOUNTRY ) );
02587 adr.setType( KABC::Address::Work );
02588 addressee.insertAddress( adr );
02589
02590 adr.setPostOfficeBox( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_PO_BOX ) );
02591 adr.setStreet( stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_STREET ) );
02592 adr.setLocality( stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_CITY ) );
02593 adr.setRegion( stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_STATE_OR_PROVINCE ) );
02594 adr.setPostalCode( stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_POSTAL_CODE ) );
02595 adr.setCountry( stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_COUNTRY ) );
02596 adr.setType( KABC::Address::Dom );
02597 addressee.insertAddress(adr);
02598
02599
02600
02601
02602
02603 QString nr;
02604 nr = stringProp( tnefMsg, MAPI_TAG_PR_HOME_TELEPHONE_NUMBER );
02605 addressee.insertPhoneNumber( KABC::PhoneNumber( nr, KABC::PhoneNumber::Home ) );
02606 nr = stringProp( tnefMsg, MAPI_TAG_PR_BUSINESS_TELEPHONE_NUMBER );
02607 addressee.insertPhoneNumber( KABC::PhoneNumber( nr, KABC::PhoneNumber::Work ) );
02608 nr = stringProp( tnefMsg, MAPI_TAG_PR_MOBILE_TELEPHONE_NUMBER );
02609 addressee.insertPhoneNumber( KABC::PhoneNumber( nr, KABC::PhoneNumber::Cell ) );
02610 nr = stringProp( tnefMsg, MAPI_TAG_PR_HOME_FAX_NUMBER );
02611 addressee.insertPhoneNumber( KABC::PhoneNumber( nr, KABC::PhoneNumber::Fax | KABC::PhoneNumber::Home ) );
02612 nr = stringProp( tnefMsg, MAPI_TAG_PR_BUSINESS_FAX_NUMBER );
02613 addressee.insertPhoneNumber( KABC::PhoneNumber( nr, KABC::PhoneNumber::Fax | KABC::PhoneNumber::Work ) );
02614
02615 s = tnefMsg->findProp( MAPI_TAG_PR_BIRTHDAY )
02616 .replace( QChar( '-' ), QString::null )
02617 .replace( QChar( ':' ), QString::null );
02618 if( !s.isEmpty() )
02619 addressee.setBirthday( QDateTime::fromString( s ) );
02620
02621 bOk = ( !addressee.isEmpty() );
02622 } else if( "IPM.NOTE" == msgClass ) {
02623
02624 }
02625 }
02626 }
02627
02628
02629 QString iCal = calFormat.toString( &cal );
02630 if( !iCal.isEmpty() )
02631
02632 return iCal;
02633
02634
02635 KABC::VCardConverter converter;
02636 return converter.createVCard( addressee );
02637 }
02638
02639
02640 QString IncidenceFormatter::formatTNEFInvitation( const QByteArray& tnef,
02641 Calendar *mCalendar, InvitationFormatterHelper *helper )
02642 {
02643 QString vPart = IncidenceFormatter::msTNEFToVPart( tnef );
02644 QString iCal = IncidenceFormatter::formatICalInvitation( vPart, mCalendar, helper );
02645 if( !iCal.isEmpty() )
02646 return iCal;
02647 return vPart;
02648 }
02649
02650
02651
02652
02653
02654
02655
02656
02657 class IncidenceFormatter::ToolTipVisitor : public IncidenceBase::Visitor
02658 {
02659 public:
02660 ToolTipVisitor()
02661 : mCalendar( 0 ), mRichText( true ), mResult( "" ) {}
02662
02663 bool act( Calendar *calendar, IncidenceBase *incidence,
02664 const QDate &date=QDate(), bool richText=true )
02665 {
02666 mCalendar = calendar;
02667 mDate = date;
02668 mRichText = richText;
02669 mResult = "";
02670 return incidence ? incidence->accept( *this ) : false;
02671 }
02672 QString result() const { return mResult; }
02673
02674 protected:
02675 bool visit( Event *event );
02676 bool visit( Todo *todo );
02677 bool visit( Journal *journal );
02678 bool visit( FreeBusy *fb );
02679
02680 QString dateRangeText( Event *event, const QDate &date );
02681 QString dateRangeText( Todo *todo, const QDate &date );
02682 QString dateRangeText( Journal *journal );
02683 QString dateRangeText( FreeBusy *fb );
02684
02685 QString generateToolTip( Incidence* incidence, QString dtRangeText );
02686
02687 protected:
02688 Calendar *mCalendar;
02689 QDate mDate;
02690 bool mRichText;
02691 QString mResult;
02692 };
02693
02694 QString IncidenceFormatter::ToolTipVisitor::dateRangeText( Event *event, const QDate &date )
02695 {
02696 QString ret;
02697 QString tmp;
02698
02699 QDateTime startDt = event->dtStart();
02700 QDateTime endDt = event->dtEnd();
02701 if ( event->doesRecur() ) {
02702 if ( date.isValid() ) {
02703 QDateTime dt( date, QTime( 0, 0, 0 ) );
02704 int diffDays = startDt.daysTo( dt );
02705 dt = dt.addSecs( -1 );
02706 startDt.setDate( event->recurrence()->getNextDateTime( dt ).date() );
02707 if ( event->hasEndDate() ) {
02708 endDt = endDt.addDays( diffDays );
02709 if ( startDt > endDt ) {
02710 startDt.setDate( event->recurrence()->getPreviousDateTime( dt ).date() );
02711 endDt = startDt.addDays( event->dtStart().daysTo( event->dtEnd() ) );
02712 }
02713 }
02714 }
02715 }
02716 if ( event->isMultiDay() ) {
02717
02718 tmp = "<br>" + i18n("Event start", "<i>From:</i> %1");
02719 if (event->doesFloat())
02720 ret += tmp.arg( IncidenceFormatter::dateToString( startDt, false ).replace(" ", " ") );
02721 else
02722 ret += tmp.arg( IncidenceFormatter::dateToString( startDt ).replace(" ", " ") );
02723
02724 tmp = "<br>" + i18n("Event end","<i>To:</i> %1");
02725 if (event->doesFloat())
02726 ret += tmp.arg( IncidenceFormatter::dateToString( endDt, false ).replace(" ", " ") );
02727 else
02728 ret += tmp.arg( IncidenceFormatter::dateToString( endDt ).replace(" ", " ") );
02729
02730 } else {
02731
02732 ret += "<br>"+i18n("<i>Date:</i> %1").
02733 arg( IncidenceFormatter::dateToString( startDt, false ).replace(" ", " ") );
02734 if ( !event->doesFloat() ) {
02735 const QString dtStartTime =
02736 IncidenceFormatter::timeToString( startDt, true ).replace( " ", " " );
02737 const QString dtEndTime =
02738 IncidenceFormatter::timeToString( endDt, true ).replace( " ", " " );
02739 if ( dtStartTime == dtEndTime ) {
02740 tmp = "<br>" + i18n("time for event, to prevent ugly line breaks",
02741 "<i>Time:</i> %1").
02742 arg( dtStartTime );
02743 } else {
02744 tmp = "<br>" + i18n("time range for event, to prevent ugly line breaks",
02745 "<i>Time:</i> %1 - %2").
02746 arg( dtStartTime, dtEndTime );
02747 }
02748 ret += tmp;
02749 }
02750
02751 }
02752 return ret;
02753 }
02754
02755 QString IncidenceFormatter::ToolTipVisitor::dateRangeText( Todo *todo, const QDate &date )
02756 {
02757 QString ret;
02758 bool floats( todo->doesFloat() );
02759
02760 if ( todo->hasStartDate() && todo->dtStart().isValid() ) {
02761 QDateTime startDt = todo->dtStart();
02762 if ( todo->doesRecur() ) {
02763 if ( date.isValid() ) {
02764 startDt.setDate( date );
02765 }
02766 }
02767 ret += "<br>" +
02768 i18n("<i>Start:</i> %1").
02769 arg( IncidenceFormatter::dateTimeToString( startDt, floats, false ).
02770 replace( " ", " " ) );
02771 }
02772
02773 if ( todo->hasDueDate() && todo->dtDue().isValid() ) {
02774 QDateTime dueDt = todo->dtDue();
02775 if ( todo->doesRecur() ) {
02776 if ( date.isValid() ) {
02777 dueDt.addDays( todo->dtDue().date().daysTo( date ) );
02778 }
02779 }
02780 ret += "<br>" +
02781 i18n("<i>Due:</i> %1").
02782 arg( IncidenceFormatter::dateTimeToString( todo->dtDue(), floats, false ).
02783 replace( " ", " " ) );
02784 }
02785
02786 if ( todo->isCompleted() ) {
02787 ret += "<br>" +
02788 i18n("<i>Completed:</i> %1").
02789 arg( todo->completedStr().replace( " ", " " ) );
02790 } else {
02791 ret += "<br>" +
02792 i18n( "%1% completed" ).arg(todo->percentComplete() );
02793 }
02794
02795 return ret;
02796 }
02797
02798 QString IncidenceFormatter::ToolTipVisitor::dateRangeText( Journal*journal )
02799 {
02800 QString ret;
02801 if (journal->dtStart().isValid() ) {
02802 ret += "<br>" +
02803 i18n("<i>Date:</i> %1").
02804 arg( IncidenceFormatter::dateToString( journal->dtStart(), false ) );
02805 }
02806 return ret;
02807 }
02808
02809 QString IncidenceFormatter::ToolTipVisitor::dateRangeText( FreeBusy *fb )
02810 {
02811 QString tmp( "<br>" + i18n("<i>Period start:</i> %1") );
02812 QString ret = tmp.arg( KGlobal::locale()->formatDateTime( fb->dtStart() ) );
02813 tmp = "<br>" + i18n("<i>Period start:</i> %1");
02814 ret += tmp.arg( KGlobal::locale()->formatDateTime( fb->dtEnd() ) );
02815 return ret;
02816 }
02817
02818
02819
02820 bool IncidenceFormatter::ToolTipVisitor::visit( Event *event )
02821 {
02822 mResult = generateToolTip( event, dateRangeText( event, mDate ) );
02823 return !mResult.isEmpty();
02824 }
02825
02826 bool IncidenceFormatter::ToolTipVisitor::visit( Todo *todo )
02827 {
02828 mResult = generateToolTip( todo, dateRangeText( todo, mDate ) );
02829 return !mResult.isEmpty();
02830 }
02831
02832 bool IncidenceFormatter::ToolTipVisitor::visit( Journal *journal )
02833 {
02834 mResult = generateToolTip( journal, dateRangeText( journal ) );
02835 return !mResult.isEmpty();
02836 }
02837
02838 bool IncidenceFormatter::ToolTipVisitor::visit( FreeBusy *fb )
02839 {
02840 mResult = "<qt><b>" + i18n("Free/Busy information for %1")
02841 .arg(fb->organizer().fullName()) + "</b>";
02842 mResult += dateRangeText( fb );
02843 mResult += "</qt>";
02844 return !mResult.isEmpty();
02845 }
02846
02847 QString IncidenceFormatter::ToolTipVisitor::generateToolTip( Incidence* incidence, QString dtRangeText )
02848 {
02849 if ( !incidence )
02850 return QString::null;
02851
02852 QString tmp = "<qt><b>"+ incidence->summary().replace("\n", "<br>")+"</b>";
02853
02854 if ( mCalendar ) {
02855 QString calStr = IncidenceFormatter::resourceString( mCalendar, incidence );
02856 if ( !calStr.isEmpty() ) {
02857 tmp += "<br>" + i18n( "<i>Calendar:</i> %1" ).arg( calStr );
02858 }
02859 }
02860
02861 tmp += dtRangeText;
02862
02863 if (!incidence->location().isEmpty()) {
02864 tmp += "<br>"+i18n("<i>Location:</i> %1").
02865 arg( incidence->location().replace("\n", "<br>") );
02866 }
02867 if (!incidence->description().isEmpty()) {
02868 QString desc(incidence->description());
02869 if (desc.length()>120) {
02870 desc = desc.left(120) + "...";
02871 }
02872 tmp += "<br>----------<br>" + i18n("<i>Description:</i><br>") + desc.replace("\n", "<br>");
02873 }
02874 tmp += "</qt>";
02875 return tmp;
02876 }
02877
02878 QString IncidenceFormatter::toolTipString( IncidenceBase *incidence, bool richText )
02879 {
02880 return toolTipStr( 0, incidence, QDate(), richText );
02881 }
02882
02883 QString IncidenceFormatter::toolTipStr( Calendar *calendar,
02884 IncidenceBase *incidence,
02885 const QDate &date,
02886 bool richText )
02887 {
02888 ToolTipVisitor v;
02889 if ( v.act( calendar, incidence, date, richText ) ) {
02890 return v.result();
02891 } else {
02892 return QString::null;
02893 }
02894 }
02895
02896
02897
02898
02899
02900 class IncidenceFormatter::MailBodyVisitor : public IncidenceBase::Visitor
02901 {
02902 public:
02903 MailBodyVisitor() : mResult( "" ) {}
02904
02905 bool act( IncidenceBase *incidence )
02906 {
02907 mResult = "";
02908 return incidence ? incidence->accept( *this ) : false;
02909 }
02910 QString result() const { return mResult; }
02911
02912 protected:
02913 bool visit( Event *event );
02914 bool visit( Todo *todo );
02915 bool visit( Journal *journal );
02916 bool visit( FreeBusy * ) { mResult = i18n("This is a Free Busy Object"); return !mResult.isEmpty(); }
02917 protected:
02918 QString mResult;
02919 };
02920
02921
02922 static QString mailBodyIncidence( Incidence *incidence )
02923 {
02924 QString body;
02925 if ( !incidence->summary().isEmpty() ) {
02926 body += i18n("Summary: %1\n").arg( incidence->summary() );
02927 }
02928 if ( !incidence->organizer().isEmpty() ) {
02929 body += i18n("Organizer: %1\n").arg( incidence->organizer().fullName() );
02930 }
02931 if ( !incidence->location().isEmpty() ) {
02932 body += i18n("Location: %1\n").arg( incidence->location() );
02933 }
02934 return body;
02935 }
02936
02937 bool IncidenceFormatter::MailBodyVisitor::visit( Event *event )
02938 {
02939 QString recurrence[]= {i18n("no recurrence", "None"),
02940 i18n("Minutely"), i18n("Hourly"), i18n("Daily"),
02941 i18n("Weekly"), i18n("Monthly Same Day"), i18n("Monthly Same Position"),
02942 i18n("Yearly"), i18n("Yearly"), i18n("Yearly")};
02943
02944 mResult = mailBodyIncidence( event );
02945 mResult += i18n("Start Date: %1\n").
02946 arg( IncidenceFormatter::dateToString( event->dtStart(), true ) );
02947 if ( !event->doesFloat() ) {
02948 mResult += i18n("Start Time: %1\n").
02949 arg( IncidenceFormatter::timeToString( event->dtStart(), true ) );
02950 }
02951 if ( event->dtStart() != event->dtEnd() ) {
02952 mResult += i18n("End Date: %1\n").
02953 arg( IncidenceFormatter::dateToString( event->dtEnd(), true ) );
02954 }
02955 if ( !event->doesFloat() ) {
02956 mResult += i18n("End Time: %1\n").
02957 arg( IncidenceFormatter::timeToString( event->dtEnd(), true ) );
02958 }
02959 if ( event->doesRecur() ) {
02960 Recurrence *recur = event->recurrence();
02961
02962 mResult += i18n("Recurs: %1\n")
02963 .arg( recurrence[ recur->recurrenceType() ] );
02964 mResult += i18n("Frequency: %1\n")
02965 .arg( event->recurrence()->frequency() );
02966
02967 if ( recur->duration() > 0 ) {
02968 mResult += i18n ("Repeats once", "Repeats %n times", recur->duration());
02969 mResult += '\n';
02970 } else {
02971 if ( recur->duration() != -1 ) {
02972
02973 QString endstr;
02974 if ( event->doesFloat() ) {
02975 endstr = KGlobal::locale()->formatDate( recur->endDate() );
02976 } else {
02977 endstr = KGlobal::locale()->formatDateTime( recur->endDateTime() );
02978 }
02979 mResult += i18n("Repeat until: %1\n").arg( endstr );
02980 } else {
02981 mResult += i18n("Repeats forever\n");
02982 }
02983 }
02984 }
02985 QString details = event->description();
02986 if ( !details.isEmpty() ) {
02987 mResult += i18n("Details:\n%1\n").arg( details );
02988 }
02989 return !mResult.isEmpty();
02990 }
02991
02992 bool IncidenceFormatter::MailBodyVisitor::visit( Todo *todo )
02993 {
02994 mResult = mailBodyIncidence( todo );
02995
02996 if ( todo->hasStartDate() ) {
02997 mResult += i18n("Start Date: %1\n").
02998 arg( IncidenceFormatter::dateToString( todo->dtStart( false ), true ) );
02999 if ( !todo->doesFloat() ) {
03000 mResult += i18n("Start Time: %1\n").
03001 arg( IncidenceFormatter::timeToString( todo->dtStart( false ),true ) );
03002 }
03003 }
03004 if ( todo->hasDueDate() ) {
03005 mResult += i18n("Due Date: %1\n").
03006 arg( IncidenceFormatter::dateToString( todo->dtDue(), true ) );
03007 if ( !todo->doesFloat() ) {
03008 mResult += i18n("Due Time: %1\n").
03009 arg( IncidenceFormatter::timeToString( todo->dtDue(), true ) );
03010 }
03011 }
03012 QString details = todo->description();
03013 if ( !details.isEmpty() ) {
03014 mResult += i18n("Details:\n%1\n").arg( details );
03015 }
03016 return !mResult.isEmpty();
03017 }
03018
03019 bool IncidenceFormatter::MailBodyVisitor::visit( Journal *journal )
03020 {
03021 mResult = mailBodyIncidence( journal );
03022 mResult += i18n("Date: %1\n").
03023 arg( IncidenceFormatter::dateToString( journal->dtStart(), true ) );
03024 if ( !journal->doesFloat() ) {
03025 mResult += i18n("Time: %1\n").
03026 arg( IncidenceFormatter::timeToString( journal->dtStart(), true ) );
03027 }
03028 if ( !journal->description().isEmpty() )
03029 mResult += i18n("Text of the journal:\n%1\n").arg( journal->description() );
03030 return !mResult.isEmpty();
03031 }
03032
03033
03034
03035 QString IncidenceFormatter::mailBodyString( IncidenceBase *incidence )
03036 {
03037 if ( !incidence )
03038 return QString::null;
03039
03040 MailBodyVisitor v;
03041 if ( v.act( incidence ) ) {
03042 return v.result();
03043 }
03044 return QString::null;
03045 }
03046
03047
03048
03049
03050
03051 QString IncidenceFormatter::recurrenceString(Incidence * incidence)
03052 {
03053 if ( !incidence->doesRecur() )
03054 return i18n( "No recurrence" );
03055
03056
03057 QStringList dayList;
03058 dayList.append( i18n( "31st Last" ) );
03059 dayList.append( i18n( "30th Last" ) );
03060 dayList.append( i18n( "29th Last" ) );
03061 dayList.append( i18n( "28th Last" ) );
03062 dayList.append( i18n( "27th Last" ) );
03063 dayList.append( i18n( "26th Last" ) );
03064 dayList.append( i18n( "25th Last" ) );
03065 dayList.append( i18n( "24th Last" ) );
03066 dayList.append( i18n( "23rd Last" ) );
03067 dayList.append( i18n( "22nd Last" ) );
03068 dayList.append( i18n( "21st Last" ) );
03069 dayList.append( i18n( "20th Last" ) );
03070 dayList.append( i18n( "19th Last" ) );
03071 dayList.append( i18n( "18th Last" ) );
03072 dayList.append( i18n( "17th Last" ) );
03073 dayList.append( i18n( "16th Last" ) );
03074 dayList.append( i18n( "15th Last" ) );
03075 dayList.append( i18n( "14th Last" ) );
03076 dayList.append( i18n( "13th Last" ) );
03077 dayList.append( i18n( "12th Last" ) );
03078 dayList.append( i18n( "11th Last" ) );
03079 dayList.append( i18n( "10th Last" ) );
03080 dayList.append( i18n( "9th Last" ) );
03081 dayList.append( i18n( "8th Last" ) );
03082 dayList.append( i18n( "7th Last" ) );
03083 dayList.append( i18n( "6th Last" ) );
03084 dayList.append( i18n( "5th Last" ) );
03085 dayList.append( i18n( "4th Last" ) );
03086 dayList.append( i18n( "3rd Last" ) );
03087 dayList.append( i18n( "2nd Last" ) );
03088 dayList.append( i18n( "last day of the month", "Last" ) );
03089 dayList.append( i18n( "unknown day of the month", "unknown" ) );
03090 dayList.append( i18n( "1st" ) );
03091 dayList.append( i18n( "2nd" ) );
03092 dayList.append( i18n( "3rd" ) );
03093 dayList.append( i18n( "4th" ) );
03094 dayList.append( i18n( "5th" ) );
03095
03096 QString recurString;
03097 const KCalendarSystem *calSys = KGlobal::locale()->calendar();;
03098
03099 Recurrence *recurs = incidence->recurrence();
03100 switch ( recurs->recurrenceType() ) {
03101
03102 case Recurrence::rNone:
03103 recurString = i18n( "no recurrence", "None" );
03104 break;
03105 case Recurrence::rDaily:
03106 recurString = i18n( "Every day", "Every %1 days", recurs->frequency() );
03107 break;
03108 case Recurrence::rWeekly:
03109 {
03110 QString dayNames;
03111
03112 int weekStart = KGlobal::locale()->weekStartDay();
03113 bool addSpace = false;
03114 for ( int i = 0; i < 7; ++i ) {
03115 if ( recurs->days().testBit( (i+weekStart+6)%7 )) {
03116 if (addSpace) dayNames.append(" ");
03117 dayNames.append( calSys->weekDayName( ((i+weekStart+6)%7)+1, true ) );
03118 addSpace=true;
03119 }
03120 }
03121 recurString = i18n( "Every week on %1",
03122 "Every %n weeks on %1",
03123 recurs->frequency()).arg( dayNames );
03124 break;
03125 }
03126 case Recurrence::rMonthlyPos:
03127 {
03128 KCal::RecurrenceRule::WDayPos rule = recurs->monthPositions()[0];
03129 recurString = i18n( "Every month on the %1 %2",
03130 "Every %n months on the %1 %2",
03131 recurs->frequency() ).arg(dayList[rule.pos() + 31]).arg(
03132 calSys->weekDayName( rule.day(),false ) );
03133 break;
03134 }
03135 case Recurrence::rMonthlyDay:
03136 {
03137 int days = recurs->monthDays()[0];
03138 if (days < 0) {
03139 recurString = i18n( "Every month on the %1 day",
03140 "Every %n months on the %1 day",
03141 recurs->frequency() ).arg( dayList[days + 31] );
03142 } else {
03143 recurString = i18n( "Every month on day %1",
03144 "Every %n months on day %1",
03145 recurs->frequency() ).arg( recurs->monthDays()[0] );
03146 }
03147 break;
03148 }
03149
03150 case Recurrence::rYearlyMonth:
03151 {
03152 recurString = i18n( "Every year on day %1 of %2",
03153 "Every %n years on day %1 of %2",
03154 recurs->frequency() )
03155 .arg(recurs->yearDates()[0])
03156 .arg(calSys->monthName( recurs->yearMonths()[0], recurs->startDate().year() ) );
03157 break;
03158 }
03159 case Recurrence::rYearlyPos:
03160 {
03161 KCal::RecurrenceRule::WDayPos rule = recurs->yearPositions()[0];
03162 recurString = i18n( "Every year on the %1 %2 of %3",
03163 "Every %n years on the %1 %2of %3",
03164 recurs->frequency()).arg( dayList[rule.pos() + 31] )
03165 .arg( calSys->weekDayName( rule.day(), false ))
03166 .arg( calSys->monthName( recurs->yearMonths()[0], recurs->startDate().year() ) );
03167 break;
03168 }
03169 case Recurrence::rYearlyDay:
03170 {
03171 recurString = i18n( "Every year on day %1",
03172 "Every %n years on day %1",
03173 recurs->frequency()).arg( recurs->yearDays()[0] );
03174 break;
03175 }
03176
03177 default:
03178 return i18n( "Incidence recurs" );
03179 }
03180
03181 return recurString;
03182 }
03183
03184 QString IncidenceFormatter::timeToString( const QDateTime &date, bool shortfmt )
03185 {
03186 return KGlobal::locale()->formatTime( date.time(), !shortfmt );
03187 }
03188
03189 QString IncidenceFormatter::dateToString( const QDateTime &date, bool shortfmt )
03190 {
03191 return
03192 KGlobal::locale()->formatDate( date.date(), shortfmt );
03193 }
03194
03195 QString IncidenceFormatter::dateTimeToString( const QDateTime &date,
03196 bool allDay, bool shortfmt )
03197 {
03198 if ( allDay ) {
03199 return dateToString( date, shortfmt );
03200 }
03201
03202 return KGlobal::locale()->formatDateTime( date, shortfmt );
03203 }
03204
03205 QString IncidenceFormatter::resourceString( Calendar *calendar, Incidence *incidence )
03206 {
03207 if ( !calendar || !incidence ) {
03208 return QString::null;
03209 }
03210
03211 CalendarResources *calendarResource = dynamic_cast<CalendarResources*>( calendar );
03212 if ( !calendarResource ) {
03213 return QString::null;
03214 }
03215
03216 ResourceCalendar *resourceCalendar = calendarResource->resource( incidence );
03217 if ( resourceCalendar ) {
03218 if ( !resourceCalendar->subresources().isEmpty() ) {
03219 QString subRes = resourceCalendar->subresourceIdentifier( incidence );
03220 if ( subRes.isEmpty() ) {
03221 return resourceCalendar->resourceName();
03222 } else {
03223 return resourceCalendar->labelForSubresource( subRes );
03224 }
03225 }
03226 return resourceCalendar->resourceName();
03227 }
03228
03229 return QString::null;
03230 }