korganizer

calprintdefaultplugins.cpp
1 /*
2  This file is part of KOrganizer.
3 
4  Copyright (c) 1998 Preston Brown <pbrown@kde.org>
5  Copyright (c) 2003 Reinhold Kainhofer <reinhold@kainhofer.com>
6  Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
7  Copyright (c) 2008 Ron Goodheart <ron.goodheart@gmail.com>
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 
23  As a special exception, permission is given to link this program
24  with any edition of TQt, and distribute the resulting executable,
25  without including the source code for TQt in the source distribution.
26 */
27 
28 #ifndef KORG_NOPRINTER
29 
30 #include <tqpainter.h>
31 #include <tqdatetimeedit.h>
32 #include <tqcheckbox.h>
33 #include <tqlineedit.h>
34 #include <tqbuttongroup.h>
35 
36 #include <kdebug.h>
37 #include <tdeconfig.h>
38 #include <kcalendarsystem.h>
39 #include <knuminput.h>
40 #include <kcombobox.h>
41 
42 #include <libkcal/incidenceformatter.h>
43 
44 #include "calprintdefaultplugins.h"
45 
46 #include "calprintincidenceconfig_base.h"
47 #include "calprintdayconfig_base.h"
48 #include "calprintweetdeconfig_base.h"
49 #include "calprintmonthconfig_base.h"
50 #include "calprinttodoconfig_base.h"
51 
52 static TQString cleanString( const TQString &instr )
53 {
54  TQString ret = instr;
55  return ret.replace( '\n', ' ' );
56 }
57 
58 /**************************************************************
59  * Print Incidence
60  **************************************************************/
61 
62 CalPrintIncidence::CalPrintIncidence() : CalPrintPluginBase()
63 {
64 }
65 
66 CalPrintIncidence::~CalPrintIncidence()
67 {
68 }
69 
70 TQWidget *CalPrintIncidence::createConfigWidget( TQWidget *w )
71 {
72  return new CalPrintIncidenceConfig_Base( w );
73 }
74 
75 void CalPrintIncidence::readSettingsWidget()
76 {
77  CalPrintIncidenceConfig_Base *cfg =
78  dynamic_cast<CalPrintIncidenceConfig_Base*>( mConfigWidget );
79  if ( cfg ) {
80  mUseColors = cfg->mColors->isChecked();
81  mShowOptions = cfg->mShowDetails->isChecked();
82  mShowSubitemsNotes = cfg->mShowSubitemsNotes->isChecked();
83  mShowAttendees = cfg->mShowAttendees->isChecked();
84  mShowAttachments = cfg->mShowAttachments->isChecked();
85  }
86 }
87 
88 void CalPrintIncidence::setSettingsWidget()
89 {
90  CalPrintIncidenceConfig_Base *cfg =
91  dynamic_cast<CalPrintIncidenceConfig_Base*>( mConfigWidget );
92  if ( cfg ) {
93  cfg->mColors->setChecked( mUseColors );
94  cfg->mShowDetails->setChecked(mShowOptions);
95  cfg->mShowSubitemsNotes->setChecked(mShowSubitemsNotes);
96  cfg->mShowAttendees->setChecked(mShowAttendees);
97  cfg->mShowAttachments->setChecked(mShowAttachments);
98  }
99 }
100 
101 void CalPrintIncidence::loadConfig()
102 {
103  if ( mConfig ) {
104  mUseColors = mConfig->readBoolEntry( "Use Colors", false );
105  mShowOptions = mConfig->readBoolEntry( "Show Options", false );
106  mShowSubitemsNotes = mConfig->readBoolEntry( "Show Subitems and Notes", false );
107  mShowAttendees = mConfig->readBoolEntry( "Use Attendees", false );
108  mShowAttachments = mConfig->readBoolEntry( "Use Attachments", false );
109  }
110  setSettingsWidget();
111 }
112 
113 void CalPrintIncidence::saveConfig()
114 {
115  readSettingsWidget();
116  if ( mConfig ) {
117  mConfig->writeEntry( "Use Colors", mUseColors );
118  mConfig->writeEntry( "Show Options", mShowOptions );
119  mConfig->writeEntry( "Show Subitems and Notes", mShowSubitemsNotes );
120  mConfig->writeEntry( "Use Attendees", mShowAttendees );
121  mConfig->writeEntry( "Use Attachments", mShowAttachments );
122  }
123 }
124 
125 
126 class TimePrintStringsVisitor : public IncidenceBase::Visitor
127 {
128  public:
129  TimePrintStringsVisitor() {}
130 
131  bool act( IncidenceBase *incidence )
132  {
133  return incidence->accept( *this );
134  }
135  TQString mStartCaption, mStartString;
136  TQString mEndCaption, mEndString;
137  TQString mDurationCaption, mDurationString;
138 
139  protected:
140  bool visit( Event *event ) {
141  if ( event->dtStart().isValid() ) {
142  mStartCaption = i18n( "Start date: " );
143  mStartString = IncidenceFormatter::dateTimeToString(
144  event->dtStart(), event->doesFloat(), false );
145  } else {
146  mStartCaption = i18n( "No start date" );
147  mStartString = TQString();
148  }
149 
150  if ( event->hasEndDate() ) {
151  mEndCaption = i18n( "End date: " );
152  mEndString = IncidenceFormatter::dateTimeToString(
153  event->dtEnd(), event->doesFloat(), false );
154  } else if ( event->hasDuration() ) {
155  mEndCaption = i18n("Duration: ");
156  int mins = event->duration() / 60;
157  if ( mins >= 60 ) {
158  mEndString += i18n( "1 hour ", "%n hours ", mins/60 );
159  }
160  if ( mins%60 > 0 ) {
161  mEndString += i18n( "1 minute ", "%n minutes ", mins%60 );
162  }
163  } else {
164  mEndCaption = i18n("No end date");
165  mEndString = TQString();
166  }
167  return true;
168  }
169  bool visit( Todo *todo ) {
170  if ( todo->hasStartDate() ) {
171  mStartCaption = i18n( "Start date: " );
172  mStartString = IncidenceFormatter::dateTimeToString(
173  todo->dtStart(), todo->doesFloat(), false );
174  } else {
175  mStartCaption = i18n( "No start date" );
176  mStartString = TQString();
177  }
178 
179  if ( todo->hasDueDate() ) {
180  mEndCaption = i18n( "Due date: " );
181  mEndString = IncidenceFormatter::dateTimeToString(
182  todo->dtDue(), todo->doesFloat(), false );
183  } else {
184  mEndCaption = i18n("No due date");
185  mEndString = TQString();
186  }
187  return true;
188  }
189  bool visit( Journal *journal ) {
190  mStartCaption = i18n( "Start date: " );
191  mStartString = IncidenceFormatter::dateTimeToString(
192  journal->dtStart(), journal->doesFloat(), false );
193  mEndCaption = TQString();
194  mEndString = TQString();
195  return true;
196  }
197 };
198 
199 int CalPrintIncidence::printCaptionAndText( TQPainter &p, const TQRect &box, const TQString &caption, const TQString &text, TQFont captionFont, TQFont textFont )
200 {
201  TQFontMetrics captionFM( captionFont );
202  int textWd = captionFM.width( caption );
203  TQRect textRect( box );
204 
205  TQFont oldFont( p.font() );
206  p.setFont( captionFont );
207  p.drawText( box, TQt::AlignLeft|TQt::AlignTop|TQt::SingleLine, caption );
208 
209  if ( !text.isEmpty() ) {
210  textRect.setLeft( textRect.left() + textWd );
211  p.setFont( textFont );
212  p.drawText( textRect, TQt::AlignLeft|TQt::AlignTop|TQt::SingleLine, text );
213  }
214  p.setFont( oldFont );
215  return textRect.bottom();
216 }
217 
218 #include <tqfontdatabase.h>
219 void CalPrintIncidence::print( TQPainter &p, int width, int height )
220 {
221  TQFont oldFont(p.font());
222  TQFont textFont( "sans-serif", 11, TQFont::Normal );
223  TQFont captionFont( "sans-serif", 11, TQFont::Bold );
224  p.setFont( textFont );
225  int lineHeight = p.fontMetrics().lineSpacing();
226  TQString cap, txt;
227 
228 
229  Incidence::List::ConstIterator it;
230  for ( it=mSelectedIncidences.begin(); it!=mSelectedIncidences.end(); ++it ) {
231  // don't do anything on a 0-pointer!
232  if ( !(*it) ) continue;
233  if ( it != mSelectedIncidences.begin() ) mPrinter->newPage();
234 
235 
236  // PAGE Layout (same for landscape and portrait! astonishingly, it looks good with both!):
237  // +-----------------------------------+
238  // | Header: Summary |
239  // +===================================+
240  // | start: ______ end: _________ |
241  // | repeats: ___________________ |
242  // | reminder: __________________ |
243  // +-----------------------------------+
244  // | Location: ______________________ |
245  // +------------------------+----------+
246  // | Description: | Notes or |
247  // | | Subitems |
248  // | | |
249  // | | |
250  // | | |
251  // | | |
252  // | | |
253  // | | |
254  // | | |
255  // | | |
256  // +------------------------+----------+
257  // | Attachments: | Settings |
258  // | | |
259  // +------------------------+----------+
260  // | Attendees: |
261  // | |
262  // +-----------------------------------+
263  // | Categories: _____________________ |
264  // +-----------------------------------+
265 
266  TQRect box( 0, 0, width, height );
267  TQRect titleBox( box );
268  titleBox.setHeight( headerHeight() );
269  // Draw summary as header, no small calendars in title bar, expand height if needed
270  int titleBottom = drawHeader( p, (*it)->summary(), TQDate(), TQDate(), titleBox, true );
271  titleBox.setBottom( titleBottom );
272 
273  TQRect timesBox( titleBox );
274  timesBox.setTop( titleBox.bottom() + padding() );
275  timesBox.setHeight( height / 8 );
276 
277  TimePrintStringsVisitor stringVis;
278  int h = timesBox.top();
279  if ( stringVis.act(*it) ) {
280  TQRect textRect( timesBox.left()+padding(), timesBox.top()+padding(), 0, lineHeight );
281  textRect.setRight( timesBox.center().x() );
282  h = printCaptionAndText( p, textRect, stringVis.mStartCaption, stringVis.mStartString, captionFont, textFont );
283 
284  textRect.setLeft( textRect.right() );
285  textRect.setRight( timesBox.right() - padding() );
286  h = TQMAX( printCaptionAndText( p, textRect, stringVis.mEndCaption, stringVis.mEndString, captionFont, textFont ), h );
287  }
288 
289  // Convert recurrence to a string
290  if ( (*it)->doesRecur() ) {
291  TQRect recurBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight );
292  KCal::Recurrence *recurs = (*it)->recurrence();
293 
294  TQString displayString = IncidenceFormatter::recurrenceString((*it));
295  // exception dates
296  TQString exceptString;
297  if ( !recurs->exDates().isEmpty() ) {
298  exceptString = i18n("except for listed dates", " except");
299  for ( uint i = 0; i < recurs->exDates().size(); i++ ) {
300  exceptString.append(" ");
301  exceptString.append( TDEGlobal::locale()->formatDate(recurs->exDates()[i],
302  true) );
303  }
304  }
305  displayString.append(exceptString);
306  h = TQMAX( printCaptionAndText( p, recurBox, i18n( "Repeats: "), displayString, captionFont, textFont ), h );
307  }
308 
309  // Alarms Printing
310  TQRect alarmBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight );
311  Alarm::List alarms = (*it)->alarms();
312  if ( alarms.count() == 0 ) {
313  cap = i18n("No reminders");
314  txt = TQString();
315  } else {
316  cap = i18n("Reminder: ", "%n reminders: ", alarms.count() );
317 
318  TQStringList alarmStrings;
319  KCal::Alarm::List::ConstIterator it;
320  for ( it = alarms.begin(); it != alarms.end(); ++it ) {
321  Alarm *alarm = *it;
322 
323  // Alarm offset, copied from koeditoralarms.cpp:
324  TQString offsetstr;
325  int offset = 0;
326  if ( alarm->hasStartOffset() ) {
327  offset = alarm->startOffset().asSeconds();
328  if ( offset < 0 ) {
329  offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the start");
330  offset = -offset;
331  } else {
332  offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the start");
333  }
334  } else if ( alarm->hasEndOffset() ) {
335  offset = alarm->endOffset().asSeconds();
336  if ( offset < 0 ) {
337  offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the end");
338  offset = -offset;
339  } else {
340  offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the end");
341  }
342  }
343 
344  offset = offset / 60; // make minutes
345  int useoffset = offset;
346 
347  if ( offset % (24*60) == 0 && offset>0 ) { // divides evenly into days?
348  useoffset = offset / (24*60);
349  offsetstr = offsetstr.arg( i18n("1 day", "%n days", useoffset ) );
350  } else if (offset % 60 == 0 && offset>0 ) { // divides evenly into hours?
351  useoffset = offset / 60;
352  offsetstr = offsetstr.arg( i18n("1 hour", "%n hours", useoffset ) );
353  } else {
354  useoffset = offset;
355  offsetstr = offsetstr.arg( i18n("1 minute", "%n minutes", useoffset ) );
356  }
357  alarmStrings << offsetstr;
358  }
359  txt = alarmStrings.join( i18n("Spacer for the joined list of categories", ", ") );
360 
361  }
362  h = TQMAX( printCaptionAndText( p, alarmBox, cap, txt, captionFont, textFont ), h );
363 
364 
365  TQRect organizerBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight );
366  h = TQMAX( printCaptionAndText( p, organizerBox, i18n("Organizer: "), (*it)->organizer().fullName(), captionFont, textFont ), h );
367 
368  // Finally, draw the frame around the time information...
369  timesBox.setBottom( TQMAX( timesBox.bottom(), h+padding() ) );
370  drawBox( p, BOX_BORDER_WIDTH, timesBox );
371 
372 
373  TQRect locationBox( timesBox );
374  locationBox.setTop( timesBox.bottom() + padding() );
375  locationBox.setHeight( 0 );
376  int locationBottom = drawBoxWithCaption( p, locationBox, i18n("Location: "),
377  (*it)->location(), /*sameLine=*/true, /*expand=*/true, captionFont, textFont );
378  locationBox.setBottom( locationBottom );
379 
380 
381  // Now start constructing the boxes from the bottom:
382  TQRect footerBox( locationBox );
383  footerBox.setBottom( box.bottom() );
384  footerBox.setTop( footerBox.bottom() - lineHeight - 2*padding() );
385 
386  TQRect categoriesBox( footerBox );
387  categoriesBox.setBottom( footerBox.top() );
388  categoriesBox.setTop( categoriesBox.bottom() - lineHeight - 2*padding() );
389 
390  TQRect attendeesBox( box.left(), categoriesBox.top()-padding()-box.height()/9, box.width(), box.height()/9 );
391 
392  TQRect attachmentsBox( box.left(), attendeesBox.top()-padding()-box.height()/9, box.width()*3/4 - padding(), box.height()/9 );
393  TQRect optionsBox( attachmentsBox.right() + padding(), attachmentsBox.top(), 0, 0 );
394  optionsBox.setRight( box.right() );
395  optionsBox.setBottom( attachmentsBox.bottom() );
396  TQRect notesBox( optionsBox.left(), locationBox.bottom() + padding(), optionsBox.width(), 0 );
397  notesBox.setBottom( optionsBox.top() - padding() );
398 
399  TQRect descriptionBox( notesBox );
400  descriptionBox.setLeft( box.left() );
401  descriptionBox.setRight( attachmentsBox.right() );
402  // Adjust boxes depending on the show options...
403  if (!mShowSubitemsNotes) {
404  descriptionBox.setRight( box.right() );
405  }
406  if (!mShowAttachments || !mShowAttendees) {
407  descriptionBox.setBottom( attachmentsBox.bottom() );
408  optionsBox.setTop( attendeesBox.top() );
409  optionsBox.setBottom( attendeesBox.bottom() );
410  notesBox.setBottom( attachmentsBox.bottom() );
411  if (mShowOptions) {
412  attendeesBox.setRight( attachmentsBox.right() );
413  }
414  if (!mShowAttachments && !mShowAttendees) {
415  if (mShowSubitemsNotes) {
416  descriptionBox.setBottom( attendeesBox.bottom() );
417  }
418  if (!mShowOptions) {
419  descriptionBox.setBottom( attendeesBox.bottom() );
420  notesBox.setBottom( attendeesBox.bottom() );
421  }
422  }
423  }
424  if (mShowAttachments) {
425  if (!mShowOptions) {
426  attachmentsBox.setRight( box.right() );
427  attachmentsBox.setRight( box.right() );
428  }
429  if (!mShowAttendees) {
430  attachmentsBox.setTop( attendeesBox.top() );
431  attachmentsBox.setBottom( attendeesBox.bottom() );
432  }
433  }
434 
435  drawBoxWithCaption( p, descriptionBox, i18n("Description:"),
436  (*it)->description(), /*sameLine=*/false,
437  /*expand=*/false, captionFont, textFont );
438 
439  if ( mShowSubitemsNotes ) {
440  if ( (*it)->relations().isEmpty() || (*it)->type() != "Todo" ) {
441  int notesPosition = drawBoxWithCaption( p, notesBox, i18n("Notes:"),
442  TQString(), /*sameLine=*/false, /*expand=*/false,
443  captionFont, textFont );
444  TQPen oldPen( p.pen() );
445  p.setPen( TQt::DotLine );
446  while ( (notesPosition += int(1.5*lineHeight)) < notesBox.bottom() ) {
447  p.drawLine( notesBox.left()+padding(), notesPosition, notesBox.right()-padding(), notesPosition );
448  }
449  p.setPen( oldPen );
450  } else {
451  Incidence::List relations = (*it)->relations();
452  TQString subitemCaption;
453  if ( relations.count() == 0 ) {
454  subitemCaption = i18n( "No Subitems" );
455  txt == "";
456  } else {
457  subitemCaption = i18n( "1 Subitem:",
458  "%1 Subitems:",
459  relations.count() );
460  }
461  Incidence::List::ConstIterator rit;
462  TQString subitemString;
463  TQString statusString;
464  TQString datesString;
465  int count = 0;
466  for ( rit = relations.begin(); rit != relations.end(); ++rit ) {
467  ++count;
468  if ( !(*rit) ) { // defensive, skip any zero pointers
469  continue;
470  }
471  // format the status
472  statusString = (*rit)->statusStr();
473  if ( statusString.isEmpty() ) {
474  if ( (*rit)->status() == Incidence::StatusNone ) {
475  statusString = i18n( "no status", "none" );
476  } else {
477  statusString = i18n( "unknown status", "unknown" );
478  }
479  }
480  // format the dates if provided
481  datesString = "";
482  if ( (*rit)->dtStart().isValid() ) {
483  datesString += i18n(
484  "Start Date: %1\n").arg(
485  TDEGlobal::locale()->formatDate( (*rit)->dtStart().date(),
486  true ) );
487  if ( !(*rit)->doesFloat() ) {
488  datesString += i18n(
489  "Start Time: %1\n").arg(
490  TDEGlobal::locale()->formatTime((*rit)->dtStart().time(),
491  false, false) );
492  }
493  }
494  if ( (*rit)->dtEnd().isValid() ) {
495  subitemString += i18n(
496  "Due Date: %1\n").arg(
497  TDEGlobal::locale()->formatDate( (*rit)->dtEnd().date(),
498  true ) );
499  if ( !(*rit)->doesFloat() ) {
500  subitemString += i18n(
501  "subitem due time", "Due Time: %1\n").arg(
502  TDEGlobal::locale()->formatTime((*rit)->dtEnd().time(),
503  false, false) );
504  }
505  }
506  subitemString += i18n("subitem counter", "%1: ", count);
507  subitemString += (*rit)->summary();
508  subitemString += "\n";
509  if ( !datesString.isEmpty() ) {
510  subitemString += datesString;
511  subitemString += "\n";
512  }
513  subitemString += i18n( "subitem Status: statusString",
514  "Status: %1\n").arg( statusString );
515  subitemString += IncidenceFormatter::recurrenceString((*rit)) + "\n";
516  subitemString += i18n( "subitem Priority: N",
517  "Priority: %1\n").arg( (*rit)->priority() );
518  subitemString += i18n( "subitem Secrecy: secrecyString",
519  "Secrecy: %1\n").arg( (*rit)->secrecyStr() );
520  subitemString += "\n";
521  }
522  drawBoxWithCaption( p, notesBox, i18n("Subitems:"),
523  (*it)->description(), /*sameLine=*/false,
524  /*expand=*/false, captionFont, textFont );
525  }
526  }
527 
528  if ( mShowAttachments ) {
529  Attachment::List attachments = (*it)->attachments();
530  TQString attachmentCaption;
531  if ( attachments.count() == 0 ) {
532  attachmentCaption = i18n( "No Attachments" );
533  txt = TQString();
534  } else {
535  attachmentCaption = i18n( "1 Attachment:", "%1 Attachments:", attachments.count() );
536  }
537  TQString attachmentString;
538  Attachment::List::ConstIterator ait = attachments.begin();
539  for ( ; ait != attachments.end(); ++ait ) {
540  if (!attachmentString.isEmpty()) {
541  attachmentString += i18n( "Spacer for list of attachments", " " );
542  }
543  attachmentString.append((*ait)->label());
544  }
545  drawBoxWithCaption( p, attachmentsBox,
546  attachmentCaption, attachmentString,
547  /*sameLine=*/false, /*expand=*/false,
548  captionFont, textFont );
549  }
550 
551  if ( mShowAttendees ) {
552  Attendee::List attendees = (*it)->attendees();
553  TQString attendeeCaption;
554  if ( attendees.count() == 0 )
555  attendeeCaption = i18n("No Attendees");
556  else
557  attendeeCaption = i18n("1 Attendee:", "%n Attendees:", attendees.count() );
558  TQString attendeeString;
559  for ( Attendee::List::ConstIterator ait = attendees.begin(); ait != attendees.end(); ++ait ) {
560  if ( !attendeeString.isEmpty() ) attendeeString += "\n";
561  attendeeString += i18n("Formatting of an attendee: "
562  "'Name (Role): Status', e.g. 'Reinhold Kainhofer "
563  "<reinhold@kainhofer.com> (Participant): Awaiting Response'",
564  "%1 (%2): %3")
565  .arg( (*ait)->fullName() )
566  .arg( (*ait)->roleStr() ).arg( (*ait)->statusStr() );
567  }
568  drawBoxWithCaption( p, attendeesBox, i18n("Attendees:"), attendeeString,
569  /*sameLine=*/false, /*expand=*/false, captionFont, textFont );
570  }
571 
572  if ( mShowOptions ) {
573  TQString optionsString;
574  if ( !(*it)->statusStr().isEmpty() ) {
575  optionsString += i18n("Status: %1").arg( (*it)->statusStr() );
576  optionsString += "\n";
577  }
578  if ( !(*it)->secrecyStr().isEmpty() ) {
579  optionsString += i18n("Secrecy: %1").arg( (*it)->secrecyStr() );
580  optionsString += "\n";
581  }
582  if ( (*it)->type() == "Event" ) {
583  Event *e = static_cast<Event*>(*it);
584  if ( e->transparency() == Event::Opaque ) {
585  optionsString += i18n("Show as: Busy");
586  } else {
587  optionsString += i18n("Show as: Free");
588  }
589  optionsString += "\n";
590  } else if ( (*it)->type() == "Todo" ) {
591  Todo *t = static_cast<Todo*>(*it);
592  if ( t->isOverdue() ) {
593  optionsString += i18n("This task is overdue!");
594  optionsString += "\n";
595  }
596  } else if ( (*it)->type() == "Journal" ) {
597  //TODO: Anything Journal-specific?
598  }
599  drawBoxWithCaption( p, optionsBox, i18n("Settings: "),
600  optionsString, /*sameLine=*/false, /*expand=*/false, captionFont, textFont );
601  }
602 
603  drawBoxWithCaption( p, categoriesBox, i18n("Categories: "),
604  (*it)->categories().join( i18n("Spacer for the joined list of categories", ", ") ),
605  /*sameLine=*/true, /*expand=*/false, captionFont, textFont );
606 
607  drawFooter( p, footerBox );
608  }
609  p.setFont( oldFont );
610 }
611 
612 /**************************************************************
613  * Print Day
614  **************************************************************/
615 
616 CalPrintDay::CalPrintDay() : CalPrintPluginBase()
617 {
618 }
619 
620 CalPrintDay::~CalPrintDay()
621 {
622 }
623 
624 TQWidget *CalPrintDay::createConfigWidget( TQWidget *w )
625 {
626  return new CalPrintDayConfig_Base( w );
627 }
628 
629 void CalPrintDay::readSettingsWidget()
630 {
631  CalPrintDayConfig_Base *cfg =
632  dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget );
633  if ( cfg ) {
634  mFromDate = cfg->mFromDate->date();
635  mToDate = cfg->mToDate->date();
636 
637  mStartTime = cfg->mFromTime->time();
638  mEndTime = cfg->mToTime->time();
639  mIncludeAllEvents = cfg->mIncludeAllEvents->isChecked();
640 
641  mIncludeTodos = cfg->mIncludeTodos->isChecked();
642  mUseColors = cfg->mColors->isChecked();
643  }
644 }
645 
646 void CalPrintDay::setSettingsWidget()
647 {
648  CalPrintDayConfig_Base *cfg =
649  dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget );
650  if ( cfg ) {
651  cfg->mFromDate->setDate( mFromDate );
652  cfg->mToDate->setDate( mToDate );
653 
654  cfg->mFromTime->setTime( mStartTime );
655  cfg->mToTime->setTime( mEndTime );
656  cfg->mIncludeAllEvents->setChecked( mIncludeAllEvents );
657 
658  cfg->mIncludeTodos->setChecked( mIncludeTodos );
659  cfg->mColors->setChecked( mUseColors );
660  }
661 }
662 
663 void CalPrintDay::loadConfig()
664 {
665  if ( mConfig ) {
666  TQDate dt;
667  TQTime tm1( dayStart() );
668  TQDateTime startTm( dt, tm1 );
669  TQDateTime endTm( dt, tm1.addSecs( 12 * 60 * 60 ) );
670  mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time();
671  mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time();
672  mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
673  mIncludeAllEvents = mConfig->readBoolEntry( "Include all events", false );
674  }
675  setSettingsWidget();
676 }
677 
678 void CalPrintDay::saveConfig()
679 {
680  readSettingsWidget();
681  if ( mConfig ) {
682  mConfig->writeEntry( "Start time", TQDateTime( TQDate(), mStartTime ) );
683  mConfig->writeEntry( "End time", TQDateTime( TQDate(), mEndTime ) );
684  mConfig->writeEntry( "Include todos", mIncludeTodos );
685  mConfig->writeEntry( "Include all events", mIncludeAllEvents );
686  }
687 }
688 
689 void CalPrintDay::setDateRange( const TQDate& from, const TQDate& to )
690 {
692  CalPrintDayConfig_Base *cfg =
693  dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget );
694  if ( cfg ) {
695  cfg->mFromDate->setDate( from );
696  cfg->mToDate->setDate( to );
697  }
698 }
699 
700 void CalPrintDay::print( TQPainter &p, int width, int height )
701 {
702  TQDate curDay( mFromDate );
703 
704  TQRect headerBox( 0, 0, width, headerHeight() );
705  TQRect footerBox( 0, height - footerHeight(), width, footerHeight() );
706  height -= footerHeight();
707 
708  TDELocale *local = TDEGlobal::locale();
709 
710  do {
711  TQTime curStartTime( mStartTime );
712  TQTime curEndTime( mEndTime );
713 
714  // For an invalid time range, simply show one hour, starting at the hour
715  // before the given start time
716  if ( curEndTime <= curStartTime ) {
717  curStartTime = TQTime( curStartTime.hour(), 0, 0 );
718  curEndTime = curStartTime.addSecs( 3600 );
719  }
720 
721  drawHeader( p, local->formatDate( curDay ), curDay, TQDate(), headerBox );
722  Event::List eventList = mCalendar->events( curDay,
723  EventSortStartDate,
724  SortDirectionAscending );
725 
726  // split out the all day events as they will be printed in a separate box
727  Event::List alldayEvents, timedEvents;
728  Event::List::ConstIterator it;
729  for ( it = eventList.begin(); it != eventList.end(); ++it ) {
730  if ( (*it)->doesFloat() ) {
731  alldayEvents.append( *it );
732  } else {
733  timedEvents.append( *it );
734  }
735  }
736 
737  int fontSize = 11;
738  TQFont textFont( "sans-serif", fontSize, TQFont::Normal );
739  p.setFont( textFont );
740  uint lineSpacing = p.fontMetrics().lineSpacing();
741 
742  uint maxAllDayEvents = 8; // the max we allow to be printed, sorry.
743  uint allDayHeight = TQMIN( alldayEvents.count(), maxAllDayEvents ) * lineSpacing;
744  allDayHeight = TQMAX( allDayHeight, ( 5 * lineSpacing ) ) + ( 2 * padding() );
745  TQRect allDayBox( TIMELINE_WIDTH + padding(), headerBox.bottom() + padding(),
746  width - TIMELINE_WIDTH - padding(), allDayHeight );
747  if ( alldayEvents.count() > 0 ) {
748  // draw the side bar for all-day events
749  TQFont oldFont( p.font() );
750  p.setFont( TQFont( "sans-serif", 9, TQFont::Normal ) );
751  drawVerticalBox( p,
752  BOX_BORDER_WIDTH,
753  TQRect( 0, headerBox.bottom() + padding(), TIMELINE_WIDTH, allDayHeight ),
754  i18n( "Today's Events" ),
755  TQt::AlignHCenter | TQt::AlignVCenter | TQt::WordBreak );
756  p.setFont( oldFont );
757 
758  // now draw at most maxAllDayEvents in the all-day box
759  drawBox( p, BOX_BORDER_WIDTH, allDayBox );
760 
761  Event::List::ConstIterator it;
762  TQRect eventBox( allDayBox );
763  eventBox.setLeft( TIMELINE_WIDTH + ( 2 * padding() ) );
764  eventBox.setTop( eventBox.top() + padding() );
765  eventBox.setBottom( eventBox.top() + lineSpacing );
766  uint count = 0;
767  for ( it = alldayEvents.begin(); it != alldayEvents.end(); ++it ) {
768  if ( count == maxAllDayEvents ) {
769  break;
770  }
771  count++;
772  TQString str;
773  if ( (*it)->location().isEmpty() ) {
774  str = cleanString( (*it)->summary() );
775  } else {
776  str = i18n( "summary, location", "%1, %2" ).
777  arg( cleanString( (*it)->summary() ), cleanString( (*it)->location() ) );
778  }
779  printEventString( p, eventBox, str );
780  eventBox.setTop( eventBox.bottom() );
781  eventBox.setBottom( eventBox.top() + lineSpacing );
782  }
783  } else {
784  allDayBox.setBottom( headerBox.bottom() );
785  }
786 
787  TQRect dayBox( allDayBox );
788  dayBox.setTop( allDayBox.bottom() + padding() );
789  dayBox.setBottom( height );
790  drawAgendaDayBox( p, timedEvents, curDay, mIncludeAllEvents,
791  curStartTime, curEndTime, dayBox );
792 
793  TQRect tlBox( dayBox );
794  tlBox.setLeft( 0 );
795  tlBox.setWidth( TIMELINE_WIDTH );
796  drawTimeLine( p, curStartTime, curEndTime, tlBox );
797 
798  drawFooter( p, footerBox );
799 
800  curDay = curDay.addDays( 1 );
801  if ( curDay <= mToDate ) {
802  mPrinter->newPage();
803  }
804  } while ( curDay <= mToDate );
805 }
806 
807 
808 
809 /**************************************************************
810  * Print Week
811  **************************************************************/
812 
813 CalPrintWeek::CalPrintWeek() : CalPrintPluginBase()
814 {
815 }
816 
817 CalPrintWeek::~CalPrintWeek()
818 {
819 }
820 
821 TQWidget *CalPrintWeek::createConfigWidget( TQWidget *w )
822 {
823  return new CalPrintWeekConfig_Base( w );
824 }
825 
826 void CalPrintWeek::readSettingsWidget()
827 {
828  CalPrintWeekConfig_Base *cfg =
829  dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
830  if ( cfg ) {
831  mFromDate = cfg->mFromDate->date();
832  mToDate = cfg->mToDate->date();
833 
834  mWeekPrintType = (eWeekPrintType)( cfg->mPrintType->id(
835  cfg->mPrintType->selected() ) );
836 
837  mStartTime = cfg->mFromTime->time();
838  mEndTime = cfg->mToTime->time();
839 
840  mIncludeTodos = cfg->mIncludeTodos->isChecked();
841  mUseColors = cfg->mColors->isChecked();
842  }
843 }
844 
845 void CalPrintWeek::setSettingsWidget()
846 {
847  CalPrintWeekConfig_Base *cfg =
848  dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
849  if ( cfg ) {
850  cfg->mFromDate->setDate( mFromDate );
851  cfg->mToDate->setDate( mToDate );
852 
853  cfg->mPrintType->setButton( mWeekPrintType );
854 
855  cfg->mFromTime->setTime( mStartTime );
856  cfg->mToTime->setTime( mEndTime );
857 
858  cfg->mIncludeTodos->setChecked( mIncludeTodos );
859  cfg->mColors->setChecked( mUseColors );
860  }
861 }
862 
863 void CalPrintWeek::loadConfig()
864 {
865  if ( mConfig ) {
866  TQDate dt;
867  TQTime tm1( dayStart() );
868  TQDateTime startTm( dt, tm1 );
869  TQDateTime endTm( dt, tm1.addSecs( 43200 ) );
870  mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time();
871  mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time();
872  mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
873  mWeekPrintType =(eWeekPrintType)( mConfig->readNumEntry( "Print type", (int)Filofax ) );
874  }
875  setSettingsWidget();
876 }
877 
878 void CalPrintWeek::saveConfig()
879 {
880  readSettingsWidget();
881  if ( mConfig ) {
882  mConfig->writeEntry( "Start time", TQDateTime( TQDate(), mStartTime ) );
883  mConfig->writeEntry( "End time", TQDateTime( TQDate(), mEndTime ) );
884  mConfig->writeEntry( "Include todos", mIncludeTodos );
885  mConfig->writeEntry( "Print type", int( mWeekPrintType ) );
886  }
887 }
888 
889 KPrinter::Orientation CalPrintWeek::defaultOrientation()
890 {
891  if ( mWeekPrintType == Filofax ) return KPrinter::Portrait;
892  else if ( mWeekPrintType == SplitWeek ) return KPrinter::Portrait;
893  else return KPrinter::Landscape;
894 }
895 
896 void CalPrintWeek::setDateRange( const TQDate &from, const TQDate &to )
897 {
899  CalPrintWeekConfig_Base *cfg =
900  dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
901  if ( cfg ) {
902  cfg->mFromDate->setDate( from );
903  cfg->mToDate->setDate( to );
904  }
905 }
906 
907 void CalPrintWeek::print( TQPainter &p, int width, int height )
908 {
909  TQDate curWeek, fromWeek, toWeek;
910 
911  // correct begin and end to first and last day of week
912  int weekdayCol = weekdayColumn( mFromDate.dayOfWeek() );
913  fromWeek = mFromDate.addDays( -weekdayCol );
914  weekdayCol = weekdayColumn( mFromDate.dayOfWeek() );
915  toWeek = mToDate.addDays( 6 - weekdayCol );
916 
917  curWeek = fromWeek.addDays( 6 );
918  TDELocale *local = TDEGlobal::locale();
919 
920  TQString line1, line2, title;
921  TQRect headerBox( 0, 0, width, headerHeight() );
922  TQRect footerBox( 0, height - footerHeight(), width, footerHeight() );
923  height -= footerHeight();
924 
925  TQRect weekBox( headerBox );
926  weekBox.setTop( headerBox.bottom() + padding() );
927  weekBox.setBottom( height );
928 
929  switch ( mWeekPrintType ) {
930  case Filofax:
931  do {
932  line1 = local->formatDate( curWeek.addDays( -6 ) );
933  line2 = local->formatDate( curWeek );
934  if ( orientation() == KPrinter::Landscape ) {
935  title = i18n("date from-to", "%1 - %2");
936  } else {
937  title = i18n("date from-\nto", "%1 -\n%2");;
938  }
939  title = title.arg( line1 ).arg( line2 );
940  drawHeader( p, title, curWeek.addDays( -6 ), TQDate(), headerBox );
941 
942  drawWeek( p, curWeek, weekBox );
943 
944  drawFooter( p, footerBox );
945 
946  curWeek = curWeek.addDays( 7 );
947  if ( curWeek <= toWeek )
948  mPrinter->newPage();
949  } while ( curWeek <= toWeek );
950  break;
951 
952  case Timetable:
953  default:
954  do {
955  line1 = local->formatDate( curWeek.addDays( -6 ) );
956  line2 = local->formatDate( curWeek );
957  if ( orientation() == KPrinter::Landscape ) {
958  title = i18n("date from - to (week number)", "%1 - %2 (Week %3)");
959  } else {
960  title = i18n("date from -\nto (week number)", "%1 -\n%2 (Week %3)");
961  }
962  title = title.arg( line1 ).arg( line2 ).arg( curWeek.weekNumber() );
963  drawHeader( p, title, curWeek, TQDate(), headerBox );
964 
965  TQRect weekBox( headerBox );
966  weekBox.setTop( headerBox.bottom() + padding() );
967  weekBox.setBottom( height );
968  drawTimeTable( p, fromWeek, curWeek, mStartTime, mEndTime, weekBox );
969 
970  drawFooter( p, footerBox );
971 
972  fromWeek = fromWeek.addDays( 7 );
973  curWeek = fromWeek.addDays( 6 );
974  if ( curWeek <= toWeek )
975  mPrinter->newPage();
976  } while ( curWeek <= toWeek );
977  break;
978 
979  case SplitWeek: {
980  TQRect weekBox1( weekBox );
981  // On the left side there are four days (mo-th) plus the timeline,
982  // on the right there are only three days (fr-su) plus the timeline. Don't
983  // use the whole width, but rather give them the same width as on the left.
984  weekBox1.setRight( int( ( width - TIMELINE_WIDTH ) * 3. / 4. + TIMELINE_WIDTH ) );
985  do {
986  TQDate endLeft( fromWeek.addDays( 3 ) );
987  int hh = headerHeight();
988 
989  drawTimeTable( p, fromWeek, endLeft,
990  mStartTime, mEndTime, weekBox );
991  mPrinter->newPage();
992  drawSplitHeaderRight( p, fromWeek, curWeek, TQDate(), width, hh );
993  drawTimeTable( p, endLeft.addDays( 1 ), curWeek,
994  mStartTime, mEndTime, weekBox1 );
995 
996  drawFooter( p, footerBox );
997 
998  fromWeek = fromWeek.addDays( 7 );
999  curWeek = fromWeek.addDays( 6 );
1000  if ( curWeek <= toWeek )
1001  mPrinter->newPage();
1002  } while ( curWeek <= toWeek );
1003  }
1004  break;
1005  }
1006 }
1007 
1008 
1009 
1010 
1011 /**************************************************************
1012  * Print Month
1013  **************************************************************/
1014 
1015 CalPrintMonth::CalPrintMonth() : CalPrintPluginBase()
1016 {
1017 }
1018 
1019 CalPrintMonth::~CalPrintMonth()
1020 {
1021 }
1022 
1023 TQWidget *CalPrintMonth::createConfigWidget( TQWidget *w )
1024 {
1025  return new CalPrintMonthConfig_Base( w );
1026 }
1027 
1028 void CalPrintMonth::readSettingsWidget()
1029 {
1030  CalPrintMonthConfig_Base *cfg =
1031  dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
1032  if ( cfg ) {
1033  mFromDate = TQDate( cfg->mFromYear->value(), cfg->mFromMonth->currentItem()+1, 1 );
1034  mToDate = TQDate( cfg->mToYear->value(), cfg->mToMonth->currentItem()+1, 1 );
1035 
1036  mWeekNumbers = cfg->mWeekNumbers->isChecked();
1037  mRecurDaily = cfg->mRecurDaily->isChecked();
1038  mRecurWeekly = cfg->mRecurWeekly->isChecked();
1039  mIncludeTodos = cfg->mIncludeTodos->isChecked();
1040 // mUseColors = cfg->mColors->isChecked();
1041  }
1042 }
1043 
1044 void CalPrintMonth::setSettingsWidget()
1045 {
1046  CalPrintMonthConfig_Base *cfg =
1047  dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
1048  setDateRange( mFromDate, mToDate );
1049  if ( cfg ) {
1050  cfg->mWeekNumbers->setChecked( mWeekNumbers );
1051  cfg->mRecurDaily->setChecked( mRecurDaily );
1052  cfg->mRecurWeekly->setChecked( mRecurWeekly );
1053  cfg->mIncludeTodos->setChecked( mIncludeTodos );
1054 // cfg->mColors->setChecked( mUseColors );
1055  }
1056 }
1057 
1058 void CalPrintMonth::loadConfig()
1059 {
1060  if ( mConfig ) {
1061  mWeekNumbers = mConfig->readBoolEntry( "Print week numbers", true );
1062  mRecurDaily = mConfig->readBoolEntry( "Print daily incidences", true );
1063  mRecurWeekly = mConfig->readBoolEntry( "Print weekly incidences", true );
1064  mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
1065  }
1066  setSettingsWidget();
1067 }
1068 
1069 void CalPrintMonth::saveConfig()
1070 {
1071  readSettingsWidget();
1072  if ( mConfig ) {
1073  mConfig->writeEntry( "Print week numbers", mWeekNumbers );
1074  mConfig->writeEntry( "Print daily incidences", mRecurDaily );
1075  mConfig->writeEntry( "Print weekly incidences", mRecurWeekly );
1076  mConfig->writeEntry( "Include todos", mIncludeTodos );
1077  }
1078 }
1079 
1080 void CalPrintMonth::setDateRange( const TQDate &from, const TQDate &to )
1081 {
1083  CalPrintMonthConfig_Base *cfg =
1084  dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
1085  const KCalendarSystem *calSys = calendarSystem();
1086  if ( cfg && calSys ) {
1087  cfg->mFromMonth->clear();
1088  for ( int i=0; i<calSys->monthsInYear( mFromDate ); ++i ) {
1089  cfg->mFromMonth->insertItem( calSys->monthName( i+1, mFromDate.year() ) );
1090  }
1091  cfg->mToMonth->clear();
1092  for ( int i=0; i<calSys->monthsInYear( mToDate ); ++i ) {
1093  cfg->mToMonth->insertItem( calSys->monthName( i+1, mToDate.year() ) );
1094  }
1095  }
1096  if ( cfg ) {
1097  cfg->mFromMonth->setCurrentItem( from.month()-1 );
1098  cfg->mFromYear->setValue( to.year() );
1099  cfg->mToMonth->setCurrentItem( mToDate.month()-1 );
1100  cfg->mToYear->setValue( mToDate.year() );
1101  }
1102 }
1103 
1104 void CalPrintMonth::print( TQPainter &p, int width, int height )
1105 {
1106  TQDate curMonth, fromMonth, toMonth;
1107 
1108  fromMonth = mFromDate.addDays( -( mFromDate.day() - 1 ) );
1109  toMonth = mToDate.addDays( mToDate.daysInMonth() - mToDate.day() );
1110 
1111  curMonth = fromMonth;
1112  const KCalendarSystem *calSys = calendarSystem();
1113  if ( !calSys ) return;
1114 
1115  TQRect headerBox( 0, 0, width, headerHeight() );
1116  TQRect footerBox( 0, height - footerHeight(), width, footerHeight() );
1117  height -= footerHeight();
1118 
1119  TQRect monthBox( 0, 0, width, height );
1120  monthBox.setTop( headerBox.bottom() + padding() );
1121 
1122  do {
1123  TQString title( i18n("monthname year", "%1 %2") );
1124  title = title.arg( calSys->monthName( curMonth ) )
1125  .arg( curMonth.year() );
1126  TQDate tmp( fromMonth );
1127  int weekdayCol = weekdayColumn( tmp.dayOfWeek() );
1128  tmp = tmp.addDays( -weekdayCol );
1129 
1130  drawHeader( p, title, curMonth.addMonths( -1 ), curMonth.addMonths( 1 ),
1131  headerBox );
1132  drawMonthTable( p, curMonth, mWeekNumbers, mRecurDaily, mRecurWeekly, monthBox );
1133 
1134  drawFooter( p, footerBox );
1135 
1136  curMonth = curMonth.addDays( curMonth.daysInMonth() );
1137  if ( curMonth <= toMonth ) mPrinter->newPage();
1138  } while ( curMonth <= toMonth );
1139 
1140 }
1141 
1142 
1143 
1144 
1145 /**************************************************************
1146  * Print Todos
1147  **************************************************************/
1148 
1149 CalPrintTodos::CalPrintTodos() : CalPrintPluginBase()
1150 {
1151  mTodoSortField = TodoFieldUnset;
1152  mTodoSortDirection = TodoDirectionUnset;
1153 }
1154 
1155 CalPrintTodos::~CalPrintTodos()
1156 {
1157 }
1158 
1159 TQWidget *CalPrintTodos::createConfigWidget( TQWidget *w )
1160 {
1161  return new CalPrintTodoConfig_Base( w );
1162 }
1163 
1164 void CalPrintTodos::readSettingsWidget()
1165 {
1166  CalPrintTodoConfig_Base *cfg =
1167  dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget );
1168  if ( cfg ) {
1169  mPageTitle = cfg->mTitle->text();
1170 
1171  mTodoPrintType = (eTodoPrintType)( cfg->mPrintType->id(
1172  cfg->mPrintType->selected() ) );
1173 
1174  mFromDate = cfg->mFromDate->date();
1175  mToDate = cfg->mToDate->date();
1176 
1177  mIncludeDescription = cfg->mDescription->isChecked();
1178  mIncludePriority = cfg->mPriority->isChecked();
1179  mIncludeDueDate = cfg->mDueDate->isChecked();
1180  mIncludePercentComplete = cfg->mPercentComplete->isChecked();
1181  mConnectSubTodos = cfg->mConnectSubTodos->isChecked();
1182  mStrikeOutCompleted = cfg->mStrikeOutCompleted->isChecked();
1183 
1184  mTodoSortField = (eTodoSortField)cfg->mSortField->currentItem();
1185  mTodoSortDirection = (eTodoSortDirection)cfg->mSortDirection->currentItem();
1186  }
1187 }
1188 
1189 void CalPrintTodos::setSettingsWidget()
1190 {
1191 // kdDebug(5850) << "CalPrintTodos::setSettingsWidget" << endl;
1192 
1193  CalPrintTodoConfig_Base *cfg =
1194  dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget );
1195  if ( cfg ) {
1196  cfg->mTitle->setText( mPageTitle );
1197 
1198  cfg->mPrintType->setButton( mTodoPrintType );
1199 
1200  cfg->mFromDate->setDate( mFromDate );
1201  cfg->mToDate->setDate( mToDate );
1202 
1203  cfg->mDescription->setChecked( mIncludeDescription );
1204  cfg->mPriority->setChecked( mIncludePriority );
1205  cfg->mDueDate->setChecked( mIncludeDueDate );
1206  cfg->mPercentComplete->setChecked( mIncludePercentComplete );
1207  cfg->mConnectSubTodos->setChecked( mConnectSubTodos );
1208  cfg->mStrikeOutCompleted->setChecked( mStrikeOutCompleted );
1209 
1210  if ( mTodoSortField != TodoFieldUnset ) {
1211  // do not insert if already done so.
1212  cfg->mSortField->insertItem( i18n("Summary") );
1213  cfg->mSortField->insertItem( i18n("Start Date") );
1214  cfg->mSortField->insertItem( i18n("Due Date") );
1215  cfg->mSortField->insertItem( i18n("Priority") );
1216  cfg->mSortField->insertItem( i18n("Percent Complete") );
1217  cfg->mSortField->setCurrentItem( (int)mTodoSortField );
1218  }
1219 
1220  if ( mTodoSortDirection != TodoDirectionUnset ) {
1221  // do not insert if already done so.
1222  cfg->mSortDirection->insertItem( i18n("Ascending") );
1223  cfg->mSortDirection->insertItem( i18n("Descending") );
1224  cfg->mSortDirection->setCurrentItem( (int)mTodoSortDirection );
1225  }
1226  }
1227 }
1228 
1229 void CalPrintTodos::loadConfig()
1230 {
1231  if ( mConfig ) {
1232  mPageTitle = mConfig->readEntry( "Page title", i18n("To-do list") );
1233  mTodoPrintType = (eTodoPrintType)mConfig->readNumEntry( "Print type", (int)TodosAll );
1234  mIncludeDescription = mConfig->readBoolEntry( "Include description", true );
1235  mIncludePriority = mConfig->readBoolEntry( "Include priority", true );
1236  mIncludeDueDate = mConfig->readBoolEntry( "Include due date", true );
1237  mIncludePercentComplete = mConfig->readBoolEntry( "Include percentage completed", true );
1238  mConnectSubTodos = mConfig->readBoolEntry( "Connect subtodos", true );
1239  mStrikeOutCompleted = mConfig->readBoolEntry( "Strike out completed summaries", true );
1240  mTodoSortField = (eTodoSortField)mConfig->readNumEntry( "Sort field", (int)TodoFieldSummary );
1241  mTodoSortDirection = (eTodoSortDirection)mConfig->readNumEntry( "Sort direction", (int)TodoDirectionAscending );
1242  }
1243  setSettingsWidget();
1244 }
1245 
1246 void CalPrintTodos::saveConfig()
1247 {
1248  readSettingsWidget();
1249  if ( mConfig ) {
1250  mConfig->writeEntry( "Page title", mPageTitle );
1251  mConfig->writeEntry( "Print type", int( mTodoPrintType ) );
1252  mConfig->writeEntry( "Include description", mIncludeDescription );
1253  mConfig->writeEntry( "Include priority", mIncludePriority );
1254  mConfig->writeEntry( "Include due date", mIncludeDueDate );
1255  mConfig->writeEntry( "Include percentage completed", mIncludePercentComplete );
1256  mConfig->writeEntry( "Connect subtodos", mConnectSubTodos );
1257  mConfig->writeEntry( "Strike out completed summaries", mStrikeOutCompleted );
1258  mConfig->writeEntry( "Sort field", mTodoSortField );
1259  mConfig->writeEntry( "Sort direction", mTodoSortDirection );
1260  }
1261 }
1262 
1263 void CalPrintTodos::print( TQPainter &p, int width, int height )
1264 {
1265  // TODO: Find a good way to guarantee a nicely designed output
1266  int pospriority = 0;
1267  int possummary = 100;
1268  int posdue = width - 65;
1269  int poscomplete = posdue - 70; //Complete column is to right of the Due column
1270  int lineSpacing = 15;
1271  int fontHeight = 10;
1272 
1273  TQRect headerBox( 0, 0, width, headerHeight() );
1274  TQRect footerBox( 0, height - footerHeight(), width, footerHeight() );
1275  height -= footerHeight();
1276 
1277  // Draw the First Page Header
1278  drawHeader( p, mPageTitle, mFromDate, TQDate(), headerBox );
1279 
1280  // Draw the Column Headers
1281  int mCurrentLinePos = headerHeight() + 5;
1282  TQString outStr;
1283  TQFont oldFont( p.font() );
1284 
1285  p.setFont( TQFont( "sans-serif", 9, TQFont::Bold ) );
1286  lineSpacing = p.fontMetrics().lineSpacing();
1287  mCurrentLinePos += lineSpacing;
1288  if ( mIncludePriority ) {
1289  outStr += i18n( "Priority" );
1290  p.drawText( pospriority, mCurrentLinePos - 2, outStr );
1291  } else {
1292  pospriority = -1;
1293  }
1294 
1295  outStr.truncate( 0 );
1296  outStr += i18n( "Summary" );
1297  p.drawText( possummary, mCurrentLinePos - 2, outStr );
1298 
1299  if ( mIncludePercentComplete ) {
1300  if ( !mIncludeDueDate ) //move Complete column to the right
1301  poscomplete = posdue; //if not print the Due Date column
1302  outStr.truncate( 0 );
1303  outStr += i18n( "Complete" );
1304  p.drawText( poscomplete, mCurrentLinePos - 2, outStr );
1305  } else {
1306  poscomplete = -1;
1307  }
1308 
1309  if ( mIncludeDueDate ) {
1310  outStr.truncate( 0 );
1311  outStr += i18n( "Due" );
1312  p.drawText( posdue, mCurrentLinePos - 2, outStr );
1313  } else {
1314  posdue = -1;
1315  }
1316 
1317  p.setFont( TQFont( "sans-serif", 10 ) );
1318  fontHeight = p.fontMetrics().height();
1319 
1320  Todo::List todoList;
1321  Todo::List tempList;
1322  Todo::List::ConstIterator it;
1323 
1324  // Convert sort options to the corresponding enums
1325  TodoSortField sortField = TodoSortSummary;
1326  switch( mTodoSortField ) {
1327  case TodoFieldSummary:
1328  sortField = TodoSortSummary; break;
1329  case TodoFieldStartDate:
1330  sortField = TodoSortStartDate; break;
1331  case TodoFieldDueDate:
1332  sortField = TodoSortDueDate; break;
1333  case TodoFieldPriority:
1334  sortField = TodoSortPriority; break;
1335  case TodoFieldPercentComplete:
1336  sortField = TodoSortPercentComplete; break;
1337  case TodoFieldUnset:
1338  break;
1339  }
1340 
1341  SortDirection sortDirection;
1342  switch( mTodoSortDirection ) {
1343  case TodoDirectionAscending:
1344  sortDirection = SortDirectionAscending; break;
1345  case TodoDirectionDescending:
1346  sortDirection = SortDirectionDescending; break;
1347  case TodoDirectionUnset:
1348  break;
1349  }
1350 
1351  // Create list of to-dos which will be printed
1352  todoList = mCalendar->todos( sortField, sortDirection );
1353  switch( mTodoPrintType ) {
1354  case TodosAll:
1355  break;
1356  case TodosUnfinished:
1357  for( it = todoList.begin(); it!= todoList.end(); ++it ) {
1358  if ( !(*it)->isCompleted() )
1359  tempList.append( *it );
1360  }
1361  todoList = tempList;
1362  break;
1363  case TodosDueRange:
1364  for( it = todoList.begin(); it!= todoList.end(); ++it ) {
1365  if ( (*it)->hasDueDate() ) {
1366  if ( (*it)->dtDue().date() >= mFromDate &&
1367  (*it)->dtDue().date() <= mToDate )
1368  tempList.append( *it );
1369  } else {
1370  tempList.append( *it );
1371  }
1372  }
1373  todoList = tempList;
1374  break;
1375  }
1376 
1377  // Print to-dos
1378  int count = 0;
1379  for ( it=todoList.begin(); it!=todoList.end(); ++it ) {
1380  Todo *currEvent = *it;
1381 
1382  // Skip sub-to-dos. They will be printed recursively in drawTodo()
1383  if ( !currEvent->relatedTo() ) {
1384  count++;
1385  drawTodo( count, currEvent, p,
1386  sortField, sortDirection,
1387  mConnectSubTodos,
1388  mStrikeOutCompleted, mIncludeDescription,
1389  pospriority, possummary, posdue, poscomplete,
1390  0, 0, mCurrentLinePos, width, height, todoList );
1391  }
1392  }
1393 
1394  drawFooter( p, footerBox );
1395  p.setFont( oldFont );
1396 }
1397 
1398 #endif
Base class for KOrganizer printing classes.
bool hasStartOffset() const
Duration endOffset() const
bool hasEndOffset() const
Duration startOffset() const
int asSeconds() const
virtual TQDateTime dtEnd() const
Transparency transparency() const
bool hasEndDate() const
virtual bool visit(Event *)
bool doesFloat() const
virtual TQDateTime dtStart() const
virtual bool accept(Visitor &)
Incidence * relatedTo() const
bool hasDueDate() const
bool hasStartDate() const
bool isOverdue() const
TQDateTime dtStart(bool first=false) const
TQDateTime dtDue(bool first=false) const
virtual void setDateRange(const TQDate &from, const TQDate &to)
Set date range which should be printed.
Definition: printplugin.h:141
TodoSortField
TodoSortSummary
TodoSortDueDate
TodoSortPriority
TodoSortPercentComplete
TodoSortStartDate
SortDirection
SortDirectionAscending
SortDirectionDescending