KCal Library
htmlexport.cpp
00001 /* 00002 This file is part of the kcal 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 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 //@cond PRIVATE 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 //@endcond 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 // Write HTML header 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 // FIXME: Write header 00115 // (Heading, Calendar-Owner, Calendar-Date, ...) 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 // Write Week View 00123 if ( d->mSettings->weekView() ) { 00124 createWeekView( ts ); 00125 } 00126 // Write Month View 00127 if ( d->mSettings->monthView() ) { 00128 createMonthView( ts ); 00129 } 00130 // Write Event List 00131 if ( d->mSettings->eventView() ) { 00132 createEventList( ts ); 00133 } 00134 } 00135 00136 // Write Todo List 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 // Write Journals 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 // Write Free/Busy 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 // Write HTML trailer 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 ); // go back to first day in month 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 // Write header 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 // Write table header 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 // Write days 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 // Only print events within the from-to range 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 location", 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 // FIXME: Sort list by priorities. This is brute force and should be 00382 // replaced by a real sorting algorithm. 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 // Create top-level list. 00424 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) { 00425 if ( !(*it)->relatedTo() ) { 00426 createTodo( ts, *it ); 00427 } 00428 } 00429 00430 // Create sub-level lists 00431 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) { 00432 Incidence::List relations = (*it)->relations(); 00433 if ( relations.count() ) { 00434 // Generate sub-to-do list 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 // FIXME: Sort list by priorities. This is brute force and should be 00447 // replaced by a real sorting algorithm. 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 // 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( 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 // FIXME: Implement this in a translatable way! 00677 QString trailer = i18nc( "@info/plain", "This page was created " ); 00678 00679 /* bool hasPerson = false; 00680 bool hasCredit = false; 00681 bool hasCreditURL = false; 00682 QString mail, name, credit, creditURL;*/ 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 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Apr 30 2012 21:49:42 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Apr 30 2012 21:49:42 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.