KCalUtils Library
htmlexport.cpp
00001 /* 00002 This file is part of the kcalutils library. 00003 00004 Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> 00005 Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 */ 00022 #include "htmlexport.h" 00023 #include "htmlexportsettings.h" 00024 #include "stringify.h" 00025 00026 #include <kcalcore/memorycalendar.h> 00027 using namespace KCalCore; 00028 00029 #include <KDebug> 00030 #include <KCalendarSystem> 00031 #include <KGlobal> 00032 #include <KLocale> 00033 00034 #include <QtCore/QFile> 00035 #include <QtCore/QMap> 00036 #include <QtCore/QTextStream> 00037 #include <QtGui/QApplication> 00038 00039 using namespace KCalUtils; 00040 00041 static QString cleanChars( const QString &txt ); 00042 00043 //@cond PRIVATE 00044 class KCalUtils::HtmlExport::Private 00045 { 00046 public: 00047 Private( MemoryCalendar *calendar, HTMLExportSettings *settings ) 00048 : mCalendar( calendar ), mSettings( settings ) 00049 {} 00050 00051 MemoryCalendar *mCalendar; 00052 HTMLExportSettings *mSettings; 00053 QMap<QDate,QString> mHolidayMap; 00054 }; 00055 //@endcond 00056 00057 HtmlExport::HtmlExport( MemoryCalendar *calendar, HTMLExportSettings *settings ) 00058 : d( new Private( calendar, settings ) ) 00059 { 00060 } 00061 00062 HtmlExport::~HtmlExport() 00063 { 00064 delete d; 00065 } 00066 00067 bool HtmlExport::save( const QString &fileName ) 00068 { 00069 QString fn( fileName ); 00070 if ( fn.isEmpty() && d->mSettings ) { 00071 fn = d->mSettings->outputFile(); 00072 } 00073 if ( !d->mSettings || fn.isEmpty() ) { 00074 return false; 00075 } 00076 QFile f( fileName ); 00077 if ( !f.open( QIODevice::WriteOnly ) ) { 00078 return false; 00079 } 00080 QTextStream ts( &f ); 00081 bool success = save( &ts ); 00082 f.close(); 00083 return success; 00084 } 00085 00086 bool HtmlExport::save( QTextStream *ts ) 00087 { 00088 if ( !d->mSettings ) { 00089 return false; 00090 } 00091 ts->setCodec( "UTF-8" ); 00092 // Write HTML header 00093 *ts << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "; 00094 *ts << "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl; 00095 00096 *ts << "<html><head>" << endl; 00097 *ts << " <meta http-equiv=\"Content-Type\" content=\"text/html; charset="; 00098 *ts << "UTF-8\" />" << endl; 00099 if ( !d->mSettings->pageTitle().isEmpty() ) { 00100 *ts << " <title>" << d->mSettings->pageTitle() << "</title>" << endl; 00101 } 00102 *ts << " <style type=\"text/css\">" << endl; 00103 *ts << styleSheet(); 00104 *ts << " </style>" << endl; 00105 *ts << "</head><body>" << endl; 00106 00107 // FIXME: Write header 00108 // (Heading, Calendar-Owner, Calendar-Date, ...) 00109 00110 if ( d->mSettings->eventView() || d->mSettings->monthView() || d->mSettings->weekView() ) { 00111 if ( !d->mSettings->eventTitle().isEmpty() ) { 00112 *ts << "<h1>" << d->mSettings->eventTitle() << "</h1>" << endl; 00113 } 00114 00115 // Write Week View 00116 if ( d->mSettings->weekView() ) { 00117 createWeekView( ts ); 00118 } 00119 // Write Month View 00120 if ( d->mSettings->monthView() ) { 00121 createMonthView( ts ); 00122 } 00123 // Write Event List 00124 if ( d->mSettings->eventView() ) { 00125 createEventList( ts ); 00126 } 00127 } 00128 00129 // Write Todo List 00130 if ( d->mSettings->todoView() ) { 00131 if ( !d->mSettings->todoListTitle().isEmpty() ) { 00132 *ts << "<h1>" << d->mSettings->todoListTitle() << "</h1>" << endl; 00133 } 00134 createTodoList( ts ); 00135 } 00136 00137 // Write Journals 00138 if ( d->mSettings->journalView() ) { 00139 if ( !d->mSettings->journalTitle().isEmpty() ) { 00140 *ts << "<h1>" << d->mSettings->journalTitle() << "</h1>" << endl; 00141 } 00142 createJournalView( ts ); 00143 } 00144 00145 // Write Free/Busy 00146 if ( d->mSettings->freeBusyView() ) { 00147 if ( !d->mSettings->freeBusyTitle().isEmpty() ) { 00148 *ts << "<h1>" << d->mSettings->freeBusyTitle() << "</h1>" << endl; 00149 } 00150 createFreeBusyView( ts ); 00151 } 00152 00153 createFooter( ts ); 00154 00155 // Write HTML trailer 00156 *ts << "</body></html>" << endl; 00157 00158 return true; 00159 } 00160 00161 void HtmlExport::createMonthView( QTextStream *ts ) 00162 { 00163 QDate start = fromDate(); 00164 start.setYMD( start.year(), start.month(), 1 ); // go back to first day in month 00165 00166 QDate end( start.year(), start.month(), start.daysInMonth() ); 00167 00168 int startmonth = start.month(); 00169 int startyear = start.year(); 00170 00171 while ( start < toDate() ) { 00172 // Write header 00173 QDate hDate( start.year(), start.month(), 1 ); 00174 QString hMon = hDate.toString( "MMMM" ); 00175 QString hYear = hDate.toString( "yyyy" ); 00176 *ts << "<h2>" 00177 << i18nc( "@title month and year", "%1 %2", hMon, hYear ) 00178 << "</h2>" << endl; 00179 if ( KGlobal::locale()->weekStartDay() == 1 ) { 00180 start = start.addDays( 1 - start.dayOfWeek() ); 00181 } else { 00182 if ( start.dayOfWeek() != 7 ) { 00183 start = start.addDays( -start.dayOfWeek() ); 00184 } 00185 } 00186 *ts << "<table border=\"1\">" << endl; 00187 00188 // Write table header 00189 *ts << " <tr>"; 00190 for ( int i=0; i < 7; ++i ) { 00191 *ts << "<th>" << KGlobal::locale()->calendar()->weekDayName( start.addDays(i) ) << "</th>"; 00192 } 00193 *ts << "</tr>" << endl; 00194 00195 // Write days 00196 while ( start <= end ) { 00197 *ts << " <tr>" << endl; 00198 for ( int i=0; i < 7; ++i ) { 00199 *ts << " <td valign=\"top\"><table border=\"0\">"; 00200 00201 *ts << "<tr><td "; 00202 if ( d->mHolidayMap.contains( start ) || start.dayOfWeek() == 7 ) { 00203 *ts << "class=\"dateholiday\""; 00204 } else { 00205 *ts << "class=\"date\""; 00206 } 00207 *ts << ">" << QString::number( start.day() ); 00208 00209 if ( d->mHolidayMap.contains( start ) ) { 00210 *ts << " <em>" << d->mHolidayMap[start] << "</em>"; 00211 } 00212 00213 *ts << "</td></tr><tr><td valign=\"top\">"; 00214 00215 // Only print events within the from-to range 00216 if ( start >= fromDate() && start <= toDate() ) { 00217 Event::List events = d->mCalendar->events( start, d->mCalendar->timeSpec(), 00218 EventSortStartDate, 00219 SortDirectionAscending ); 00220 if ( events.count() ) { 00221 *ts << "<table>"; 00222 Event::List::ConstIterator it; 00223 for ( it = events.constBegin(); it != events.constEnd(); ++it ) { 00224 if ( checkSecrecy( *it ) ) { 00225 createEvent( ts, *it, start, false ); 00226 } 00227 } 00228 *ts << "</table>"; 00229 } else { 00230 *ts << " "; 00231 } 00232 } 00233 00234 *ts << "</td></tr></table></td>" << endl; 00235 start = start.addDays( 1 ); 00236 } 00237 *ts << " </tr>" << endl; 00238 } 00239 *ts << "</table>" << endl; 00240 startmonth += 1; 00241 if ( startmonth > 12 ) { 00242 startyear += 1; 00243 startmonth = 1; 00244 } 00245 start.setYMD( startyear, startmonth, 1 ); 00246 end.setYMD( start.year(), start.month(), start.daysInMonth() ); 00247 } 00248 } 00249 00250 void HtmlExport::createEventList( QTextStream *ts ) 00251 { 00252 int columns = 3; 00253 *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">" << endl; 00254 *ts << " <tr>" << endl; 00255 *ts << " <th class=\"sum\">" << i18nc( "@title:column event start time", 00256 "Start Time" ) << "</th>" << endl; 00257 *ts << " <th>" << i18nc( "@title:column event end time", 00258 "End Time" ) << "</th>" << endl; 00259 *ts << " <th>" << i18nc( "@title:column event description", 00260 "Event" ) << "</th>" << endl; 00261 if ( d->mSettings->eventLocation() ) { 00262 *ts << " <th>" << i18nc( "@title:column event locatin", 00263 "Location" ) << "</th>" << endl; 00264 ++columns; 00265 } 00266 if ( d->mSettings->eventCategories() ) { 00267 *ts << " <th>" << i18nc( "@title:column event categories", 00268 "Categories" ) << "</th>" << endl; 00269 ++columns; 00270 } 00271 if ( d->mSettings->eventAttendees() ) { 00272 *ts << " <th>" << i18nc( "@title:column event attendees", 00273 "Attendees" ) << "</th>" << endl; 00274 ++columns; 00275 } 00276 00277 *ts << " </tr>" << endl; 00278 00279 for ( QDate dt = fromDate(); dt <= toDate(); dt = dt.addDays(1) ) { 00280 kDebug() << "Getting events for" << dt.toString(); 00281 Event::List events = d->mCalendar->events( dt, d->mCalendar->timeSpec(), 00282 EventSortStartDate, 00283 SortDirectionAscending ); 00284 if ( events.count() ) { 00285 *ts << " <tr><td colspan=\"" << QString::number( columns ) 00286 << "\" class=\"datehead\"><i>" 00287 << KGlobal::locale()->formatDate( dt ) 00288 << "</i></td></tr>" << endl; 00289 00290 Event::List::ConstIterator it; 00291 for ( it = events.constBegin(); it != events.constEnd(); ++it ) { 00292 if ( checkSecrecy( *it ) ) { 00293 createEvent( ts, *it, dt ); 00294 } 00295 } 00296 } 00297 } 00298 00299 *ts << "</table>" << endl; 00300 } 00301 00302 void HtmlExport::createEvent ( QTextStream *ts, 00303 const Event::Ptr &event, 00304 const QDate &date, 00305 bool withDescription ) 00306 { 00307 kDebug() << event->summary(); 00308 *ts << " <tr>" << endl; 00309 00310 if ( !event->allDay() ) { 00311 if ( event->isMultiDay( d->mCalendar->timeSpec() ) && ( event->dtStart().date() != date ) ) { 00312 *ts << " <td> </td>" << endl; 00313 } else { 00314 *ts << " <td valign=\"top\">" 00315 << Stringify::formatTime( event->dtStart(), true, d->mCalendar->timeSpec() ) 00316 << "</td>" << endl; 00317 } 00318 if ( event->isMultiDay( d->mCalendar->timeSpec() ) && ( event->dtEnd().date() != date ) ) { 00319 *ts << " <td> </td>" << endl; 00320 } else { 00321 *ts << " <td valign=\"top\">" 00322 << Stringify::formatTime( event->dtEnd(), true, d->mCalendar->timeSpec() ) 00323 << "</td>" << endl; 00324 } 00325 } else { 00326 *ts << " <td> </td><td> </td>" << endl; 00327 } 00328 00329 *ts << " <td class=\"sum\">" << endl; 00330 *ts << " <b>" << cleanChars( event->summary() ) << "</b>" << endl; 00331 if ( withDescription && !event->description().isEmpty() ) { 00332 *ts << " <p>" << breakString( cleanChars( event->description() ) ) << "</p>" << endl; 00333 } 00334 *ts << " </td>" << endl; 00335 00336 if ( d->mSettings->eventLocation() ) { 00337 *ts << " <td>" << endl; 00338 formatLocation( ts, event ); 00339 *ts << " </td>" << endl; 00340 } 00341 00342 if ( d->mSettings->eventCategories() ) { 00343 *ts << " <td>" << endl; 00344 formatCategories( ts, event ); 00345 *ts << " </td>" << endl; 00346 } 00347 00348 if ( d->mSettings->eventAttendees() ) { 00349 *ts << " <td>" << endl; 00350 formatAttendees( ts, event ); 00351 *ts << " </td>" << endl; 00352 } 00353 00354 *ts << " </tr>" << endl; 00355 } 00356 00357 void HtmlExport::createTodoList ( QTextStream *ts ) 00358 { 00359 Todo::List rawTodoList = d->mCalendar->todos(); 00360 00361 int index = 0; 00362 while ( index < rawTodoList.count() ) { 00363 Todo::Ptr ev = rawTodoList[ index ]; 00364 Todo::Ptr subev = ev; 00365 const QString uid = ev->relatedTo(); 00366 if ( !uid.isEmpty() ) { 00367 Incidence::Ptr inc = d->mCalendar->incidence( uid ); 00368 if ( inc && inc->type() == Incidence::TypeTodo ) { 00369 Todo::Ptr todo = inc.staticCast<Todo>(); 00370 if ( !rawTodoList.contains( todo ) ) { 00371 rawTodoList.append( todo ); 00372 } 00373 } 00374 } 00375 index = rawTodoList.indexOf( subev ); 00376 ++index; 00377 } 00378 00379 // FIXME: Sort list by priorities. This is brute force and should be 00380 // replaced by a real sorting algorithm. 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\">" << endl; 00398 *ts << " <tr>" << endl; 00399 *ts << " <th class=\"sum\">" << i18nc( "@title:column", "To-do" ) << "</th>" << endl; 00400 *ts << " <th>" << i18nc( "@title:column to-do priority", "Priority" ) << "</th>" << endl; 00401 *ts << " <th>" << i18nc( "@title:column to-do percent completed", 00402 "Completed" ) << "</th>" << endl; 00403 if ( d->mSettings->taskDueDate() ) { 00404 *ts << " <th>" << i18nc( "@title:column to-do due date", "Due Date" ) << "</th>" << endl; 00405 ++columns; 00406 } 00407 if ( d->mSettings->taskLocation() ) { 00408 *ts << " <th>" << i18nc( "@title:column to-do location", "Location" ) << "</th>" << endl; 00409 ++columns; 00410 } 00411 if ( d->mSettings->taskCategories() ) { 00412 *ts << " <th>" << i18nc( "@title:column to-do categories", "Categories" ) << "</th>" << endl; 00413 ++columns; 00414 } 00415 if ( d->mSettings->taskAttendees() ) { 00416 *ts << " <th>" << i18nc( "@title:column to-do attendees", "Attendees" ) << "</th>" << endl; 00417 ++columns; 00418 } 00419 *ts << " </tr>" << endl; 00420 00421 // Create top-level list. 00422 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) { 00423 if ( (*it)->relatedTo().isEmpty() ) { 00424 createTodo( ts, *it ); 00425 } 00426 } 00427 00428 // Create sub-level lists 00429 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) { 00430 Incidence::List relations = d->mCalendar->relations( ( *it )->uid() ); 00431 00432 if ( relations.count() ) { 00433 // Generate sub-to-do list 00434 *ts << " <tr>" << endl; 00435 *ts << " <td class=\"subhead\" colspan="; 00436 *ts << "\"" << QString::number(columns) << "\""; 00437 *ts << "><a name=\"sub" << (*it)->uid() << "\"></a>" 00438 << i18nc( "@title:column sub-to-dos of the parent to-do", 00439 "Sub-To-dos of: " ) << "<a href=\"#" 00440 << (*it)->uid() << "\"><b>" << cleanChars( (*it)->summary() ) 00441 << "</b></a></td>" << endl; 00442 *ts << " </tr>" << endl; 00443 00444 Todo::List sortedList; 00445 // FIXME: Sort list by priorities. This is brute force and should be 00446 // replaced by a real sorting algorithm. 00447 for ( int i = 1; i <= 9; ++i ) { 00448 Incidence::List::ConstIterator it2; 00449 for ( it2 = relations.constBegin(); it2 != relations.constEnd(); ++it2 ) { 00450 Todo::Ptr ev3 = (*it2).staticCast<Todo>(); 00451 if ( ev3 && ev3->priority() == i ) { 00452 sortedList.append( ev3 ); 00453 } 00454 } 00455 } 00456 Incidence::List::ConstIterator it2; 00457 for ( it2 = relations.constBegin(); it2 != relations.constEnd(); ++it2 ) { 00458 Todo::Ptr ev3 = (*it2).staticCast<Todo>(); 00459 if ( ev3 && ev3->priority() == 0 ) { 00460 sortedList.append( ev3 ); 00461 } 00462 } 00463 00464 Todo::List::ConstIterator it3; 00465 for ( it3 = sortedList.constBegin(); it3 != sortedList.constEnd(); ++it3 ) { 00466 createTodo( ts, *it3 ); 00467 } 00468 } 00469 } 00470 00471 *ts << "</table>" << endl; 00472 } 00473 00474 void HtmlExport::createTodo( QTextStream *ts, const Todo::Ptr &todo ) 00475 { 00476 kDebug(); 00477 00478 const bool completed = todo->isCompleted(); 00479 00480 Incidence::List relations = d->mCalendar->relations( todo->uid() ); 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 << " " << Stringify::formatDate( 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 // FIXME: Implement this! 00567 } 00568 00569 void HtmlExport::createJournalView( QTextStream *ts ) 00570 { 00571 Q_UNUSED( ts ); 00572 // Journal::List rawJournalList = d->mCalendar->journals(); 00573 // FIXME: Implement this! 00574 } 00575 00576 void HtmlExport::createFreeBusyView( QTextStream *ts ) 00577 { 00578 Q_UNUSED( ts ); 00579 // FIXME: Implement this! 00580 } 00581 00582 bool HtmlExport::checkSecrecy( const Incidence::Ptr &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, 00599 const Incidence::Ptr &incidence ) 00600 { 00601 if ( !incidence->location().isEmpty() ) { 00602 *ts << " " << cleanChars( incidence->location() ) << endl; 00603 } else { 00604 *ts << " " << endl; 00605 } 00606 } 00607 00608 void HtmlExport::formatCategories( QTextStream *ts, 00609 const Incidence::Ptr &incidence ) 00610 { 00611 if ( !incidence->categoriesStr().isEmpty() ) { 00612 *ts << " " << cleanChars( incidence->categoriesStr() ) << endl; 00613 } else { 00614 *ts << " " << endl; 00615 } 00616 } 00617 00618 void HtmlExport::formatAttendees( QTextStream *ts, 00619 const Incidence::Ptr &incidence ) 00620 { 00621 Attendee::List attendees = incidence->attendees(); 00622 if ( attendees.count() ) { 00623 *ts << "<em>"; 00624 *ts << incidence->organizer()->fullName(); 00625 *ts << "</em><br />"; 00626 Attendee::List::ConstIterator it; 00627 for ( it = attendees.constBegin(); it != attendees.constEnd(); ++it ) { 00628 Attendee::Ptr a( *it ); 00629 if ( !a->email().isEmpty() ) { 00630 *ts << "<a href=\"mailto:" << a->email(); 00631 *ts << "\">" << cleanChars( a->name() ) << "</a>"; 00632 } else { 00633 *ts << " " << cleanChars( a->name() ); 00634 } 00635 *ts << "<br />" << endl; 00636 } 00637 } else { 00638 *ts << " " << endl; 00639 } 00640 } 00641 00642 QString HtmlExport::breakString( const QString &text ) 00643 { 00644 int number = text.count( "\n" ); 00645 if ( number <= 0 ) { 00646 return text; 00647 } else { 00648 QString out; 00649 QString tmpText = text; 00650 int pos = 0; 00651 QString tmp; 00652 for ( int i = 0; i <= number; ++i ) { 00653 pos = tmpText.indexOf( "\n" ); 00654 tmp = tmpText.left( pos ); 00655 tmpText = tmpText.right( tmpText.length() - pos - 1 ); 00656 out += tmp + "<br />"; 00657 } 00658 return out; 00659 } 00660 } 00661 00662 void HtmlExport::createFooter( QTextStream *ts ) 00663 { 00664 // FIXME: Implement this in a translatable way! 00665 QString trailer = i18nc( "@info/plain", "This page was created " ); 00666 00667 /* bool hasPerson = false; 00668 bool hasCredit = false; 00669 bool hasCreditURL = false; 00670 QString mail, name, credit, creditURL;*/ 00671 if ( !d->mSettings->eMail().isEmpty() ) { 00672 if ( !d->mSettings->name().isEmpty() ) { 00673 trailer += i18nc( "@info/plain page creator email link with name", 00674 "by <link url='mailto:%1'>%2</link> ", 00675 d->mSettings->eMail(), d->mSettings->name() ); 00676 } else { 00677 trailer += i18nc( "@info/plain page creator email link", 00678 "by <link url='mailto:%1'>%2</link> ", 00679 d->mSettings->eMail(), d->mSettings->eMail() ); 00680 } 00681 } else { 00682 if ( !d->mSettings->name().isEmpty() ) { 00683 trailer += i18nc( "@info/plain page creator name only", 00684 "by %1 ", d->mSettings->name() ); 00685 } 00686 } 00687 if ( !d->mSettings->creditName().isEmpty() ) { 00688 if ( !d->mSettings->creditURL().isEmpty() ) { 00689 trailer += i18nc( "@info/plain page credit with name and link", 00690 "with <link url='%1'>%2</link>", 00691 d->mSettings->creditURL(), d->mSettings->creditName() ); 00692 } else { 00693 trailer += i18nc( "@info/plain page credit name only", 00694 "with %1", d->mSettings->creditName() ); 00695 } 00696 } 00697 *ts << "<p>" << trailer << "</p>" << endl; 00698 } 00699 00700 QString cleanChars( const QString &text ) 00701 { 00702 QString txt = text; 00703 txt = txt.replace( '&', "&" ); 00704 txt = txt.replace( '<', "<" ); 00705 txt = txt.replace( '>', ">" ); 00706 txt = txt.replace( '\"', """ ); 00707 txt = txt.replace( QString::fromUtf8( "ä" ), "ä" ); 00708 txt = txt.replace( QString::fromUtf8( "Ä" ), "Ä" ); 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 00717 return txt; 00718 } 00719 00720 QString HtmlExport::styleSheet() const 00721 { 00722 if ( !d->mSettings->styleSheet().isEmpty() ) { 00723 return d->mSettings->styleSheet(); 00724 } 00725 00726 QString css; 00727 00728 if ( QApplication::isRightToLeft() ) { 00729 css += " body { background-color:white; color:black; direction: rtl }\n"; 00730 css += " td { text-align:center; background-color:#eee }\n"; 00731 css += " th { text-align:center; background-color:#228; color:white }\n"; 00732 css += " td.sumdone { background-color:#ccc }\n"; 00733 css += " td.done { background-color:#ccc }\n"; 00734 css += " td.subhead { text-align:center; background-color:#ccf }\n"; 00735 css += " td.datehead { text-align:center; background-color:#ccf }\n"; 00736 css += " td.space { background-color:white }\n"; 00737 css += " td.dateholiday { color:red }\n"; 00738 } else { 00739 css += " body { background-color:white; color:black }\n"; 00740 css += " td { text-align:center; background-color:#eee }\n"; 00741 css += " th { text-align:center; background-color:#228; color:white }\n"; 00742 css += " td.sum { text-align:left }\n"; 00743 css += " td.sumdone { text-align:left; background-color:#ccc }\n"; 00744 css += " td.done { background-color:#ccc }\n"; 00745 css += " td.subhead { text-align:center; background-color:#ccf }\n"; 00746 css += " td.datehead { text-align:center; background-color:#ccf }\n"; 00747 css += " td.space { background-color:white }\n"; 00748 css += " td.date { text-align:left }\n"; 00749 css += " td.dateholiday { text-align:left; color:red }\n"; 00750 } 00751 00752 return css; 00753 } 00754 00755 void HtmlExport::addHoliday( const QDate &date, const QString &name ) 00756 { 00757 if ( d->mHolidayMap[date].isEmpty() ) { 00758 d->mHolidayMap[date] = name; 00759 } else { 00760 d->mHolidayMap[date] = i18nc( "@info/plain holiday by date and name", 00761 "%1, %2", d->mHolidayMap[date], name ); 00762 } 00763 } 00764 00765 QDate HtmlExport::fromDate() const 00766 { 00767 return d->mSettings->dateStart().date(); 00768 } 00769 00770 QDate HtmlExport::toDate() const 00771 { 00772 return d->mSettings->dateEnd().date(); 00773 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 14 2012 04:49:07 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 14 2012 04:49:07 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.