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

KCalUtils Library

  • sources
  • kde-4.14
  • kdepimlibs
  • 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 <KLocalizedString>
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(QLatin1String("MMMM"));
175  QString hYear = hDate.toString(QLatin1String("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(QLatin1String("\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(QLatin1String("\n"));
654  tmp = tmpText.left(pos);
655  tmpText = tmpText.right(tmpText.length() - pos - 1);
656  out += tmp + QLatin1String("<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(QLatin1Char('&'), QLatin1String("&amp;"));
704  txt = txt.replace(QLatin1Char('<'), QLatin1String("&lt;"));
705  txt = txt.replace(QLatin1Char('>'), QLatin1String("&gt;"));
706  txt = txt.replace(QLatin1Char('\"'), QLatin1String("&quot;"));
707  txt = txt.replace(QString::fromUtf8("ä"), QLatin1String("&auml;"));
708  txt = txt.replace(QString::fromUtf8("Ä"), QLatin1String("&Auml;"));
709  txt = txt.replace(QString::fromUtf8("ö"), QLatin1String("&ouml;"));
710  txt = txt.replace(QString::fromUtf8("Ö"), QLatin1String("&Ouml;"));
711  txt = txt.replace(QString::fromUtf8("ü"), QLatin1String("&uuml;"));
712  txt = txt.replace(QString::fromUtf8("Ü"), QLatin1String("&Uuml;"));
713  txt = txt.replace(QString::fromUtf8("ß"), QLatin1String("&szlig;"));
714  txt = txt.replace(QString::fromUtf8("€"), QLatin1String("&euro;"));
715  txt = txt.replace(QString::fromUtf8("é"), QLatin1String("&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 += QLatin1String(" body { background-color:white; color:black; direction: rtl }\n");
730  css += QLatin1String(" td { text-align:center; background-color:#eee }\n");
731  css += QLatin1String(" th { text-align:center; background-color:#228; color:white }\n");
732  css += QLatin1String(" td.sumdone { background-color:#ccc }\n");
733  css += QLatin1String(" td.done { background-color:#ccc }\n");
734  css += QLatin1String(" td.subhead { text-align:center; background-color:#ccf }\n");
735  css += QLatin1String(" td.datehead { text-align:center; background-color:#ccf }\n");
736  css += QLatin1String(" td.space { background-color:white }\n");
737  css += QLatin1String(" td.dateholiday { color:red }\n");
738  } else {
739  css += QLatin1String(" body { background-color:white; color:black }\n");
740  css += QLatin1String(" td { text-align:center; background-color:#eee }\n");
741  css += QLatin1String(" th { text-align:center; background-color:#228; color:white }\n");
742  css += QLatin1String(" td.sum { text-align:left }\n");
743  css += QLatin1String(" td.sumdone { text-align:left; background-color:#ccc }\n");
744  css += QLatin1String(" td.done { background-color:#ccc }\n");
745  css += QLatin1String(" td.subhead { text-align:center; background-color:#ccf }\n");
746  css += QLatin1String(" td.datehead { text-align:center; background-color:#ccf }\n");
747  css += QLatin1String(" td.space { background-color:white }\n");
748  css += QLatin1String(" td.date { text-align:left }\n");
749  css += QLatin1String(" 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 }
QTextStream::setCodec
void setCodec(QTextCodec *codec)
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QApplication::isRightToLeft
bool isRightToLeft()
KCalUtils::HtmlExport::save
bool save(const QString &fileName=QString())
Writes out the calendar in HTML format.
Definition: htmlexport.cpp:67
QVector::append
void append(const T &value)
QDate::daysInMonth
int daysInMonth() const
memorycalendar.h
QVector::indexOf
int indexOf(const T &value, int from) const
QVector::constEnd
const_iterator constEnd() const
QMap
KCalUtils::Stringify::formatDate
KCALUTILS_EXPORT QString formatDate(const KDateTime &dt, bool shortfmt=true, const KDateTime::Spec &spec=KDateTime::Spec())
Build a QString date representation of a KDateTime object.
Definition: stringify.cpp:222
QDate::month
int month() const
QFile
QTextStream
QDate::dayOfWeek
int dayOfWeek() const
QString::number
QString number(int n, int base)
QVector::contains
bool contains(const T &value) const
QString::fromUtf8
QString fromUtf8(const char *str, int size)
KCalCore::MemoryCalendar
QSharedPointer
QDate::setYMD
bool setYMD(int y, int m, int d)
QString::isEmpty
bool isEmpty() const
QDate::day
int day() const
stringify.h
This file is part of the API for handling calendar data and provides static functions for formatting ...
QDate
QDate::year
int year() const
QString
SortDirectionAscending
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
QString::right
QString right(int n) const
QLatin1Char
QFile::close
virtual void close()
QString::replace
QString & replace(int position, int n, QChar after)
QVector::constBegin
const_iterator constBegin() const
QVector
QLatin1String
KCalUtils::Stringify::formatTime
KCALUTILS_EXPORT QString formatTime(const KDateTime &dt, bool shortfmt=true, const KDateTime::Spec &spec=KDateTime::Spec())
Build a QString time representation of a KDateTime object.
Definition: stringify.cpp:207
QString::count
int count() const
KCalCore::Todo
QVector::count
int count(const T &value) const
QString::length
int length() const
QString::left
QString left(int n) const
QDate::addDays
QDate addDays(int ndays) const
QSharedPointer::staticCast
QSharedPointer< X > staticCast() const
EventSortStartDate
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:37:46 by doxygen 1.8.7 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 API Reference

Skip menu "kdepimlibs 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

Search



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