23 #include <tqapplication.h>
25 #include <tqtextstream.h>
26 #include <tqtextcodec.h>
29 #include <kcharsets.h>
30 #include <tdeglobal.h>
31 #include <tdelocale.h>
33 #include <kcalendarsystem.h>
36 #include <libkcal/event.h>
37 #include <libkcal/incidenceformatter.h>
38 #include <libkcal/todo.h>
41 #include <tdeabc/stdaddressbook.h>
43 #include "htmlexport.h"
44 #include "htmlexportsettings.h"
49 mCalendar( calendar ), mSettings( settings )
55 TQString fn( fileName );
56 if ( fn.isEmpty() && mSettings ) {
57 fn = mSettings->outputFile();
59 if ( !mSettings || fn.isEmpty() ) {
63 if ( !f.open(IO_WriteOnly)) {
67 bool success =
save(&ts);
74 if ( !mSettings )
return false;
75 ts->setEncoding( TQTextStream::UnicodeUTF8 );
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";
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";
89 *ts <<
"</head><body>\n";
94 if ( mSettings->eventView() || mSettings->monthView() || mSettings->weekView() ) {
95 if (!mSettings->eventTitle().isEmpty())
96 *ts <<
"<h1>" << mSettings->eventTitle() <<
"</h1>\n";
99 if ( mSettings->weekView() )
100 createWeekView( ts );
102 if ( mSettings->monthView() )
103 createMonthView( ts );
105 if ( mSettings->eventView() )
106 createEventList( ts );
110 if ( mSettings->todoView() ) {
111 if ( !mSettings->todoListTitle().isEmpty())
112 *ts <<
"<h1>" << mSettings->todoListTitle() <<
"</h1>\n";
117 if ( mSettings->journalView() ) {
118 if ( !mSettings->journalTitle().isEmpty())
119 *ts <<
"<h1>" << mSettings->journalTitle() <<
"</h1>\n";
120 createJournalView(ts);
124 if ( mSettings->freeBusyView() ) {
125 if ( !mSettings->freeBusyTitle().isEmpty())
126 *ts <<
"<h1>" << mSettings->freeBusyTitle() <<
"</h1>\n";
127 createFreeBusyView(ts);
133 *ts <<
"</body></html>\n";
138 void HtmlExport::createMonthView(TQTextStream *ts)
140 TQDate start = fromDate();
141 start.setYMD( start.year(), start.month(), 1 );
143 TQDate end( start.year(), start.month(), start.daysInMonth() );
145 int startmonth = start.month();
146 int startyear = start.year();
148 while ( start < toDate() ) {
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());
155 if (start.dayOfWeek() != 7) {
156 start = start.addDays(-start.dayOfWeek());
159 *ts <<
"<table border=\"1\">\n";
163 for(
int i=0; i<7; ++i) {
164 *ts <<
"<th>" << TDEGlobal::locale()->calendar()->weekDayName( start.addDays(i) ) <<
"</th>";
169 while (start <= end) {
171 for(
int i=0;i<7;++i) {
172 *ts <<
" <td valign=\"top\"><table border=\"0\">";
175 if (mHolidayMap.contains(start) || start.dayOfWeek() == 7) {
176 *ts <<
"class=\"dateholiday\"";
178 *ts <<
"class=\"date\"";
180 *ts <<
">" << TQString::number(start.day());
182 if (mHolidayMap.contains(start)) {
183 *ts <<
" <em>" << mHolidayMap[start] <<
"</em>";
186 *ts <<
"</td></tr><tr><td valign=\"top\">";
189 if ( start >= fromDate() && start <= toDate() ) {
193 if (events.count()) {
195 Event::List::ConstIterator it;
196 for( it = events.begin(); it != events.end(); ++it ) {
197 if ( checkSecrecy( *it ) ) {
198 createEvent( ts, *it, start,
false );
207 *ts <<
"</td></tr></table></td>\n";
208 start = start.addDays(1);
214 if ( startmonth > 12 ) {
218 start.setYMD( startyear, startmonth, 1 );
219 end.setYMD(start.year(),start.month(),start.daysInMonth());
223 void HtmlExport::createEventList (TQTextStream *ts)
226 *ts <<
"<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">\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";
235 if ( mSettings->eventCategories() ) {
236 *ts <<
" <th>" << i18n(
"Categories") <<
"</th>\n";
239 if ( mSettings->eventAttendees() ) {
240 *ts <<
" <th>" << i18n(
"Attendees") <<
"</th>\n";
246 for ( TQDate dt = fromDate(); dt <= toDate(); dt = dt.addDays(1) ) {
247 kdDebug(5850) <<
"Getting events for " << TQString(dt.toString()) << endl;
251 if (events.count()) {
252 Event::List::ConstIterator it;
254 for( it = events.begin(); it != events.end(); ++it ) {
255 if ( checkSecrecy( *it ) ) {
257 *ts <<
" <tr><td colspan=\"" << TQString::number(columns)
258 <<
"\" class=\"datehead\"><i>"
259 << TDEGlobal::locale()->formatDate(dt)
260 <<
"</i></td></tr>\n";
263 createEvent( ts, *it, dt );
272 void HtmlExport::createEvent (TQTextStream *ts,
Event *event,
273 TQDate date,
bool withDescription)
275 kdDebug(5850) <<
"HtmlExport::createEvent(): " <<
event->summary() << endl;
280 *ts <<
" <td> </td>\n";
282 *ts <<
" <td valign=\"top\">"
283 << IncidenceFormatter::timeToString( event->
dtStart(),
true )
287 *ts <<
" <td> </td>\n";
289 *ts <<
" <td valign=\"top\">"
290 << IncidenceFormatter::timeToString( event->
dtEnd(),
true )
294 *ts <<
" <td> </td><td> </td>\n";
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";
304 if ( mSettings->eventLocation() ) {
306 formatLocation( ts, event );
310 if ( mSettings->eventCategories() ) {
312 formatCategories( ts, event );
316 if ( mSettings->eventAttendees() ) {
318 formatAttendees( ts, event );
325 void HtmlExport::createTodoList ( TQTextStream *ts )
329 Todo::List::Iterator it = rawTodoList.begin();
330 while ( it != rawTodoList.end() ) {
335 if ( rawTodoList.find(
static_cast<Todo *
>( ev->
relatedTo() ) ) ==
336 rawTodoList.end() ) {
337 rawTodoList.append(
static_cast<Todo *
>( ev->
relatedTo() ) );
341 it = rawTodoList.find( subev );
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 );
355 for( it = rawTodoList.begin(); it != rawTodoList.end(); ++it ) {
356 if ( (*it)->priority() == 0 && checkSecrecy( *it ) ) {
357 todoList.append( *it );
362 *ts <<
"<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">\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";
371 if ( mSettings->taskLocation() ) {
372 *ts <<
" <th>" << i18n(
"Location") <<
"</th>\n";
375 if ( mSettings->taskCategories() ) {
376 *ts <<
" <th>" << i18n(
"Categories") <<
"</th>\n";
379 if ( mSettings->taskAttendees() ) {
380 *ts <<
" <th>" << i18n(
"Attendees") <<
"</th>\n";
386 for( it = todoList.begin(); it != todoList.end(); ++it ) {
387 if ( !(*it)->relatedTo() ) createTodo( ts, *it );
391 for( it = todoList.begin(); it != todoList.end(); ++it ) {
393 if (relations.count()) {
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";
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 );
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 );
420 Todo::List::ConstIterator it3;
421 for( it3 = sortedList.begin(); it3 != sortedList.end(); ++it3 ) {
422 createTodo( ts, *it3 );
430 void HtmlExport::createTodo (TQTextStream *ts,
Todo *todo)
432 kdDebug(5850) <<
"HtmlExport::createTodo()" << endl;
439 *ts <<
" <td class=\"sum";
440 if (completed) *ts <<
"done";
442 *ts <<
" <a name=\"" << todo->
uid() <<
"\"></a>\n";
443 *ts <<
" <b>" << cleanChars(todo->
summary()) <<
"</b>\n";
445 *ts <<
" <p>" << breakString(cleanChars(todo->
description())) <<
"</p>\n";
447 if (relations.count()) {
448 *ts <<
" <div align=\"right\"><a href=\"#sub" << todo->
uid()
449 <<
"\">" << i18n(
"Sub-Tasks") <<
"</a></div>\n";
454 if (completed) *ts <<
" class=\"done\"";
456 *ts <<
" " << todo->
priority() <<
"\n";
460 if (completed) *ts <<
" class=\"done\"";
465 if ( mSettings->taskDueDate() ) {
467 if (completed) *ts <<
" class=\"done\"";
470 *ts <<
" " << IncidenceFormatter::dateToString( todo->
dtDue(
true ) ) <<
"\n";
477 if ( mSettings->taskLocation() ) {
479 if (completed) *ts <<
" class=\"done\"";
481 formatLocation(ts,todo);
485 if ( mSettings->taskCategories() ) {
487 if (completed) *ts <<
" class=\"done\"";
489 formatCategories(ts,todo);
493 if ( mSettings->taskAttendees() ) {
495 if (completed) *ts <<
" class=\"done\"";
497 formatAttendees(ts,todo);
504 void HtmlExport::createWeekView( TQTextStream * )
509 void HtmlExport::createJournalView( TQTextStream * )
515 void HtmlExport::createFreeBusyView( TQTextStream * )
520 bool HtmlExport::checkSecrecy(
Incidence *incidence )
522 int secrecy = incidence->
secrecy();
523 if ( secrecy == Incidence::SecrecyPublic ) {
526 if ( secrecy == Incidence::SecrecyPrivate && !mSettings->excludePrivate() ) {
529 if ( secrecy == Incidence::SecrecyConfidential &&
530 !mSettings->excludeConfidential() ) {
536 void HtmlExport::formatLocation (TQTextStream *ts,
Incidence *event)
539 *ts <<
" " << cleanChars(event->
location()) <<
"\n";
545 void HtmlExport::formatCategories (TQTextStream *ts,
Incidence *event)
554 void HtmlExport::formatAttendees( TQTextStream *ts,
Incidence *event )
557 if (attendees.count()) {
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";
568 else *ts <<
event->organizer().fullName();
570 *ts <<
event->organizer().fullName();
572 *ts <<
"</em><br />";
573 Attendee::List::ConstIterator it;
574 for( it = attendees.begin(); it != attendees.end(); ++it ) {
576 if (!a->email().isEmpty()) {
577 *ts <<
"<a href=\"mailto:" << a->email();
578 *ts <<
"\">" << cleanChars(a->name()) <<
"</a>";
581 *ts <<
" " << cleanChars(a->name());
583 *ts <<
"<br />" <<
"\n";
590 TQString HtmlExport::breakString(
const TQString &text)
592 int number = text.contains(
"\n");
597 TQString tmpText = text;
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 />";
610 void HtmlExport::createFooter( TQTextStream *ts )
613 TQString trailer = i18n(
"This page was created ");
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() );
623 trailer += i18n(
"by <a href=\"mailto:%1\">%2</a> ").arg( mSettings->eMail() ).arg( mSettings->eMail() );
625 if (!mSettings->name().isEmpty())
626 trailer += i18n(
"by %1 ").arg( mSettings->name() );
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() );
634 trailer += i18n(
"with %1").arg( mSettings->creditName() );
636 *ts <<
"<p>" << trailer <<
"</p>\n";
640 TQString HtmlExport::cleanChars(
const TQString &text)
643 txt = txt.replace(
"&",
"&" );
644 txt = txt.replace(
"<",
"<" );
645 txt = txt.replace(
">",
">" );
646 txt = txt.replace(
"\"",
""" );
647 txt = txt.replace( TQString::fromUtf8(
"ä"),
"ä" );
648 txt = txt.replace( TQString::fromUtf8(
"á"),
"á" );
649 txt = txt.replace( TQString::fromUtf8(
"à"),
"à" );
650 txt = txt.replace( TQString::fromUtf8(
"â"),
"â" );
651 txt = txt.replace( TQString::fromUtf8(
"Ä"),
"Ä" );
652 txt = txt.replace( TQString::fromUtf8(
"ó"),
"ó" );
653 txt = txt.replace( TQString::fromUtf8(
"ô"),
"ô" );
654 txt = txt.replace( TQString::fromUtf8(
"ö"),
"ö" );
655 txt = txt.replace( TQString::fromUtf8(
"Ö"),
"Ö" );
656 txt = txt.replace( TQString::fromUtf8(
"ü"),
"ü" );
657 txt = txt.replace( TQString::fromUtf8(
"Ü"),
"Ü" );
658 txt = txt.replace( TQString::fromUtf8(
"ß"),
"ß" );
659 txt = txt.replace( TQString::fromUtf8(
"€"),
"€" );
660 txt = txt.replace( TQString::fromUtf8(
"é"),
"é" );
661 txt = txt.replace( TQString::fromUtf8(
"ë"),
"ë" );
662 txt = txt.replace( TQString::fromUtf8(
"è"),
"è" );
663 txt = txt.replace( TQString::fromUtf8(
"ñ"),
"ñ" );
664 txt = txt.replace( TQString::fromUtf8(
"ç"),
"ç" );
669 TQString HtmlExport::styleSheet()
const
671 if ( !mSettings->styleSheet().isEmpty() )
672 return mSettings->styleSheet();
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";
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";
704 void HtmlExport::addHoliday(
const TQDate &date,
const TQString &name)
706 if ( mHolidayMap[date].isEmpty() ) {
707 mHolidayMap[date] = name;
709 mHolidayMap[date] = i18n(
"list of holidays",
"%1, %2").arg(mHolidayMap[date]).arg(name);
713 TQDate HtmlExport::fromDate()
const
715 return mSettings->dateStart().date();
718 TQDate HtmlExport::toDate()
const
720 return mSettings->dateEnd().date();
Provides the main "calendar" object class.
This class represents information related to an attendee of an event.
This is the main "calendar" object class.
virtual Event::List events(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Return a sorted, filtered list of all Events for this Calendar.
virtual Todo::List todos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Return a sorted, filtered list of all Todos for this Calendar.
This class provides an Event in the sense of RFC2445.
virtual TQDateTime dtEnd() const
Return end date and time.
bool isMultiDay() const
Return true if the event spans multiple days, otherwise return false.
HtmlExport(Calendar *calendar, HTMLExportSettings *settings)
Create new HTML exporter for calendar.
bool save(const TQString &fileName=TQString())
Writes out the calendar in HTML format.
bool doesFloat() const
Return true or false depending on whether the incidence "floats," i.e.
TQString uid() const
Return the unique id for the event.
virtual TQDateTime dtStart() const
returns an event's starting date/time as a TQDateTime.
This class provides the base class common to all calendar components.
int secrecy() const
Return the event's secrecy.
TQString description() const
Return long description.
Incidence * relatedTo() const
What event does this one relate to?
int priority() const
Return priority.
Incidence::List relations() const
All events that are related to this event.
TQString location() const
Return the event's/todo's location.
TQString categoriesStr() const
Return categories as a comma separated string.
TQString summary() const
Return short summary.
This class provides a Todo in the sense of RFC2445.
bool hasDueDate() const
Returns true if the todo has a due date, otherwise return false.
bool isCompleted() const
Returns true if the todo is 100% completed, otherwise return false.
int percentComplete() const
Returns how many percent of the task are completed.
TQDateTime dtDue(bool first=false) const
Returns due date and time.
Namespace KCal is for global classes, objects and/or functions in libkcal.
@ EventSortStartDate
Sort Events chronologically, by start date.
@ SortDirectionAscending
Sort in ascending order (first to last)