• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.10.5 API Reference
  • KDE Home
  • Contact Us
 

KCalUtils Library

  • kcalutils
htmlexport.cpp
1 /*
2  This file is part of the kcalutils library.
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 #include "htmlexport.h"
23 #include "htmlexportsettings.h"
24 #include "stringify.h"
25 
26 #include <kcalcore/memorycalendar.h>
27 using namespace KCalCore;
28 
29 #include <KDebug>
30 #include <KCalendarSystem>
31 #include <KGlobal>
32 #include <KLocale>
33 
34 #include <QtCore/QFile>
35 #include <QtCore/QMap>
36 #include <QtCore/QTextStream>
37 #include <QApplication>
38 
39 using namespace KCalUtils;
40 
41 static QString cleanChars( const QString &txt );
42 
43 //@cond PRIVATE
44 class KCalUtils::HtmlExport::Private
45 {
46  public:
47  Private( MemoryCalendar *calendar, HTMLExportSettings *settings )
48  : mCalendar( calendar ), mSettings( settings )
49  {}
50 
51  MemoryCalendar *mCalendar;
52  HTMLExportSettings *mSettings;
53  QMap<QDate,QString> mHolidayMap;
54 };
55 //@endcond
56 
57 HtmlExport::HtmlExport( MemoryCalendar *calendar, HTMLExportSettings *settings )
58  : d( new Private( calendar, settings ) )
59 {
60 }
61 
62 HtmlExport::~HtmlExport()
63 {
64  delete d;
65 }
66 
67 bool HtmlExport::save( const QString &fileName )
68 {
69  QString fn( fileName );
70  if ( fn.isEmpty() && d->mSettings ) {
71  fn = d->mSettings->outputFile();
72  }
73  if ( !d->mSettings || fn.isEmpty() ) {
74  return false;
75  }
76  QFile f( fileName );
77  if ( !f.open( QIODevice::WriteOnly ) ) {
78  return false;
79  }
80  QTextStream ts( &f );
81  bool success = save( &ts );
82  f.close();
83  return success;
84 }
85 
86 bool HtmlExport::save( QTextStream *ts )
87 {
88  if ( !d->mSettings ) {
89  return false;
90  }
91  ts->setCodec( "UTF-8" );
92  // Write HTML header
93  *ts << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" ";
94  *ts << "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl;
95 
96  *ts << "<html><head>" << endl;
97  *ts << " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=";
98  *ts << "UTF-8\" />" << endl;
99  if ( !d->mSettings->pageTitle().isEmpty() ) {
100  *ts << " <title>" << d->mSettings->pageTitle() << "</title>" << endl;
101  }
102  *ts << " <style type=\"text/css\">" << endl;
103  *ts << styleSheet();
104  *ts << " </style>" << endl;
105  *ts << "</head><body>" << endl;
106 
107  // FIXME: Write header
108  // (Heading, Calendar-Owner, Calendar-Date, ...)
109 
110  if ( d->mSettings->eventView() || d->mSettings->monthView() || d->mSettings->weekView() ) {
111  if ( !d->mSettings->eventTitle().isEmpty() ) {
112  *ts << "<h1>" << d->mSettings->eventTitle() << "</h1>" << endl;
113  }
114 
115  // Write Week View
116  if ( d->mSettings->weekView() ) {
117  createWeekView( ts );
118  }
119  // Write Month View
120  if ( d->mSettings->monthView() ) {
121  createMonthView( ts );
122  }
123  // Write Event List
124  if ( d->mSettings->eventView() ) {
125  createEventList( ts );
126  }
127  }
128 
129  // Write Todo List
130  if ( d->mSettings->todoView() ) {
131  if ( !d->mSettings->todoListTitle().isEmpty() ) {
132  *ts << "<h1>" << d->mSettings->todoListTitle() << "</h1>" << endl;
133  }
134  createTodoList( ts );
135  }
136 
137  // Write Journals
138  if ( d->mSettings->journalView() ) {
139  if ( !d->mSettings->journalTitle().isEmpty() ) {
140  *ts << "<h1>" << d->mSettings->journalTitle() << "</h1>" << endl;
141  }
142  createJournalView( ts );
143  }
144 
145  // Write Free/Busy
146  if ( d->mSettings->freeBusyView() ) {
147  if ( !d->mSettings->freeBusyTitle().isEmpty() ) {
148  *ts << "<h1>" << d->mSettings->freeBusyTitle() << "</h1>" << endl;
149  }
150  createFreeBusyView( ts );
151  }
152 
153  createFooter( ts );
154 
155  // Write HTML trailer
156  *ts << "</body></html>" << endl;
157 
158  return true;
159 }
160 
161 void HtmlExport::createMonthView( QTextStream *ts )
162 {
163  QDate start = fromDate();
164  start.setYMD( start.year(), start.month(), 1 ); // go back to first day in month
165 
166  QDate end( start.year(), start.month(), start.daysInMonth() );
167 
168  int startmonth = start.month();
169  int startyear = start.year();
170 
171  while ( start < toDate() ) {
172  // Write header
173  QDate hDate( start.year(), start.month(), 1 );
174  QString hMon = hDate.toString( "MMMM" );
175  QString hYear = hDate.toString( "yyyy" );
176  *ts << "<h2>"
177  << i18nc( "@title month and year", "%1 %2", hMon, hYear )
178  << "</h2>" << endl;
179  if ( KGlobal::locale()->weekStartDay() == 1 ) {
180  start = start.addDays( 1 - start.dayOfWeek() );
181  } else {
182  if ( start.dayOfWeek() != 7 ) {
183  start = start.addDays( -start.dayOfWeek() );
184  }
185  }
186  *ts << "<table border=\"1\">" << endl;
187 
188  // Write table header
189  *ts << " <tr>";
190  for ( int i=0; i < 7; ++i ) {
191  *ts << "<th>" << KGlobal::locale()->calendar()->weekDayName( start.addDays(i) ) << "</th>";
192  }
193  *ts << "</tr>" << endl;
194 
195  // Write days
196  while ( start <= end ) {
197  *ts << " <tr>" << endl;
198  for ( int i=0; i < 7; ++i ) {
199  *ts << " <td valign=\"top\"><table border=\"0\">";
200 
201  *ts << "<tr><td ";
202  if ( d->mHolidayMap.contains( start ) || start.dayOfWeek() == 7 ) {
203  *ts << "class=\"dateholiday\"";
204  } else {
205  *ts << "class=\"date\"";
206  }
207  *ts << ">" << QString::number( start.day() );
208 
209  if ( d->mHolidayMap.contains( start ) ) {
210  *ts << " <em>" << d->mHolidayMap[start] << "</em>";
211  }
212 
213  *ts << "</td></tr><tr><td valign=\"top\">";
214 
215  // Only print events within the from-to range
216  if ( start >= fromDate() && start <= toDate() ) {
217  Event::List events = d->mCalendar->events( start, d->mCalendar->timeSpec(),
218  EventSortStartDate,
219  SortDirectionAscending );
220  if ( events.count() ) {
221  *ts << "<table>";
222  Event::List::ConstIterator it;
223  for ( it = events.constBegin(); it != events.constEnd(); ++it ) {
224  if ( checkSecrecy( *it ) ) {
225  createEvent( ts, *it, start, false );
226  }
227  }
228  *ts << "</table>";
229  } else {
230  *ts << "&nbsp;";
231  }
232  }
233 
234  *ts << "</td></tr></table></td>" << endl;
235  start = start.addDays( 1 );
236  }
237  *ts << " </tr>" << endl;
238  }
239  *ts << "</table>" << endl;
240  startmonth += 1;
241  if ( startmonth > 12 ) {
242  startyear += 1;
243  startmonth = 1;
244  }
245  start.setYMD( startyear, startmonth, 1 );
246  end.setYMD( start.year(), start.month(), start.daysInMonth() );
247  }
248 }
249 
250 void HtmlExport::createEventList( QTextStream *ts )
251 {
252  int columns = 3;
253  *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">" << endl;
254  *ts << " <tr>" << endl;
255  *ts << " <th class=\"sum\">" << i18nc( "@title:column event start time",
256  "Start Time" ) << "</th>" << endl;
257  *ts << " <th>" << i18nc( "@title:column event end time",
258  "End Time" ) << "</th>" << endl;
259  *ts << " <th>" << i18nc( "@title:column event description",
260  "Event" ) << "</th>" << endl;
261  if ( d->mSettings->eventLocation() ) {
262  *ts << " <th>" << i18nc( "@title:column event locatin",
263  "Location" ) << "</th>" << endl;
264  ++columns;
265  }
266  if ( d->mSettings->eventCategories() ) {
267  *ts << " <th>" << i18nc( "@title:column event categories",
268  "Categories" ) << "</th>" << endl;
269  ++columns;
270  }
271  if ( d->mSettings->eventAttendees() ) {
272  *ts << " <th>" << i18nc( "@title:column event attendees",
273  "Attendees" ) << "</th>" << endl;
274  ++columns;
275  }
276 
277  *ts << " </tr>" << endl;
278 
279  for ( QDate dt = fromDate(); dt <= toDate(); dt = dt.addDays(1) ) {
280  kDebug() << "Getting events for" << dt.toString();
281  Event::List events = d->mCalendar->events( dt, d->mCalendar->timeSpec(),
282  EventSortStartDate,
283  SortDirectionAscending );
284  if ( events.count() ) {
285  *ts << " <tr><td colspan=\"" << QString::number( columns )
286  << "\" class=\"datehead\"><i>"
287  << KGlobal::locale()->formatDate( dt )
288  << "</i></td></tr>" << endl;
289 
290  Event::List::ConstIterator it;
291  for ( it = events.constBegin(); it != events.constEnd(); ++it ) {
292  if ( checkSecrecy( *it ) ) {
293  createEvent( ts, *it, dt );
294  }
295  }
296  }
297  }
298 
299  *ts << "</table>" << endl;
300 }
301 
302 void HtmlExport::createEvent ( QTextStream *ts,
303  const Event::Ptr &event,
304  const QDate &date,
305  bool withDescription )
306 {
307  kDebug() << event->summary();
308  *ts << " <tr>" << endl;
309 
310  if ( !event->allDay() ) {
311  if ( event->isMultiDay( d->mCalendar->timeSpec() ) && ( event->dtStart().date() != date ) ) {
312  *ts << " <td>&nbsp;</td>" << endl;
313  } else {
314  *ts << " <td valign=\"top\">"
315  << Stringify::formatTime( event->dtStart(), true, d->mCalendar->timeSpec() )
316  << "</td>" << endl;
317  }
318  if ( event->isMultiDay( d->mCalendar->timeSpec() ) && ( event->dtEnd().date() != date ) ) {
319  *ts << " <td>&nbsp;</td>" << endl;
320  } else {
321  *ts << " <td valign=\"top\">"
322  << Stringify::formatTime( event->dtEnd(), true, d->mCalendar->timeSpec() )
323  << "</td>" << endl;
324  }
325  } else {
326  *ts << " <td>&nbsp;</td><td>&nbsp;</td>" << endl;
327  }
328 
329  *ts << " <td class=\"sum\">" << endl;
330  *ts << " <b>" << cleanChars( event->summary() ) << "</b>" << endl;
331  if ( withDescription && !event->description().isEmpty() ) {
332  *ts << " <p>" << breakString( cleanChars( event->description() ) ) << "</p>" << endl;
333  }
334  *ts << " </td>" << endl;
335 
336  if ( d->mSettings->eventLocation() ) {
337  *ts << " <td>" << endl;
338  formatLocation( ts, event );
339  *ts << " </td>" << endl;
340  }
341 
342  if ( d->mSettings->eventCategories() ) {
343  *ts << " <td>" << endl;
344  formatCategories( ts, event );
345  *ts << " </td>" << endl;
346  }
347 
348  if ( d->mSettings->eventAttendees() ) {
349  *ts << " <td>" << endl;
350  formatAttendees( ts, event );
351  *ts << " </td>" << endl;
352  }
353 
354  *ts << " </tr>" << endl;
355 }
356 
357 void HtmlExport::createTodoList ( QTextStream *ts )
358 {
359  Todo::List rawTodoList = d->mCalendar->todos();
360 
361  int index = 0;
362  while ( index < rawTodoList.count() ) {
363  Todo::Ptr ev = rawTodoList[ index ];
364  Todo::Ptr subev = ev;
365  const QString uid = ev->relatedTo();
366  if ( !uid.isEmpty() ) {
367  Incidence::Ptr inc = d->mCalendar->incidence( uid );
368  if ( inc && inc->type() == Incidence::TypeTodo ) {
369  Todo::Ptr todo = inc.staticCast<Todo>();
370  if ( !rawTodoList.contains( todo ) ) {
371  rawTodoList.append( todo );
372  }
373  }
374  }
375  index = rawTodoList.indexOf( subev );
376  ++index;
377  }
378 
379  // FIXME: Sort list by priorities. This is brute force and should be
380  // replaced by a real sorting algorithm.
381  Todo::List todoList;
382  Todo::List::ConstIterator it;
383  for ( int i = 1; i <= 9; ++i ) {
384  for ( it = rawTodoList.constBegin(); it != rawTodoList.constEnd(); ++it ) {
385  if ( (*it)->priority() == i && checkSecrecy( *it ) ) {
386  todoList.append( *it );
387  }
388  }
389  }
390  for ( it = rawTodoList.constBegin(); it != rawTodoList.constEnd(); ++it ) {
391  if ( (*it)->priority() == 0 && checkSecrecy( *it ) ) {
392  todoList.append( *it );
393  }
394  }
395 
396  int columns = 3;
397  *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">" << endl;
398  *ts << " <tr>" << endl;
399  *ts << " <th class=\"sum\">" << i18nc( "@title:column", "To-do" ) << "</th>" << endl;
400  *ts << " <th>" << i18nc( "@title:column to-do priority", "Priority" ) << "</th>" << endl;
401  *ts << " <th>" << i18nc( "@title:column to-do percent completed",
402  "Completed" ) << "</th>" << endl;
403  if ( d->mSettings->taskDueDate() ) {
404  *ts << " <th>" << i18nc( "@title:column to-do due date", "Due Date" ) << "</th>" << endl;
405  ++columns;
406  }
407  if ( d->mSettings->taskLocation() ) {
408  *ts << " <th>" << i18nc( "@title:column to-do location", "Location" ) << "</th>" << endl;
409  ++columns;
410  }
411  if ( d->mSettings->taskCategories() ) {
412  *ts << " <th>" << i18nc( "@title:column to-do categories", "Categories" ) << "</th>" << endl;
413  ++columns;
414  }
415  if ( d->mSettings->taskAttendees() ) {
416  *ts << " <th>" << i18nc( "@title:column to-do attendees", "Attendees" ) << "</th>" << endl;
417  ++columns;
418  }
419  *ts << " </tr>" << endl;
420 
421  // Create top-level list.
422  for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
423  if ( (*it)->relatedTo().isEmpty() ) {
424  createTodo( ts, *it );
425  }
426  }
427 
428  // Create sub-level lists
429  for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
430  Incidence::List relations = d->mCalendar->relations( ( *it )->uid() );
431 
432  if ( relations.count() ) {
433  // Generate sub-to-do list
434  *ts << " <tr>" << endl;
435  *ts << " <td class=\"subhead\" colspan=";
436  *ts << "\"" << QString::number(columns) << "\"";
437  *ts << "><a name=\"sub" << (*it)->uid() << "\"></a>"
438  << i18nc( "@title:column sub-to-dos of the parent to-do",
439  "Sub-To-dos of: " ) << "<a href=\"#"
440  << (*it)->uid() << "\"><b>" << cleanChars( (*it)->summary() )
441  << "</b></a></td>" << endl;
442  *ts << " </tr>" << endl;
443 
444  Todo::List sortedList;
445  // FIXME: Sort list by priorities. This is brute force and should be
446  // replaced by a real sorting algorithm.
447  for ( int i = 1; i <= 9; ++i ) {
448  Incidence::List::ConstIterator it2;
449  for ( it2 = relations.constBegin(); it2 != relations.constEnd(); ++it2 ) {
450  Todo::Ptr ev3 = (*it2).staticCast<Todo>();
451  if ( ev3 && ev3->priority() == i ) {
452  sortedList.append( ev3 );
453  }
454  }
455  }
456  Incidence::List::ConstIterator it2;
457  for ( it2 = relations.constBegin(); it2 != relations.constEnd(); ++it2 ) {
458  Todo::Ptr ev3 = (*it2).staticCast<Todo>();
459  if ( ev3 && ev3->priority() == 0 ) {
460  sortedList.append( ev3 );
461  }
462  }
463 
464  Todo::List::ConstIterator it3;
465  for ( it3 = sortedList.constBegin(); it3 != sortedList.constEnd(); ++it3 ) {
466  createTodo( ts, *it3 );
467  }
468  }
469  }
470 
471  *ts << "</table>" << endl;
472 }
473 
474 void HtmlExport::createTodo( QTextStream *ts, const Todo::Ptr &todo )
475 {
476  kDebug();
477 
478  const bool completed = todo->isCompleted();
479 
480  Incidence::List relations = d->mCalendar->relations( todo->uid() );
481 
482  *ts << "<tr>" << endl;
483 
484  *ts << " <td class=\"sum";
485  if (completed) *ts << "done";
486  *ts << "\">" << endl;
487  *ts << " <a name=\"" << todo->uid() << "\"></a>" << endl;
488  *ts << " <b>" << cleanChars( todo->summary() ) << "</b>" << endl;
489  if ( !todo->description().isEmpty() ) {
490  *ts << " <p>" << breakString( cleanChars( todo->description() ) ) << "</p>" << endl;
491  }
492  if ( relations.count() ) {
493  *ts << " <div align=\"right\"><a href=\"#sub" << todo->uid()
494  << "\">" << i18nc( "@title:column sub-to-dos of the parent to-do",
495  "Sub-To-dos" ) << "</a></div>" << endl;
496  }
497  *ts << " </td>" << endl;
498 
499  *ts << " <td";
500  if ( completed ) {
501  *ts << " class=\"done\"";
502  }
503  *ts << ">" << endl;
504  *ts << " " << todo->priority() << endl;
505  *ts << " </td>" << endl;
506 
507  *ts << " <td";
508  if ( completed ) {
509  *ts << " class=\"done\"";
510  }
511  *ts << ">" << endl;
512  *ts << " " << i18nc( "@info/plain to-do percent complete",
513  "%1 %", todo->percentComplete() ) << endl;
514  *ts << " </td>" << endl;
515 
516  if ( d->mSettings->taskDueDate() ) {
517  *ts << " <td";
518  if ( completed ) {
519  *ts << " class=\"done\"";
520  }
521  *ts << ">" << endl;
522  if ( todo->hasDueDate() ) {
523  *ts << " " << Stringify::formatDate( todo->dtDue( true ) ) << endl;
524  } else {
525  *ts << " &nbsp;" << endl;
526  }
527  *ts << " </td>" << endl;
528  }
529 
530  if ( d->mSettings->taskLocation() ) {
531  *ts << " <td";
532  if ( completed ) {
533  *ts << " class=\"done\"";
534  }
535  *ts << ">" << endl;
536  formatLocation( ts, todo );
537  *ts << " </td>" << endl;
538  }
539 
540  if ( d->mSettings->taskCategories() ) {
541  *ts << " <td";
542  if ( completed ) {
543  *ts << " class=\"done\"";
544  }
545  *ts << ">" << endl;
546  formatCategories( ts, todo );
547  *ts << " </td>" << endl;
548  }
549 
550  if ( d->mSettings->taskAttendees() ) {
551  *ts << " <td";
552  if ( completed ) {
553  *ts << " class=\"done\"";
554  }
555  *ts << ">" << endl;
556  formatAttendees( ts, todo );
557  *ts << " </td>" << endl;
558  }
559 
560  *ts << "</tr>" << endl;
561 }
562 
563 void HtmlExport::createWeekView( QTextStream *ts )
564 {
565  Q_UNUSED( ts );
566  // FIXME: Implement this!
567 }
568 
569 void HtmlExport::createJournalView( QTextStream *ts )
570 {
571  Q_UNUSED( ts );
572 // Journal::List rawJournalList = d->mCalendar->journals();
573  // FIXME: Implement this!
574 }
575 
576 void HtmlExport::createFreeBusyView( QTextStream *ts )
577 {
578  Q_UNUSED( ts );
579  // FIXME: Implement this!
580 }
581 
582 bool HtmlExport::checkSecrecy( const Incidence::Ptr &incidence )
583 {
584  int secrecy = incidence->secrecy();
585  if ( secrecy == Incidence::SecrecyPublic ) {
586  return true;
587  }
588  if ( secrecy == Incidence::SecrecyPrivate && !d->mSettings->excludePrivate() ) {
589  return true;
590  }
591  if ( secrecy == Incidence::SecrecyConfidential &&
592  !d->mSettings->excludeConfidential() ) {
593  return true;
594  }
595  return false;
596 }
597 
598 void HtmlExport::formatLocation( QTextStream *ts,
599  const Incidence::Ptr &incidence )
600 {
601  if ( !incidence->location().isEmpty() ) {
602  *ts << " " << cleanChars( incidence->location() ) << endl;
603  } else {
604  *ts << " &nbsp;" << endl;
605  }
606 }
607 
608 void HtmlExport::formatCategories( QTextStream *ts,
609  const Incidence::Ptr &incidence )
610 {
611  if ( !incidence->categoriesStr().isEmpty() ) {
612  *ts << " " << cleanChars( incidence->categoriesStr() ) << endl;
613  } else {
614  *ts << " &nbsp;" << endl;
615  }
616 }
617 
618 void HtmlExport::formatAttendees( QTextStream *ts,
619  const Incidence::Ptr &incidence )
620 {
621  Attendee::List attendees = incidence->attendees();
622  if ( attendees.count() ) {
623  *ts << "<em>";
624  *ts << incidence->organizer()->fullName();
625  *ts << "</em><br />";
626  Attendee::List::ConstIterator it;
627  for ( it = attendees.constBegin(); it != attendees.constEnd(); ++it ) {
628  Attendee::Ptr a( *it );
629  if ( !a->email().isEmpty() ) {
630  *ts << "<a href=\"mailto:" << a->email();
631  *ts << "\">" << cleanChars( a->name() ) << "</a>";
632  } else {
633  *ts << " " << cleanChars( a->name() );
634  }
635  *ts << "<br />" << endl;
636  }
637  } else {
638  *ts << " &nbsp;" << endl;
639  }
640 }
641 
642 QString HtmlExport::breakString( const QString &text )
643 {
644  int number = text.count( "\n" );
645  if ( number <= 0 ) {
646  return text;
647  } else {
648  QString out;
649  QString tmpText = text;
650  int pos = 0;
651  QString tmp;
652  for ( int i = 0; i <= number; ++i ) {
653  pos = tmpText.indexOf( "\n" );
654  tmp = tmpText.left( pos );
655  tmpText = tmpText.right( tmpText.length() - pos - 1 );
656  out += tmp + "<br />";
657  }
658  return out;
659  }
660 }
661 
662 void HtmlExport::createFooter( QTextStream *ts )
663 {
664  // FIXME: Implement this in a translatable way!
665  QString trailer = i18nc( "@info/plain", "This page was created " );
666 
667 /* bool hasPerson = false;
668  bool hasCredit = false;
669  bool hasCreditURL = false;
670  QString mail, name, credit, creditURL;*/
671  if ( !d->mSettings->eMail().isEmpty() ) {
672  if ( !d->mSettings->name().isEmpty() ) {
673  trailer += i18nc( "@info/plain page creator email link with name",
674  "by <link url='mailto:%1'>%2</link> ",
675  d->mSettings->eMail(), d->mSettings->name() );
676  } else {
677  trailer += i18nc( "@info/plain page creator email link",
678  "by <link url='mailto:%1'>%2</link> ",
679  d->mSettings->eMail(), d->mSettings->eMail() );
680  }
681  } else {
682  if ( !d->mSettings->name().isEmpty() ) {
683  trailer += i18nc( "@info/plain page creator name only",
684  "by %1 ", d->mSettings->name() );
685  }
686  }
687  if ( !d->mSettings->creditName().isEmpty() ) {
688  if ( !d->mSettings->creditURL().isEmpty() ) {
689  trailer += i18nc( "@info/plain page credit with name and link",
690  "with <link url='%1'>%2</link>",
691  d->mSettings->creditURL(), d->mSettings->creditName() );
692  } else {
693  trailer += i18nc( "@info/plain page credit name only",
694  "with %1", d->mSettings->creditName() );
695  }
696  }
697  *ts << "<p>" << trailer << "</p>" << endl;
698 }
699 
700 QString cleanChars( const QString &text )
701 {
702  QString txt = text;
703  txt = txt.replace( '&', "&amp;" );
704  txt = txt.replace( '<', "&lt;" );
705  txt = txt.replace( '>', "&gt;" );
706  txt = txt.replace( '\"', "&quot;" );
707  txt = txt.replace( QString::fromUtf8( "ä" ), "&auml;" );
708  txt = txt.replace( QString::fromUtf8( "Ä" ), "&Auml;" );
709  txt = txt.replace( QString::fromUtf8( "ö" ), "&ouml;" );
710  txt = txt.replace( QString::fromUtf8( "Ö" ), "&Ouml;" );
711  txt = txt.replace( QString::fromUtf8( "ü" ), "&uuml;" );
712  txt = txt.replace( QString::fromUtf8( "Ü" ), "&Uuml;" );
713  txt = txt.replace( QString::fromUtf8( "ß" ), "&szlig;" );
714  txt = txt.replace( QString::fromUtf8( "€" ), "&euro;" );
715  txt = txt.replace( QString::fromUtf8( "é" ), "&eacute;" );
716 
717  return txt;
718 }
719 
720 QString HtmlExport::styleSheet() const
721 {
722  if ( !d->mSettings->styleSheet().isEmpty() ) {
723  return d->mSettings->styleSheet();
724  }
725 
726  QString css;
727 
728  if ( QApplication::isRightToLeft() ) {
729  css += " body { background-color:white; color:black; direction: rtl }\n";
730  css += " td { text-align:center; background-color:#eee }\n";
731  css += " th { text-align:center; background-color:#228; color:white }\n";
732  css += " td.sumdone { background-color:#ccc }\n";
733  css += " td.done { background-color:#ccc }\n";
734  css += " td.subhead { text-align:center; background-color:#ccf }\n";
735  css += " td.datehead { text-align:center; background-color:#ccf }\n";
736  css += " td.space { background-color:white }\n";
737  css += " td.dateholiday { color:red }\n";
738  } else {
739  css += " body { background-color:white; color:black }\n";
740  css += " td { text-align:center; background-color:#eee }\n";
741  css += " th { text-align:center; background-color:#228; color:white }\n";
742  css += " td.sum { text-align:left }\n";
743  css += " td.sumdone { text-align:left; background-color:#ccc }\n";
744  css += " td.done { background-color:#ccc }\n";
745  css += " td.subhead { text-align:center; background-color:#ccf }\n";
746  css += " td.datehead { text-align:center; background-color:#ccf }\n";
747  css += " td.space { background-color:white }\n";
748  css += " td.date { text-align:left }\n";
749  css += " td.dateholiday { text-align:left; color:red }\n";
750  }
751 
752  return css;
753 }
754 
755 void HtmlExport::addHoliday( const QDate &date, const QString &name )
756 {
757  if ( d->mHolidayMap[date].isEmpty() ) {
758  d->mHolidayMap[date] = name;
759  } else {
760  d->mHolidayMap[date] = i18nc( "@info/plain holiday by date and name",
761  "%1, %2", d->mHolidayMap[date], name );
762  }
763 }
764 
765 QDate HtmlExport::fromDate() const
766 {
767  return d->mSettings->dateStart().date();
768 }
769 
770 QDate HtmlExport::toDate() const
771 {
772  return d->mSettings->dateEnd().date();
773 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jul 13 2013 01:26:45 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KCalUtils Library

Skip menu "KCalUtils Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.10.5 API Reference

Skip menu "kdepimlibs-4.10.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal