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         mStartString = IncidenceFormatter::dateTimeToString(
00139           event->dtStart(), event->doesFloat(), false );
00140       } else {
00141         mStartCaption = i18n( "No start date" );
00142         mStartString = QString::null;
00143       }
00144 
00145       if ( event->hasEndDate() ) {
00146         mEndCaption = i18n( "End date: " );
00147         mEndString = IncidenceFormatter::dateTimeToString(
00148           event->dtEnd(), event->doesFloat(), false );
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         mStartString = IncidenceFormatter::dateTimeToString(
00168           todo->dtStart(), todo->doesFloat(), false );
00169       } else {
00170         mStartCaption = i18n( "No start date" );
00171         mStartString = QString::null;
00172       }
00173 
00174       if ( todo->hasDueDate() ) {
00175         mEndCaption = i18n( "Due date: " );
00176         mEndString = IncidenceFormatter::dateTimeToString(
00177           todo->dtDue(), todo->doesFloat(), false );
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       mStartString = IncidenceFormatter::dateTimeToString(
00187         journal->dtStart(), journal->doesFloat(), false );
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   QFont oldFont(p.font());
00217   QFont textFont( "sans-serif", 11, QFont::Normal );
00218   QFont captionFont( "sans-serif", 11, QFont::Bold );
00219   p.setFont( textFont );
00220   int lineHeight = p.fontMetrics().lineSpacing();
00221   QString cap, txt;
00222 
00223 
00224   Incidence::List::ConstIterator it;
00225   for ( it=mSelectedIncidences.begin(); it!=mSelectedIncidences.end(); ++it ) {
00226     // don't do anything on a 0-pointer!
00227     if ( !(*it) ) continue;
00228     if ( it != mSelectedIncidences.begin() ) mPrinter->newPage();
00229 
00230 
00231     // PAGE Layout (same for landscape and portrait! astonishingly, it looks good with both!):
00232     //  +-----------------------------------+
00233     //  | Header:  Summary                  |
00234     //  +===================================+
00235     //  | start: ______   end: _________    |
00236     //  | repeats: ___________________      |
00237     //  | reminder: __________________      |
00238     //  +-----------------------------------+
00239     //  | Location: ______________________  |
00240     //  +------------------------+----------+
00241     //  | Description:           | Notes or |
00242     //  |                        | Subitems |
00243     //  |                        |          |
00244     //  |                        |          |
00245     //  |                        |          |
00246     //  |                        |          |
00247     //  |                        |          |
00248     //  |                        |          |
00249     //  |                        |          |
00250     //  |                        |          |
00251     //  +------------------------+----------+
00252     //  | Attachments:           | Settings |
00253     //  |                        |          |
00254     //  +------------------------+----------+
00255     //  | Attendees:                        |
00256     //  |                                   |
00257     //  +-----------------------------------+
00258     //  | Categories: _____________________ |
00259     //  +-----------------------------------+
00260 
00261     QRect box( 0, 0, width, height );
00262     QRect titleBox( box );
00263     titleBox.setHeight( headerHeight() );
00264     // Draw summary as header, no small calendars in title bar, expand height if needed
00265     int titleBottom = drawHeader( p, (*it)->summary(), QDate(), QDate(), titleBox, true );
00266     titleBox.setBottom( titleBottom );
00267 
00268     QRect timesBox( titleBox );
00269     timesBox.setTop( titleBox.bottom() + padding() );
00270     timesBox.setHeight( height / 8 );
00271 
00272     TimePrintStringsVisitor stringVis;
00273     int h = timesBox.top();
00274     if ( stringVis.act(*it) ) {
00275       QRect textRect( timesBox.left()+padding(), timesBox.top()+padding(), 0, lineHeight );
00276       textRect.setRight( timesBox.center().x() );
00277       h = printCaptionAndText( p, textRect, stringVis.mStartCaption, stringVis.mStartString, captionFont, textFont );
00278 
00279       textRect.setLeft( textRect.right() );
00280       textRect.setRight( timesBox.right() - padding() );
00281       h = QMAX( printCaptionAndText( p, textRect, stringVis.mEndCaption, stringVis.mEndString, captionFont, textFont ), h );
00282     }
00283 
00284     // Convert recurrence to a string
00285     if ( (*it)->doesRecur() ) {
00286       QRect recurBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight );
00287       KCal::Recurrence *recurs = (*it)->recurrence();
00288 
00289       QString displayString = IncidenceFormatter::recurrenceString((*it));
00290       // exception dates
00291       QString exceptString;
00292       if ( !recurs->exDates().isEmpty() ) {
00293         exceptString = i18n("except for listed dates", " except");
00294         for ( uint i = 0; i < recurs->exDates().size(); i++ ) {
00295           exceptString.append(" ");
00296           exceptString.append( KGlobal::locale()->formatDate(recurs->exDates()[i],
00297                                true) );
00298         }
00299       }
00300       displayString.append(exceptString);
00301       h = QMAX( printCaptionAndText( p, recurBox, i18n( "Repeats: "), displayString, captionFont, textFont ), h );
00302     }
00303 
00304     // Alarms Printing
00305     QRect alarmBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight );
00306     Alarm::List alarms = (*it)->alarms();
00307     if ( alarms.count() == 0 ) {
00308       cap = i18n("No reminders");
00309       txt = QString();
00310     } else {
00311       cap = i18n("Reminder: ", "%n reminders: ", alarms.count() );
00312 
00313       QStringList alarmStrings;
00314       KCal::Alarm::List::ConstIterator it;
00315       for ( it = alarms.begin(); it != alarms.end(); ++it ) {
00316         Alarm *alarm = *it;
00317 
00318         // Alarm offset, copied from koeditoralarms.cpp:
00319         QString offsetstr;
00320         int offset = 0;
00321         if ( alarm->hasStartOffset() ) {
00322           offset = alarm->startOffset().asSeconds();
00323           if ( offset < 0 ) {
00324             offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the start");
00325             offset = -offset;
00326           } else {
00327             offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the start");
00328           }
00329         } else if ( alarm->hasEndOffset() ) {
00330           offset = alarm->endOffset().asSeconds();
00331           if ( offset < 0 ) {
00332             offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the end");
00333             offset = -offset;
00334           } else {
00335             offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the end");
00336           }
00337         }
00338 
00339         offset = offset / 60; // make minutes
00340         int useoffset = offset;
00341 
00342         if ( offset % (24*60) == 0 && offset>0 ) { // divides evenly into days?
00343           useoffset = offset / (24*60);
00344           offsetstr = offsetstr.arg( i18n("1 day", "%n days", useoffset ) );
00345         } else if (offset % 60 == 0 && offset>0 ) { // divides evenly into hours?
00346           useoffset = offset / 60;
00347           offsetstr = offsetstr.arg( i18n("1 hour", "%n hours", useoffset ) );
00348         } else {
00349           useoffset = offset;
00350           offsetstr = offsetstr.arg( i18n("1 minute", "%n minutes", useoffset ) );
00351         }
00352         alarmStrings << offsetstr;
00353       }
00354       txt = alarmStrings.join( i18n("Spacer for the joined list of categories", ", ") );
00355 
00356     }
00357     h = QMAX( printCaptionAndText( p, alarmBox, cap, txt, captionFont, textFont ), h );
00358 
00359 
00360     QRect organizerBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight );
00361     h = QMAX( printCaptionAndText( p, organizerBox, i18n("Organizer: "), (*it)->organizer().fullName(), captionFont, textFont ), h );
00362 
00363     // Finally, draw the frame around the time information...
00364     timesBox.setBottom( QMAX( timesBox.bottom(), h+padding() ) );
00365     drawBox( p, BOX_BORDER_WIDTH, timesBox );
00366 
00367 
00368     QRect locationBox( timesBox );
00369     locationBox.setTop( timesBox.bottom() + padding() );
00370     locationBox.setHeight( 0 );
00371     int locationBottom = drawBoxWithCaption( p, locationBox, i18n("Location: "),
00372          (*it)->location(), /*sameLine=*/true, /*expand=*/true, captionFont, textFont );
00373     locationBox.setBottom( locationBottom );
00374 
00375 
00376     // Now start constructing the boxes from the bottom:
00377     QRect footerBox( locationBox );
00378     footerBox.setBottom( box.bottom() );
00379     footerBox.setTop( footerBox.bottom() - lineHeight - 2*padding() );
00380 
00381     QRect categoriesBox( footerBox );
00382     categoriesBox.setBottom( footerBox.top() );
00383     categoriesBox.setTop( categoriesBox.bottom() - lineHeight - 2*padding() );
00384 
00385     QRect attendeesBox( box.left(), categoriesBox.top()-padding()-box.height()/9, box.width(), box.height()/9 );
00386 
00387     QRect attachmentsBox( box.left(), attendeesBox.top()-padding()-box.height()/9, box.width()*3/4 - padding(), box.height()/9 );
00388     QRect optionsBox( attachmentsBox.right() + padding(), attachmentsBox.top(), 0, 0 );
00389     optionsBox.setRight( box.right() );
00390     optionsBox.setBottom( attachmentsBox.bottom() );
00391     QRect notesBox( optionsBox.left(), locationBox.bottom() + padding(), optionsBox.width(), 0 );
00392     notesBox.setBottom( optionsBox.top() - padding() );
00393 
00394     QRect descriptionBox( notesBox );
00395     descriptionBox.setLeft( box.left() );
00396     descriptionBox.setRight( attachmentsBox.right() );
00397     // Adjust boxes depending on the show options...
00398     if (!mShowSubitemsNotes) {
00399       descriptionBox.setRight( box.right() );
00400     }
00401     if (!mShowAttachments || !mShowAttendees) {
00402         descriptionBox.setBottom( attachmentsBox.bottom() );
00403         optionsBox.setTop( attendeesBox.top() );
00404         optionsBox.setBottom( attendeesBox.bottom() );
00405         notesBox.setBottom( attachmentsBox.bottom() );
00406         if (mShowOptions) {
00407           attendeesBox.setRight( attachmentsBox.right() );
00408         }
00409       if (!mShowAttachments && !mShowAttendees) {
00410         if (mShowSubitemsNotes) {
00411           descriptionBox.setBottom( attendeesBox.bottom() );
00412         }
00413         if (!mShowOptions) {
00414           descriptionBox.setBottom( attendeesBox.bottom() );
00415           notesBox.setBottom( attendeesBox.bottom() );
00416         }
00417       }
00418     }
00419     if (mShowAttachments) {
00420       if (!mShowOptions) {
00421         attachmentsBox.setRight( box.right() );
00422         attachmentsBox.setRight( box.right() );
00423       }
00424       if (!mShowAttendees) {
00425         attachmentsBox.setTop( attendeesBox.top() );
00426         attachmentsBox.setBottom( attendeesBox.bottom() );
00427       }
00428     }
00429 
00430     drawBoxWithCaption( p, descriptionBox, i18n("Description:"),
00431                         (*it)->description(), /*sameLine=*/false,
00432                         /*expand=*/false, captionFont, textFont );
00433 
00434     if ( mShowSubitemsNotes ) {
00435       if ( (*it)->relations().isEmpty() || (*it)->type() != "Todo" ) {
00436         int notesPosition = drawBoxWithCaption( p, notesBox, i18n("Notes:"),
00437                          QString::null, /*sameLine=*/false, /*expand=*/false,
00438                          captionFont, textFont );
00439         QPen oldPen( p.pen() );
00440         p.setPen( Qt::DotLine );
00441         while ( (notesPosition += int(1.5*lineHeight)) < notesBox.bottom() ) {
00442           p.drawLine( notesBox.left()+padding(), notesPosition, notesBox.right()-padding(), notesPosition );
00443         }
00444         p.setPen( oldPen );
00445       } else {
00446         Incidence::List relations = (*it)->relations();
00447         QString subitemCaption;
00448         if ( relations.count() == 0 ) {
00449           subitemCaption = i18n( "No Subitems" );
00450           txt == "";
00451         } else {
00452           subitemCaption = i18n( "1 Subitem:",
00453                           "%1 Subitems:",
00454                           relations.count() );
00455         }
00456         Incidence::List::ConstIterator rit;
00457         QString subitemString;
00458         QString statusString;
00459         QString datesString;
00460         int count = 0;
00461         for ( rit = relations.begin(); rit != relations.end(); ++rit ) {
00462           ++count;
00463           if ( !(*rit) ) { // defensive, skip any zero pointers
00464             continue;
00465           }
00466           // format the status
00467           statusString = (*rit)->statusStr();
00468           if ( statusString.isEmpty() ) {
00469             if ( (*rit)->status() == Incidence::StatusNone ) {
00470               statusString = i18n( "no status", "none" );
00471             } else {
00472               statusString = i18n( "unknown status", "unknown" );
00473             }
00474           }
00475           // format the dates if provided
00476           datesString = "";
00477           if ( (*rit)->dtStart().isValid() ) {
00478                 datesString += i18n(
00479                 "Start Date: %1\n").arg(
00480                 KGlobal::locale()->formatDate( (*rit)->dtStart().date(),
00481                                 true ) );
00482             if ( !(*rit)->doesFloat() ) {
00483                 datesString += i18n(
00484                 "Start Time: %1\n").arg(
00485                 KGlobal::locale()->formatTime((*rit)->dtStart().time(),
00486                      false, false) );
00487             }
00488           }
00489           if ( (*rit)->dtEnd().isValid() ) {
00490             subitemString += i18n(
00491                 "Due Date: %1\n").arg(
00492                 KGlobal::locale()->formatDate( (*rit)->dtEnd().date(),
00493                                 true ) );
00494             if ( !(*rit)->doesFloat() ) {
00495               subitemString += i18n(
00496                   "subitem due time", "Due Time: %1\n").arg(
00497                   KGlobal::locale()->formatTime((*rit)->dtEnd().time(),
00498                       false, false) );
00499             }
00500           }
00501           subitemString += i18n("subitem counter", "%1: ", count);
00502           subitemString += (*rit)->summary();
00503           subitemString += "\n";
00504           if ( !datesString.isEmpty() ) {
00505             subitemString += datesString;
00506             subitemString += "\n";
00507           }
00508           subitemString += i18n( "subitem Status: statusString",
00509                                   "Status: %1\n").arg( statusString );
00510           subitemString += IncidenceFormatter::recurrenceString((*rit)) + "\n";
00511           subitemString += i18n( "subitem Priority: N",
00512                                   "Priority: %1\n").arg( (*rit)->priority() );
00513           subitemString += i18n( "subitem Secrecy: secrecyString",
00514                                   "Secrecy: %1\n").arg( (*rit)->secrecyStr() );
00515           subitemString += "\n";
00516         }
00517         drawBoxWithCaption( p, notesBox, i18n("Subitems:"),
00518                             (*it)->description(), /*sameLine=*/false,
00519                             /*expand=*/false, captionFont, textFont );
00520       }
00521     }
00522 
00523     if ( mShowAttachments ) {
00524       Attachment::List attachments = (*it)->attachments();
00525       QString attachmentCaption;
00526       if ( attachments.count() == 0 ) {
00527         attachmentCaption = i18n( "No Attachments" );
00528         txt = QString();
00529       } else {
00530         attachmentCaption = i18n( "1 Attachment:", "%1 Attachments:", attachments.count() );
00531       }
00532       QString attachmentString;
00533       Attachment::List::ConstIterator ait = attachments.begin();
00534       for ( ; ait != attachments.end(); ++ait ) {
00535         if (!attachmentString.isEmpty()) {
00536           attachmentString += i18n( "Spacer for list of attachments", "  " );
00537         }
00538         attachmentString.append((*ait)->label());
00539       }
00540       drawBoxWithCaption( p, attachmentsBox,
00541                         attachmentCaption, attachmentString,
00542                         /*sameLine=*/false, /*expand=*/false,
00543                         captionFont, textFont );
00544     }
00545 
00546     if ( mShowAttendees ) {
00547       Attendee::List attendees = (*it)->attendees();
00548       QString attendeeCaption;
00549       if ( attendees.count() == 0 )
00550         attendeeCaption = i18n("No Attendees");
00551       else
00552         attendeeCaption = i18n("1 Attendee:", "%n Attendees:", attendees.count() );
00553       QString attendeeString;
00554       for ( Attendee::List::ConstIterator ait = attendees.begin(); ait != attendees.end(); ++ait ) {
00555         if ( !attendeeString.isEmpty() ) attendeeString += "\n";
00556         attendeeString += i18n("Formatting of an attendee: "
00557                "'Name (Role): Status', e.g. 'Reinhold Kainhofer "
00558                "<reinhold@kainhofer.com> (Participant): Awaiting Response'",
00559                "%1 (%2): %3")
00560                        .arg( (*ait)->fullName() )
00561                        .arg( (*ait)->roleStr() ).arg( (*ait)->statusStr() );
00562       }
00563       drawBoxWithCaption( p, attendeesBox, i18n("Attendees:"), attendeeString,
00564                /*sameLine=*/false, /*expand=*/false, captionFont, textFont );
00565     }
00566 
00567     if ( mShowOptions ) {
00568       QString optionsString;
00569       if ( !(*it)->statusStr().isEmpty() ) {
00570         optionsString += i18n("Status: %1").arg( (*it)->statusStr() );
00571         optionsString += "\n";
00572       }
00573       if ( !(*it)->secrecyStr().isEmpty() ) {
00574         optionsString += i18n("Secrecy: %1").arg( (*it)->secrecyStr() );
00575         optionsString += "\n";
00576       }
00577       if ( (*it)->type() == "Event" ) {
00578         Event *e = static_cast<Event*>(*it);
00579         if ( e->transparency() == Event::Opaque ) {
00580           optionsString += i18n("Show as: Busy");
00581         } else {
00582           optionsString += i18n("Show as: Free");
00583         }
00584         optionsString += "\n";
00585       } else if ( (*it)->type() == "Todo" ) {
00586         Todo *t = static_cast<Todo*>(*it);
00587         if ( t->isOverdue() ) {
00588           optionsString += i18n("This task is overdue!");
00589           optionsString += "\n";
00590         }
00591       } else if ( (*it)->type() == "Journal" ) {
00592         //TODO: Anything Journal-specific?
00593       }
00594       drawBoxWithCaption( p, optionsBox, i18n("Settings: "),
00595              optionsString, /*sameLine=*/false, /*expand=*/false, captionFont, textFont );
00596     }
00597 
00598     drawBoxWithCaption( p, categoriesBox, i18n("Categories: "),
00599            (*it)->categories().join( i18n("Spacer for the joined list of categories", ", ") ),
00600            /*sameLine=*/true, /*expand=*/false, captionFont, textFont );
00601 
00602     drawFooter( p, footerBox );
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   QRect headerBox( 0, 0, width, headerHeight() );
00700   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
00701   height -= footerHeight();
00702 
00703   KLocale *local = KGlobal::locale();
00704 
00705   do {
00706     QTime curStartTime( mStartTime );
00707     QTime curEndTime( mEndTime );
00708 
00709     // For an invalid time range, simply show one hour, starting at the hour
00710     // before the given start time
00711     if ( curEndTime <= curStartTime ) {
00712       curStartTime = QTime( curStartTime.hour(), 0, 0 );
00713       curEndTime = curStartTime.addSecs( 3600 );
00714     }
00715 
00716     drawHeader( p, local->formatDate( curDay ), curDay, QDate(), headerBox );
00717     Event::List eventList = mCalendar->events( curDay,
00718                                                EventSortStartDate,
00719                                                SortDirectionAscending );
00720 
00721     p.setFont( QFont( "sans-serif", 12 ) );
00722 
00723     // TODO: Find a good way to determine the height of the all-day box
00724     QRect allDayBox( TIMELINE_WIDTH + padding(), headerBox.bottom() + padding(),
00725                      0, height - headerBox.bottom() - padding() );
00726     allDayBox.setRight( width );
00727 
00728     QRect dayBox( allDayBox );
00729     drawAgendaDayBox( p, eventList, curDay, mIncludeAllEvents,
00730                       curStartTime, curEndTime, dayBox );
00731 
00732     QRect tlBox( dayBox );
00733     tlBox.setLeft( 0 );
00734     tlBox.setWidth( TIMELINE_WIDTH );
00735     drawTimeLine( p, curStartTime, curEndTime, tlBox );
00736 
00737     drawFooter( p, footerBox );
00738 
00739     curDay = curDay.addDays( 1 );
00740     if ( curDay <= mToDate ) {
00741       mPrinter->newPage();
00742     }
00743   } while ( curDay <= mToDate );
00744 }
00745 
00746 
00747 
00748 /**************************************************************
00749  *           Print Week
00750  **************************************************************/
00751 
00752 CalPrintWeek::CalPrintWeek() : CalPrintPluginBase()
00753 {
00754 }
00755 
00756 CalPrintWeek::~CalPrintWeek()
00757 {
00758 }
00759 
00760 QWidget *CalPrintWeek::createConfigWidget( QWidget *w )
00761 {
00762   return new CalPrintWeekConfig_Base( w );
00763 }
00764 
00765 void CalPrintWeek::readSettingsWidget()
00766 {
00767   CalPrintWeekConfig_Base *cfg =
00768       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00769   if ( cfg ) {
00770     mFromDate = cfg->mFromDate->date();
00771     mToDate = cfg->mToDate->date();
00772 
00773     mWeekPrintType = (eWeekPrintType)( cfg->mPrintType->id(
00774       cfg->mPrintType->selected() ) );
00775 
00776     mStartTime = cfg->mFromTime->time();
00777     mEndTime = cfg->mToTime->time();
00778 
00779     mIncludeTodos = cfg->mIncludeTodos->isChecked();
00780     mUseColors = cfg->mColors->isChecked();
00781   }
00782 }
00783 
00784 void CalPrintWeek::setSettingsWidget()
00785 {
00786   CalPrintWeekConfig_Base *cfg =
00787       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00788   if ( cfg ) {
00789     cfg->mFromDate->setDate( mFromDate );
00790     cfg->mToDate->setDate( mToDate );
00791 
00792     cfg->mPrintType->setButton( mWeekPrintType );
00793 
00794     cfg->mFromTime->setTime( mStartTime );
00795     cfg->mToTime->setTime( mEndTime );
00796 
00797     cfg->mIncludeTodos->setChecked( mIncludeTodos );
00798     cfg->mColors->setChecked( mUseColors );
00799   }
00800 }
00801 
00802 void CalPrintWeek::loadConfig()
00803 {
00804   if ( mConfig ) {
00805     QDate dt;
00806     QTime tm1( dayStart() );
00807     QDateTime startTm( dt, tm1  );
00808     QDateTime endTm( dt, tm1.addSecs( 43200 ) );
00809     mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time();
00810     mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time();
00811     mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
00812     mWeekPrintType =(eWeekPrintType)( mConfig->readNumEntry( "Print type", (int)Filofax ) );
00813   }
00814   setSettingsWidget();
00815 }
00816 
00817 void CalPrintWeek::saveConfig()
00818 {
00819   readSettingsWidget();
00820   if ( mConfig ) {
00821     mConfig->writeEntry( "Start time", QDateTime( QDate(), mStartTime ) );
00822     mConfig->writeEntry( "End time", QDateTime( QDate(), mEndTime ) );
00823     mConfig->writeEntry( "Include todos", mIncludeTodos );
00824     mConfig->writeEntry( "Print type", int( mWeekPrintType ) );
00825   }
00826 }
00827 
00828 KPrinter::Orientation CalPrintWeek::defaultOrientation()
00829 {
00830   if ( mWeekPrintType == Filofax ) return KPrinter::Portrait;
00831   else if ( mWeekPrintType == SplitWeek ) return KPrinter::Portrait;
00832   else return KPrinter::Landscape;
00833 }
00834 
00835 void CalPrintWeek::setDateRange( const QDate &from, const QDate &to )
00836 {
00837   CalPrintPluginBase::setDateRange( from, to );
00838   CalPrintWeekConfig_Base *cfg =
00839       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00840   if ( cfg ) {
00841     cfg->mFromDate->setDate( from );
00842     cfg->mToDate->setDate( to );
00843   }
00844 }
00845 
00846 void CalPrintWeek::print( QPainter &p, int width, int height )
00847 {
00848   QDate curWeek, fromWeek, toWeek;
00849 
00850   // correct begin and end to first and last day of week
00851   int weekdayCol = weekdayColumn( mFromDate.dayOfWeek() );
00852   fromWeek = mFromDate.addDays( -weekdayCol );
00853   weekdayCol = weekdayColumn( mFromDate.dayOfWeek() );
00854   toWeek = mToDate.addDays( 6 - weekdayCol );
00855 
00856   curWeek = fromWeek.addDays( 6 );
00857   KLocale *local = KGlobal::locale();
00858 
00859   QString line1, line2, title;
00860   QRect headerBox( 0, 0, width, headerHeight() );
00861   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
00862   height -= footerHeight();
00863 
00864   QRect weekBox( headerBox );
00865   weekBox.setTop( headerBox.bottom() + padding() );
00866   weekBox.setBottom( height );
00867 
00868   switch ( mWeekPrintType ) {
00869     case Filofax:
00870       do {
00871         line1 = local->formatDate( curWeek.addDays( -6 ) );
00872         line2 = local->formatDate( curWeek );
00873         if ( orientation() == KPrinter::Landscape ) {
00874           title = i18n("date from-to", "%1 - %2");
00875         } else {
00876           title = i18n("date from-\nto", "%1 -\n%2");;
00877         }
00878         title = title.arg( line1 ).arg( line2 );
00879         drawHeader( p, title, curWeek.addDays( -6 ), QDate(), headerBox );
00880 
00881         drawWeek( p, curWeek, weekBox );
00882 
00883         drawFooter( p, footerBox );
00884 
00885         curWeek = curWeek.addDays( 7 );
00886         if ( curWeek <= toWeek )
00887           mPrinter->newPage();
00888       } while ( curWeek <= toWeek );
00889       break;
00890 
00891     case Timetable:
00892     default:
00893       do {
00894         line1 = local->formatDate( curWeek.addDays( -6 ) );
00895         line2 = local->formatDate( curWeek );
00896         if ( orientation() == KPrinter::Landscape ) {
00897           title = i18n("date from - to (week number)", "%1 - %2 (Week %3)");
00898         } else {
00899           title = i18n("date from -\nto (week number)", "%1 -\n%2 (Week %3)");
00900         }
00901         title = title.arg( line1 ).arg( line2 ).arg( curWeek.weekNumber() );
00902         drawHeader( p, title, curWeek, QDate(), headerBox );
00903 
00904         QRect weekBox( headerBox );
00905         weekBox.setTop( headerBox.bottom() + padding() );
00906         weekBox.setBottom( height );
00907         drawTimeTable( p, fromWeek, curWeek, mStartTime, mEndTime, weekBox );
00908 
00909         drawFooter( p, footerBox );
00910 
00911         fromWeek = fromWeek.addDays( 7 );
00912         curWeek = fromWeek.addDays( 6 );
00913         if ( curWeek <= toWeek )
00914           mPrinter->newPage();
00915       } while ( curWeek <= toWeek );
00916       break;
00917 
00918     case SplitWeek: {
00919       QRect weekBox1( weekBox );
00920       // On the left side there are four days (mo-th) plus the timeline,
00921       // on the right there are only three days (fr-su) plus the timeline. Don't
00922       // use the whole width, but rather give them the same width as on the left.
00923       weekBox1.setRight( int( ( width - TIMELINE_WIDTH ) * 3. / 4. + TIMELINE_WIDTH ) );
00924       do {
00925         QDate endLeft( fromWeek.addDays( 3 ) );
00926         int hh = headerHeight();
00927 
00928         drawTimeTable( p, fromWeek, endLeft,
00929                        mStartTime, mEndTime, weekBox );
00930         mPrinter->newPage();
00931         drawSplitHeaderRight( p, fromWeek, curWeek, QDate(), width, hh );
00932         drawTimeTable( p, endLeft.addDays( 1 ), curWeek,
00933                        mStartTime, mEndTime, weekBox1 );
00934 
00935         drawFooter( p, footerBox );
00936 
00937         fromWeek = fromWeek.addDays( 7 );
00938         curWeek = fromWeek.addDays( 6 );
00939         if ( curWeek <= toWeek )
00940           mPrinter->newPage();
00941       } while ( curWeek <= toWeek );
00942       }
00943       break;
00944   }
00945 }
00946 
00947 
00948 
00949 
00950 /**************************************************************
00951  *           Print Month
00952  **************************************************************/
00953 
00954 CalPrintMonth::CalPrintMonth() : CalPrintPluginBase()
00955 {
00956 }
00957 
00958 CalPrintMonth::~CalPrintMonth()
00959 {
00960 }
00961 
00962 QWidget *CalPrintMonth::createConfigWidget( QWidget *w )
00963 {
00964   return new CalPrintMonthConfig_Base( w );
00965 }
00966 
00967 void CalPrintMonth::readSettingsWidget()
00968 {
00969   CalPrintMonthConfig_Base *cfg =
00970       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
00971   if ( cfg ) {
00972     mFromDate = QDate( cfg->mFromYear->value(), cfg->mFromMonth->currentItem()+1, 1 );
00973     mToDate = QDate( cfg->mToYear->value(), cfg->mToMonth->currentItem()+1, 1 );
00974 
00975     mWeekNumbers =  cfg->mWeekNumbers->isChecked();
00976     mRecurDaily = cfg->mRecurDaily->isChecked();
00977     mRecurWeekly = cfg->mRecurWeekly->isChecked();
00978     mIncludeTodos = cfg->mIncludeTodos->isChecked();
00979 //    mUseColors = cfg->mColors->isChecked();
00980   }
00981 }
00982 
00983 void CalPrintMonth::setSettingsWidget()
00984 {
00985   CalPrintMonthConfig_Base *cfg =
00986       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
00987   setDateRange( mFromDate, mToDate );
00988   if ( cfg ) {
00989     cfg->mWeekNumbers->setChecked( mWeekNumbers );
00990     cfg->mRecurDaily->setChecked( mRecurDaily );
00991     cfg->mRecurWeekly->setChecked( mRecurWeekly );
00992     cfg->mIncludeTodos->setChecked( mIncludeTodos );
00993 //    cfg->mColors->setChecked( mUseColors );
00994   }
00995 }
00996 
00997 void CalPrintMonth::loadConfig()
00998 {
00999   if ( mConfig ) {
01000     mWeekNumbers = mConfig->readBoolEntry( "Print week numbers", true );
01001     mRecurDaily = mConfig->readBoolEntry( "Print daily incidences", true );
01002     mRecurWeekly = mConfig->readBoolEntry( "Print weekly incidences", true );
01003     mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
01004   }
01005   setSettingsWidget();
01006 }
01007 
01008 void CalPrintMonth::saveConfig()
01009 {
01010   readSettingsWidget();
01011   if ( mConfig ) {
01012     mConfig->writeEntry( "Print week numbers", mWeekNumbers );
01013     mConfig->writeEntry( "Print daily incidences", mRecurDaily );
01014     mConfig->writeEntry( "Print weekly incidences", mRecurWeekly );
01015     mConfig->writeEntry( "Include todos", mIncludeTodos );
01016   }
01017 }
01018 
01019 void CalPrintMonth::setDateRange( const QDate &from, const QDate &to )
01020 {
01021   CalPrintPluginBase::setDateRange( from, to );
01022   CalPrintMonthConfig_Base *cfg =
01023       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
01024   const KCalendarSystem *calSys = calendarSystem();
01025   if ( cfg && calSys ) {
01026     cfg->mFromMonth->clear();
01027     for ( int i=0; i<calSys->monthsInYear( mFromDate ); ++i ) {
01028       cfg->mFromMonth->insertItem( calSys->monthName( i+1, mFromDate.year() ) );
01029     }
01030     cfg->mToMonth->clear();
01031     for ( int i=0; i<calSys->monthsInYear( mToDate ); ++i ) {
01032       cfg->mToMonth->insertItem( calSys->monthName( i+1, mToDate.year() ) );
01033     }
01034   }
01035   if ( cfg ) {
01036     cfg->mFromMonth->setCurrentItem( from.month()-1 );
01037     cfg->mFromYear->setValue( to.year() );
01038     cfg->mToMonth->setCurrentItem( mToDate.month()-1 );
01039     cfg->mToYear->setValue( mToDate.year() );
01040   }
01041 }
01042 
01043 void CalPrintMonth::print( QPainter &p, int width, int height )
01044 {
01045   QDate curMonth, fromMonth, toMonth;
01046 
01047   fromMonth = mFromDate.addDays( -( mFromDate.day() - 1 ) );
01048   toMonth = mToDate.addDays( mToDate.daysInMonth() - mToDate.day() );
01049 
01050   curMonth = fromMonth;
01051   const KCalendarSystem *calSys = calendarSystem();
01052   if ( !calSys ) return;
01053 
01054   QRect headerBox( 0, 0, width, headerHeight() );
01055   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
01056   height -= footerHeight();
01057 
01058   QRect monthBox( 0, 0, width, height );
01059   monthBox.setTop( headerBox.bottom() + padding() );
01060 
01061   do {
01062     QString title( i18n("monthname year", "%1 %2") );
01063     title = title.arg( calSys->monthName( curMonth ) )
01064                  .arg( curMonth.year() );
01065     QDate tmp( fromMonth );
01066     int weekdayCol = weekdayColumn( tmp.dayOfWeek() );
01067     tmp = tmp.addDays( -weekdayCol );
01068 
01069     drawHeader( p, title, curMonth.addMonths( -1 ), curMonth.addMonths( 1 ),
01070                 headerBox );
01071     drawMonthTable( p, curMonth, mWeekNumbers, mRecurDaily, mRecurWeekly, monthBox );
01072 
01073     drawFooter( p, footerBox );
01074 
01075     curMonth = curMonth.addDays( curMonth.daysInMonth() );
01076     if ( curMonth <= toMonth ) mPrinter->newPage();
01077   } while ( curMonth <= toMonth );
01078 
01079 }
01080 
01081 
01082 
01083 
01084 /**************************************************************
01085  *           Print Todos
01086  **************************************************************/
01087 
01088 CalPrintTodos::CalPrintTodos() : CalPrintPluginBase()
01089 {
01090   mTodoSortField = TodoFieldUnset;
01091   mTodoSortDirection = TodoDirectionUnset;
01092 }
01093 
01094 CalPrintTodos::~CalPrintTodos()
01095 {
01096 }
01097 
01098 QWidget *CalPrintTodos::createConfigWidget( QWidget *w )
01099 {
01100   return new CalPrintTodoConfig_Base( w );
01101 }
01102 
01103 void CalPrintTodos::readSettingsWidget()
01104 {
01105   CalPrintTodoConfig_Base *cfg =
01106       dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget );
01107   if ( cfg ) {
01108     mPageTitle = cfg->mTitle->text();
01109 
01110     mTodoPrintType = (eTodoPrintType)( cfg->mPrintType->id(
01111       cfg->mPrintType->selected() ) );
01112 
01113     mFromDate = cfg->mFromDate->date();
01114     mToDate = cfg->mToDate->date();
01115 
01116     mIncludeDescription = cfg->mDescription->isChecked();
01117     mIncludePriority = cfg->mPriority->isChecked();
01118     mIncludeDueDate = cfg->mDueDate->isChecked();
01119     mIncludePercentComplete = cfg->mPercentComplete->isChecked();
01120     mConnectSubTodos = cfg->mConnectSubTodos->isChecked();
01121     mStrikeOutCompleted = cfg->mStrikeOutCompleted->isChecked();
01122 
01123     mTodoSortField = (eTodoSortField)cfg->mSortField->currentItem();
01124     mTodoSortDirection = (eTodoSortDirection)cfg->mSortDirection->currentItem();
01125   }
01126 }
01127 
01128 void CalPrintTodos::setSettingsWidget()
01129 {
01130 //   kdDebug(5850) << "CalPrintTodos::setSettingsWidget" << endl;
01131 
01132   CalPrintTodoConfig_Base *cfg =
01133       dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget );
01134   if ( cfg ) {
01135     cfg->mTitle->setText( mPageTitle );
01136 
01137     cfg->mPrintType->setButton( mTodoPrintType );
01138 
01139     cfg->mFromDate->setDate( mFromDate );
01140     cfg->mToDate->setDate( mToDate );
01141 
01142     cfg->mDescription->setChecked( mIncludeDescription );
01143     cfg->mPriority->setChecked( mIncludePriority );
01144     cfg->mDueDate->setChecked( mIncludeDueDate );
01145     cfg->mPercentComplete->setChecked( mIncludePercentComplete );
01146     cfg->mConnectSubTodos->setChecked( mConnectSubTodos );
01147     cfg->mStrikeOutCompleted->setChecked( mStrikeOutCompleted );
01148 
01149     if ( mTodoSortField != TodoFieldUnset ) {
01150       // do not insert if already done so.
01151       cfg->mSortField->insertItem( i18n("Summary") );
01152       cfg->mSortField->insertItem( i18n("Start Date") );
01153       cfg->mSortField->insertItem( i18n("Due Date") );
01154       cfg->mSortField->insertItem( i18n("Priority") );
01155       cfg->mSortField->insertItem( i18n("Percent Complete") );
01156       cfg->mSortField->setCurrentItem( (int)mTodoSortField );
01157     }
01158 
01159     if ( mTodoSortDirection != TodoDirectionUnset ) {
01160       // do not insert if already done so.
01161       cfg->mSortDirection->insertItem( i18n("Ascending") );
01162       cfg->mSortDirection->insertItem( i18n("Descending") );
01163       cfg->mSortDirection->setCurrentItem( (int)mTodoSortDirection );
01164     }
01165   }
01166 }
01167 
01168 void CalPrintTodos::loadConfig()
01169 {
01170   if ( mConfig ) {
01171     mPageTitle = mConfig->readEntry( "Page title", i18n("To-do list") );
01172     mTodoPrintType = (eTodoPrintType)mConfig->readNumEntry( "Print type", (int)TodosAll );
01173     mIncludeDescription = mConfig->readBoolEntry( "Include description", true );
01174     mIncludePriority = mConfig->readBoolEntry( "Include priority", true );
01175     mIncludeDueDate = mConfig->readBoolEntry( "Include due date", true );
01176     mIncludePercentComplete = mConfig->readBoolEntry( "Include percentage completed", true );
01177     mConnectSubTodos = mConfig->readBoolEntry( "Connect subtodos", true );
01178     mStrikeOutCompleted = mConfig->readBoolEntry( "Strike out completed summaries",  true );
01179     mTodoSortField = (eTodoSortField)mConfig->readNumEntry( "Sort field", (int)TodoFieldSummary );
01180     mTodoSortDirection = (eTodoSortDirection)mConfig->readNumEntry( "Sort direction", (int)TodoDirectionAscending );
01181   }
01182   setSettingsWidget();
01183 }
01184 
01185 void CalPrintTodos::saveConfig()
01186 {
01187   readSettingsWidget();
01188   if ( mConfig ) {
01189     mConfig->writeEntry( "Page title", mPageTitle );
01190     mConfig->writeEntry( "Print type", int( mTodoPrintType ) );
01191     mConfig->writeEntry( "Include description", mIncludeDescription );
01192     mConfig->writeEntry( "Include priority", mIncludePriority );
01193     mConfig->writeEntry( "Include due date", mIncludeDueDate );
01194     mConfig->writeEntry( "Include percentage completed", mIncludePercentComplete );
01195     mConfig->writeEntry( "Connect subtodos", mConnectSubTodos );
01196     mConfig->writeEntry( "Strike out completed summaries", mStrikeOutCompleted );
01197     mConfig->writeEntry( "Sort field", mTodoSortField );
01198     mConfig->writeEntry( "Sort direction", mTodoSortDirection );
01199   }
01200 }
01201 
01202 void CalPrintTodos::print( QPainter &p, int width, int height )
01203 {
01204   // TODO: Find a good way to guarantee a nicely designed output
01205   int pospriority = 0;
01206   int possummary = 100;
01207   int posdue = width - 65;
01208   int poscomplete = posdue - 70; //Complete column is to right of the Due column
01209   int lineSpacing = 15;
01210   int fontHeight = 10;
01211 
01212   QRect headerBox( 0, 0, width, headerHeight() );
01213   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
01214   height -= footerHeight();
01215 
01216   // Draw the First Page Header
01217   drawHeader( p, mPageTitle, mFromDate, QDate(), headerBox );
01218 
01219   // Draw the Column Headers
01220   int mCurrentLinePos = headerHeight() + 5;
01221   QString outStr;
01222   QFont oldFont( p.font() );
01223 
01224   p.setFont( QFont( "sans-serif", 9, QFont::Bold ) );
01225   lineSpacing = p.fontMetrics().lineSpacing();
01226   mCurrentLinePos += lineSpacing;
01227   if ( mIncludePriority ) {
01228     outStr += i18n( "Priority" );
01229     p.drawText( pospriority, mCurrentLinePos - 2, outStr );
01230   } else {
01231     pospriority = -1;
01232   }
01233 
01234   outStr.truncate( 0 );
01235   outStr += i18n( "Summary" );
01236   p.drawText( possummary, mCurrentLinePos - 2, outStr );
01237 
01238   if ( mIncludePercentComplete ) {
01239     if ( !mIncludeDueDate ) //move Complete column to the right
01240       poscomplete = posdue; //if not print the Due Date column
01241     outStr.truncate( 0 );
01242     outStr += i18n( "Complete" );
01243     p.drawText( poscomplete, mCurrentLinePos - 2, outStr );
01244   } else {
01245     poscomplete = -1;
01246   }
01247 
01248   if ( mIncludeDueDate ) {
01249     outStr.truncate( 0 );
01250     outStr += i18n( "Due" );
01251     p.drawText( posdue, mCurrentLinePos - 2, outStr );
01252   } else {
01253     posdue = -1;
01254   }
01255 
01256   p.setFont( QFont( "sans-serif", 10 ) );
01257   fontHeight = p.fontMetrics().height();
01258 
01259   Todo::List todoList;
01260   Todo::List tempList;
01261   Todo::List::ConstIterator it;
01262 
01263   // Convert sort options to the corresponding enums
01264   TodoSortField sortField = TodoSortSummary;
01265   switch( mTodoSortField ) {
01266   case TodoFieldSummary:
01267     sortField = TodoSortSummary; break;
01268   case TodoFieldStartDate:
01269     sortField = TodoSortStartDate; break;
01270   case TodoFieldDueDate:
01271     sortField = TodoSortDueDate; break;
01272   case TodoFieldPriority:
01273     sortField = TodoSortPriority; break;
01274   case TodoFieldPercentComplete:
01275     sortField = TodoSortPercentComplete; break;
01276   case TodoFieldUnset:
01277     break;
01278   }
01279 
01280   SortDirection sortDirection;
01281   switch( mTodoSortDirection ) {
01282   case TodoDirectionAscending:
01283     sortDirection = SortDirectionAscending; break;
01284   case TodoDirectionDescending:
01285     sortDirection = SortDirectionDescending; break;
01286   case TodoDirectionUnset:
01287     break;
01288   }
01289 
01290   // Create list of to-dos which will be printed
01291   todoList = mCalendar->todos( sortField,  sortDirection );
01292   switch( mTodoPrintType ) {
01293   case TodosAll:
01294     break;
01295   case TodosUnfinished:
01296     for( it = todoList.begin(); it!= todoList.end(); ++it ) {
01297       if ( !(*it)->isCompleted() )
01298         tempList.append( *it );
01299     }
01300     todoList = tempList;
01301     break;
01302   case TodosDueRange:
01303     for( it = todoList.begin(); it!= todoList.end(); ++it ) {
01304       if ( (*it)->hasDueDate() ) {
01305         if ( (*it)->dtDue().date() >= mFromDate &&
01306              (*it)->dtDue().date() <= mToDate )
01307           tempList.append( *it );
01308       } else {
01309         tempList.append( *it );
01310       }
01311     }
01312     todoList = tempList;
01313     break;
01314   }
01315 
01316   // Print to-dos
01317   int count = 0;
01318   for ( it=todoList.begin(); it!=todoList.end(); ++it ) {
01319     Todo *currEvent = *it;
01320 
01321     // Skip sub-to-dos. They will be printed recursively in drawTodo()
01322     if ( !currEvent->relatedTo() ) {
01323       count++;
01324       drawTodo( count, currEvent, p,
01325                          sortField, sortDirection,
01326                          mConnectSubTodos,
01327                          mStrikeOutCompleted, mIncludeDescription,
01328                          pospriority, possummary, posdue, poscomplete,
01329                          0, 0, mCurrentLinePos, width, height, todoList );
01330     }
01331   }
01332 
01333   drawFooter( p, footerBox );
01334   p.setFont( oldFont );
01335 }
01336 
01337 #endif
KDE Home | KDE Accessibility Home | Description of Access Keys