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

korganizer

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

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