00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "htmlexport.h"
00024 #include "htmlexportsettings.h"
00025 #include "incidenceformatter.h"
00026 #include "calendar.h"
00027 #include "event.h"
00028 #include "todo.h"
00029 #ifndef KORG_NOKABC
00030 #include "kabc/stdaddressbook.h"
00031 #endif
00032
00033 #include <kglobal.h>
00034 #include <klocale.h>
00035 #include <kdebug.h>
00036 #include <kcalendarsystem.h>
00037
00038 #include <QtCore/QFile>
00039 #include <QtCore/QTextStream>
00040 #include <QtCore/QTextCodec>
00041 #include <QtCore/QRegExp>
00042 #include <QtCore/QMap>
00043 #include <QtGui/QApplication>
00044
00045 using namespace KCal;
00046
00047 static QString cleanChars( const QString &txt );
00048
00049
00050 class KCal::HtmlExport::Private
00051 {
00052 public:
00053 Private( Calendar *calendar, HTMLExportSettings *settings )
00054 : mCalendar( calendar ),
00055 mSettings( settings )
00056 {}
00057
00058 Calendar *mCalendar;
00059 HTMLExportSettings *mSettings;
00060 QMap<QDate,QString> mHolidayMap;
00061 };
00062
00063
00064 HtmlExport::HtmlExport( Calendar *calendar, HTMLExportSettings *settings )
00065 : d( new Private( calendar, settings ) )
00066 {
00067 }
00068
00069 HtmlExport::~HtmlExport()
00070 {
00071 delete d;
00072 }
00073
00074 bool HtmlExport::save( const QString &fileName )
00075 {
00076 QString fn( fileName );
00077 if ( fn.isEmpty() && d->mSettings ) {
00078 fn = d->mSettings->outputFile();
00079 }
00080 if ( !d->mSettings || fn.isEmpty() ) {
00081 return false;
00082 }
00083 QFile f( fileName );
00084 if ( !f.open( QIODevice::WriteOnly ) ) {
00085 return false;
00086 }
00087 QTextStream ts( &f );
00088 bool success = save( &ts );
00089 f.close();
00090 return success;
00091 }
00092
00093 bool HtmlExport::save( QTextStream *ts )
00094 {
00095 if ( !d->mSettings ) {
00096 return false;
00097 }
00098 ts->setCodec( "UTF-8" );
00099
00100 *ts << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" ";
00101 *ts << "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl;
00102
00103 *ts << "<html><head>" << endl;
00104 *ts << " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=";
00105 *ts << "UTF-8\" />" << endl;
00106 if ( !d->mSettings->pageTitle().isEmpty() ) {
00107 *ts << " <title>" << d->mSettings->pageTitle() << "</title>" << endl;
00108 }
00109 *ts << " <style type=\"text/css\">" << endl;
00110 *ts << styleSheet();
00111 *ts << " </style>" << endl;
00112 *ts << "</head><body>" << endl;
00113
00114
00115
00116
00117 if ( d->mSettings->eventView() || d->mSettings->monthView() || d->mSettings->weekView() ) {
00118 if ( !d->mSettings->eventTitle().isEmpty() ) {
00119 *ts << "<h1>" << d->mSettings->eventTitle() << "</h1>" << endl;
00120 }
00121
00122
00123 if ( d->mSettings->weekView() ) {
00124 createWeekView( ts );
00125 }
00126
00127 if ( d->mSettings->monthView() ) {
00128 createMonthView( ts );
00129 }
00130
00131 if ( d->mSettings->eventView() ) {
00132 createEventList( ts );
00133 }
00134 }
00135
00136
00137 if ( d->mSettings->todoView() ) {
00138 if ( !d->mSettings->todoListTitle().isEmpty() ) {
00139 *ts << "<h1>" << d->mSettings->todoListTitle() << "</h1>" << endl;
00140 }
00141 createTodoList( ts );
00142 }
00143
00144
00145 if ( d->mSettings->journalView() ) {
00146 if ( !d->mSettings->journalTitle().isEmpty() ) {
00147 *ts << "<h1>" << d->mSettings->journalTitle() << "</h1>" << endl;
00148 }
00149 createJournalView( ts );
00150 }
00151
00152
00153 if ( d->mSettings->freeBusyView() ) {
00154 if ( !d->mSettings->freeBusyTitle().isEmpty() ) {
00155 *ts << "<h1>" << d->mSettings->freeBusyTitle() << "</h1>" << endl;
00156 }
00157 createFreeBusyView( ts );
00158 }
00159
00160 createFooter( ts );
00161
00162
00163 *ts << "</body></html>" << endl;
00164
00165 return true;
00166 }
00167
00168 void HtmlExport::createMonthView( QTextStream *ts )
00169 {
00170 QDate start = fromDate();
00171 start.setYMD( start.year(), start.month(), 1 );
00172
00173 QDate end( start.year(), start.month(), start.daysInMonth() );
00174
00175 int startmonth = start.month();
00176 int startyear = start.year();
00177
00178 while ( start < toDate() ) {
00179
00180 QDate hDate( start.year(), start.month(), 1 );
00181 QString hMon = hDate.toString( "MMMM" );
00182 QString hYear = hDate.toString( "yyyy" );
00183 *ts << "<h2>"
00184 << i18nc( "@title month and year", "%1 %2", hMon, hYear )
00185 << "</h2>" << endl;
00186 if ( KGlobal::locale()->weekStartDay() == 1 ) {
00187 start = start.addDays( 1 - start.dayOfWeek() );
00188 } else {
00189 if ( start.dayOfWeek() != 7 ) {
00190 start = start.addDays( -start.dayOfWeek() );
00191 }
00192 }
00193 *ts << "<table border=\"1\">" << endl;
00194
00195
00196 *ts << " <tr>";
00197 for ( int i=0; i < 7; ++i ) {
00198 *ts << "<th>" << KGlobal::locale()->calendar()->weekDayName( start.addDays(i) ) << "</th>";
00199 }
00200 *ts << "</tr>" << endl;
00201
00202
00203 while ( start <= end ) {
00204 *ts << " <tr>" << endl;
00205 for ( int i=0; i < 7; ++i ) {
00206 *ts << " <td valign=\"top\"><table border=\"0\">";
00207
00208 *ts << "<tr><td ";
00209 if ( d->mHolidayMap.contains( start ) || start.dayOfWeek() == 7 ) {
00210 *ts << "class=\"dateholiday\"";
00211 } else {
00212 *ts << "class=\"date\"";
00213 }
00214 *ts << ">" << QString::number( start.day() );
00215
00216 if ( d->mHolidayMap.contains( start ) ) {
00217 *ts << " <em>" << d->mHolidayMap[start] << "</em>";
00218 }
00219
00220 *ts << "</td></tr><tr><td valign=\"top\">";
00221
00222
00223 if ( start >= fromDate() && start <= toDate() ) {
00224 Event::List events = d->mCalendar->events( start, d->mCalendar->timeSpec(),
00225 EventSortStartDate,
00226 SortDirectionAscending );
00227 if ( events.count() ) {
00228 *ts << "<table>";
00229 Event::List::ConstIterator it;
00230 for ( it = events.constBegin(); it != events.constEnd(); ++it ) {
00231 if ( checkSecrecy( *it ) ) {
00232 createEvent( ts, *it, start, false );
00233 }
00234 }
00235 *ts << "</table>";
00236 } else {
00237 *ts << " ";
00238 }
00239 }
00240
00241 *ts << "</td></tr></table></td>" << endl;
00242 start = start.addDays( 1 );
00243 }
00244 *ts << " </tr>" << endl;
00245 }
00246 *ts << "</table>" << endl;
00247 startmonth += 1;
00248 if ( startmonth > 12 ) {
00249 startyear += 1;
00250 startmonth = 1;
00251 }
00252 start.setYMD( startyear, startmonth, 1 );
00253 end.setYMD( start.year(), start.month(), start.daysInMonth() );
00254 }
00255 }
00256
00257 void HtmlExport::createEventList( QTextStream *ts )
00258 {
00259 int columns = 3;
00260 *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">" << endl;
00261 *ts << " <tr>" << endl;
00262 *ts << " <th class=\"sum\">" << i18nc( "@title:column event start time",
00263 "Start Time" ) << "</th>" << endl;
00264 *ts << " <th>" << i18nc( "@title:column event end time",
00265 "End Time" ) << "</th>" << endl;
00266 *ts << " <th>" << i18nc( "@title:column event description",
00267 "Event" ) << "</th>" << endl;
00268 if ( d->mSettings->eventLocation() ) {
00269 *ts << " <th>" << i18nc( "@title:column event locatin",
00270 "Location" ) << "</th>" << endl;
00271 ++columns;
00272 }
00273 if ( d->mSettings->eventCategories() ) {
00274 *ts << " <th>" << i18nc( "@title:column event categories",
00275 "Categories" ) << "</th>" << endl;
00276 ++columns;
00277 }
00278 if ( d->mSettings->eventAttendees() ) {
00279 *ts << " <th>" << i18nc( "@title:column event attendees",
00280 "Attendees" ) << "</th>" << endl;
00281 ++columns;
00282 }
00283
00284 *ts << " </tr>" << endl;
00285
00286 for ( QDate dt = fromDate(); dt <= toDate(); dt = dt.addDays(1) ) {
00287 kDebug() << "Getting events for" << dt.toString();
00288 Event::List events = d->mCalendar->events( dt, d->mCalendar->timeSpec(),
00289 EventSortStartDate,
00290 SortDirectionAscending );
00291 if ( events.count() ) {
00292 *ts << " <tr><td colspan=\"" << QString::number( columns )
00293 << "\" class=\"datehead\"><i>"
00294 << KGlobal::locale()->formatDate( dt )
00295 << "</i></td></tr>" << endl;
00296
00297 Event::List::ConstIterator it;
00298 for ( it = events.constBegin(); it != events.constEnd(); ++it ) {
00299 if ( checkSecrecy( *it ) ) {
00300 createEvent( ts, *it, dt );
00301 }
00302 }
00303 }
00304 }
00305
00306 *ts << "</table>" << endl;
00307 }
00308
00309 void HtmlExport::createEvent ( QTextStream *ts, Event *event,
00310 QDate date, bool withDescription )
00311 {
00312 kDebug() << event->summary();
00313 *ts << " <tr>" << endl;
00314
00315 if ( !event->allDay() ) {
00316 if ( event->isMultiDay( d->mCalendar->timeSpec() ) && ( event->dtStart().date() != date ) ) {
00317 *ts << " <td> </td>" << endl;
00318 } else {
00319 *ts << " <td valign=\"top\">"
00320 << IncidenceFormatter::timeToString( event->dtStart(), true, d->mCalendar->timeSpec() )
00321 << "</td>" << endl;
00322 }
00323 if ( event->isMultiDay( d->mCalendar->timeSpec() ) && ( event->dtEnd().date() != date ) ) {
00324 *ts << " <td> </td>" << endl;
00325 } else {
00326 *ts << " <td valign=\"top\">"
00327 << IncidenceFormatter::timeToString( event->dtEnd(), true, d->mCalendar->timeSpec() )
00328 << "</td>" << endl;
00329 }
00330 } else {
00331 *ts << " <td> </td><td> </td>" << endl;
00332 }
00333
00334 *ts << " <td class=\"sum\">" << endl;
00335 *ts << " <b>" << cleanChars( event->summary() ) << "</b>" << endl;
00336 if ( withDescription && !event->description().isEmpty() ) {
00337 *ts << " <p>" << breakString( cleanChars( event->description() ) ) << "</p>" << endl;
00338 }
00339 *ts << " </td>" << endl;
00340
00341 if ( d->mSettings->eventLocation() ) {
00342 *ts << " <td>" << endl;
00343 formatLocation( ts, event );
00344 *ts << " </td>" << endl;
00345 }
00346
00347 if ( d->mSettings->eventCategories() ) {
00348 *ts << " <td>" << endl;
00349 formatCategories( ts, event );
00350 *ts << " </td>" << endl;
00351 }
00352
00353 if ( d->mSettings->eventAttendees() ) {
00354 *ts << " <td>" << endl;
00355 formatAttendees( ts, event );
00356 *ts << " </td>" << endl;
00357 }
00358
00359 *ts << " </tr>" << endl;
00360 }
00361
00362 void HtmlExport::createTodoList ( QTextStream *ts )
00363 {
00364 Todo::List rawTodoList = d->mCalendar->todos();
00365
00366 int index = 0;
00367 while ( index < rawTodoList.count() ) {
00368 Todo *ev = rawTodoList[ index ];
00369 Todo *subev = ev;
00370 if ( ev->relatedTo() ) {
00371 if ( ev->relatedTo()->type() == "Todo" ) {
00372 if ( !rawTodoList.contains( static_cast<Todo *>( ev->relatedTo() ) ) ) {
00373 rawTodoList.append( static_cast<Todo *>( ev->relatedTo() ) );
00374 }
00375 }
00376 }
00377 index = rawTodoList.indexOf( subev );
00378 ++index;
00379 }
00380
00381
00382
00383 Todo::List todoList;
00384 Todo::List::ConstIterator it;
00385 for ( int i = 1; i <= 9; ++i ) {
00386 for ( it = rawTodoList.constBegin(); it != rawTodoList.constEnd(); ++it ) {
00387 if ( (*it)->priority() == i && checkSecrecy( *it ) ) {
00388 todoList.append( *it );
00389 }
00390 }
00391 }
00392 for ( it = rawTodoList.constBegin(); it != rawTodoList.constEnd(); ++it ) {
00393 if ( (*it)->priority() == 0 && checkSecrecy( *it ) ) {
00394 todoList.append( *it );
00395 }
00396 }
00397
00398 int columns = 3;
00399 *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">" << endl;
00400 *ts << " <tr>" << endl;
00401 *ts << " <th class=\"sum\">" << i18nc( "@title:column", "To-do" ) << "</th>" << endl;
00402 *ts << " <th>" << i18nc( "@title:column to-do priority", "Priority" ) << "</th>" << endl;
00403 *ts << " <th>" << i18nc( "@title:column to-do percent completed",
00404 "Completed" ) << "</th>" << endl;
00405 if ( d->mSettings->taskDueDate() ) {
00406 *ts << " <th>" << i18nc( "@title:column to-do due date", "Due Date" ) << "</th>" << endl;
00407 ++columns;
00408 }
00409 if ( d->mSettings->taskLocation() ) {
00410 *ts << " <th>" << i18nc( "@title:column to-do location", "Location" ) << "</th>" << endl;
00411 ++columns;
00412 }
00413 if ( d->mSettings->taskCategories() ) {
00414 *ts << " <th>" << i18nc( "@title:column to-do categories", "Categories" ) << "</th>" << endl;
00415 ++columns;
00416 }
00417 if ( d->mSettings->taskAttendees() ) {
00418 *ts << " <th>" << i18nc( "@title:column to-do attendees", "Attendees" ) << "</th>" << endl;
00419 ++columns;
00420 }
00421 *ts << " </tr>" << endl;
00422
00423
00424 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
00425 if ( !(*it)->relatedTo() ) {
00426 createTodo( ts, *it );
00427 }
00428 }
00429
00430
00431 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
00432 Incidence::List relations = (*it)->relations();
00433 if ( relations.count() ) {
00434
00435 *ts << " <tr>" << endl;
00436 *ts << " <td class=\"subhead\" colspan=";
00437 *ts << "\"" << QString::number(columns) << "\"";
00438 *ts << "><a name=\"sub" << (*it)->uid() << "\"></a>"
00439 << i18nc( "@title:column sub-to-dos of the parent to-do",
00440 "Sub-To-dos of: " ) << "<a href=\"#"
00441 << (*it)->uid() << "\"><b>" << cleanChars( (*it)->summary() )
00442 << "</b></a></td>" << endl;
00443 *ts << " </tr>" << endl;
00444
00445 Todo::List sortedList;
00446
00447
00448 for ( int i = 1; i <= 9; ++i ) {
00449 Incidence::List::ConstIterator it2;
00450 for ( it2 = relations.constBegin(); it2 != relations.constEnd(); ++it2 ) {
00451 Todo *ev3 = dynamic_cast<Todo *>( *it2 );
00452 if ( ev3 && ev3->priority() == i ) {
00453 sortedList.append( ev3 );
00454 }
00455 }
00456 }
00457 Incidence::List::ConstIterator it2;
00458 for ( it2 = relations.constBegin(); it2 != relations.constEnd(); ++it2 ) {
00459 Todo *ev3 = dynamic_cast<Todo *>( *it2 );
00460 if ( ev3 && ev3->priority() == 0 ) {
00461 sortedList.append( ev3 );
00462 }
00463 }
00464
00465 Todo::List::ConstIterator it3;
00466 for ( it3 = sortedList.constBegin(); it3 != sortedList.constEnd(); ++it3 ) {
00467 createTodo( ts, *it3 );
00468 }
00469 }
00470 }
00471
00472 *ts << "</table>" << endl;
00473 }
00474
00475 void HtmlExport::createTodo( QTextStream *ts, Todo *todo )
00476 {
00477 kDebug();
00478
00479 bool completed = todo->isCompleted();
00480 Incidence::List relations = todo->relations();
00481
00482 *ts << "<tr>" << endl;
00483
00484 *ts << " <td class=\"sum";
00485 if (completed) *ts << "done";
00486 *ts << "\">" << endl;
00487 *ts << " <a name=\"" << todo->uid() << "\"></a>" << endl;
00488 *ts << " <b>" << cleanChars( todo->summary() ) << "</b>" << endl;
00489 if ( !todo->description().isEmpty() ) {
00490 *ts << " <p>" << breakString( cleanChars( todo->description() ) ) << "</p>" << endl;
00491 }
00492 if ( relations.count() ) {
00493 *ts << " <div align=\"right\"><a href=\"#sub" << todo->uid()
00494 << "\">" << i18nc( "@title:column sub-to-dos of the parent to-do",
00495 "Sub-To-dos" ) << "</a></div>" << endl;
00496 }
00497 *ts << " </td>" << endl;
00498
00499 *ts << " <td";
00500 if ( completed ) {
00501 *ts << " class=\"done\"";
00502 }
00503 *ts << ">" << endl;
00504 *ts << " " << todo->priority() << endl;
00505 *ts << " </td>" << endl;
00506
00507 *ts << " <td";
00508 if ( completed ) {
00509 *ts << " class=\"done\"";
00510 }
00511 *ts << ">" << endl;
00512 *ts << " " << i18nc( "@info/plain to-do percent complete",
00513 "%1 %", todo->percentComplete() ) << endl;
00514 *ts << " </td>" << endl;
00515
00516 if ( d->mSettings->taskDueDate() ) {
00517 *ts << " <td";
00518 if ( completed ) {
00519 *ts << " class=\"done\"";
00520 }
00521 *ts << ">" << endl;
00522 if ( todo->hasDueDate() ) {
00523 *ts << " " << IncidenceFormatter::dateToString( todo->dtDue( true ) ) << endl;
00524 } else {
00525 *ts << " " << endl;
00526 }
00527 *ts << " </td>" << endl;
00528 }
00529
00530 if ( d->mSettings->taskLocation() ) {
00531 *ts << " <td";
00532 if ( completed ) {
00533 *ts << " class=\"done\"";
00534 }
00535 *ts << ">" << endl;
00536 formatLocation( ts, todo );
00537 *ts << " </td>" << endl;
00538 }
00539
00540 if ( d->mSettings->taskCategories() ) {
00541 *ts << " <td";
00542 if ( completed ) {
00543 *ts << " class=\"done\"";
00544 }
00545 *ts << ">" << endl;
00546 formatCategories( ts, todo );
00547 *ts << " </td>" << endl;
00548 }
00549
00550 if ( d->mSettings->taskAttendees() ) {
00551 *ts << " <td";
00552 if ( completed ) {
00553 *ts << " class=\"done\"";
00554 }
00555 *ts << ">" << endl;
00556 formatAttendees( ts, todo );
00557 *ts << " </td>" << endl;
00558 }
00559
00560 *ts << "</tr>" << endl;
00561 }
00562
00563 void HtmlExport::createWeekView( QTextStream *ts )
00564 {
00565 Q_UNUSED( ts );
00566
00567 }
00568
00569 void HtmlExport::createJournalView( QTextStream *ts )
00570 {
00571 Q_UNUSED( ts );
00572
00573
00574 }
00575
00576 void HtmlExport::createFreeBusyView( QTextStream *ts )
00577 {
00578 Q_UNUSED( ts );
00579
00580 }
00581
00582 bool HtmlExport::checkSecrecy( Incidence *incidence )
00583 {
00584 int secrecy = incidence->secrecy();
00585 if ( secrecy == Incidence::SecrecyPublic ) {
00586 return true;
00587 }
00588 if ( secrecy == Incidence::SecrecyPrivate && !d->mSettings->excludePrivate() ) {
00589 return true;
00590 }
00591 if ( secrecy == Incidence::SecrecyConfidential &&
00592 !d->mSettings->excludeConfidential() ) {
00593 return true;
00594 }
00595 return false;
00596 }
00597
00598 void HtmlExport::formatLocation( QTextStream *ts, Incidence *incidence )
00599 {
00600 if ( !incidence->location().isEmpty() ) {
00601 *ts << " " << cleanChars( incidence->location() ) << endl;
00602 } else {
00603 *ts << " " << endl;
00604 }
00605 }
00606
00607 void HtmlExport::formatCategories( QTextStream *ts, Incidence *incidence )
00608 {
00609 if ( !incidence->categoriesStr().isEmpty() ) {
00610 *ts << " " << cleanChars( incidence->categoriesStr() ) << endl;
00611 } else {
00612 *ts << " " << endl;
00613 }
00614 }
00615
00616 void HtmlExport::formatAttendees( QTextStream *ts, Incidence *incidence )
00617 {
00618 Attendee::List attendees = incidence->attendees();
00619 if ( attendees.count() ) {
00620 *ts << "<em>";
00621 #if !defined(KORG_NOKABC) && !defined(KDEPIM_NO_KRESOURCES)
00622 KABC::AddressBook *add_book = KABC::StdAddressBook::self( true );
00623 KABC::Addressee::List addressList;
00624 addressList = add_book->findByEmail( incidence->organizer().email() );
00625 if ( !addressList.isEmpty() ) {
00626 KABC::Addressee o = addressList.first();
00627 if ( !o.isEmpty() && addressList.size() < 2 ) {
00628 *ts << "<a href=\"mailto:" << incidence->organizer().email() << "\">";
00629 *ts << cleanChars( o.formattedName() ) << "</a>" << endl;
00630 } else {
00631 *ts << incidence->organizer().fullName();
00632 }
00633 }
00634 #else
00635 *ts << incidence->organizer().fullName();
00636 #endif
00637 *ts << "</em><br />";
00638 Attendee::List::ConstIterator it;
00639 for ( it = attendees.constBegin(); it != attendees.constEnd(); ++it ) {
00640 Attendee *a = *it;
00641 if ( !a->email().isEmpty() ) {
00642 *ts << "<a href=\"mailto:" << a->email();
00643 *ts << "\">" << cleanChars( a->name() ) << "</a>";
00644 } else {
00645 *ts << " " << cleanChars( a->name() );
00646 }
00647 *ts << "<br />" << endl;
00648 }
00649 } else {
00650 *ts << " " << endl;
00651 }
00652 }
00653
00654 QString HtmlExport::breakString( const QString &text )
00655 {
00656 int number = text.count( "\n" );
00657 if ( number <= 0 ) {
00658 return text;
00659 } else {
00660 QString out;
00661 QString tmpText = text;
00662 int pos = 0;
00663 QString tmp;
00664 for ( int i = 0; i <= number; ++i ) {
00665 pos = tmpText.indexOf( "\n" );
00666 tmp = tmpText.left( pos );
00667 tmpText = tmpText.right( tmpText.length() - pos - 1 );
00668 out += tmp + "<br />";
00669 }
00670 return out;
00671 }
00672 }
00673
00674 void HtmlExport::createFooter( QTextStream *ts )
00675 {
00676
00677 QString trailer = i18nc( "@info/plain", "This page was created " );
00678
00679
00680
00681
00682
00683 if ( !d->mSettings->eMail().isEmpty() ) {
00684 if ( !d->mSettings->name().isEmpty() ) {
00685 trailer += i18nc( "@info/plain page creator email link with name",
00686 "by <link url='mailto:%1'>%2</link>",
00687 d->mSettings->eMail(), d->mSettings->name() );
00688 } else {
00689 trailer += i18nc( "@info/plain page creator email link",
00690 "by <link url='mailto:%1'>%2</link>",
00691 d->mSettings->eMail(), d->mSettings->eMail() );
00692 }
00693 } else {
00694 if ( !d->mSettings->name().isEmpty() ) {
00695 trailer += i18nc( "@info/plain page creator name only",
00696 "by %1 ", d->mSettings->name() );
00697 }
00698 }
00699 if ( !d->mSettings->creditName().isEmpty() ) {
00700 if ( !d->mSettings->creditURL().isEmpty() ) {
00701 trailer += i18nc( "@info/plain page credit with name and link",
00702 "with <link url='%1'>%2</link>",
00703 d->mSettings->creditURL(), d->mSettings->creditName() );
00704 } else {
00705 trailer += i18nc( "@info/plain page credit name only",
00706 "with %1", d->mSettings->creditName() );
00707 }
00708 }
00709 *ts << "<p>" << trailer << "</p>" << endl;
00710 }
00711
00712 QString cleanChars( const QString &text )
00713 {
00714 QString txt = text;
00715 txt = txt.replace( '&', "&" );
00716 txt = txt.replace( '<', "<" );
00717 txt = txt.replace( '>', ">" );
00718 txt = txt.replace( '\"', """ );
00719 txt = txt.replace( QString::fromUtf8( "ä" ), "ä" );
00720 txt = txt.replace( QString::fromUtf8( "Ä" ), "Ä" );
00721 txt = txt.replace( QString::fromUtf8( "ö" ), "ö" );
00722 txt = txt.replace( QString::fromUtf8( "Ö" ), "Ö" );
00723 txt = txt.replace( QString::fromUtf8( "ü" ), "ü" );
00724 txt = txt.replace( QString::fromUtf8( "Ü" ), "Ü" );
00725 txt = txt.replace( QString::fromUtf8( "ß" ), "ß" );
00726 txt = txt.replace( QString::fromUtf8( "€" ), "€" );
00727 txt = txt.replace( QString::fromUtf8( "é" ), "é" );
00728
00729 return txt;
00730 }
00731
00732 QString HtmlExport::styleSheet() const
00733 {
00734 if ( !d->mSettings->styleSheet().isEmpty() ) {
00735 return d->mSettings->styleSheet();
00736 }
00737
00738 QString css;
00739
00740 if ( QApplication::isRightToLeft() ) {
00741 css += " body { background-color:white; color:black; direction: rtl }\n";
00742 css += " td { text-align:center; background-color:#eee }\n";
00743 css += " th { text-align:center; background-color:#228; color:white }\n";
00744 css += " td.sumdone { background-color:#ccc }\n";
00745 css += " td.done { background-color:#ccc }\n";
00746 css += " td.subhead { text-align:center; background-color:#ccf }\n";
00747 css += " td.datehead { text-align:center; background-color:#ccf }\n";
00748 css += " td.space { background-color:white }\n";
00749 css += " td.dateholiday { color:red }\n";
00750 } else {
00751 css += " body { background-color:white; color:black }\n";
00752 css += " td { text-align:center; background-color:#eee }\n";
00753 css += " th { text-align:center; background-color:#228; color:white }\n";
00754 css += " td.sum { text-align:left }\n";
00755 css += " td.sumdone { text-align:left; background-color:#ccc }\n";
00756 css += " td.done { background-color:#ccc }\n";
00757 css += " td.subhead { text-align:center; background-color:#ccf }\n";
00758 css += " td.datehead { text-align:center; background-color:#ccf }\n";
00759 css += " td.space { background-color:white }\n";
00760 css += " td.date { text-align:left }\n";
00761 css += " td.dateholiday { text-align:left; color:red }\n";
00762 }
00763
00764 return css;
00765 }
00766
00767 void HtmlExport::addHoliday( const QDate &date, const QString &name )
00768 {
00769 if ( d->mHolidayMap[date].isEmpty() ) {
00770 d->mHolidayMap[date] = name;
00771 } else {
00772 d->mHolidayMap[date] = i18nc( "@info/plain holiday by date and name",
00773 "%1, %2", d->mHolidayMap[date], name );
00774 }
00775 }
00776
00777 QDate HtmlExport::fromDate() const
00778 {
00779 return d->mSettings->dateStart().date();
00780 }
00781
00782 QDate HtmlExport::toDate() const
00783 {
00784 return d->mSettings->dateEnd().date();
00785 }