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 footerBox( locationBox );
00380     footerBox.setBottom( box.bottom() );
00381     footerBox.setTop( footerBox.bottom() - lineHeight - 2*padding() );
00382 
00383     QRect categoriesBox( footerBox );
00384     categoriesBox.setBottom( footerBox.top() );
00385     categoriesBox.setTop( categoriesBox.bottom() - lineHeight - 2*padding() );
00386 
00387     QRect attendeesBox( box.left(), categoriesBox.top()-padding()-box.height()/9, box.width(), box.height()/9 );
00388 
00389     QRect attachmentsBox( box.left(), attendeesBox.top()-padding()-box.height()/9, box.width()*3/4 - padding(), box.height()/9 );
00390     QRect optionsBox( attachmentsBox.right() + padding(), attachmentsBox.top(), 0, 0 );
00391     optionsBox.setRight( box.right() );
00392     optionsBox.setBottom( attachmentsBox.bottom() );
00393     QRect notesBox( optionsBox.left(), locationBox.bottom() + padding(), optionsBox.width(), 0 );
00394     notesBox.setBottom( optionsBox.top() - padding() );
00395 
00396     QRect descriptionBox( notesBox );
00397     descriptionBox.setLeft( box.left() );
00398     descriptionBox.setRight( attachmentsBox.right() );
00399     // Adjust boxes depending on the show options...
00400     if (!mShowSubitemsNotes) {
00401       descriptionBox.setRight( box.right() );
00402     }
00403     if (!mShowAttachments || !mShowAttendees) {
00404         descriptionBox.setBottom( attachmentsBox.bottom() );
00405         optionsBox.setTop( attendeesBox.top() );
00406         optionsBox.setBottom( attendeesBox.bottom() );
00407         notesBox.setBottom( attachmentsBox.bottom() );
00408         if (mShowOptions) {
00409           attendeesBox.setRight( attachmentsBox.right() );
00410         }
00411       if (!mShowAttachments && !mShowAttendees) {
00412         if (mShowSubitemsNotes) {
00413           descriptionBox.setBottom( attendeesBox.bottom() );
00414         }
00415         if (!mShowOptions) {
00416           descriptionBox.setBottom( attendeesBox.bottom() );
00417           notesBox.setBottom( attendeesBox.bottom() );
00418         }
00419       }
00420     }
00421     if (mShowAttachments) {
00422       if (!mShowOptions) {
00423         attachmentsBox.setRight( box.right() );
00424         attachmentsBox.setRight( box.right() );
00425       }
00426       if (!mShowAttendees) {
00427         attachmentsBox.setTop( attendeesBox.top() );
00428         attachmentsBox.setBottom( attendeesBox.bottom() );
00429       }
00430     }
00431 
00432     drawBoxWithCaption( p, descriptionBox, i18n("Description:"),
00433                         (*it)->description(), /*sameLine=*/false,
00434                         /*expand=*/false, captionFont, textFont );
00435 
00436     if ( mShowSubitemsNotes ) {
00437       if ( (*it)->relations().isEmpty() || (*it)->type() != "Todo" ) {
00438         int notesPosition = drawBoxWithCaption( p, notesBox, i18n("Notes:"),
00439                          QString::null, /*sameLine=*/false, /*expand=*/false,
00440                          captionFont, textFont );
00441         QPen oldPen( p.pen() );
00442         p.setPen( Qt::DotLine );
00443         while ( (notesPosition += int(1.5*lineHeight)) < notesBox.bottom() ) {
00444           p.drawLine( notesBox.left()+padding(), notesPosition, notesBox.right()-padding(), notesPosition );
00445         }
00446         p.setPen( oldPen );
00447       } else {
00448         Incidence::List relations = (*it)->relations();
00449         QString subitemCaption;
00450         if ( relations.count() == 0 ) {
00451           subitemCaption = i18n( "No Subitems" );
00452           txt == "";
00453         } else {
00454           subitemCaption = i18n( "1 Subitem:",
00455                           "%1 Subitems:",
00456                           relations.count() );
00457         }
00458         Incidence::List::ConstIterator rit;
00459         QString subitemString;
00460         QString statusString;
00461         QString datesString;
00462         int count = 0;
00463         for ( rit = relations.begin(); rit != relations.end(); ++rit ) {
00464           ++count;
00465           if ( !(*rit) ) { // defensive, skip any zero pointers
00466             continue;
00467           }
00468           // format the status
00469           statusString = (*rit)->statusStr();
00470           if ( statusString.isEmpty() ) {
00471             if ( (*rit)->status() == Incidence::StatusNone ) {
00472               statusString = i18n( "no status", "none" );
00473             } else {
00474               statusString = i18n( "unknown status", "unknown" );
00475             }
00476           }
00477           // format the dates if provided
00478           datesString = "";
00479           if ( (*rit)->dtStart().isValid() ) {
00480                 datesString += i18n(
00481                 "Start Date: %1\n").arg(
00482                 KGlobal::locale()->formatDate( (*rit)->dtStart().date(),
00483                                 true ) );
00484             if ( !(*rit)->doesFloat() ) {
00485                 datesString += i18n(
00486                 "Start Time: %1\n").arg(
00487                 KGlobal::locale()->formatTime((*rit)->dtStart().time(),
00488                      false, false) );
00489             }
00490           }
00491           if ( (*rit)->dtEnd().isValid() ) {
00492             subitemString += i18n(
00493                 "Due Date: %1\n").arg(
00494                 KGlobal::locale()->formatDate( (*rit)->dtEnd().date(),
00495                                 true ) );
00496             if ( !(*rit)->doesFloat() ) {
00497               subitemString += i18n(
00498                   "subitem due time", "Due Time: %1\n").arg(
00499                   KGlobal::locale()->formatTime((*rit)->dtEnd().time(),
00500                       false, false) );
00501             }
00502           }
00503           subitemString += i18n("subitem counter", "%1: ", count);
00504           subitemString += (*rit)->summary();
00505           subitemString += "\n";
00506           if ( !datesString.isEmpty() ) {
00507             subitemString += datesString;
00508             subitemString += "\n";
00509           }
00510           subitemString += i18n( "subitem Status: statusString",
00511                                   "Status: %1\n").arg( statusString );
00512           subitemString += IncidenceFormatter::recurrenceString((*rit)) + "\n";
00513           subitemString += i18n( "subitem Priority: N",
00514                                   "Priority: %1\n").arg( (*rit)->priority() );
00515           subitemString += i18n( "subitem Secrecy: secrecyString",
00516                                   "Secrecy: %1\n").arg( (*rit)->secrecyStr() );
00517           subitemString += "\n";
00518         }
00519         drawBoxWithCaption( p, notesBox, i18n("Subitems:"),
00520                             (*it)->description(), /*sameLine=*/false,
00521                             /*expand=*/false, captionFont, textFont );
00522       }
00523     }
00524 
00525     if ( mShowAttachments ) {
00526       Attachment::List attachments = (*it)->attachments();
00527       QString attachmentCaption;
00528       if ( attachments.count() == 0 ) {
00529         attachmentCaption = i18n( "No Attachments" );
00530         txt = QString();
00531       } else {
00532         attachmentCaption = i18n( "1 Attachment:", "%1 Attachments:", attachments.count() );
00533       }
00534       QString attachmentString;
00535       Attachment::List::ConstIterator ait = attachments.begin();
00536       for ( ; ait != attachments.end(); ++ait ) {
00537         if (!attachmentString.isEmpty()) {
00538           attachmentString += i18n( "Spacer for list of attachments", "  " );
00539         }
00540         attachmentString.append((*ait)->label());
00541       }
00542       drawBoxWithCaption( p, attachmentsBox,
00543                         attachmentCaption, attachmentString,
00544                         /*sameLine=*/false, /*expand=*/false,
00545                         captionFont, textFont );
00546       int attachStart = drawBoxWithCaption( p, attachmentsBox,
00547                         QString()/*i18n("Attachments:")*/, QString(), /*sameLine=*/false,
00548                         /*expand=*/false, captionFont, textFont );
00549     }
00550 
00551     if ( mShowAttendees ) {
00552       Attendee::List attendees = (*it)->attendees();
00553       QString attendeeCaption;
00554       if ( attendees.count() == 0 )
00555         attendeeCaption = i18n("No Attendees");
00556       else
00557         attendeeCaption = i18n("1 Attendee:", "%n Attendees:", attendees.count() );
00558       QString attendeeString;
00559       for ( Attendee::List::ConstIterator ait = attendees.begin(); ait != attendees.end(); ++ait ) {
00560         if ( !attendeeString.isEmpty() ) attendeeString += "\n";
00561         attendeeString += i18n("Formatting of an attendee: "
00562                "'Name (Role): Status', e.g. 'Reinhold Kainhofer "
00563                "<reinhold@kainhofer.com> (Participant): Awaiting Response'",
00564                "%1 (%2): %3")
00565                        .arg( (*ait)->fullName() )
00566                        .arg( (*ait)->roleStr() ).arg( (*ait)->statusStr() );
00567       }
00568       drawBoxWithCaption( p, attendeesBox, i18n("Attendees:"), attendeeString,
00569                /*sameLine=*/false, /*expand=*/false, captionFont, textFont );
00570     }
00571 
00572     if ( mShowOptions ) {
00573       QString optionsString;
00574       if ( !(*it)->statusStr().isEmpty() ) {
00575         optionsString += i18n("Status: %1").arg( (*it)->statusStr() );
00576         optionsString += "\n";
00577       }
00578       if ( !(*it)->secrecyStr().isEmpty() ) {
00579         optionsString += i18n("Secrecy: %1").arg( (*it)->secrecyStr() );
00580         optionsString += "\n";
00581       }
00582       if ( (*it)->type() == "Event" ) {
00583         Event *e = static_cast<Event*>(*it);
00584         if ( e->transparency() == Event::Opaque ) {
00585           optionsString += i18n("Show as: Busy");
00586         } else {
00587           optionsString += i18n("Show as: Free");
00588         }
00589         optionsString += "\n";
00590       } else if ( (*it)->type() == "Todo" ) {
00591         Todo *t = static_cast<Todo*>(*it);
00592         if ( t->isOverdue() ) {
00593           optionsString += i18n("This task is overdue!");
00594           optionsString += "\n";
00595         }
00596       } else if ( (*it)->type() == "Journal" ) {
00597         //TODO: Anything Journal-specific?
00598       }
00599       drawBoxWithCaption( p, optionsBox, i18n("Settings: "),
00600              optionsString, /*sameLine=*/false, /*expand=*/false, captionFont, textFont );
00601     }
00602 
00603     drawBoxWithCaption( p, categoriesBox, i18n("Categories: "),
00604            (*it)->categories().join( i18n("Spacer for the joined list of categories", ", ") ),
00605            /*sameLine=*/true, /*expand=*/false, captionFont, textFont );
00606 
00607     drawFooter( p, footerBox );
00608   }
00609   p.setFont( oldFont );
00610 }
00611 
00612 /**************************************************************
00613  *           Print Day
00614  **************************************************************/
00615 
00616 CalPrintDay::CalPrintDay() : CalPrintPluginBase()
00617 {
00618 }
00619 
00620 CalPrintDay::~CalPrintDay()
00621 {
00622 }
00623 
00624 QWidget *CalPrintDay::createConfigWidget( QWidget *w )
00625 {
00626   return new CalPrintDayConfig_Base( w );
00627 }
00628 
00629 void CalPrintDay::readSettingsWidget()
00630 {
00631   CalPrintDayConfig_Base *cfg =
00632       dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget );
00633   if ( cfg ) {
00634     mFromDate = cfg->mFromDate->date();
00635     mToDate = cfg->mToDate->date();
00636 
00637     mStartTime = cfg->mFromTime->time();
00638     mEndTime = cfg->mToTime->time();
00639     mIncludeAllEvents = cfg->mIncludeAllEvents->isChecked();
00640 
00641     mIncludeTodos = cfg->mIncludeTodos->isChecked();
00642     mUseColors = cfg->mColors->isChecked();
00643   }
00644 }
00645 
00646 void CalPrintDay::setSettingsWidget()
00647 {
00648   CalPrintDayConfig_Base *cfg =
00649       dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget );
00650   if ( cfg ) {
00651     cfg->mFromDate->setDate( mFromDate );
00652     cfg->mToDate->setDate( mToDate );
00653 
00654     cfg->mFromTime->setTime( mStartTime );
00655     cfg->mToTime->setTime( mEndTime );
00656     cfg->mIncludeAllEvents->setChecked( mIncludeAllEvents );
00657 
00658     cfg->mIncludeTodos->setChecked( mIncludeTodos );
00659     cfg->mColors->setChecked( mUseColors );
00660   }
00661 }
00662 
00663 void CalPrintDay::loadConfig()
00664 {
00665   if ( mConfig ) {
00666     QDate dt;
00667     QTime tm1( dayStart() );
00668     QDateTime startTm( dt, tm1 );
00669     QDateTime endTm( dt, tm1.addSecs( 12 * 60 * 60 ) );
00670     mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time();
00671     mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time();
00672     mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
00673     mIncludeAllEvents = mConfig->readBoolEntry( "Include all events", false );
00674   }
00675   setSettingsWidget();
00676 }
00677 
00678 void CalPrintDay::saveConfig()
00679 {
00680   readSettingsWidget();
00681   if ( mConfig ) {
00682     mConfig->writeEntry( "Start time", QDateTime( QDate(), mStartTime ) );
00683     mConfig->writeEntry( "End time", QDateTime( QDate(), mEndTime ) );
00684     mConfig->writeEntry( "Include todos", mIncludeTodos );
00685     mConfig->writeEntry( "Include all events", mIncludeAllEvents );
00686   }
00687 }
00688 
00689 void CalPrintDay::setDateRange( const QDate& from, const QDate& to )
00690 {
00691   CalPrintPluginBase::setDateRange( from, to );
00692   CalPrintDayConfig_Base *cfg =
00693       dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget );
00694   if ( cfg ) {
00695     cfg->mFromDate->setDate( from );
00696     cfg->mToDate->setDate( to );
00697   }
00698 }
00699 
00700 void CalPrintDay::print( QPainter &p, int width, int height )
00701 {
00702   QDate curDay( mFromDate );
00703 
00704   QRect headerBox( 0, 0, width, headerHeight() );
00705   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
00706   height -= footerHeight();
00707 
00708   KLocale *local = KGlobal::locale();
00709 
00710   do {
00711     QTime curStartTime( mStartTime );
00712     QTime curEndTime( mEndTime );
00713 
00714     // For an invalid time range, simply show one hour, starting at the hour
00715     // before the given start time
00716     if ( curEndTime <= curStartTime ) {
00717       curStartTime = QTime( curStartTime.hour(), 0, 0 );
00718       curEndTime = curStartTime.addSecs( 3600 );
00719     }
00720 
00721     drawHeader( p, local->formatDate( curDay ), curDay, QDate(), headerBox );
00722     Event::List eventList = mCalendar->events( curDay,
00723                                                EventSortStartDate,
00724                                                SortDirectionAscending );
00725 
00726     p.setFont( QFont( "sans-serif", 12 ) );
00727 
00728     // TODO: Find a good way to determine the height of the all-day box
00729     QRect allDayBox( TIMELINE_WIDTH + padding(), headerBox.bottom() + padding(),
00730                      0, height - headerBox.bottom() - padding() );
00731     allDayBox.setRight( width );
00732 
00733     QRect dayBox( allDayBox );
00734     drawAgendaDayBox( p, eventList, curDay, mIncludeAllEvents,
00735                       curStartTime, curEndTime, dayBox );
00736 
00737     QRect tlBox( dayBox );
00738     tlBox.setLeft( 0 );
00739     tlBox.setWidth( TIMELINE_WIDTH );
00740     drawTimeLine( p, curStartTime, curEndTime, tlBox );
00741 
00742     drawFooter( p, footerBox );
00743 
00744     curDay = curDay.addDays( 1 );
00745     if ( curDay <= mToDate ) {
00746       mPrinter->newPage();
00747     }
00748   } while ( curDay <= mToDate );
00749 }
00750 
00751 
00752 
00753 /**************************************************************
00754  *           Print Week
00755  **************************************************************/
00756 
00757 CalPrintWeek::CalPrintWeek() : CalPrintPluginBase()
00758 {
00759 }
00760 
00761 CalPrintWeek::~CalPrintWeek()
00762 {
00763 }
00764 
00765 QWidget *CalPrintWeek::createConfigWidget( QWidget *w )
00766 {
00767   return new CalPrintWeekConfig_Base( w );
00768 }
00769 
00770 void CalPrintWeek::readSettingsWidget()
00771 {
00772   CalPrintWeekConfig_Base *cfg =
00773       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00774   if ( cfg ) {
00775     mFromDate = cfg->mFromDate->date();
00776     mToDate = cfg->mToDate->date();
00777 
00778     mWeekPrintType = (eWeekPrintType)( cfg->mPrintType->id(
00779       cfg->mPrintType->selected() ) );
00780 
00781     mStartTime = cfg->mFromTime->time();
00782     mEndTime = cfg->mToTime->time();
00783 
00784     mIncludeTodos = cfg->mIncludeTodos->isChecked();
00785     mUseColors = cfg->mColors->isChecked();
00786   }
00787 }
00788 
00789 void CalPrintWeek::setSettingsWidget()
00790 {
00791   CalPrintWeekConfig_Base *cfg =
00792       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00793   if ( cfg ) {
00794     cfg->mFromDate->setDate( mFromDate );
00795     cfg->mToDate->setDate( mToDate );
00796 
00797     cfg->mPrintType->setButton( mWeekPrintType );
00798 
00799     cfg->mFromTime->setTime( mStartTime );
00800     cfg->mToTime->setTime( mEndTime );
00801 
00802     cfg->mIncludeTodos->setChecked( mIncludeTodos );
00803     cfg->mColors->setChecked( mUseColors );
00804   }
00805 }
00806 
00807 void CalPrintWeek::loadConfig()
00808 {
00809   if ( mConfig ) {
00810     QDate dt;
00811     QTime tm1( dayStart() );
00812     QDateTime startTm( dt, tm1  );
00813     QDateTime endTm( dt, tm1.addSecs( 43200 ) );
00814     mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time();
00815     mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time();
00816     mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
00817     mWeekPrintType =(eWeekPrintType)( mConfig->readNumEntry( "Print type", (int)Filofax ) );
00818   }
00819   setSettingsWidget();
00820 }
00821 
00822 void CalPrintWeek::saveConfig()
00823 {
00824   readSettingsWidget();
00825   if ( mConfig ) {
00826     mConfig->writeEntry( "Start time", QDateTime( QDate(), mStartTime ) );
00827     mConfig->writeEntry( "End time", QDateTime( QDate(), mEndTime ) );
00828     mConfig->writeEntry( "Include todos", mIncludeTodos );
00829     mConfig->writeEntry( "Print type", int( mWeekPrintType ) );
00830   }
00831 }
00832 
00833 KPrinter::Orientation CalPrintWeek::defaultOrientation()
00834 {
00835   if ( mWeekPrintType == Filofax ) return KPrinter::Portrait;
00836   else if ( mWeekPrintType == SplitWeek ) return KPrinter::Portrait;
00837   else return KPrinter::Landscape;
00838 }
00839 
00840 void CalPrintWeek::setDateRange( const QDate &from, const QDate &to )
00841 {
00842   CalPrintPluginBase::setDateRange( from, to );
00843   CalPrintWeekConfig_Base *cfg =
00844       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00845   if ( cfg ) {
00846     cfg->mFromDate->setDate( from );
00847     cfg->mToDate->setDate( to );
00848   }
00849 }
00850 
00851 void CalPrintWeek::print( QPainter &p, int width, int height )
00852 {
00853   QDate curWeek, fromWeek, toWeek;
00854 
00855   // correct begin and end to first and last day of week
00856   int weekdayCol = weekdayColumn( mFromDate.dayOfWeek() );
00857   fromWeek = mFromDate.addDays( -weekdayCol );
00858   weekdayCol = weekdayColumn( mFromDate.dayOfWeek() );
00859   toWeek = mToDate.addDays( 6 - weekdayCol );
00860 
00861   curWeek = fromWeek.addDays( 6 );
00862   KLocale *local = KGlobal::locale();
00863 
00864   QString line1, line2, title;
00865   QRect headerBox( 0, 0, width, headerHeight() );
00866   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
00867   height -= footerHeight();
00868 
00869   QRect weekBox( headerBox );
00870   weekBox.setTop( headerBox.bottom() + padding() );
00871   weekBox.setBottom( height );
00872 
00873   switch ( mWeekPrintType ) {
00874     case Filofax:
00875       do {
00876         line1 = local->formatDate( curWeek.addDays( -6 ) );
00877         line2 = local->formatDate( curWeek );
00878         if ( orientation() == KPrinter::Landscape ) {
00879           title = i18n("date from-to", "%1 - %2");
00880         } else {
00881           title = i18n("date from-\nto", "%1 -\n%2");;
00882         }
00883         title = title.arg( line1 ).arg( line2 );
00884         drawHeader( p, title, curWeek.addDays( -6 ), QDate(), headerBox );
00885 
00886         drawWeek( p, curWeek, weekBox );
00887 
00888         drawFooter( p, footerBox );
00889 
00890         curWeek = curWeek.addDays( 7 );
00891         if ( curWeek <= toWeek )
00892           mPrinter->newPage();
00893       } while ( curWeek <= toWeek );
00894       break;
00895 
00896     case Timetable:
00897     default:
00898       do {
00899         line1 = local->formatDate( curWeek.addDays( -6 ) );
00900         line2 = local->formatDate( curWeek );
00901         if ( orientation() == KPrinter::Landscape ) {
00902           title = i18n("date from - to (week number)", "%1 - %2 (Week %3)");
00903         } else {
00904           title = i18n("date from -\nto (week number)", "%1 -\n%2 (Week %3)");
00905         }
00906         title = title.arg( line1 ).arg( line2 ).arg( curWeek.weekNumber() );
00907         drawHeader( p, title, curWeek, QDate(), headerBox );
00908 
00909         QRect weekBox( headerBox );
00910         weekBox.setTop( headerBox.bottom() + padding() );
00911         weekBox.setBottom( height );
00912         drawTimeTable( p, fromWeek, curWeek, mStartTime, mEndTime, weekBox );
00913 
00914         drawFooter( p, footerBox );
00915 
00916         fromWeek = fromWeek.addDays( 7 );
00917         curWeek = fromWeek.addDays( 6 );
00918         if ( curWeek <= toWeek )
00919           mPrinter->newPage();
00920       } while ( curWeek <= toWeek );
00921       break;
00922 
00923     case SplitWeek: {
00924       QRect weekBox1( weekBox );
00925       // On the left side there are four days (mo-th) plus the timeline,
00926       // on the right there are only three days (fr-su) plus the timeline. Don't
00927       // use the whole width, but rather give them the same width as on the left.
00928       weekBox1.setRight( int( ( width - TIMELINE_WIDTH ) * 3. / 4. + TIMELINE_WIDTH ) );
00929       do {
00930         QDate endLeft( fromWeek.addDays( 3 ) );
00931         int hh = headerHeight();
00932 
00933         drawTimeTable( p, fromWeek, endLeft,
00934                        mStartTime, mEndTime, weekBox );
00935         mPrinter->newPage();
00936         drawSplitHeaderRight( p, fromWeek, curWeek, QDate(), width, hh );
00937         drawTimeTable( p, endLeft.addDays( 1 ), curWeek,
00938                        mStartTime, mEndTime, weekBox1 );
00939 
00940         drawFooter( p, footerBox );
00941 
00942         fromWeek = fromWeek.addDays( 7 );
00943         curWeek = fromWeek.addDays( 6 );
00944         if ( curWeek <= toWeek )
00945           mPrinter->newPage();
00946       } while ( curWeek <= toWeek );
00947       }
00948       break;
00949   }
00950 }
00951 
00952 
00953 
00954 
00955 /**************************************************************
00956  *           Print Month
00957  **************************************************************/
00958 
00959 CalPrintMonth::CalPrintMonth() : CalPrintPluginBase()
00960 {
00961 }
00962 
00963 CalPrintMonth::~CalPrintMonth()
00964 {
00965 }
00966 
00967 QWidget *CalPrintMonth::createConfigWidget( QWidget *w )
00968 {
00969   return new CalPrintMonthConfig_Base( w );
00970 }
00971 
00972 void CalPrintMonth::readSettingsWidget()
00973 {
00974   CalPrintMonthConfig_Base *cfg =
00975       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
00976   if ( cfg ) {
00977     mFromDate = QDate( cfg->mFromYear->value(), cfg->mFromMonth->currentItem()+1, 1 );
00978     mToDate = QDate( cfg->mToYear->value(), cfg->mToMonth->currentItem()+1, 1 );
00979 
00980     mWeekNumbers =  cfg->mWeekNumbers->isChecked();
00981     mRecurDaily = cfg->mRecurDaily->isChecked();
00982     mRecurWeekly = cfg->mRecurWeekly->isChecked();
00983     mIncludeTodos = cfg->mIncludeTodos->isChecked();
00984 //    mUseColors = cfg->mColors->isChecked();
00985   }
00986 }
00987 
00988 void CalPrintMonth::setSettingsWidget()
00989 {
00990   CalPrintMonthConfig_Base *cfg =
00991       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
00992   setDateRange( mFromDate, mToDate );
00993   if ( cfg ) {
00994     cfg->mWeekNumbers->setChecked( mWeekNumbers );
00995     cfg->mRecurDaily->setChecked( mRecurDaily );
00996     cfg->mRecurWeekly->setChecked( mRecurWeekly );
00997     cfg->mIncludeTodos->setChecked( mIncludeTodos );
00998 //    cfg->mColors->setChecked( mUseColors );
00999   }
01000 }
01001 
01002 void CalPrintMonth::loadConfig()
01003 {
01004   if ( mConfig ) {
01005     mWeekNumbers = mConfig->readBoolEntry( "Print week numbers", true );
01006     mRecurDaily = mConfig->readBoolEntry( "Print daily incidences", true );
01007     mRecurWeekly = mConfig->readBoolEntry( "Print weekly incidences", true );
01008     mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
01009   }
01010   setSettingsWidget();
01011 }
01012 
01013 void CalPrintMonth::saveConfig()
01014 {
01015   readSettingsWidget();
01016   if ( mConfig ) {
01017     mConfig->writeEntry( "Print week numbers", mWeekNumbers );
01018     mConfig->writeEntry( "Print daily incidences", mRecurDaily );
01019     mConfig->writeEntry( "Print weekly incidences", mRecurWeekly );
01020     mConfig->writeEntry( "Include todos", mIncludeTodos );
01021   }
01022 }
01023 
01024 void CalPrintMonth::setDateRange( const QDate &from, const QDate &to )
01025 {
01026   CalPrintPluginBase::setDateRange( from, to );
01027   CalPrintMonthConfig_Base *cfg =
01028       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
01029   const KCalendarSystem *calSys = calendarSystem();
01030   if ( cfg && calSys ) {
01031     cfg->mFromMonth->clear();
01032     for ( int i=0; i<calSys->monthsInYear( mFromDate ); ++i ) {
01033       cfg->mFromMonth->insertItem( calSys->monthName( i+1, mFromDate.year() ) );
01034     }
01035     cfg->mToMonth->clear();
01036     for ( int i=0; i<calSys->monthsInYear( mToDate ); ++i ) {
01037       cfg->mToMonth->insertItem( calSys->monthName( i+1, mToDate.year() ) );
01038     }
01039   }
01040   if ( cfg ) {
01041     cfg->mFromMonth->setCurrentItem( from.month()-1 );
01042     cfg->mFromYear->setValue( to.year() );
01043     cfg->mToMonth->setCurrentItem( mToDate.month()-1 );
01044     cfg->mToYear->setValue( mToDate.year() );
01045   }
01046 }
01047 
01048 void CalPrintMonth::print( QPainter &p, int width, int height )
01049 {
01050   QDate curMonth, fromMonth, toMonth;
01051 
01052   fromMonth = mFromDate.addDays( -( mFromDate.day() - 1 ) );
01053   toMonth = mToDate.addDays( mToDate.daysInMonth() - mToDate.day() );
01054 
01055   curMonth = fromMonth;
01056   const KCalendarSystem *calSys = calendarSystem();
01057   if ( !calSys ) return;
01058 
01059   QRect headerBox( 0, 0, width, headerHeight() );
01060   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
01061   height -= footerHeight();
01062 
01063   QRect monthBox( 0, 0, width, height );
01064   monthBox.setTop( headerBox.bottom() + padding() );
01065 
01066   do {
01067     QString title( i18n("monthname year", "%1 %2") );
01068     title = title.arg( calSys->monthName( curMonth ) )
01069                  .arg( curMonth.year() );
01070     QDate tmp( fromMonth );
01071     int weekdayCol = weekdayColumn( tmp.dayOfWeek() );
01072     tmp = tmp.addDays( -weekdayCol );
01073 
01074     drawHeader( p, title, curMonth.addMonths( -1 ), curMonth.addMonths( 1 ),
01075                 headerBox );
01076     drawMonthTable( p, curMonth, mWeekNumbers, mRecurDaily, mRecurWeekly, monthBox );
01077 
01078     drawFooter( p, footerBox );
01079 
01080     curMonth = curMonth.addDays( curMonth.daysInMonth() );
01081     if ( curMonth <= toMonth ) mPrinter->newPage();
01082   } while ( curMonth <= toMonth );
01083 
01084 }
01085 
01086 
01087 
01088 
01089 /**************************************************************
01090  *           Print Todos
01091  **************************************************************/
01092 
01093 CalPrintTodos::CalPrintTodos() : CalPrintPluginBase()
01094 {
01095   mTodoSortField = TodoFieldUnset;
01096   mTodoSortDirection = TodoDirectionUnset;
01097 }
01098 
01099 CalPrintTodos::~CalPrintTodos()
01100 {
01101 }
01102 
01103 QWidget *CalPrintTodos::createConfigWidget( QWidget *w )
01104 {
01105   return new CalPrintTodoConfig_Base( w );
01106 }
01107 
01108 void CalPrintTodos::readSettingsWidget()
01109 {
01110   CalPrintTodoConfig_Base *cfg =
01111       dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget );
01112   if ( cfg ) {
01113     mPageTitle = cfg->mTitle->text();
01114 
01115     mTodoPrintType = (eTodoPrintType)( cfg->mPrintType->id(
01116       cfg->mPrintType->selected() ) );
01117 
01118     mFromDate = cfg->mFromDate->date();
01119     mToDate = cfg->mToDate->date();
01120 
01121     mIncludeDescription = cfg->mDescription->isChecked();
01122     mIncludePriority = cfg->mPriority->isChecked();
01123     mIncludeDueDate = cfg->mDueDate->isChecked();
01124     mIncludePercentComplete = cfg->mPercentComplete->isChecked();
01125     mConnectSubTodos = cfg->mConnectSubTodos->isChecked();
01126     mStrikeOutCompleted = cfg->mStrikeOutCompleted->isChecked();
01127 
01128     mTodoSortField = (eTodoSortField)cfg->mSortField->currentItem();
01129     mTodoSortDirection = (eTodoSortDirection)cfg->mSortDirection->currentItem();
01130   }
01131 }
01132 
01133 void CalPrintTodos::setSettingsWidget()
01134 {
01135 //   kdDebug(5850) << "CalPrintTodos::setSettingsWidget" << endl;
01136 
01137   CalPrintTodoConfig_Base *cfg =
01138       dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget );
01139   if ( cfg ) {
01140     cfg->mTitle->setText( mPageTitle );
01141 
01142     cfg->mPrintType->setButton( mTodoPrintType );
01143 
01144     cfg->mFromDate->setDate( mFromDate );
01145     cfg->mToDate->setDate( mToDate );
01146 
01147     cfg->mDescription->setChecked( mIncludeDescription );
01148     cfg->mPriority->setChecked( mIncludePriority );
01149     cfg->mDueDate->setChecked( mIncludeDueDate );
01150     cfg->mPercentComplete->setChecked( mIncludePercentComplete );
01151     cfg->mConnectSubTodos->setChecked( mConnectSubTodos );
01152     cfg->mStrikeOutCompleted->setChecked( mStrikeOutCompleted );
01153 
01154     if ( mTodoSortField != TodoFieldUnset ) {
01155       // do not insert if already done so.
01156       cfg->mSortField->insertItem( i18n("Summary") );
01157       cfg->mSortField->insertItem( i18n("Start Date") );
01158       cfg->mSortField->insertItem( i18n("Due Date") );
01159       cfg->mSortField->insertItem( i18n("Priority") );
01160       cfg->mSortField->insertItem( i18n("Percent Complete") );
01161       cfg->mSortField->setCurrentItem( (int)mTodoSortField );
01162     }
01163 
01164     if ( mTodoSortDirection != TodoDirectionUnset ) {
01165       // do not insert if already done so.
01166       cfg->mSortDirection->insertItem( i18n("Ascending") );
01167       cfg->mSortDirection->insertItem( i18n("Descending") );
01168       cfg->mSortDirection->setCurrentItem( (int)mTodoSortDirection );
01169     }
01170   }
01171 }
01172 
01173 void CalPrintTodos::loadConfig()
01174 {
01175   if ( mConfig ) {
01176     mPageTitle = mConfig->readEntry( "Page title", i18n("To-do list") );
01177     mTodoPrintType = (eTodoPrintType)mConfig->readNumEntry( "Print type", (int)TodosAll );
01178     mIncludeDescription = mConfig->readBoolEntry( "Include description", true );
01179     mIncludePriority = mConfig->readBoolEntry( "Include priority", true );
01180     mIncludeDueDate = mConfig->readBoolEntry( "Include due date", true );
01181     mIncludePercentComplete = mConfig->readBoolEntry( "Include percentage completed", true );
01182     mConnectSubTodos = mConfig->readBoolEntry( "Connect subtodos", true );
01183     mStrikeOutCompleted = mConfig->readBoolEntry( "Strike out completed summaries",  true );
01184     mTodoSortField = (eTodoSortField)mConfig->readNumEntry( "Sort field", (int)TodoFieldSummary );
01185     mTodoSortDirection = (eTodoSortDirection)mConfig->readNumEntry( "Sort direction", (int)TodoDirectionAscending );
01186   }
01187   setSettingsWidget();
01188 }
01189 
01190 void CalPrintTodos::saveConfig()
01191 {
01192   readSettingsWidget();
01193   if ( mConfig ) {
01194     mConfig->writeEntry( "Page title", mPageTitle );
01195     mConfig->writeEntry( "Print type", int( mTodoPrintType ) );
01196     mConfig->writeEntry( "Include description", mIncludeDescription );
01197     mConfig->writeEntry( "Include priority", mIncludePriority );
01198     mConfig->writeEntry( "Include due date", mIncludeDueDate );
01199     mConfig->writeEntry( "Include percentage completed", mIncludePercentComplete );
01200     mConfig->writeEntry( "Connect subtodos", mConnectSubTodos );
01201     mConfig->writeEntry( "Strike out completed summaries", mStrikeOutCompleted );
01202     mConfig->writeEntry( "Sort field", mTodoSortField );
01203     mConfig->writeEntry( "Sort direction", mTodoSortDirection );
01204   }
01205 }
01206 
01207 void CalPrintTodos::print( QPainter &p, int width, int height )
01208 {
01209   // TODO: Find a good way to guarantee a nicely designed output
01210   int pospriority = 10;
01211   int possummary = 60;
01212   int posdue = width - 65;
01213   int poscomplete = posdue - 70; //Complete column is to right of the Due column
01214   int lineSpacing = 15;
01215   int fontHeight = 10;
01216 
01217   QRect headerBox( 0, 0, width, headerHeight() );
01218   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
01219   height -= footerHeight();
01220 
01221   // Draw the First Page Header
01222   drawHeader( p, mPageTitle, mFromDate, QDate(), headerBox );
01223 
01224   // Draw the Column Headers
01225   int mCurrentLinePos = headerHeight() + 5;
01226   QString outStr;
01227   QFont oldFont( p.font() );
01228 
01229   p.setFont( QFont( "sans-serif", 10, QFont::Bold ) );
01230   lineSpacing = p.fontMetrics().lineSpacing();
01231   mCurrentLinePos += lineSpacing;
01232   if ( mIncludePriority ) {
01233     outStr += i18n( "Priority" );
01234     p.drawText( pospriority, mCurrentLinePos - 2, outStr );
01235   } else {
01236     possummary = 10;
01237     pospriority = -1;
01238   }
01239 
01240   outStr.truncate( 0 );
01241   outStr += i18n( "Summary" );
01242   p.drawText( possummary, mCurrentLinePos - 2, outStr );
01243 
01244   if ( mIncludePercentComplete ) {
01245     if ( !mIncludeDueDate ) //move Complete column to the right
01246       poscomplete = posdue; //if not print the Due Date column
01247     outStr.truncate( 0 );
01248     outStr += i18n( "Complete" );
01249     p.drawText( poscomplete, mCurrentLinePos - 2, outStr );
01250   } else {
01251     poscomplete = -1;
01252   }
01253 
01254   if ( mIncludeDueDate ) {
01255     outStr.truncate( 0 );
01256     outStr += i18n( "Due" );
01257     p.drawText( posdue, mCurrentLinePos - 2, outStr );
01258   } else {
01259     posdue = -1;
01260   }
01261 
01262   p.setFont( QFont( "sans-serif", 10 ) );
01263   fontHeight = p.fontMetrics().height();
01264 
01265   Todo::List todoList;
01266   Todo::List tempList;
01267   Todo::List::ConstIterator it;
01268 
01269   // Convert sort options to the corresponding enums
01270   TodoSortField sortField = TodoSortSummary;
01271   switch( mTodoSortField ) {
01272   case TodoFieldSummary:
01273     sortField = TodoSortSummary; break;
01274   case TodoFieldStartDate:
01275     sortField = TodoSortStartDate; break;
01276   case TodoFieldDueDate:
01277     sortField = TodoSortDueDate; break;
01278   case TodoFieldPriority:
01279     sortField = TodoSortPriority; break;
01280   case TodoFieldPercentComplete:
01281     sortField = TodoSortPercentComplete; break;
01282   case TodoFieldUnset:
01283     break;
01284   }
01285 
01286   SortDirection sortDirection;
01287   switch( mTodoSortDirection ) {
01288   case TodoDirectionAscending:
01289     sortDirection = SortDirectionAscending; break;
01290   case TodoDirectionDescending:
01291     sortDirection = SortDirectionDescending; break;
01292   case TodoDirectionUnset:
01293     break;
01294   }
01295 
01296   // Create list of to-dos which will be printed
01297   todoList = mCalendar->todos( sortField,  sortDirection );
01298   switch( mTodoPrintType ) {
01299   case TodosAll:
01300     break;
01301   case TodosUnfinished:
01302     for( it = todoList.begin(); it!= todoList.end(); ++it ) {
01303       if ( !(*it)->isCompleted() )
01304         tempList.append( *it );
01305     }
01306     todoList = tempList;
01307     break;
01308   case TodosDueRange:
01309     for( it = todoList.begin(); it!= todoList.end(); ++it ) {
01310       if ( (*it)->hasDueDate() ) {
01311         if ( (*it)->dtDue().date() >= mFromDate &&
01312              (*it)->dtDue().date() <= mToDate )
01313           tempList.append( *it );
01314       } else {
01315         tempList.append( *it );
01316       }
01317     }
01318     todoList = tempList;
01319     break;
01320   }
01321 
01322   // Print to-dos
01323   int count = 0;
01324   for ( it=todoList.begin(); it!=todoList.end(); ++it ) {
01325     Todo *currEvent = *it;
01326 
01327     // Skip sub-to-dos. They will be printed recursively in drawTodo()
01328     if ( !currEvent->relatedTo() ) {
01329       count++;
01330       drawTodo( count, currEvent, p,
01331                          sortField, sortDirection,
01332                          mConnectSubTodos,
01333                          mStrikeOutCompleted, mIncludeDescription,
01334                          pospriority, possummary, posdue, poscomplete,
01335                          0, 0, mCurrentLinePos, width, height, todoList );
01336     }
01337   }
01338 
01339   drawFooter( p, footerBox );
01340   p.setFont( oldFont );
01341 }
01342 
01343 #endif
KDE Home | KDE Accessibility Home | Description of Access Keys