korganizer

calprintdefaultplugins.cpp

00001 /*
00002     This file is part of KOrganizer.
00003 
00004     Copyright (c) 1998 Preston Brown <pbrown@kde.org>
00005     Copyright (c) 2003 Reinhold Kainhofer <reinhold@kainhofer.com>
00006     Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
00007   Copyright (c) 2008 Ron Goodheart <ron.goodheart@gmail.com>
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017     GNU General Public License for more details.
00018 
00019     You should have received a copy of the GNU General Public License
00020     along with this program; if not, write to the Free Software
00021     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00022 
00023     As a special exception, permission is given to link this program
00024     with any edition of Qt, and distribute the resulting executable,
00025     without including the source code for Qt in the source distribution.
00026 */
00027 
00028 #ifndef KORG_NOPRINTER
00029 
00030 #include <qpainter.h>
00031 #include <qdatetimeedit.h>
00032 #include <qcheckbox.h>
00033 #include <qlineedit.h>
00034 #include <qbuttongroup.h>
00035 
00036 #include <kdebug.h>
00037 #include <kconfig.h>
00038 #include <kcalendarsystem.h>
00039 #include <knuminput.h>
00040 #include <kcombobox.h>
00041 
00042 #include <libkcal/incidenceformatter.h>
00043 
00044 #include "calprintdefaultplugins.h"
00045 
00046 #include "calprintincidenceconfig_base.h"
00047 #include "calprintdayconfig_base.h"
00048 #include "calprintweekconfig_base.h"
00049 #include "calprintmonthconfig_base.h"
00050 #include "calprinttodoconfig_base.h"
00051 
00052 
00053 /**************************************************************
00054  *           Print Incidence
00055  **************************************************************/
00056 
00057 CalPrintIncidence::CalPrintIncidence() : CalPrintPluginBase()
00058 {
00059 }
00060 
00061 CalPrintIncidence::~CalPrintIncidence()
00062 {
00063 }
00064 
00065 QWidget *CalPrintIncidence::createConfigWidget( QWidget *w )
00066 {
00067   return new CalPrintIncidenceConfig_Base( w );
00068 }
00069 
00070 void CalPrintIncidence::readSettingsWidget()
00071 {
00072   CalPrintIncidenceConfig_Base *cfg =
00073       dynamic_cast<CalPrintIncidenceConfig_Base*>( mConfigWidget );
00074   if ( cfg ) {
00075     mUseColors = cfg->mColors->isChecked();
00076     mShowOptions = cfg->mShowDetails->isChecked();
00077     mShowSubitemsNotes = cfg->mShowSubitemsNotes->isChecked();
00078     mShowAttendees = cfg->mShowAttendees->isChecked();
00079     mShowAttachments = cfg->mShowAttachments->isChecked();
00080   }
00081 }
00082 
00083 void CalPrintIncidence::setSettingsWidget()
00084 {
00085   CalPrintIncidenceConfig_Base *cfg =
00086       dynamic_cast<CalPrintIncidenceConfig_Base*>( mConfigWidget );
00087   if ( cfg ) {
00088     cfg->mColors->setChecked( mUseColors );
00089     cfg->mShowDetails->setChecked(mShowOptions);
00090     cfg->mShowSubitemsNotes->setChecked(mShowSubitemsNotes);
00091     cfg->mShowAttendees->setChecked(mShowAttendees);
00092     cfg->mShowAttachments->setChecked(mShowAttachments);
00093   }
00094 }
00095 
00096 void CalPrintIncidence::loadConfig()
00097 {
00098   if ( mConfig ) {
00099     mUseColors = mConfig->readBoolEntry( "Use Colors", false );
00100     mShowOptions = mConfig->readBoolEntry( "Show Options", false );
00101     mShowSubitemsNotes = mConfig->readBoolEntry( "Show Subitems and Notes", false );
00102     mShowAttendees = mConfig->readBoolEntry( "Use Attendees", false );
00103     mShowAttachments = mConfig->readBoolEntry( "Use Attachments", false );
00104   }
00105   setSettingsWidget();
00106 }
00107 
00108 void CalPrintIncidence::saveConfig()
00109 {
00110   readSettingsWidget();
00111   if ( mConfig ) {
00112     mConfig->writeEntry( "Use Colors", mUseColors );
00113     mConfig->writeEntry( "Show Options", mShowOptions );
00114     mConfig->writeEntry( "Show Subitems and Notes", mShowSubitemsNotes );
00115     mConfig->writeEntry( "Use Attendees", mShowAttendees );
00116     mConfig->writeEntry( "Use Attachments", mShowAttachments );
00117   }
00118 }
00119 
00120 
00121 class TimePrintStringsVisitor : public IncidenceBase::Visitor
00122 {
00123   public:
00124     TimePrintStringsVisitor() {}
00125 
00126     bool act( IncidenceBase *incidence )
00127     {
00128       return incidence->accept( *this );
00129     }
00130     QString mStartCaption, mStartString;
00131     QString mEndCaption, mEndString;
00132     QString mDurationCaption, mDurationString;
00133 
00134   protected:
00135     bool visit( Event *event ) {
00136       if ( event->dtStart().isValid() ) {
00137         mStartCaption =  i18n("Start date: ");
00138         // Show date/time or only date, depending on whether it's an all-day event
00139 // TODO: Add shortfmt param to dtStartStr, dtEndStr and dtDueStr!!!
00140         mStartString = (event->doesFloat()) ? (event->dtStartDateStr(false)) : (event->dtStartStr());
00141       } else {
00142         mStartCaption = i18n("No start date");
00143         mStartString = QString::null;
00144       }
00145     
00146       if ( event->hasEndDate() ) {
00147         mEndCaption = i18n("End date: ");
00148         mEndString = (event->doesFloat()) ? (event->dtEndDateStr(false)) : (event->dtEndStr());
00149       } else if ( event->hasDuration() ) {
00150         mEndCaption = i18n("Duration: ");
00151         int mins = event->duration() / 60;
00152         if ( mins >= 60 ) {
00153           mEndString += i18n( "1 hour ", "%n hours ", mins/60 );
00154         }
00155         if ( mins%60 > 0 ) {
00156           mEndString += i18n( "1 minute ", "%n minutes ",  mins%60 );
00157         }
00158       } else {
00159         mEndCaption = i18n("No end date");
00160         mEndString = QString::null;
00161       }
00162       return true;
00163     }
00164     bool visit( Todo *todo ) {
00165       if ( todo->hasStartDate() ) {
00166         mStartCaption =  i18n("Start date: ");
00167         // Show date/time or only date, depending on whether it's an all-day event
00168 // TODO: Add shortfmt param to dtStartStr, dtEndStr and dtDueStr!!!
00169         mStartString = (todo->doesFloat()) ? (todo->dtStartDateStr(false)) : (todo->dtStartStr());
00170       } else {
00171         mStartCaption = i18n("No start date");
00172         mStartString = QString::null;
00173       }
00174     
00175       if ( todo->hasDueDate() ) {
00176         mEndCaption = i18n("Due date: ");
00177         mEndString = (todo->doesFloat()) ? (todo->dtDueDateStr(false)) : (todo->dtDueStr());
00178       } else {
00179         mEndCaption = i18n("No due date");
00180         mEndString = QString::null;
00181       }
00182       return true;
00183     }
00184     bool visit( Journal *journal ) {
00185       mStartCaption = i18n("Start date: ");
00186 // TODO: Add shortfmt param to dtStartStr, dtEndStr and dtDueStr!!!
00187       mStartString = (journal->doesFloat()) ? (journal->dtStartDateStr(false)) : (journal->dtStartStr());
00188       mEndCaption = QString::null;
00189       mEndString = QString::null;
00190       return true;
00191     }
00192 };
00193 
00194 int CalPrintIncidence::printCaptionAndText( QPainter &p, const QRect &box, const QString &caption, const QString &text, QFont captionFont, QFont textFont )
00195 {
00196   QFontMetrics captionFM( captionFont );
00197   int textWd = captionFM.width( caption );
00198   QRect textRect( box );
00199 
00200   QFont oldFont( p.font() );
00201   p.setFont( captionFont );
00202   p.drawText( box, Qt::AlignLeft|Qt::AlignTop|Qt::SingleLine, caption );
00203 
00204   if ( !text.isEmpty() ) {
00205     textRect.setLeft( textRect.left() + textWd );
00206     p.setFont( textFont );
00207     p.drawText( textRect, Qt::AlignLeft|Qt::AlignTop|Qt::SingleLine, text );
00208   }
00209   p.setFont( oldFont );
00210   return textRect.bottom();
00211 }
00212 
00213 #include <qfontdatabase.h>
00214 void CalPrintIncidence::print( QPainter &p, int width, int height )
00215 {
00216   KLocale *local = KGlobal::locale();
00217 
00218   QFont oldFont(p.font());
00219   QFont textFont( "sans-serif", 11, QFont::Normal );
00220   QFont captionFont( "sans-serif", 11, QFont::Bold );
00221   p.setFont( textFont );
00222   int lineHeight = p.fontMetrics().lineSpacing();
00223   QString cap, txt;
00224 
00225 
00226   Incidence::List::ConstIterator it;
00227   for ( it=mSelectedIncidences.begin(); it!=mSelectedIncidences.end(); ++it ) {
00228     // don't do anything on a 0-pointer!
00229     if ( !(*it) ) continue;
00230     if ( it != mSelectedIncidences.begin() ) mPrinter->newPage();
00231 
00232 
00233     // PAGE Layout (same for landscape and portrait! astonishingly, it looks good with both!):
00234     //  +-----------------------------------+
00235     //  | Header:  Summary                  |
00236     //  +===================================+
00237     //  | start: ______   end: _________    |
00238     //  | repeats: ___________________      |
00239     //  | reminder: __________________      |
00240     //  +-----------------------------------+
00241     //  | Location: ______________________  |
00242     //  +------------------------+----------+
00243     //  | Description:           | Notes or |
00244     //  |                        | Subitems |
00245     //  |                        |          |
00246     //  |                        |          |
00247     //  |                        |          |
00248     //  |                        |          |
00249     //  |                        |          |
00250     //  |                        |          |
00251     //  |                        |          |
00252     //  |                        |          |
00253     //  +------------------------+----------+
00254     //  | Attachments:           | Settings |
00255     //  |                        |          |
00256     //  +------------------------+----------+
00257     //  | Attendees:                        |
00258     //  |                                   |
00259     //  +-----------------------------------+
00260     //  | Categories: _____________________ |
00261     //  +-----------------------------------+
00262 
00263     QRect box( 0, 0, width, height );
00264     QRect titleBox( box );
00265     titleBox.setHeight( headerHeight() );
00266     // Draw summary as header, no small calendars in title bar, expand height if needed
00267     int titleBottom = drawHeader( p, (*it)->summary(), QDate(), QDate(), titleBox, true );
00268     titleBox.setBottom( titleBottom );
00269 
00270     QRect timesBox( titleBox );
00271     timesBox.setTop( titleBox.bottom() + padding() );
00272     timesBox.setHeight( height / 8 );
00273     
00274     TimePrintStringsVisitor stringVis;
00275     int h = timesBox.top();
00276     if ( stringVis.act(*it) ) {
00277       QRect textRect( timesBox.left()+padding(), timesBox.top()+padding(), 0, lineHeight );
00278       textRect.setRight( timesBox.center().x() );
00279       h = printCaptionAndText( p, textRect, stringVis.mStartCaption, stringVis.mStartString, captionFont, textFont );
00280 
00281       textRect.setLeft( textRect.right() );
00282       textRect.setRight( timesBox.right() - padding() );
00283       h = QMAX( printCaptionAndText( p, textRect, stringVis.mEndCaption, stringVis.mEndString, captionFont, textFont ), h );
00284     }
00285     
00286     // Convert recurrence to a string
00287     if ( (*it)->doesRecur() ) {
00288       QRect recurBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight );
00289       KCal::Recurrence *recurs = (*it)->recurrence();
00290 
00291       QString displayString = IncidenceFormatter::recurrenceString((*it));
00292       // exception dates
00293       QString exceptString;
00294       if ( !recurs->exDates().isEmpty() ) {
00295         exceptString = i18n("except for listed dates", " except");
00296         for ( uint i = 0; i < recurs->exDates().size(); i++ ) {
00297           exceptString.append(" ");
00298           exceptString.append( KGlobal::locale()->formatDate(recurs->exDates()[i],
00299                                true) );
00300         }
00301       }
00302       displayString.append(exceptString);
00303       h = QMAX( printCaptionAndText( p, recurBox, i18n( "Repeats: "), displayString, captionFont, textFont ), h );
00304     }
00305 
00306     // Alarms Printing
00307     QRect alarmBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight );
00308     Alarm::List alarms = (*it)->alarms();
00309     if ( alarms.count() == 0 ) {
00310       cap = i18n("No reminders");
00311       txt = QString();
00312     } else {
00313       cap = i18n("Reminder: ", "%n reminders: ", alarms.count() );
00314       
00315       QStringList alarmStrings;
00316       KCal::Alarm::List::ConstIterator it;
00317       for ( it = alarms.begin(); it != alarms.end(); ++it ) {
00318         Alarm *alarm = *it;
00319       
00320         // Alarm offset, copied from koeditoralarms.cpp:
00321         QString offsetstr;
00322         int offset = 0;
00323         if ( alarm->hasStartOffset() ) {
00324           offset = alarm->startOffset().asSeconds();
00325           if ( offset < 0 ) {
00326             offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the start");
00327             offset = -offset;
00328           } else {
00329             offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the start");
00330           }
00331         } else if ( alarm->hasEndOffset() ) {
00332           offset = alarm->endOffset().asSeconds();
00333           if ( offset < 0 ) {
00334             offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the end");
00335             offset = -offset;
00336           } else {
00337             offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the end");
00338           }
00339         }
00340 
00341         offset = offset / 60; // make minutes
00342         int useoffset = offset;
00343 
00344         if ( offset % (24*60) == 0 && offset>0 ) { // divides evenly into days?
00345           useoffset = offset / (24*60);
00346           offsetstr = offsetstr.arg( i18n("1 day", "%n days", useoffset ) );
00347         } else if (offset % 60 == 0 && offset>0 ) { // divides evenly into hours?
00348           useoffset = offset / 60;
00349           offsetstr = offsetstr.arg( i18n("1 hour", "%n hours", useoffset ) );
00350         } else {
00351           useoffset = offset;
00352           offsetstr = offsetstr.arg( i18n("1 minute", "%n minutes", useoffset ) );
00353         }
00354         alarmStrings << offsetstr;
00355       }
00356       txt = alarmStrings.join( i18n("Spacer for the joined list of categories", ", ") );
00357 
00358     }
00359     h = QMAX( printCaptionAndText( p, alarmBox, cap, txt, captionFont, textFont ), h );
00360 
00361 
00362     QRect organizerBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight );
00363     h = QMAX( printCaptionAndText( p, organizerBox, i18n("Organizer: "), (*it)->organizer().fullName(), captionFont, textFont ), h );
00364     
00365     // Finally, draw the frame around the time information...
00366     timesBox.setBottom( QMAX( timesBox.bottom(), h+padding() ) );
00367     drawBox( p, BOX_BORDER_WIDTH, timesBox );
00368 
00369 
00370     QRect locationBox( timesBox );
00371     locationBox.setTop( timesBox.bottom() + padding() );
00372     locationBox.setHeight( 0 );
00373     int locationBottom = drawBoxWithCaption( p, locationBox, i18n("Location: "),
00374          (*it)->location(), /*sameLine=*/true, /*expand=*/true, captionFont, textFont );
00375     locationBox.setBottom( locationBottom );
00376 
00377 
00378     // Now start constructing the boxes from the bottom:
00379     QRect categoriesBox( locationBox );
00380     categoriesBox.setBottom( box.bottom() );
00381     categoriesBox.setTop( categoriesBox.bottom() - lineHeight - 2*padding() );
00382 
00383 
00384     QRect attendeesBox( box.left(), categoriesBox.top()-padding()-box.height()/9, box.width(), box.height()/9 );
00385 
00386     QRect attachmentsBox( box.left(), attendeesBox.top()-padding()-box.height()/9, box.width()*3/4 - padding(), box.height()/9 );
00387     QRect optionsBox( attachmentsBox.right() + padding(), attachmentsBox.top(), 0, 0 );
00388     optionsBox.setRight( box.right() );
00389     optionsBox.setBottom( attachmentsBox.bottom() );
00390     QRect notesBox( optionsBox.left(), locationBox.bottom() + padding(), optionsBox.width(), 0 );
00391     notesBox.setBottom( optionsBox.top() - padding() );
00392 
00393     QRect descriptionBox( notesBox );
00394     descriptionBox.setLeft( box.left() );
00395     descriptionBox.setRight( attachmentsBox.right() );
00396     // Adjust boxes depending on the show options...    
00397     if (!mShowSubitemsNotes) {
00398       descriptionBox.setRight( box.right() );
00399     }
00400     if (!mShowAttachments || !mShowAttendees) {
00401         descriptionBox.setBottom( attachmentsBox.bottom() );
00402         optionsBox.setTop( attendeesBox.top() );
00403         optionsBox.setBottom( attendeesBox.bottom() );
00404         notesBox.setBottom( attachmentsBox.bottom() );
00405         if (mShowOptions) {
00406           attendeesBox.setRight( attachmentsBox.right() );
00407         }
00408       if (!mShowAttachments && !mShowAttendees) {
00409         if (mShowSubitemsNotes) {
00410           descriptionBox.setBottom( attendeesBox.bottom() );  
00411         }
00412         if (!mShowOptions) {
00413           descriptionBox.setBottom( attendeesBox.bottom() );  
00414           notesBox.setBottom( attendeesBox.bottom() );
00415         }
00416       }
00417     }
00418     if (mShowAttachments) {
00419       if (!mShowOptions) {
00420         attachmentsBox.setRight( box.right() );        
00421         attachmentsBox.setRight( box.right() );
00422       }
00423       if (!mShowAttendees) {
00424         attachmentsBox.setTop( attendeesBox.top() );
00425         attachmentsBox.setBottom( attendeesBox.bottom() );
00426       }
00427     }
00428     
00429     drawBoxWithCaption( p, descriptionBox, i18n("Description:"), 
00430                         (*it)->description(), /*sameLine=*/false, 
00431                         /*expand=*/false, captionFont, textFont );
00432     
00433     if ( mShowSubitemsNotes ) {
00434       if ( (*it)->relations().isEmpty() || (*it)->type() != "Todo" ) {
00435         int notesPosition = drawBoxWithCaption( p, notesBox, i18n("Notes:"), 
00436                          QString::null, /*sameLine=*/false, /*expand=*/false, 
00437                          captionFont, textFont );
00438         QPen oldPen( p.pen() );
00439         p.setPen( Qt::DotLine );
00440         while ( (notesPosition += int(1.5*lineHeight)) < notesBox.bottom() ) {
00441           p.drawLine( notesBox.left()+padding(), notesPosition, notesBox.right()-padding(), notesPosition );
00442         }
00443         p.setPen( oldPen );
00444       } else {
00445         Incidence::List relations = (*it)->relations();
00446         QString subitemCaption;
00447         if ( relations.count() == 0 ) {
00448           subitemCaption = i18n( "No Subitems" );
00449           txt == "";
00450         } else {
00451           subitemCaption = i18n( "1 Subitem:", 
00452                           "%1 Subitems:", 
00453                           relations.count() );
00454         }
00455         Incidence::List::ConstIterator rit;
00456         QString subitemString;
00457         QString statusString;
00458         QString datesString;
00459         int count = 0;
00460         for ( rit = relations.begin(); rit != relations.end(); ++rit ) {
00461           ++count;
00462           if ( !(*rit) ) { // defensive, skip any zero pointers
00463             continue;
00464           }
00465           // format the status
00466           statusString = (*rit)->statusStr();
00467           if ( statusString.isEmpty() ) {
00468             if ( (*rit)->status() == Incidence::StatusNone ) {
00469               statusString = i18n( "no status", "none" );
00470             } else {
00471               statusString = i18n( "unknown status", "unknown" );
00472             }
00473           }
00474           // format the dates if provided
00475           datesString = "";
00476           if ( (*rit)->dtStart().isValid() ) {
00477                 datesString += i18n( 
00478                 "Start Date: %1\n").arg(
00479                 KGlobal::locale()->formatDate( (*rit)->dtStart().date(),
00480                                 true ) );
00481             if ( !(*rit)->doesFloat() ) {
00482                 datesString += i18n( 
00483                 "Start Time: %1\n").arg(
00484                 KGlobal::locale()->formatTime((*rit)->dtStart().time(),
00485                      false, false) );
00486             }
00487           }
00488           if ( (*rit)->dtEnd().isValid() ) {
00489             subitemString += i18n( 
00490                 "Due Date: %1\n").arg(
00491                 KGlobal::locale()->formatDate( (*rit)->dtEnd().date(),
00492                                 true ) );
00493             if ( !(*rit)->doesFloat() ) {
00494               subitemString += i18n( 
00495                   "subitem due time", "Due Time: %1\n").arg(
00496                   KGlobal::locale()->formatTime((*rit)->dtEnd().time(), 
00497                       false, false) );
00498             }
00499           }
00500           subitemString += i18n("subitem counter", "%1: ", count);
00501           subitemString += (*rit)->summary();
00502           subitemString += "\n";
00503           if ( !datesString.isEmpty() ) {
00504             subitemString += datesString;
00505             subitemString += "\n";
00506           }
00507           subitemString += i18n( "subitem Status: statusString", 
00508                                   "Status: %1\n").arg( statusString );
00509           subitemString += IncidenceFormatter::recurrenceString((*rit)) + "\n";
00510           subitemString += i18n( "subitem Priority: N", 
00511                                   "Priority: %1\n").arg( (*rit)->priority() );
00512           subitemString += i18n( "subitem Secrecy: secrecyString",
00513                                   "Secrecy: %1\n").arg( (*rit)->secrecyStr() );
00514           subitemString += "\n";
00515         }
00516         drawBoxWithCaption( p, notesBox, i18n("Subitems:"), 
00517                             (*it)->description(), /*sameLine=*/false, 
00518                             /*expand=*/false, captionFont, textFont );
00519       }
00520     }
00521 
00522     if ( mShowAttachments ) {
00523       Attachment::List attachments = (*it)->attachments();
00524       QString attachmentCaption;
00525       if ( attachments.count() == 0 ) {
00526         attachmentCaption = i18n( "No Attachments" );
00527         txt = QString();
00528       } else {
00529         attachmentCaption = i18n( "1 Attachment:", "%1 Attachments:", attachments.count() );
00530       }
00531       QString attachmentString;
00532       Attachment::List::ConstIterator ait = attachments.begin();
00533       for ( ; ait != attachments.end(); ++ait ) {
00534         if (!attachmentString.isEmpty()) {
00535           attachmentString += i18n( "Spacer for list of attachments", "  " );
00536         }
00537         attachmentString.append((*ait)->label());
00538       }
00539       drawBoxWithCaption( p, attachmentsBox,
00540                         attachmentCaption, attachmentString, 
00541                         /*sameLine=*/false, /*expand=*/false, 
00542                         captionFont, textFont );
00543       int attachStart = drawBoxWithCaption( p, attachmentsBox, 
00544                         QString()/*i18n("Attachments:")*/, QString(), /*sameLine=*/false, 
00545                         /*expand=*/false, captionFont, textFont );
00546     }
00547 
00548     if ( mShowAttendees ) {
00549       Attendee::List attendees = (*it)->attendees();
00550       QString attendeeCaption;
00551       if ( attendees.count() == 0 )
00552         attendeeCaption = i18n("No Attendees");
00553       else
00554         attendeeCaption = i18n("1 Attendee:", "%n Attendees:", attendees.count() );
00555       QString attendeeString;
00556       for ( Attendee::List::ConstIterator ait = attendees.begin(); ait != attendees.end(); ++ait ) {
00557         if ( !attendeeString.isEmpty() ) attendeeString += "\n";
00558         attendeeString += i18n("Formatting of an attendee: "
00559                "'Name (Role): Status', e.g. 'Reinhold Kainhofer "
00560                "<reinhold@kainhofer.com> (Participant): Awaiting Response'",
00561                "%1 (%2): %3")
00562                        .arg( (*ait)->fullName() )
00563                        .arg( (*ait)->roleStr() ).arg( (*ait)->statusStr() );
00564       }
00565       drawBoxWithCaption( p, attendeesBox, i18n("Attendees:"), attendeeString, 
00566                /*sameLine=*/false, /*expand=*/false, captionFont, textFont );
00567     }
00568 
00569     if ( mShowOptions ) {
00570       QString optionsString;
00571       if ( !(*it)->statusStr().isEmpty() ) {
00572         optionsString += i18n("Status: %1").arg( (*it)->statusStr() );
00573         optionsString += "\n";
00574       }
00575       if ( !(*it)->secrecyStr().isEmpty() ) {
00576         optionsString += i18n("Secrecy: %1").arg( (*it)->secrecyStr() );
00577         optionsString += "\n";
00578       }
00579       if ( (*it)->type() == "Event" ) {
00580         Event *e = static_cast<Event*>(*it);
00581         if ( e->transparency() == Event::Opaque ) {
00582           optionsString += i18n("Show as: Busy");
00583         } else {
00584           optionsString += i18n("Show as: Free");
00585         }
00586         optionsString += "\n";
00587       } else if ( (*it)->type() == "Todo" ) {
00588         Todo *t = static_cast<Todo*>(*it);
00589         if ( t->isOverdue() ) {
00590           optionsString += i18n("This task is overdue!");
00591           optionsString += "\n";
00592         }
00593       } else if ( (*it)->type() == "Journal" ) {
00594         //TODO: Anything Journal-specific?
00595       }
00596       drawBoxWithCaption( p, optionsBox, i18n("Settings: "),
00597              optionsString, /*sameLine=*/false, /*expand=*/false, captionFont, textFont );
00598     }
00599     
00600     drawBoxWithCaption( p, categoriesBox, i18n("Categories: "),
00601            (*it)->categories().join( i18n("Spacer for the joined list of categories", ", ") ),
00602            /*sameLine=*/true, /*expand=*/false, captionFont, textFont );
00603   }
00604   p.setFont( oldFont );
00605 }
00606 
00607 /**************************************************************
00608  *           Print Day
00609  **************************************************************/
00610 
00611 CalPrintDay::CalPrintDay() : CalPrintPluginBase()
00612 {
00613 }
00614 
00615 CalPrintDay::~CalPrintDay()
00616 {
00617 }
00618 
00619 QWidget *CalPrintDay::createConfigWidget( QWidget *w )
00620 {
00621   return new CalPrintDayConfig_Base( w );
00622 }
00623 
00624 void CalPrintDay::readSettingsWidget()
00625 {
00626   CalPrintDayConfig_Base *cfg =
00627       dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget );
00628   if ( cfg ) {
00629     mFromDate = cfg->mFromDate->date();
00630     mToDate = cfg->mToDate->date();
00631 
00632     mStartTime = cfg->mFromTime->time();
00633     mEndTime = cfg->mToTime->time();
00634     mIncludeAllEvents = cfg->mIncludeAllEvents->isChecked();
00635 
00636     mIncludeTodos = cfg->mIncludeTodos->isChecked();
00637     mUseColors = cfg->mColors->isChecked();
00638   }
00639 }
00640 
00641 void CalPrintDay::setSettingsWidget()
00642 {
00643   CalPrintDayConfig_Base *cfg =
00644       dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget );
00645   if ( cfg ) {
00646     cfg->mFromDate->setDate( mFromDate );
00647     cfg->mToDate->setDate( mToDate );
00648 
00649     cfg->mFromTime->setTime( mStartTime );
00650     cfg->mToTime->setTime( mEndTime );
00651     cfg->mIncludeAllEvents->setChecked( mIncludeAllEvents );
00652 
00653     cfg->mIncludeTodos->setChecked( mIncludeTodos );
00654     cfg->mColors->setChecked( mUseColors );
00655   }
00656 }
00657 
00658 void CalPrintDay::loadConfig()
00659 {
00660   if ( mConfig ) {
00661     QDate dt;
00662     QTime tm1( dayStart() );
00663     QDateTime startTm( dt, tm1 );
00664     QDateTime endTm( dt, tm1.addSecs( 12 * 60 * 60 ) );
00665     mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time();
00666     mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time();
00667     mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
00668     mIncludeAllEvents = mConfig->readBoolEntry( "Include all events", false );
00669   }
00670   setSettingsWidget();
00671 }
00672 
00673 void CalPrintDay::saveConfig()
00674 {
00675   readSettingsWidget();
00676   if ( mConfig ) {
00677     mConfig->writeEntry( "Start time", QDateTime( QDate(), mStartTime ) );
00678     mConfig->writeEntry( "End time", QDateTime( QDate(), mEndTime ) );
00679     mConfig->writeEntry( "Include todos", mIncludeTodos );
00680     mConfig->writeEntry( "Include all events", mIncludeAllEvents );
00681   }
00682 }
00683 
00684 void CalPrintDay::setDateRange( const QDate& from, const QDate& to )
00685 {
00686   CalPrintPluginBase::setDateRange( from, to );
00687   CalPrintDayConfig_Base *cfg =
00688       dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget );
00689   if ( cfg ) {
00690     cfg->mFromDate->setDate( from );
00691     cfg->mToDate->setDate( to );
00692   }
00693 }
00694 
00695 void CalPrintDay::print( QPainter &p, int width, int height )
00696 {
00697   QDate curDay( mFromDate );
00698 
00699   do {
00700     QTime curStartTime( mStartTime );
00701     QTime curEndTime( mEndTime );
00702 
00703     // For an invalid time range, simply show one hour, starting at the hour
00704     // before the given start time
00705     if ( curEndTime <= curStartTime ) {
00706       curStartTime = QTime( curStartTime.hour(), 0, 0 );
00707       curEndTime = curStartTime.addSecs( 3600 );
00708     }
00709 
00710     KLocale *local = KGlobal::locale();
00711     QRect headerBox( 0, 0, width, headerHeight() );
00712     drawHeader( p, local->formatDate( curDay ), curDay, QDate(), headerBox );
00713 
00714 
00715     Event::List eventList = mCalendar->events( curDay,
00716                                                EventSortStartDate,
00717                                                SortDirectionAscending );
00718 
00719     p.setFont( QFont( "sans-serif", 12 ) );
00720 
00721     // TODO: Find a good way to determine the height of the all-day box
00722     QRect allDayBox( TIMELINE_WIDTH + padding(), headerBox.bottom() + padding(),
00723                      0, height / 20 );
00724     allDayBox.setRight( width );
00725     int allDayHeight = drawAllDayBox( p, eventList, curDay, true, allDayBox );
00726 
00727     QRect dayBox( allDayBox );
00728     dayBox.setTop( allDayHeight /*allDayBox.bottom()*/ );
00729     dayBox.setBottom( height );
00730     drawAgendaDayBox( p, eventList, curDay, mIncludeAllEvents,
00731                       curStartTime, curEndTime, dayBox );
00732 
00733     QRect tlBox( dayBox );
00734     tlBox.setLeft( 0 );
00735     tlBox.setWidth( TIMELINE_WIDTH );
00736     drawTimeLine( p, curStartTime, curEndTime, tlBox );
00737     curDay = curDay.addDays( 1 );
00738     if ( curDay <= mToDate ) mPrinter->newPage();
00739   } while ( curDay <= mToDate );
00740 }
00741 
00742 
00743 
00744 /**************************************************************
00745  *           Print Week
00746  **************************************************************/
00747 
00748 CalPrintWeek::CalPrintWeek() : CalPrintPluginBase()
00749 {
00750 }
00751 
00752 CalPrintWeek::~CalPrintWeek()
00753 {
00754 }
00755 
00756 QWidget *CalPrintWeek::createConfigWidget( QWidget *w )
00757 {
00758   return new CalPrintWeekConfig_Base( w );
00759 }
00760 
00761 void CalPrintWeek::readSettingsWidget()
00762 {
00763   CalPrintWeekConfig_Base *cfg =
00764       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00765   if ( cfg ) {
00766     mFromDate = cfg->mFromDate->date();
00767     mToDate = cfg->mToDate->date();
00768 
00769     mWeekPrintType = (eWeekPrintType)( cfg->mPrintType->id(
00770       cfg->mPrintType->selected() ) );
00771 
00772     mStartTime = cfg->mFromTime->time();
00773     mEndTime = cfg->mToTime->time();
00774 
00775     mIncludeTodos = cfg->mIncludeTodos->isChecked();
00776     mUseColors = cfg->mColors->isChecked();
00777   }
00778 }
00779 
00780 void CalPrintWeek::setSettingsWidget()
00781 {
00782   CalPrintWeekConfig_Base *cfg =
00783       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00784   if ( cfg ) {
00785     cfg->mFromDate->setDate( mFromDate );
00786     cfg->mToDate->setDate( mToDate );
00787 
00788     cfg->mPrintType->setButton( mWeekPrintType );
00789 
00790     cfg->mFromTime->setTime( mStartTime );
00791     cfg->mToTime->setTime( mEndTime );
00792 
00793     cfg->mIncludeTodos->setChecked( mIncludeTodos );
00794     cfg->mColors->setChecked( mUseColors );
00795   }
00796 }
00797 
00798 void CalPrintWeek::loadConfig()
00799 {
00800   if ( mConfig ) {
00801     QDate dt;
00802     QTime tm1( dayStart() );
00803     QDateTime startTm( dt, tm1  );
00804     QDateTime endTm( dt, tm1.addSecs( 43200 ) );
00805     mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time();
00806     mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time();
00807     mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
00808     mWeekPrintType =(eWeekPrintType)( mConfig->readNumEntry( "Print type", (int)Filofax ) );
00809   }
00810   setSettingsWidget();
00811 }
00812 
00813 void CalPrintWeek::saveConfig()
00814 {
00815   readSettingsWidget();
00816   if ( mConfig ) {
00817     mConfig->writeEntry( "Start time", QDateTime( QDate(), mStartTime ) );
00818     mConfig->writeEntry( "End time", QDateTime( QDate(), mEndTime ) );
00819     mConfig->writeEntry( "Include todos", mIncludeTodos );
00820     mConfig->writeEntry( "Print type", int( mWeekPrintType ) );
00821   }
00822 }
00823 
00824 KPrinter::Orientation CalPrintWeek::defaultOrientation()
00825 {
00826   if ( mWeekPrintType == Filofax ) return KPrinter::Portrait;
00827   else if ( mWeekPrintType == SplitWeek ) return KPrinter::Portrait;
00828   else return KPrinter::Landscape;
00829 }
00830 
00831 void CalPrintWeek::setDateRange( const QDate &from, const QDate &to )
00832 {
00833   CalPrintPluginBase::setDateRange( from, to );
00834   CalPrintWeekConfig_Base *cfg =
00835       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00836   if ( cfg ) {
00837     cfg->mFromDate->setDate( from );
00838     cfg->mToDate->setDate( to );
00839   }
00840 }
00841 
00842 void CalPrintWeek::print( QPainter &p, int width, int height )
00843 {
00844   QDate curWeek, fromWeek, toWeek;
00845 
00846   // correct begin and end to first and last day of week
00847   int weekdayCol = weekdayColumn( mFromDate.dayOfWeek() );
00848   fromWeek = mFromDate.addDays( -weekdayCol );
00849   weekdayCol = weekdayColumn( mFromDate.dayOfWeek() );
00850   toWeek = mToDate.addDays( 6 - weekdayCol );
00851 
00852   curWeek = fromWeek.addDays( 6 );
00853   KLocale *local = KGlobal::locale();
00854 
00855   QString line1, line2, title;
00856   QRect headerBox( 0, 0, width, headerHeight() );
00857   QRect weekBox( headerBox );
00858   weekBox.setTop( headerBox.bottom() + padding() );
00859   weekBox.setBottom( height );
00860 
00861   switch ( mWeekPrintType ) {
00862     case Filofax:
00863       do {
00864         line1 = local->formatDate( curWeek.addDays( -6 ) );
00865         line2 = local->formatDate( curWeek );
00866         if ( orientation() == KPrinter::Landscape ) {
00867           title = i18n("date from-to", "%1 - %2");
00868         } else {
00869           title = i18n("date from-\nto", "%1 -\n%2");;
00870         }
00871         title = title.arg( line1 ).arg( line2 );
00872         drawHeader( p, title, curWeek.addDays( -6 ), QDate(), headerBox );
00873         drawWeek( p, curWeek, weekBox );
00874         curWeek = curWeek.addDays( 7 );
00875         if ( curWeek <= toWeek )
00876           mPrinter->newPage();
00877       } while ( curWeek <= toWeek );
00878       break;
00879 
00880     case Timetable:
00881     default:
00882       do {
00883         line1 = local->formatDate( curWeek.addDays( -6 ) );
00884         line2 = local->formatDate( curWeek );
00885         if ( orientation() == KPrinter::Landscape ) {
00886           title = i18n("date from - to (week number)", "%1 - %2 (Week %3)");
00887         } else {
00888           title = i18n("date from -\nto (week number)", "%1 -\n%2 (Week %3)");
00889         }
00890         title = title.arg( line1 ).arg( line2 ).arg( curWeek.weekNumber() );
00891         drawHeader( p, title, curWeek, QDate(), headerBox );
00892         QRect weekBox( headerBox );
00893         weekBox.setTop( headerBox.bottom() + padding() );
00894         weekBox.setBottom( height );
00895 
00896         drawTimeTable( p, fromWeek, curWeek, mStartTime, mEndTime, weekBox );
00897         fromWeek = fromWeek.addDays( 7 );
00898         curWeek = fromWeek.addDays( 6 );
00899         if ( curWeek <= toWeek )
00900           mPrinter->newPage();
00901       } while ( curWeek <= toWeek );
00902       break;
00903 
00904     case SplitWeek: {
00905       QRect weekBox1( weekBox );
00906       // On the left side there are four days (mo-th) plus the timeline,
00907       // on the right there are only three days (fr-su) plus the timeline. Don't
00908       // use the whole width, but rather give them the same width as on the left.
00909       weekBox1.setRight( int( ( width - TIMELINE_WIDTH ) * 3. / 4. + TIMELINE_WIDTH ) );
00910       do {
00911         QDate endLeft( fromWeek.addDays( 3 ) );
00912         int hh = headerHeight();
00913 
00914         drawTimeTable( p, fromWeek, endLeft,
00915                        mStartTime, mEndTime, weekBox );
00916         mPrinter->newPage();
00917         drawSplitHeaderRight( p, fromWeek, curWeek, QDate(), width, hh );
00918         drawTimeTable( p, endLeft.addDays( 1 ), curWeek,
00919                        mStartTime, mEndTime, weekBox1 );
00920 
00921         fromWeek = fromWeek.addDays( 7 );
00922         curWeek = fromWeek.addDays( 6 );
00923         if ( curWeek <= toWeek )
00924           mPrinter->newPage();
00925       } while ( curWeek <= toWeek );
00926       }
00927       break;
00928   }
00929 }
00930 
00931 
00932 
00933 
00934 /**************************************************************
00935  *           Print Month
00936  **************************************************************/
00937 
00938 CalPrintMonth::CalPrintMonth() : CalPrintPluginBase()
00939 {
00940 }
00941 
00942 CalPrintMonth::~CalPrintMonth()
00943 {
00944 }
00945 
00946 QWidget *CalPrintMonth::createConfigWidget( QWidget *w )
00947 {
00948   return new CalPrintMonthConfig_Base( w );
00949 }
00950 
00951 void CalPrintMonth::readSettingsWidget()
00952 {
00953   CalPrintMonthConfig_Base *cfg =
00954       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
00955   if ( cfg ) {
00956     mFromDate = QDate( cfg->mFromYear->value(), cfg->mFromMonth->currentItem()+1, 1 );
00957     mToDate = QDate( cfg->mToYear->value(), cfg->mToMonth->currentItem()+1, 1 );
00958 
00959     mWeekNumbers =  cfg->mWeekNumbers->isChecked();
00960     mRecurDaily = cfg->mRecurDaily->isChecked();
00961     mRecurWeekly = cfg->mRecurWeekly->isChecked();
00962     mIncludeTodos = cfg->mIncludeTodos->isChecked();
00963 //    mUseColors = cfg->mColors->isChecked();
00964   }
00965 }
00966 
00967 void CalPrintMonth::setSettingsWidget()
00968 {
00969   CalPrintMonthConfig_Base *cfg =
00970       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
00971   setDateRange( mFromDate, mToDate );
00972   if ( cfg ) {
00973     cfg->mWeekNumbers->setChecked( mWeekNumbers );
00974     cfg->mRecurDaily->setChecked( mRecurDaily );
00975     cfg->mRecurWeekly->setChecked( mRecurWeekly );
00976     cfg->mIncludeTodos->setChecked( mIncludeTodos );
00977 //    cfg->mColors->setChecked( mUseColors );
00978   }
00979 }
00980 
00981 void CalPrintMonth::loadConfig()
00982 {
00983   if ( mConfig ) {
00984     mWeekNumbers = mConfig->readBoolEntry( "Print week numbers", true );
00985     mRecurDaily = mConfig->readBoolEntry( "Print daily incidences", true );
00986     mRecurWeekly = mConfig->readBoolEntry( "Print weekly incidences", true );
00987     mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
00988   }
00989   setSettingsWidget();
00990 }
00991 
00992 void CalPrintMonth::saveConfig()
00993 {
00994   readSettingsWidget();
00995   if ( mConfig ) {
00996     mConfig->writeEntry( "Print week numbers", mWeekNumbers );
00997     mConfig->writeEntry( "Print daily incidences", mRecurDaily );
00998     mConfig->writeEntry( "Print weekly incidences", mRecurWeekly );
00999     mConfig->writeEntry( "Include todos", mIncludeTodos );
01000   }
01001 }
01002 
01003 void CalPrintMonth::setDateRange( const QDate &from, const QDate &to )
01004 {
01005   CalPrintPluginBase::setDateRange( from, to );
01006   CalPrintMonthConfig_Base *cfg =
01007       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
01008   const KCalendarSystem *calSys = calendarSystem();
01009   if ( cfg && calSys ) {
01010     cfg->mFromMonth->clear();
01011     for ( int i=0; i<calSys->monthsInYear( mFromDate ); ++i ) {
01012       cfg->mFromMonth->insertItem( calSys->monthName( i+1, mFromDate.year() ) );
01013     }
01014     cfg->mToMonth->clear();
01015     for ( int i=0; i<calSys->monthsInYear( mToDate ); ++i ) {
01016       cfg->mToMonth->insertItem( calSys->monthName( i+1, mToDate.year() ) );
01017     }
01018   }
01019   if ( cfg ) {
01020     cfg->mFromMonth->setCurrentItem( from.month()-1 );
01021     cfg->mFromYear->setValue( to.year() );
01022     cfg->mToMonth->setCurrentItem( mToDate.month()-1 );
01023     cfg->mToYear->setValue( mToDate.year() );
01024   }
01025 }
01026 
01027 void CalPrintMonth::print( QPainter &p, int width, int height )
01028 {
01029   QDate curMonth, fromMonth, toMonth;
01030 
01031   fromMonth = mFromDate.addDays( -( mFromDate.day() - 1 ) );
01032   toMonth = mToDate.addDays( mToDate.daysInMonth() - mToDate.day() );
01033 
01034   curMonth = fromMonth;
01035   const KCalendarSystem *calSys = calendarSystem();
01036   if ( !calSys ) return;
01037 
01038   QRect headerBox( 0, 0, width, headerHeight() );
01039   QRect monthBox( 0, 0, width, height );
01040   monthBox.setTop( headerBox.bottom() + padding() );
01041 
01042   do {
01043     QString title( i18n("monthname year", "%1 %2") );
01044     title = title.arg( calSys->monthName( curMonth ) )
01045                  .arg( curMonth.year() );
01046     QDate tmp( fromMonth );
01047     int weekdayCol = weekdayColumn( tmp.dayOfWeek() );
01048     tmp = tmp.addDays( -weekdayCol );
01049 
01050     drawHeader( p, title, curMonth.addMonths( -1 ), curMonth.addMonths( 1 ),
01051                 headerBox );
01052     drawMonthTable( p, curMonth, mWeekNumbers, mRecurDaily, mRecurWeekly, monthBox );
01053     curMonth = curMonth.addDays( curMonth.daysInMonth() );
01054     if ( curMonth <= toMonth ) mPrinter->newPage();
01055   } while ( curMonth <= toMonth );
01056 
01057 }
01058 
01059 
01060 
01061 
01062 /**************************************************************
01063  *           Print Todos
01064  **************************************************************/
01065 
01066 CalPrintTodos::CalPrintTodos() : CalPrintPluginBase()
01067 {
01068   mTodoSortField = TodoFieldUnset;
01069   mTodoSortDirection = TodoDirectionUnset;
01070 }
01071 
01072 CalPrintTodos::~CalPrintTodos()
01073 {
01074 }
01075 
01076 QWidget *CalPrintTodos::createConfigWidget( QWidget *w )
01077 {
01078   return new CalPrintTodoConfig_Base( w );
01079 }
01080 
01081 void CalPrintTodos::readSettingsWidget()
01082 {
01083   CalPrintTodoConfig_Base *cfg =
01084       dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget );
01085   if ( cfg ) {
01086     mPageTitle = cfg->mTitle->text();
01087 
01088     mTodoPrintType = (eTodoPrintType)( cfg->mPrintType->id(
01089       cfg->mPrintType->selected() ) );
01090 
01091     mFromDate = cfg->mFromDate->date();
01092     mToDate = cfg->mToDate->date();
01093 
01094     mIncludeDescription = cfg->mDescription->isChecked();
01095     mIncludePriority = cfg->mPriority->isChecked();
01096     mIncludeDueDate = cfg->mDueDate->isChecked();
01097     mIncludePercentComplete = cfg->mPercentComplete->isChecked();
01098     mConnectSubTodos = cfg->mConnectSubTodos->isChecked();
01099     mStrikeOutCompleted = cfg->mStrikeOutCompleted->isChecked();
01100 
01101     mTodoSortField = (eTodoSortField)cfg->mSortField->currentItem();
01102     mTodoSortDirection = (eTodoSortDirection)cfg->mSortDirection->currentItem();
01103   }
01104 }
01105 
01106 void CalPrintTodos::setSettingsWidget()
01107 {
01108 //   kdDebug(5850) << "CalPrintTodos::setSettingsWidget" << endl;
01109 
01110   CalPrintTodoConfig_Base *cfg =
01111       dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget );
01112   if ( cfg ) {
01113     cfg->mTitle->setText( mPageTitle );
01114 
01115     cfg->mPrintType->setButton( mTodoPrintType );
01116 
01117     cfg->mFromDate->setDate( mFromDate );
01118     cfg->mToDate->setDate( mToDate );
01119 
01120     cfg->mDescription->setChecked( mIncludeDescription );
01121     cfg->mPriority->setChecked( mIncludePriority );
01122     cfg->mDueDate->setChecked( mIncludeDueDate );
01123     cfg->mPercentComplete->setChecked( mIncludePercentComplete );
01124     cfg->mConnectSubTodos->setChecked( mConnectSubTodos );
01125     cfg->mStrikeOutCompleted->setChecked( mStrikeOutCompleted );
01126 
01127     if ( mTodoSortField != TodoFieldUnset ) {
01128       // do not insert if already done so.
01129       cfg->mSortField->insertItem( i18n("Summary") );
01130       cfg->mSortField->insertItem( i18n("Start Date") );
01131       cfg->mSortField->insertItem( i18n("Due Date") );
01132       cfg->mSortField->insertItem( i18n("Priority") );
01133       cfg->mSortField->insertItem( i18n("Percent Complete") );
01134       cfg->mSortField->setCurrentItem( (int)mTodoSortField );
01135     }
01136 
01137     if ( mTodoSortDirection != TodoDirectionUnset ) {
01138       // do not insert if already done so.
01139       cfg->mSortDirection->insertItem( i18n("Ascending") );
01140       cfg->mSortDirection->insertItem( i18n("Descending") );
01141       cfg->mSortDirection->setCurrentItem( (int)mTodoSortDirection );
01142     }
01143   }
01144 }
01145 
01146 void CalPrintTodos::loadConfig()
01147 {
01148   if ( mConfig ) {
01149     mPageTitle = mConfig->readEntry( "Page title", i18n("To-do list") );
01150     mTodoPrintType = (eTodoPrintType)mConfig->readNumEntry( "Print type", (int)TodosAll );
01151     mIncludeDescription = mConfig->readBoolEntry( "Include description", true );
01152     mIncludePriority = mConfig->readBoolEntry( "Include priority", true );
01153     mIncludeDueDate = mConfig->readBoolEntry( "Include due date", true );
01154     mIncludePercentComplete = mConfig->readBoolEntry( "Include percentage completed", true );
01155     mConnectSubTodos = mConfig->readBoolEntry( "Connect subtodos", true );
01156     mStrikeOutCompleted = mConfig->readBoolEntry( "Strike out completed summaries",  true );
01157     mTodoSortField = (eTodoSortField)mConfig->readNumEntry( "Sort field", (int)TodoFieldSummary );
01158     mTodoSortDirection = (eTodoSortDirection)mConfig->readNumEntry( "Sort direction", (int)TodoDirectionAscending );
01159   }
01160   setSettingsWidget();
01161 }
01162 
01163 void CalPrintTodos::saveConfig()
01164 {
01165   readSettingsWidget();
01166   if ( mConfig ) {
01167     mConfig->writeEntry( "Page title", mPageTitle );
01168     mConfig->writeEntry( "Print type", int( mTodoPrintType ) );
01169     mConfig->writeEntry( "Include description", mIncludeDescription );
01170     mConfig->writeEntry( "Include priority", mIncludePriority );
01171     mConfig->writeEntry( "Include due date", mIncludeDueDate );
01172     mConfig->writeEntry( "Include percentage completed", mIncludePercentComplete );
01173     mConfig->writeEntry( "Connect subtodos", mConnectSubTodos );
01174     mConfig->writeEntry( "Strike out completed summaries", mStrikeOutCompleted );
01175     mConfig->writeEntry( "Sort field", mTodoSortField );
01176     mConfig->writeEntry( "Sort direction", mTodoSortDirection );
01177   }
01178 }
01179 
01180 void CalPrintTodos::print( QPainter &p, int width, int height )
01181 {
01182   // TODO: Find a good way to guarantee a nicely designed output
01183   int pospriority = 10;
01184   int possummary = 60;
01185   int posdue = width - 65;
01186   int poscomplete = posdue - 70; //Complete column is to right of the Due column
01187   int lineSpacing = 15;
01188   int fontHeight = 10;
01189 
01190   // Draw the First Page Header
01191   drawHeader( p, mPageTitle, mFromDate, QDate(),
01192                        QRect( 0, 0, width, headerHeight() ) );
01193 
01194   // Draw the Column Headers
01195   int mCurrentLinePos = headerHeight() + 5;
01196   QString outStr;
01197   QFont oldFont( p.font() );
01198 
01199   p.setFont( QFont( "sans-serif", 10, QFont::Bold ) );
01200   lineSpacing = p.fontMetrics().lineSpacing();
01201   mCurrentLinePos += lineSpacing;
01202   if ( mIncludePriority ) {
01203     outStr += i18n( "Priority" );
01204     p.drawText( pospriority, mCurrentLinePos - 2, outStr );
01205   } else {
01206     possummary = 10;
01207     pospriority = -1;
01208   }
01209 
01210   outStr.truncate( 0 );
01211   outStr += i18n( "Summary" );
01212   p.drawText( possummary, mCurrentLinePos - 2, outStr );
01213 
01214   if ( mIncludePercentComplete ) {
01215     if ( !mIncludeDueDate ) //move Complete column to the right
01216       poscomplete = posdue; //if not print the Due Date column
01217     outStr.truncate( 0 );
01218     outStr += i18n( "Complete" );
01219     p.drawText( poscomplete, mCurrentLinePos - 2, outStr );
01220   } else {
01221     poscomplete = -1;
01222   }
01223 
01224   if ( mIncludeDueDate ) {
01225     outStr.truncate( 0 );
01226     outStr += i18n( "Due" );
01227     p.drawText( posdue, mCurrentLinePos - 2, outStr );
01228   } else {
01229     posdue = -1;
01230   }
01231 
01232   p.setFont( QFont( "sans-serif", 10 ) );
01233   fontHeight = p.fontMetrics().height();
01234 
01235   Todo::List todoList;
01236   Todo::List tempList;
01237   Todo::List::ConstIterator it;
01238 
01239   // Convert sort options to the corresponding enums
01240   TodoSortField sortField = TodoSortSummary;
01241   switch( mTodoSortField ) {
01242   case TodoFieldSummary:
01243     sortField = TodoSortSummary; break;
01244   case TodoFieldStartDate:
01245     sortField = TodoSortStartDate; break;
01246   case TodoFieldDueDate:
01247     sortField = TodoSortDueDate; break;
01248   case TodoFieldPriority:
01249     sortField = TodoSortPriority; break;
01250   case TodoFieldPercentComplete:
01251     sortField = TodoSortPercentComplete; break;
01252   case TodoFieldUnset:
01253     break;
01254   }
01255 
01256   SortDirection sortDirection;
01257   switch( mTodoSortDirection ) {
01258   case TodoDirectionAscending:
01259     sortDirection = SortDirectionAscending; break;
01260   case TodoDirectionDescending:
01261     sortDirection = SortDirectionDescending; break;
01262   case TodoDirectionUnset:
01263     break;
01264   }
01265 
01266   // Create list of to-dos which will be printed
01267   todoList = mCalendar->todos( sortField,  sortDirection );
01268   switch( mTodoPrintType ) {
01269   case TodosAll:
01270     break;
01271   case TodosUnfinished:
01272     for( it = todoList.begin(); it!= todoList.end(); ++it ) {
01273       if ( !(*it)->isCompleted() )
01274         tempList.append( *it );
01275     }
01276     todoList = tempList;
01277     break;
01278   case TodosDueRange:
01279     for( it = todoList.begin(); it!= todoList.end(); ++it ) {
01280       if ( (*it)->hasDueDate() ) {
01281         if ( (*it)->dtDue().date() >= mFromDate &&
01282              (*it)->dtDue().date() <= mToDate )
01283           tempList.append( *it );
01284       } else {
01285         tempList.append( *it );
01286       }
01287     }
01288     todoList = tempList;
01289     break;
01290   }
01291 
01292   // Print to-dos
01293   int count = 0;
01294   for ( it=todoList.begin(); it!=todoList.end(); ++it ) {
01295     Todo *currEvent = *it;
01296 
01297     // Skip sub-to-dos. They will be printed recursively in drawTodo()
01298     if ( !currEvent->relatedTo() ) {
01299       count++;
01300       drawTodo( count, currEvent, p,
01301                          sortField, sortDirection,
01302                          mConnectSubTodos,
01303                          mStrikeOutCompleted, mIncludeDescription,
01304                          pospriority, possummary, posdue, poscomplete,
01305                          0, 0, mCurrentLinePos, width, height, todoList );
01306     }
01307   }
01308   p.setFont( oldFont );
01309 }
01310 
01311 
01312 #endif