libkcal

htmlexport.cpp
1 /*
2  This file is part of libkcal.
3 
4  Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
22 
23 #include <tqapplication.h>
24 #include <tqfile.h>
25 #include <tqtextstream.h>
26 #include <tqtextcodec.h>
27 #include <tqregexp.h>
28 
29 #include <kcharsets.h>
30 #include <tdeglobal.h>
31 #include <tdelocale.h>
32 #include <kdebug.h>
33 #include <kcalendarsystem.h>
34 
35 #include <libkcal/calendar.h>
36 #include <libkcal/event.h>
37 #include <libkcal/incidenceformatter.h>
38 #include <libkcal/todo.h>
39 
40 #ifndef KORG_NOKABC
41  #include <tdeabc/stdaddressbook.h>
42 #endif
43 #include "htmlexport.h"
44 #include "htmlexportsettings.h"
45 
46 using namespace KCal;
47 
48 HtmlExport::HtmlExport( Calendar *calendar, HTMLExportSettings *settings ) :
49  mCalendar( calendar ), mSettings( settings )
50 {
51 }
52 
53 bool HtmlExport::save( const TQString &fileName )
54 {
55  TQString fn( fileName );
56  if ( fn.isEmpty() && mSettings ) {
57  fn = mSettings->outputFile();
58  }
59  if ( !mSettings || fn.isEmpty() ) {
60  return false;
61  }
62  TQFile f( fileName );
63  if ( !f.open(IO_WriteOnly)) {
64  return false;
65  }
66  TQTextStream ts(&f);
67  bool success = save(&ts);
68  f.close();
69  return success;
70 }
71 
72 bool HtmlExport::save(TQTextStream *ts)
73 {
74  if ( !mSettings ) return false;
75  ts->setEncoding( TQTextStream::UnicodeUTF8 );
76 
77  // Write HTML header
78  *ts << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" ";
79  *ts << "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
80 
81  *ts << "<html><head>" << endl;
82  *ts << " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=";
83  *ts << "UTF-8\" />\n";
84  if ( !mSettings->pageTitle().isEmpty())
85  *ts << " <title>" << mSettings->pageTitle() << "</title>\n";
86  *ts << " <style type=\"text/css\">\n";
87  *ts << styleSheet();
88  *ts << " </style>\n";
89  *ts << "</head><body>\n";
90 
91  // FIXME: Write header
92  // (Heading, Calendar-Owner, Calendar-Date, ...)
93 
94  if ( mSettings->eventView() || mSettings->monthView() || mSettings->weekView() ) {
95  if (!mSettings->eventTitle().isEmpty())
96  *ts << "<h1>" << mSettings->eventTitle() << "</h1>\n";
97 
98  // Write Week View
99  if ( mSettings->weekView() )
100  createWeekView( ts );
101  // Write Month View
102  if ( mSettings->monthView() )
103  createMonthView( ts );
104  // Write Event List
105  if ( mSettings->eventView() )
106  createEventList( ts );
107  }
108 
109  // Write Todo List
110  if ( mSettings->todoView() ) {
111  if ( !mSettings->todoListTitle().isEmpty())
112  *ts << "<h1>" << mSettings->todoListTitle() << "</h1>\n";
113  createTodoList(ts);
114  }
115 
116  // Write Journals
117  if ( mSettings->journalView() ) {
118  if ( !mSettings->journalTitle().isEmpty())
119  *ts << "<h1>" << mSettings->journalTitle() << "</h1>\n";
120  createJournalView(ts);
121  }
122 
123  // Write Free/Busy
124  if ( mSettings->freeBusyView() ) {
125  if ( !mSettings->freeBusyTitle().isEmpty())
126  *ts << "<h1>" << mSettings->freeBusyTitle() << "</h1>\n";
127  createFreeBusyView(ts);
128  }
129 
130  createFooter( ts );
131 
132  // Write HTML trailer
133  *ts << "</body></html>\n";
134 
135  return true;
136 }
137 
138 void HtmlExport::createMonthView(TQTextStream *ts)
139 {
140  TQDate start = fromDate();
141  start.setYMD( start.year(), start.month(), 1 ); // go back to first day in month
142 
143  TQDate end( start.year(), start.month(), start.daysInMonth() );
144 
145  int startmonth = start.month();
146  int startyear = start.year();
147 
148  while ( start < toDate() ) {
149  // Write header
150  *ts << "<h2>" << (i18n("month_year","%1 %2").arg(TDEGlobal::locale()->calendar()->monthName(start))
151  .arg(start.year())) << "</h2>\n";
152  if ( TDEGlobal::locale()->weekStartDay() == 1 ) {
153  start = start.addDays(1 - start.dayOfWeek());
154  } else {
155  if (start.dayOfWeek() != 7) {
156  start = start.addDays(-start.dayOfWeek());
157  }
158  }
159  *ts << "<table border=\"1\">\n";
160 
161  // Write table header
162  *ts << " <tr>";
163  for(int i=0; i<7; ++i) {
164  *ts << "<th>" << TDEGlobal::locale()->calendar()->weekDayName( start.addDays(i) ) << "</th>";
165  }
166  *ts << "</tr>\n";
167 
168  // Write days
169  while (start <= end) {
170  *ts << " <tr>\n";
171  for(int i=0;i<7;++i) {
172  *ts << " <td valign=\"top\"><table border=\"0\">";
173 
174  *ts << "<tr><td ";
175  if (mHolidayMap.contains(start) || start.dayOfWeek() == 7) {
176  *ts << "class=\"dateholiday\"";
177  } else {
178  *ts << "class=\"date\"";
179  }
180  *ts << ">" << TQString::number(start.day());
181 
182  if (mHolidayMap.contains(start)) {
183  *ts << " <em>" << mHolidayMap[start] << "</em>";
184  }
185 
186  *ts << "</td></tr><tr><td valign=\"top\">";
187 
188  // Only print events within the from-to range
189  if ( start >= fromDate() && start <= toDate() ) {
190  Event::List events = mCalendar->events( start,
193  if (events.count()) {
194  *ts << "<table>";
195  Event::List::ConstIterator it;
196  for( it = events.begin(); it != events.end(); ++it ) {
197  if ( checkSecrecy( *it ) ) {
198  createEvent( ts, *it, start, false );
199  }
200  }
201  *ts << "</table>";
202  } else {
203  *ts << "&nbsp;";
204  }
205  }
206 
207  *ts << "</td></tr></table></td>\n";
208  start = start.addDays(1);
209  }
210  *ts << " </tr>\n";
211  }
212  *ts << "</table>\n";
213  startmonth += 1;
214  if ( startmonth > 12 ) {
215  startyear += 1;
216  startmonth = 1;
217  }
218  start.setYMD( startyear, startmonth, 1 );
219  end.setYMD(start.year(),start.month(),start.daysInMonth());
220  }
221 }
222 
223 void HtmlExport::createEventList (TQTextStream *ts)
224 {
225  int columns = 3;
226  *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">\n";
227  *ts << " <tr>\n";
228  *ts << " <th class=\"sum\">" << i18n("Start Time") << "</th>\n";
229  *ts << " <th>" << i18n("End Time") << "</th>\n";
230  *ts << " <th>" << i18n("Event") << "</th>\n";
231  if ( mSettings->eventLocation() ) {
232  *ts << " <th>" << i18n("Location") << "</th>\n";
233  ++columns;
234  }
235  if ( mSettings->eventCategories() ) {
236  *ts << " <th>" << i18n("Categories") << "</th>\n";
237  ++columns;
238  }
239  if ( mSettings->eventAttendees() ) {
240  *ts << " <th>" << i18n("Attendees") << "</th>\n";
241  ++columns;
242  }
243 
244  *ts << " </tr>\n";
245 
246  for ( TQDate dt = fromDate(); dt <= toDate(); dt = dt.addDays(1) ) {
247  kdDebug(5850) << "Getting events for " << TQString(dt.toString()) << endl;
248  Event::List events = mCalendar->events(dt,
251  if (events.count()) {
252  Event::List::ConstIterator it;
253  bool first = true;
254  for( it = events.begin(); it != events.end(); ++it ) {
255  if ( checkSecrecy( *it ) ) {
256  if ( first ) {
257  *ts << " <tr><td colspan=\"" << TQString::number(columns)
258  << "\" class=\"datehead\"><i>"
259  << TDEGlobal::locale()->formatDate(dt)
260  << "</i></td></tr>\n";
261  first = false;
262  }
263  createEvent( ts, *it, dt );
264  }
265  }
266  }
267  }
268 
269  *ts << "</table>\n";
270 }
271 
272 void HtmlExport::createEvent (TQTextStream *ts, Event *event,
273  TQDate date,bool withDescription)
274 {
275  kdDebug(5850) << "HtmlExport::createEvent(): " << event->summary() << endl;
276  *ts << " <tr>\n";
277 
278  if (!event->doesFloat()) {
279  if (event->isMultiDay() && (event->dtStart().date() != date)) {
280  *ts << " <td>&nbsp;</td>\n";
281  } else {
282  *ts << " <td valign=\"top\">"
283  << IncidenceFormatter::timeToString( event->dtStart(), true )
284  << "</td>\n";
285  }
286  if (event->isMultiDay() && (event->dtEnd().date() != date)) {
287  *ts << " <td>&nbsp;</td>\n";
288  } else {
289  *ts << " <td valign=\"top\">"
290  << IncidenceFormatter::timeToString( event->dtEnd(), true )
291  << "</td>\n";
292  }
293  } else {
294  *ts << " <td>&nbsp;</td><td>&nbsp;</td>\n";
295  }
296 
297  *ts << " <td class=\"sum\">\n";
298  *ts << " <b>" << cleanChars(event->summary()) << "</b>\n";
299  if ( withDescription && !event->description().isEmpty() ) {
300  *ts << " <p>" << breakString( cleanChars( event->description() ) ) << "</p>\n";
301  }
302  *ts << " </td>\n";
303 
304  if ( mSettings->eventLocation() ) {
305  *ts << " <td>\n";
306  formatLocation( ts, event );
307  *ts << " </td>\n";
308  }
309 
310  if ( mSettings->eventCategories() ) {
311  *ts << " <td>\n";
312  formatCategories( ts, event );
313  *ts << " </td>\n";
314  }
315 
316  if ( mSettings->eventAttendees() ) {
317  *ts << " <td>\n";
318  formatAttendees( ts, event );
319  *ts << " </td>\n";
320  }
321 
322  *ts << " </tr>\n";
323 }
324 
325 void HtmlExport::createTodoList ( TQTextStream *ts )
326 {
327  Todo::List rawTodoList = mCalendar->todos();
328 
329  Todo::List::Iterator it = rawTodoList.begin();
330  while ( it != rawTodoList.end() ) {
331  Todo *ev = *it;
332  Todo *subev = ev;
333  if ( ev->relatedTo() ) {
334  if ( ev->relatedTo()->type()=="Todo" ) {
335  if ( rawTodoList.find( static_cast<Todo *>( ev->relatedTo() ) ) ==
336  rawTodoList.end() ) {
337  rawTodoList.append( static_cast<Todo *>( ev->relatedTo() ) );
338  }
339  }
340  }
341  it = rawTodoList.find( subev );
342  ++it;
343  }
344 
345  // FIXME: Sort list by priorities. This is brute force and should be
346  // replaced by a real sorting algorithm.
347  Todo::List todoList;
348  for ( int i = 1; i <= 9; ++i ) {
349  for( it = rawTodoList.begin(); it != rawTodoList.end(); ++it ) {
350  if ( (*it)->priority() == i && checkSecrecy( *it ) ) {
351  todoList.append( *it );
352  }
353  }
354  }
355  for( it = rawTodoList.begin(); it != rawTodoList.end(); ++it ) {
356  if ( (*it)->priority() == 0 && checkSecrecy( *it ) ) {
357  todoList.append( *it );
358  }
359  }
360 
361  int columns = 3;
362  *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">\n";
363  *ts << " <tr>\n";
364  *ts << " <th class=\"sum\">" << i18n("Task") << "</th>\n";
365  *ts << " <th>" << i18n("Priority") << "</th>\n";
366  *ts << " <th>" << i18n("Completed") << "</th>\n";
367  if ( mSettings->taskDueDate() ) {
368  *ts << " <th>" << i18n("Due Date") << "</th>\n";
369  ++columns;
370  }
371  if ( mSettings->taskLocation() ) {
372  *ts << " <th>" << i18n("Location") << "</th>\n";
373  ++columns;
374  }
375  if ( mSettings->taskCategories() ) {
376  *ts << " <th>" << i18n("Categories") << "</th>\n";
377  ++columns;
378  }
379  if ( mSettings->taskAttendees() ) {
380  *ts << " <th>" << i18n("Attendees") << "</th>\n";
381  ++columns;
382  }
383  *ts << " </tr>\n";
384 
385  // Create top-level list.
386  for( it = todoList.begin(); it != todoList.end(); ++it ) {
387  if ( !(*it)->relatedTo() ) createTodo( ts, *it );
388  }
389 
390  // Create sub-level lists
391  for( it = todoList.begin(); it != todoList.end(); ++it ) {
392  Incidence::List relations = (*it)->relations();
393  if (relations.count()) {
394  // Generate sub-task list of event ev
395  *ts << " <tr>\n";
396  *ts << " <td class=\"subhead\" colspan=";
397  *ts << "\"" << TQString::number(columns) << "\"";
398  *ts << "><a name=\"sub" << (*it)->uid() << "\"></a>"
399  << i18n("Sub-Tasks of: ") << "<a href=\"#"
400  << (*it)->uid() << "\"><b>" << cleanChars( (*it)->summary())
401  << "</b></a></td>\n";
402  *ts << " </tr>\n";
403 
404  Todo::List sortedList;
405  // FIXME: Sort list by priorities. This is brute force and should be
406  // replaced by a real sorting algorithm.
407  for ( int i = 1; i <= 9; ++i ) {
408  Incidence::List::ConstIterator it2;
409  for( it2 = relations.begin(); it2 != relations.end(); ++it2 ) {
410  Todo *ev3 = dynamic_cast<Todo *>( *it2 );
411  if ( ev3 && ev3->priority() == i ) sortedList.append( ev3 );
412  }
413  }
414  Incidence::List::ConstIterator it2;
415  for( it2 = relations.begin(); it2 != relations.end(); ++it2 ) {
416  Todo *ev3 = dynamic_cast<Todo *>( *it2 );
417  if ( ev3 && ev3->priority() == 0 ) sortedList.append( ev3 );
418  }
419 
420  Todo::List::ConstIterator it3;
421  for( it3 = sortedList.begin(); it3 != sortedList.end(); ++it3 ) {
422  createTodo( ts, *it3 );
423  }
424  }
425  }
426 
427  *ts << "</table>\n";
428 }
429 
430 void HtmlExport::createTodo (TQTextStream *ts,Todo *todo)
431 {
432  kdDebug(5850) << "HtmlExport::createTodo()" << endl;
433 
434  bool completed = todo->isCompleted();
435  Incidence::List relations = todo->relations();
436 
437  *ts << "<tr>\n";
438 
439  *ts << " <td class=\"sum";
440  if (completed) *ts << "done";
441  *ts << "\">\n";
442  *ts << " <a name=\"" << todo->uid() << "\"></a>\n";
443  *ts << " <b>" << cleanChars(todo->summary()) << "</b>\n";
444  if (!todo->description().isEmpty()) {
445  *ts << " <p>" << breakString(cleanChars(todo->description())) << "</p>\n";
446  }
447  if (relations.count()) {
448  *ts << " <div align=\"right\"><a href=\"#sub" << todo->uid()
449  << "\">" << i18n("Sub-Tasks") << "</a></div>\n";
450  }
451  *ts << " </td>\n";
452 
453  *ts << " <td";
454  if (completed) *ts << " class=\"done\"";
455  *ts << ">\n";
456  *ts << " " << todo->priority() << "\n";
457  *ts << " </td>\n";
458 
459  *ts << " <td";
460  if (completed) *ts << " class=\"done\"";
461  *ts << ">\n";
462  *ts << " " << i18n("%1 %").arg(todo->percentComplete()) << "\n";
463  *ts << " </td>\n";
464 
465  if ( mSettings->taskDueDate() ) {
466  *ts << " <td";
467  if (completed) *ts << " class=\"done\"";
468  *ts << ">\n";
469  if (todo->hasDueDate()) {
470  *ts << " " << IncidenceFormatter::dateToString( todo->dtDue( true ) ) << "\n";
471  } else {
472  *ts << " &nbsp;\n";
473  }
474  *ts << " </td>\n";
475  }
476 
477  if ( mSettings->taskLocation() ) {
478  *ts << " <td";
479  if (completed) *ts << " class=\"done\"";
480  *ts << ">\n";
481  formatLocation(ts,todo);
482  *ts << " </td>\n";
483  }
484 
485  if ( mSettings->taskCategories() ) {
486  *ts << " <td";
487  if (completed) *ts << " class=\"done\"";
488  *ts << ">\n";
489  formatCategories(ts,todo);
490  *ts << " </td>\n";
491  }
492 
493  if ( mSettings->taskAttendees() ) {
494  *ts << " <td";
495  if (completed) *ts << " class=\"done\"";
496  *ts << ">\n";
497  formatAttendees(ts,todo);
498  *ts << " </td>\n";
499  }
500 
501  *ts << "</tr>\n";
502 }
503 
504 void HtmlExport::createWeekView( TQTextStream */*ts*/ )
505 {
506  // FIXME: Implement this!
507 }
508 
509 void HtmlExport::createJournalView( TQTextStream */*ts*/ )
510 {
511 // Journal::List rawJournalList = mCalendar->journals();
512  // FIXME: Implement this!
513 }
514 
515 void HtmlExport::createFreeBusyView( TQTextStream */*ts*/ )
516 {
517  // FIXME: Implement this!
518 }
519 
520 bool HtmlExport::checkSecrecy( Incidence *incidence )
521 {
522  int secrecy = incidence->secrecy();
523  if ( secrecy == Incidence::SecrecyPublic ) {
524  return true;
525  }
526  if ( secrecy == Incidence::SecrecyPrivate && !mSettings->excludePrivate() ) {
527  return true;
528  }
529  if ( secrecy == Incidence::SecrecyConfidential &&
530  !mSettings->excludeConfidential() ) {
531  return true;
532  }
533  return false;
534 }
535 
536 void HtmlExport::formatLocation (TQTextStream *ts,Incidence *event)
537 {
538  if (!event->location().isEmpty()) {
539  *ts << " " << cleanChars(event->location()) << "\n";
540  } else {
541  *ts << " &nbsp;\n";
542  }
543 }
544 
545 void HtmlExport::formatCategories (TQTextStream *ts,Incidence *event)
546 {
547  if (!event->categoriesStr().isEmpty()) {
548  *ts << " " << cleanChars(event->categoriesStr()) << "\n";
549  } else {
550  *ts << " &nbsp;\n";
551  }
552 }
553 
554 void HtmlExport::formatAttendees( TQTextStream *ts, Incidence *event )
555 {
556  Attendee::List attendees = event->attendees();
557  if (attendees.count()) {
558  *ts << "<em>";
559 #ifndef KORG_NOKABC
560  TDEABC::AddressBook *add_book = TDEABC::StdAddressBook::self( true );
561  TDEABC::Addressee::List addressList;
562  addressList = add_book->findByEmail(event->organizer().email());
563  TDEABC::Addressee o = addressList.first();
564  if (!o.isEmpty() && addressList.size()<2) {
565  *ts << "<a href=\"mailto:" << event->organizer().email() << "\">";
566  *ts << cleanChars(o.formattedName()) << "</a>\n";
567  }
568  else *ts << event->organizer().fullName();
569 #else
570  *ts << event->organizer().fullName();
571 #endif
572  *ts << "</em><br />";
573  Attendee::List::ConstIterator it;
574  for( it = attendees.begin(); it != attendees.end(); ++it ) {
575  Attendee *a = *it;
576  if (!a->email().isEmpty()) {
577  *ts << "<a href=\"mailto:" << a->email();
578  *ts << "\">" << cleanChars(a->name()) << "</a>";
579  }
580  else {
581  *ts << " " << cleanChars(a->name());
582  }
583  *ts << "<br />" << "\n";
584  }
585  } else {
586  *ts << " &nbsp;\n";
587  }
588 }
589 
590 TQString HtmlExport::breakString(const TQString &text)
591 {
592  int number = text.contains("\n");
593  if(number < 0) {
594  return text;
595  } else {
596  TQString out;
597  TQString tmpText = text;
598  int pos = 0;
599  TQString tmp;
600  for(int i=0;i<=number;i++) {
601  pos = tmpText.find("\n");
602  tmp = tmpText.left(pos);
603  tmpText = tmpText.right(tmpText.length() - pos - 1);
604  out += tmp + "<br />";
605  }
606  return out;
607  }
608 }
609 
610 void HtmlExport::createFooter( TQTextStream *ts )
611 {
612  // FIXME: Implement this in a translatable way!
613  TQString trailer = i18n("This page was created ");
614 
615 /* bool hasPerson = false;
616  bool hasCredit = false;
617  bool hasCreditURL = false;
618  TQString mail, name, credit, creditURL;*/
619  if (!mSettings->eMail().isEmpty()) {
620  if (!mSettings->name().isEmpty())
621  trailer += i18n("by <a href=\"mailto:%1\">%2</a> ").arg( mSettings->eMail() ).arg( mSettings->name() );
622  else
623  trailer += i18n("by <a href=\"mailto:%1\">%2</a> ").arg( mSettings->eMail() ).arg( mSettings->eMail() );
624  } else {
625  if (!mSettings->name().isEmpty())
626  trailer += i18n("by %1 ").arg( mSettings->name() );
627  }
628  if (!mSettings->creditName().isEmpty()) {
629  if (!mSettings->creditURL().isEmpty())
630  trailer += i18n("with <a href=\"%1\">%2</a>")
631  .arg( mSettings->creditURL() )
632  .arg( mSettings->creditName() );
633  else
634  trailer += i18n("with %1").arg( mSettings->creditName() );
635  }
636  *ts << "<p>" << trailer << "</p>\n";
637 }
638 
639 
640 TQString HtmlExport::cleanChars(const TQString &text)
641 {
642  TQString txt = text;
643  txt = txt.replace( "&", "&amp;" );
644  txt = txt.replace( "<", "&lt;" );
645  txt = txt.replace( ">", "&gt;" );
646  txt = txt.replace( "\"", "&quot;" );
647  txt = txt.replace( TQString::fromUtf8("ä"), "&auml;" );
648  txt = txt.replace( TQString::fromUtf8("á"), "&aacute;" );
649  txt = txt.replace( TQString::fromUtf8("à"), "&agrave;" );
650  txt = txt.replace( TQString::fromUtf8("â"), "&acirc;" );
651  txt = txt.replace( TQString::fromUtf8("Ä"), "&Auml;" );
652  txt = txt.replace( TQString::fromUtf8("ó"), "&oacute;" );
653  txt = txt.replace( TQString::fromUtf8("ô"), "&ocirc;" );
654  txt = txt.replace( TQString::fromUtf8("ö"), "&ouml;" );
655  txt = txt.replace( TQString::fromUtf8("Ö"), "&Ouml;" );
656  txt = txt.replace( TQString::fromUtf8("ü"), "&uuml;" );
657  txt = txt.replace( TQString::fromUtf8("Ü"), "&Uuml;" );
658  txt = txt.replace( TQString::fromUtf8("ß"), "&szlig;" );
659  txt = txt.replace( TQString::fromUtf8("€"), "&euro;" );
660  txt = txt.replace( TQString::fromUtf8("é"), "&eacute;" );
661  txt = txt.replace( TQString::fromUtf8("ë"), "&euml;" );
662  txt = txt.replace( TQString::fromUtf8("è"), "&egrave;" );
663  txt = txt.replace( TQString::fromUtf8("ñ"), "&ntilde;" );
664  txt = txt.replace( TQString::fromUtf8("ç"), "&ccedil;" );
665 
666  return txt;
667 }
668 
669 TQString HtmlExport::styleSheet() const
670 {
671  if ( !mSettings->styleSheet().isEmpty() )
672  return mSettings->styleSheet();
673 
674  TQString css;
675 
676  if ( TQApplication::reverseLayout() ) {
677  css += " body { background-color:white; color:black; direction: rtl }\n";
678  css += " td { text-align:center; background-color:#eee }\n";
679  css += " th { text-align:center; background-color:#228; color:white }\n";
680  css += " td.sumdone { background-color:#ccc }\n";
681  css += " td.done { background-color:#ccc }\n";
682  css += " td.subhead { text-align:center; background-color:#ccf }\n";
683  css += " td.datehead { text-align:center; background-color:#ccf }\n";
684  css += " td.space { background-color:white }\n";
685  css += " td.dateholiday { color:red }\n";
686  } else {
687  css += " body { background-color:white; color:black }\n";
688  css += " td { text-align:center; background-color:#eee }\n";
689  css += " th { text-align:center; background-color:#228; color:white }\n";
690  css += " td.sum { text-align:left }\n";
691  css += " td.sumdone { text-align:left; background-color:#ccc }\n";
692  css += " td.done { background-color:#ccc }\n";
693  css += " td.subhead { text-align:center; background-color:#ccf }\n";
694  css += " td.datehead { text-align:center; background-color:#ccf }\n";
695  css += " td.space { background-color:white }\n";
696  css += " td.date { text-align:left }\n";
697  css += " td.dateholiday { text-align:left; color:red }\n";
698  }
699 
700  return css;
701 }
702 
703 
704 void HtmlExport::addHoliday( const TQDate &date, const TQString &name)
705 {
706  if ( mHolidayMap[date].isEmpty() ) {
707  mHolidayMap[date] = name;
708  } else {
709  mHolidayMap[date] = i18n("list of holidays", "%1, %2").arg(mHolidayMap[date]).arg(name);
710  }
711 }
712 
713 TQDate HtmlExport::fromDate() const
714 {
715  return mSettings->dateStart().date();
716 }
717 
718 TQDate HtmlExport::toDate() const
719 {
720  return mSettings->dateEnd().date();
721 }
Incidence::List relations() const
All events that are related to this event.
Definition: incidence.cpp:365
TQString categoriesStr() const
Return categories as a comma separated string.
Definition: incidence.cpp:328
This class provides an Event in the sense of RFC2445.
Definition: event.h:32
virtual Todo::List todos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Return a sorted, filtered list of all Todos for this Calendar.
Definition: calendar.cpp:755
TQString description() const
Return long description.
Definition: incidence.cpp:280
int secrecy() const
Return the event's secrecy.
Definition: incidence.cpp:793
Definition: alarm.h:38
bool isCompleted() const
Returns true if the todo is 100% completed, otherwise return false.
Definition: todo.cpp:217
bool save(const TQString &fileName=TQString())
Writes out the calendar in HTML format.
Definition: htmlexport.cpp:53
@ SortDirectionAscending
Sort in ascending order (first to last)
Definition: calendar.h:65
bool isMultiDay() const
Return true if the event spans multiple days, otherwise return false.
Definition: event.cpp:126
This class provides a Todo in the sense of RFC2445.
Definition: todo.h:31
virtual Event::List events(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Return a sorted, filtered list of all Events for this Calendar.
Definition: calendar.cpp:458
int priority() const
Return priority.
Definition: incidence.cpp:736
@ EventSortStartDate
Sort Events chronologically, by start date.
Definition: calendar.h:79
This class provides the base class common to all calendar components.
Definition: incidence.h:47
This class represents information related to an attendee of an event.
Definition: attendee.h:36
Incidence * relatedTo() const
What event does this one relate to?
Definition: incidence.cpp:360
bool doesFloat() const
Return true or false depending on whether the incidence "floats," i.e.
TQString location() const
Return the event's/todo's location.
Definition: incidence.cpp:875
int percentComplete() const
Returns how many percent of the task are completed.
Definition: todo.cpp:263
TQString uid() const
Return the unique id for the event.
HtmlExport(Calendar *calendar, HTMLExportSettings *settings)
Create new HTML exporter for calendar.
Definition: htmlexport.cpp:48
virtual TQDateTime dtStart() const
returns an event's starting date/time as a TQDateTime.
TQString summary() const
Return short summary.
Definition: incidence.cpp:293
bool hasDueDate() const
Returns true if the todo has a due date, otherwise return false.
Definition: todo.cpp:144
TQDateTime dtDue(bool first=false) const
Returns due date and time.
Definition: todo.cpp:117
virtual TQDateTime dtEnd() const
Return end date and time.
Definition: event.cpp:85