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

korganizer

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

KDE's Doxygen guidelines are available online.

korganizer

Skip menu "korganizer"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

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