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