• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.14.10 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>
27using 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
39using namespace KCalUtils;
40
41static QString cleanChars(const QString &txt);
42
43//@cond PRIVATE
44class KCalUtils::HtmlExport::Private
45{
46public:
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
57HtmlExport::HtmlExport(MemoryCalendar *calendar, HTMLExportSettings *settings)
58 : d(new Private(calendar, settings))
59{
60}
61
62HtmlExport::~HtmlExport()
63{
64 delete d;
65}
66
67bool 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
86bool 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
161void 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
250void 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
302void 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
357void 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
474void 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
563void HtmlExport::createWeekView(QTextStream *ts)
564{
565 Q_UNUSED(ts);
566 // FIXME: Implement this!
567}
568
569void HtmlExport::createJournalView(QTextStream *ts)
570{
571 Q_UNUSED(ts);
572// Journal::List rawJournalList = d->mCalendar->journals();
573 // FIXME: Implement this!
574}
575
576void HtmlExport::createFreeBusyView(QTextStream *ts)
577{
578 Q_UNUSED(ts);
579 // FIXME: Implement this!
580}
581
582bool 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
598void 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
608void 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
618void 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
642QString 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
662void 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
700QString 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
720QString 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
755void 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
765QDate HtmlExport::fromDate() const
766{
767 return d->mSettings->dateStart().date();
768}
769
770QDate HtmlExport::toDate() const
771{
772 return d->mSettings->dateEnd().date();
773}
KCalCore::Attendee::List
QVector< Ptr > List
KCalCore::Attendee::Ptr
QSharedPointer< Attendee > Ptr
KCalCore::Event::Ptr
QSharedPointer< Event > Ptr
KCalCore::Event::List
QVector< Ptr > List
KCalCore::Incidence::List
QVector< Ptr > List
KCalCore::Incidence::SecrecyPrivate
SecrecyPrivate
KCalCore::Incidence::SecrecyConfidential
SecrecyConfidential
KCalCore::Incidence::SecrecyPublic
SecrecyPublic
KCalCore::Incidence::Ptr
QSharedPointer< Incidence > Ptr
KCalCore::MemoryCalendar
KCalCore::Todo
KCalCore::Todo::List
QVector< Ptr > List
KCalCore::Todo::Ptr
QSharedPointer< Todo > Ptr
KCalUtils::HtmlExport::save
bool save(const QString &fileName=QString())
Writes out the calendar in HTML format.
Definition: htmlexport.cpp:67
KCalUtils::HtmlExport::HtmlExport
HtmlExport(KCalCore::MemoryCalendar *calendar, HTMLExportSettings *settings)
Create new HTML exporter for calendar.
Definition: htmlexport.cpp:57
memorycalendar.h
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
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
stringify.h
This file is part of the API for handling calendar data and provides static functions for formatting ...
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Jul 21 2022 00:00:00 by doxygen 1.9.5 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.14.10 API Reference

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