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