libkcal

htmlexport.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of libkcal.
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 <qapplication.h>
00024 #include <qfile.h>
00025 #include <qtextstream.h>
00026 #include <qtextcodec.h>
00027 #include <qregexp.h>
00028 
00029 #include <kcharsets.h>
00030 #include <kglobal.h>
00031 #include <klocale.h>
00032 #include <kdebug.h>
00033 #include <kcalendarsystem.h>
00034 
00035 #include <libkcal/calendar.h>
00036 #include <libkcal/event.h>
00037 #include <libkcal/todo.h>
00038 
00039 #ifndef KORG_NOKABC
00040  #include <kabc/stdaddressbook.h>
00041 #endif
00042 #include "htmlexport.h"
00043 #include "htmlexportsettings.h"
00044 
00045 using namespace KCal;
00046 
00047 HtmlExport::HtmlExport( Calendar *calendar, HTMLExportSettings *settings ) :
00048   mCalendar( calendar ), mSettings( settings )
00049 {
00050 }
00051 
00052 bool HtmlExport::save( const QString &fileName )
00053 {
00054   QString fn( fileName );
00055   if ( fn.isEmpty() && mSettings ) {
00056     fn = mSettings->outputFile();
00057   }
00058   if ( !mSettings || fn.isEmpty() ) {
00059     return false;
00060   }
00061   QFile f( fileName );
00062   if ( !f.open(IO_WriteOnly)) {
00063     return false;
00064   }
00065   QTextStream ts(&f);
00066   bool success = save(&ts);
00067   f.close();
00068   return success;
00069 }
00070 
00071 bool HtmlExport::save(QTextStream *ts)
00072 {
00073   if ( !mSettings ) return false;
00074   ts->setEncoding( QTextStream::UnicodeUTF8 );
00075 
00076   // Write HTML header
00077   *ts << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" ";
00078   *ts << "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
00079 
00080   *ts << "<html><head>" << endl;
00081   *ts << "  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=";
00082   *ts << "UTF-8\" />\n";
00083   if ( !mSettings->pageTitle().isEmpty())
00084     *ts << "  <title>" << mSettings->pageTitle() << "</title>\n";
00085   *ts << "  <style type=\"text/css\">\n";
00086   *ts << styleSheet();
00087   *ts << "  </style>\n";
00088   *ts << "</head><body>\n";
00089 
00090   // FIXME: Write header
00091   // (Heading, Calendar-Owner, Calendar-Date, ...)
00092 
00093   if ( mSettings->eventView() || mSettings->monthView() || mSettings->weekView() ) {
00094     if (!mSettings->eventTitle().isEmpty())
00095       *ts << "<h1>" << mSettings->eventTitle() << "</h1>\n";
00096 
00097     // Write Week View
00098     if ( mSettings->weekView() )
00099       createWeekView( ts );
00100     // Write Month View
00101     if ( mSettings->monthView() )
00102       createMonthView( ts );
00103     // Write Event List
00104     if ( mSettings->eventView() )
00105       createEventList( ts );
00106   }
00107 
00108   // Write Todo List
00109   if ( mSettings->todoView() ) {
00110     if ( !mSettings->todoListTitle().isEmpty())
00111       *ts << "<h1>" << mSettings->todoListTitle() << "</h1>\n";
00112     createTodoList(ts);
00113   }
00114 
00115   // Write Journals
00116   if ( mSettings->journalView() ) {
00117     if ( !mSettings->journalTitle().isEmpty())
00118       *ts << "<h1>" << mSettings->journalTitle() << "</h1>\n";
00119     createJournalView(ts);
00120   }
00121 
00122   // Write Free/Busy
00123   if ( mSettings->freeBusyView() ) {
00124     if ( !mSettings->freeBusyTitle().isEmpty())
00125       *ts << "<h1>" << mSettings->freeBusyTitle() << "</h1>\n";
00126     createFreeBusyView(ts);
00127   }
00128 
00129   createFooter( ts );
00130 
00131   // Write HTML trailer
00132   *ts << "</body></html>\n";
00133 
00134   return true;
00135 }
00136 
00137 void HtmlExport::createMonthView(QTextStream *ts)
00138 {
00139   QDate start = fromDate();
00140   start.setYMD( start.year(), start.month(), 1 );  // go back to first day in month
00141 
00142   QDate end( start.year(), start.month(), start.daysInMonth() );
00143 
00144   int startmonth = start.month();
00145   int startyear = start.year();
00146 
00147   while ( start < toDate() ) {
00148     // Write header
00149     *ts << "<h2>" << (i18n("month_year","%1 %2").arg(KGlobal::locale()->calendar()->monthName(start))
00150         .arg(start.year())) << "</h2>\n";
00151     if ( KGlobal::locale()->weekStartDay() == 1 ) {
00152       start = start.addDays(1 - start.dayOfWeek());
00153     } else {
00154       if (start.dayOfWeek() != 7) {
00155         start = start.addDays(-start.dayOfWeek());
00156       }
00157     }
00158     *ts << "<table border=\"1\">\n";
00159 
00160     // Write table header
00161     *ts << "  <tr>";
00162     for(int i=0; i<7; ++i) {
00163       *ts << "<th>" << KGlobal::locale()->calendar()->weekDayName( start.addDays(i) ) << "</th>";
00164     }
00165     *ts << "</tr>\n";
00166 
00167     // Write days
00168     while (start <= end) {
00169       *ts << "  <tr>\n";
00170       for(int i=0;i<7;++i) {
00171         *ts << "    <td valign=\"top\"><table border=\"0\">";
00172 
00173         *ts << "<tr><td ";
00174         if (mHolidayMap.contains(start) || start.dayOfWeek() == 7) {
00175           *ts << "class=\"dateholiday\"";
00176         } else {
00177           *ts << "class=\"date\"";
00178         }
00179         *ts << ">" << QString::number(start.day());
00180 
00181         if (mHolidayMap.contains(start)) {
00182           *ts << " <em>" << mHolidayMap[start] << "</em>";
00183         }
00184 
00185         *ts << "</td></tr><tr><td valign=\"top\">";
00186 
00187         Event::List events = mCalendar->events( start,
00188                                                 EventSortStartDate,
00189                                                 SortDirectionAscending );
00190         if (events.count()) {
00191           *ts << "<table>";
00192           Event::List::ConstIterator it;
00193           for( it = events.begin(); it != events.end(); ++it ) {
00194             if ( checkSecrecy( *it ) ) {
00195               createEvent( ts, *it, start, false );
00196             }
00197           }
00198           *ts << "</table>";
00199         } else {
00200           *ts << "&nbsp;";
00201         }
00202 
00203         *ts << "</td></tr></table></td>\n";
00204         start = start.addDays(1);
00205       }
00206       *ts << "  </tr>\n";
00207     }
00208     *ts << "</table>\n";
00209     startmonth += 1;
00210     if ( startmonth > 12 ) {
00211       startyear += 1;
00212       startmonth = 1;
00213     }
00214     start.setYMD( startyear, startmonth, 1 );
00215     end.setYMD(start.year(),start.month(),start.daysInMonth());
00216   }
00217 }
00218 
00219 void HtmlExport::createEventList (QTextStream *ts)
00220 {
00221   int columns = 3;
00222   *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">\n";
00223   *ts << "  <tr>\n";
00224   *ts << "    <th class=\"sum\">" << i18n("Start Time") << "</th>\n";
00225   *ts << "    <th>" << i18n("End Time") << "</th>\n";
00226   *ts << "    <th>" << i18n("Event") << "</th>\n";
00227   if ( mSettings->eventLocation() ) {
00228     *ts << "    <th>" << i18n("Location") << "</th>\n";
00229     ++columns;
00230   }
00231   if ( mSettings->eventCategories() ) {
00232     *ts << "    <th>" << i18n("Categories") << "</th>\n";
00233     ++columns;
00234   }
00235   if ( mSettings->eventAttendees() ) {
00236     *ts << "    <th>" << i18n("Attendees") << "</th>\n";
00237     ++columns;
00238   }
00239 
00240   *ts << "  </tr>\n";
00241 
00242   for ( QDate dt = fromDate(); dt <= toDate(); dt = dt.addDays(1) ) {
00243     kdDebug(5850) << "Getting events for " << dt.toString() << endl;
00244     Event::List events = mCalendar->events(dt,
00245                                            EventSortStartDate,
00246                                            SortDirectionAscending );
00247     if (events.count()) {
00248       Event::List::ConstIterator it;
00249       bool first = true;
00250       for( it = events.begin(); it != events.end(); ++it ) {
00251         if ( checkSecrecy( *it ) ) {
00252           if ( first ) {
00253             *ts << "  <tr><td colspan=\"" << QString::number(columns)
00254             << "\" class=\"datehead\"><i>"
00255             << KGlobal::locale()->formatDate(dt)
00256             << "</i></td></tr>\n";
00257             first = false;
00258           }
00259           createEvent( ts, *it, dt );
00260         }
00261       }
00262     }
00263   }
00264 
00265   *ts << "</table>\n";
00266 }
00267 
00268 void HtmlExport::createEvent (QTextStream *ts, Event *event,
00269                                        QDate date,bool withDescription)
00270 {
00271   kdDebug(5850) << "HtmlExport::createEvent(): " << event->summary() << endl;
00272   *ts << "  <tr>\n";
00273 
00274   if (!event->doesFloat()) {
00275     if (event->isMultiDay() && (event->dtStart().date() != date)) {
00276       *ts << "    <td>&nbsp;</td>\n";
00277     } else {
00278       *ts << "    <td valign=\"top\">" << event->dtStartTimeStr() << "</td>\n";
00279     }
00280     if (event->isMultiDay() && (event->dtEnd().date() != date)) {
00281       *ts << "    <td>&nbsp;</td>\n";
00282     } else {
00283       *ts << "    <td valign=\"top\">" << event->dtEndTimeStr() << "</td>\n";
00284     }
00285   } else {
00286     *ts << "    <td>&nbsp;</td><td>&nbsp;</td>\n";
00287   }
00288 
00289   *ts << "    <td class=\"sum\">\n";
00290   *ts << "      <b>" << cleanChars(event->summary()) << "</b>\n";
00291   if ( withDescription && !event->description().isEmpty() ) {
00292     *ts << "      <p>" << breakString( cleanChars( event->description() ) ) << "</p>\n";
00293   }
00294   *ts << "    </td>\n";
00295 
00296   if ( mSettings->eventLocation() ) {
00297     *ts << "  <td>\n";
00298     formatLocation( ts, event );
00299     *ts << "  </td>\n";
00300   }
00301 
00302   if ( mSettings->eventCategories() ) {
00303     *ts << "  <td>\n";
00304     formatCategories( ts, event );
00305     *ts << "  </td>\n";
00306   }
00307 
00308   if ( mSettings->eventAttendees() ) {
00309     *ts << "  <td>\n";
00310     formatAttendees( ts, event );
00311     *ts << "  </td>\n";
00312   }
00313 
00314   *ts << "  </tr>\n";
00315 }
00316 
00317 void HtmlExport::createTodoList ( QTextStream *ts )
00318 {
00319   Todo::List rawTodoList = mCalendar->todos();
00320 
00321   Todo::List::Iterator it = rawTodoList.begin();
00322   while ( it != rawTodoList.end() ) {
00323     Todo *ev = *it;
00324     Todo *subev = ev;
00325     if ( ev->relatedTo() ) {
00326       if ( ev->relatedTo()->type()=="Todo" ) {
00327         if ( rawTodoList.find( static_cast<Todo *>( ev->relatedTo() ) ) ==
00328              rawTodoList.end() ) {
00329           rawTodoList.append( static_cast<Todo *>( ev->relatedTo() ) );
00330         }
00331       }
00332     }
00333     it = rawTodoList.find( subev );
00334     ++it;
00335   }
00336 
00337   // FIXME: Sort list by priorities. This is brute force and should be
00338   // replaced by a real sorting algorithm.
00339   Todo::List todoList;
00340   for ( int i = 1; i <= 9; ++i ) {
00341     for( it = rawTodoList.begin(); it != rawTodoList.end(); ++it ) {
00342       if ( (*it)->priority() == i && checkSecrecy( *it ) ) {
00343         todoList.append( *it );
00344       }
00345     }
00346   }
00347   for( it = rawTodoList.begin(); it != rawTodoList.end(); ++it ) {
00348     if ( (*it)->priority() == 0 && checkSecrecy( *it ) ) {
00349       todoList.append( *it );
00350     }
00351  }
00352 
00353   int columns = 3;
00354   *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">\n";
00355   *ts << "  <tr>\n";
00356   *ts << "    <th class=\"sum\">" << i18n("Task") << "</th>\n";
00357   *ts << "    <th>" << i18n("Priority") << "</th>\n";
00358   *ts << "    <th>" << i18n("Completed") << "</th>\n";
00359   if ( mSettings->taskDueDate() ) {
00360     *ts << "    <th>" << i18n("Due Date") << "</th>\n";
00361     ++columns;
00362   }
00363   if ( mSettings->taskLocation() ) {
00364     *ts << "    <th>" << i18n("Location") << "</th>\n";
00365     ++columns;
00366   }
00367   if ( mSettings->taskCategories() ) {
00368     *ts << "    <th>" << i18n("Categories") << "</th>\n";
00369     ++columns;
00370   }
00371   if ( mSettings->taskAttendees() ) {
00372     *ts << "    <th>" << i18n("Attendees") << "</th>\n";
00373     ++columns;
00374   }
00375   *ts << "  </tr>\n";
00376 
00377   // Create top-level list.
00378   for( it = todoList.begin(); it != todoList.end(); ++it ) {
00379     if ( !(*it)->relatedTo() ) createTodo( ts, *it );
00380   }
00381 
00382   // Create sub-level lists
00383   for( it = todoList.begin(); it != todoList.end(); ++it ) {
00384     Incidence::List relations = (*it)->relations();
00385     if (relations.count()) {
00386       // Generate sub-task list of event ev
00387       *ts << "  <tr>\n";
00388       *ts << "    <td class=\"subhead\" colspan=";
00389       *ts << "\"" << QString::number(columns) << "\"";
00390       *ts << "><a name=\"sub" << (*it)->uid() << "\"></a>"
00391           << i18n("Sub-Tasks of: ") << "<a href=\"#"
00392           << (*it)->uid() << "\"><b>" << cleanChars( (*it)->summary())
00393           << "</b></a></td>\n";
00394       *ts << "  </tr>\n";
00395 
00396       Todo::List sortedList;
00397       // FIXME: Sort list by priorities. This is brute force and should be
00398       // replaced by a real sorting algorithm.
00399       for ( int i = 1; i <= 9; ++i ) {
00400         Incidence::List::ConstIterator it2;
00401         for( it2 = relations.begin(); it2 != relations.end(); ++it2 ) {
00402           Todo *ev3 = dynamic_cast<Todo *>( *it2 );
00403           if ( ev3 && ev3->priority() == i ) sortedList.append( ev3 );
00404         }
00405       }
00406       Incidence::List::ConstIterator it2;
00407       for( it2 = relations.begin(); it2 != relations.end(); ++it2 ) {
00408         Todo *ev3 = dynamic_cast<Todo *>( *it2 );
00409         if ( ev3 && ev3->priority() == 0 ) sortedList.append( ev3 );
00410       }
00411 
00412       Todo::List::ConstIterator it3;
00413       for( it3 = sortedList.begin(); it3 != sortedList.end(); ++it3 ) {
00414         createTodo( ts, *it3 );
00415       }
00416     }
00417   }
00418 
00419   *ts << "</table>\n";
00420 }
00421 
00422 void HtmlExport::createTodo (QTextStream *ts,Todo *todo)
00423 {
00424   kdDebug(5850) << "HtmlExport::createTodo()" << endl;
00425 
00426   bool completed = todo->isCompleted();
00427   Incidence::List relations = todo->relations();
00428 
00429   *ts << "<tr>\n";
00430 
00431   *ts << "  <td class=\"sum";
00432   if (completed) *ts << "done";
00433   *ts << "\">\n";
00434   *ts << "    <a name=\"" << todo->uid() << "\"></a>\n";
00435   *ts << "    <b>" << cleanChars(todo->summary()) << "</b>\n";
00436   if (!todo->description().isEmpty()) {
00437     *ts << "    <p>" << breakString(cleanChars(todo->description())) << "</p>\n";
00438   }
00439   if (relations.count()) {
00440     *ts << "    <div align=\"right\"><a href=\"#sub" << todo->uid()
00441         << "\">" << i18n("Sub-Tasks") << "</a></div>\n";
00442   }
00443   *ts << "  </td>\n";
00444 
00445   *ts << "  <td";
00446   if (completed) *ts << " class=\"done\"";
00447   *ts << ">\n";
00448   *ts << "    " << todo->priority() << "\n";
00449   *ts << "  </td>\n";
00450 
00451   *ts << "  <td";
00452   if (completed) *ts << " class=\"done\"";
00453   *ts << ">\n";
00454   *ts << "    " << i18n("%1 %").arg(todo->percentComplete()) << "\n";
00455   *ts << "  </td>\n";
00456 
00457   if ( mSettings->taskDueDate() ) {
00458     *ts << "  <td";
00459     if (completed) *ts << " class=\"done\"";
00460     *ts << ">\n";
00461     if (todo->hasDueDate()) {
00462       *ts << "    " << todo->dtDueDateStr() << "\n";
00463     } else {
00464       *ts << "    &nbsp;\n";
00465     }
00466     *ts << "  </td>\n";
00467   }
00468 
00469   if ( mSettings->taskLocation() ) {
00470     *ts << "  <td";
00471     if (completed) *ts << " class=\"done\"";
00472     *ts << ">\n";
00473     formatLocation(ts,todo);
00474     *ts << "  </td>\n";
00475   }
00476 
00477   if ( mSettings->taskCategories() ) {
00478     *ts << "  <td";
00479     if (completed) *ts << " class=\"done\"";
00480     *ts << ">\n";
00481     formatCategories(ts,todo);
00482     *ts << "  </td>\n";
00483   }
00484 
00485   if ( mSettings->taskAttendees() ) {
00486     *ts << "  <td";
00487     if (completed) *ts << " class=\"done\"";
00488     *ts << ">\n";
00489     formatAttendees(ts,todo);
00490     *ts << "  </td>\n";
00491   }
00492 
00493   *ts << "</tr>\n";
00494 }
00495 
00496 void HtmlExport::createWeekView( QTextStream */*ts*/ )
00497 {
00498   // FIXME: Implement this!
00499 }
00500 
00501 void HtmlExport::createJournalView( QTextStream */*ts*/ )
00502 {
00503 //   Journal::List rawJournalList = mCalendar->journals();
00504   // FIXME: Implement this!
00505 }
00506 
00507 void HtmlExport::createFreeBusyView( QTextStream */*ts*/ )
00508 {
00509   // FIXME: Implement this!
00510 }
00511 
00512 bool HtmlExport::checkSecrecy( Incidence *incidence )
00513 {
00514   int secrecy = incidence->secrecy();
00515   if ( secrecy == Incidence::SecrecyPublic ) {
00516     return true;
00517   }
00518   if ( secrecy == Incidence::SecrecyPrivate && !mSettings->excludePrivate() ) {
00519     return true;
00520   }
00521   if ( secrecy == Incidence::SecrecyConfidential &&
00522        !mSettings->excludeConfidential() ) {
00523     return true;
00524   }
00525   return false;
00526 }
00527 
00528 void HtmlExport::formatLocation (QTextStream *ts,Incidence *event)
00529 {
00530   if (!event->location().isEmpty()) {
00531     *ts << "    " << cleanChars(event->location()) << "\n";
00532   } else {
00533     *ts << "    &nbsp;\n";
00534   }
00535 }
00536 
00537 void HtmlExport::formatCategories (QTextStream *ts,Incidence *event)
00538 {
00539   if (!event->categoriesStr().isEmpty()) {
00540     *ts << "    " << cleanChars(event->categoriesStr()) << "\n";
00541   } else {
00542     *ts << "    &nbsp;\n";
00543   }
00544 }
00545 
00546 void HtmlExport::formatAttendees( QTextStream *ts, Incidence *event )
00547 {
00548   Attendee::List attendees = event->attendees();
00549   if (attendees.count()) {
00550     *ts << "<em>";
00551 #ifndef KORG_NOKABC
00552     KABC::AddressBook *add_book = KABC::StdAddressBook::self( true );
00553     KABC::Addressee::List addressList;
00554     addressList = add_book->findByEmail(event->organizer().email());
00555     KABC::Addressee o = addressList.first();
00556     if (!o.isEmpty() && addressList.size()<2) {
00557       *ts << "<a href=\"mailto:" << event->organizer().email() << "\">";
00558       *ts << cleanChars(o.formattedName()) << "</a>\n";
00559     }
00560     else *ts << event->organizer().fullName();
00561 #else
00562     *ts << event->organizer().fullName();
00563 #endif
00564     *ts << "</em><br />";
00565     Attendee::List::ConstIterator it;
00566     for( it = attendees.begin(); it != attendees.end(); ++it ) {
00567       Attendee *a = *it;
00568       if (!a->email().isEmpty()) {
00569         *ts << "<a href=\"mailto:" << a->email();
00570         *ts << "\">" << cleanChars(a->name()) << "</a>";
00571       }
00572       else {
00573         *ts << "    " << cleanChars(a->name());
00574       }
00575       *ts << "<br />" << "\n";
00576     }
00577   } else {
00578     *ts << "    &nbsp;\n";
00579   }
00580 }
00581 
00582 QString HtmlExport::breakString(const QString &text)
00583 {
00584   int number = text.contains("\n");
00585   if(number < 0) {
00586     return text;
00587   } else {
00588     QString out;
00589     QString tmpText = text;
00590     int pos = 0;
00591     QString tmp;
00592     for(int i=0;i<=number;i++) {
00593       pos = tmpText.find("\n");
00594       tmp = tmpText.left(pos);
00595       tmpText = tmpText.right(tmpText.length() - pos - 1);
00596       out += tmp + "<br />";
00597     }
00598     return out;
00599   }
00600 }
00601 
00602 void HtmlExport::createFooter( QTextStream *ts )
00603 {
00604   // FIXME: Implement this in a translatable way!
00605   QString trailer = i18n("This page was created ");
00606 
00607 /*  bool hasPerson = false;
00608   bool hasCredit = false;
00609   bool hasCreditURL = false;
00610   QString mail, name, credit, creditURL;*/
00611   if (!mSettings->eMail().isEmpty()) {
00612     if (!mSettings->name().isEmpty())
00613       trailer += i18n("by <a href=\"mailto:%1\">%2</a> ").arg( mSettings->eMail() ).arg( mSettings->name() );
00614     else
00615       trailer += i18n("by <a href=\"mailto:%1\">%2</a> ").arg( mSettings->eMail() ).arg( mSettings->eMail() );
00616   } else {
00617     if (!mSettings->name().isEmpty())
00618       trailer += i18n("by %1 ").arg( mSettings->name() );
00619   }
00620   if (!mSettings->creditName().isEmpty()) {
00621     if (!mSettings->creditURL().isEmpty())
00622       trailer += i18n("with <a href=\"%1\">%2</a>")
00623                      .arg( mSettings->creditURL() )
00624                      .arg( mSettings->creditName() );
00625     else
00626       trailer += i18n("with %1").arg( mSettings->creditName() );
00627   }
00628   *ts << "<p>" << trailer << "</p>\n";
00629 }
00630 
00631 
00632 QString HtmlExport::cleanChars(const QString &text)
00633 {
00634   QString txt = text;
00635   txt = txt.replace( "&", "&amp;" );
00636   txt = txt.replace( "<", "&lt;" );
00637   txt = txt.replace( ">", "&gt;" );
00638   txt = txt.replace( "\"", "&quot;" );
00639   txt = txt.replace( QString::fromUtf8("ä"), "&auml;" );
00640   txt = txt.replace( QString::fromUtf8("á"), "&aacute;" );
00641   txt = txt.replace( QString::fromUtf8("à"), "&agrave;" );
00642   txt = txt.replace( QString::fromUtf8("â"), "&acirc;" );
00643   txt = txt.replace( QString::fromUtf8("Ä"), "&Auml;" );
00644   txt = txt.replace( QString::fromUtf8("ó"), "&oacute;" );
00645   txt = txt.replace( QString::fromUtf8("ô"), "&ocirc;" );
00646   txt = txt.replace( QString::fromUtf8("ö"), "&ouml;" );
00647   txt = txt.replace( QString::fromUtf8("Ö"), "&Ouml;" );
00648   txt = txt.replace( QString::fromUtf8("ü"), "&uuml;" );
00649   txt = txt.replace( QString::fromUtf8("Ü"), "&Uuml;" );
00650   txt = txt.replace( QString::fromUtf8("ß"), "&szlig;" );
00651   txt = txt.replace( QString::fromUtf8("€"), "&euro;" );
00652   txt = txt.replace( QString::fromUtf8("é"), "&eacute;" );
00653   txt = txt.replace( QString::fromUtf8("ë"), "&euml;" );
00654   txt = txt.replace( QString::fromUtf8("è"), "&egrave;" );
00655   txt = txt.replace( QString::fromUtf8("ñ"), "&ntilde;" );
00656   txt = txt.replace( QString::fromUtf8("ç"), "&ccedil;" );
00657 
00658   return txt;
00659 }
00660 
00661 QString HtmlExport::styleSheet() const
00662 {
00663   if ( !mSettings->styleSheet().isEmpty() )
00664     return mSettings->styleSheet();
00665 
00666   QString css;
00667 
00668   if ( QApplication::reverseLayout() ) {
00669     css += "    body { background-color:white; color:black; direction: rtl }\n";
00670     css += "    td { text-align:center; background-color:#eee }\n";
00671     css += "    th { text-align:center; background-color:#228; color:white }\n";
00672     css += "    td.sumdone { background-color:#ccc }\n";
00673     css += "    td.done { background-color:#ccc }\n";
00674     css += "    td.subhead { text-align:center; background-color:#ccf }\n";
00675     css += "    td.datehead { text-align:center; background-color:#ccf }\n";
00676     css += "    td.space { background-color:white }\n";
00677     css += "    td.dateholiday { color:red }\n";
00678   } else {
00679     css += "    body { background-color:white; color:black }\n";
00680     css += "    td { text-align:center; background-color:#eee }\n";
00681     css += "    th { text-align:center; background-color:#228; color:white }\n";
00682     css += "    td.sum { text-align:left }\n";
00683     css += "    td.sumdone { text-align:left; background-color:#ccc }\n";
00684     css += "    td.done { background-color:#ccc }\n";
00685     css += "    td.subhead { text-align:center; background-color:#ccf }\n";
00686     css += "    td.datehead { text-align:center; background-color:#ccf }\n";
00687     css += "    td.space { background-color:white }\n";
00688     css += "    td.date { text-align:left }\n";
00689     css += "    td.dateholiday { text-align:left; color:red }\n";
00690   }
00691 
00692   return css;
00693 }
00694 
00695 
00696 void HtmlExport::addHoliday( const QDate &date, const QString &name)
00697 {
00698   if ( mHolidayMap[date].isEmpty() ) {
00699     mHolidayMap[date] = name;
00700   } else {
00701     mHolidayMap[date] = i18n("list of holidays", "%1, %2").arg(mHolidayMap[date]).arg(name);
00702   }
00703 }
00704 
00705 QDate HtmlExport::fromDate() const
00706 {
00707   return mSettings->dateStart().date();
00708 }
00709 
00710 QDate HtmlExport::toDate() const
00711 {
00712   return mSettings->dateEnd().date();
00713 }