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   do {
00709     QTime curStartTime( mStartTime );
00710     QTime curEndTime( mEndTime );
00711 
00712     // For an invalid time range, simply show one hour, starting at the hour
00713     // before the given start time
00714     if ( curEndTime <= curStartTime ) {
00715       curStartTime = QTime( curStartTime.hour(), 0, 0 );
00716       curEndTime = curStartTime.addSecs( 3600 );
00717     }
00718 
00719     KLocale *local = KGlobal::locale();
00720     drawHeader( p, local->formatDate( curDay ), curDay, QDate(), headerBox );
00721 
00722 
00723     Event::List eventList = mCalendar->events( curDay,
00724                                                EventSortStartDate,
00725                                                SortDirectionAscending );
00726 
00727     p.setFont( QFont( "sans-serif", 12 ) );
00728 
00729     // TODO: Find a good way to determine the height of the all-day box
00730     QRect allDayBox( TIMELINE_WIDTH + padding(), headerBox.bottom() + padding(),
00731                      0, height / 20 );
00732     allDayBox.setRight( width );
00733     int allDayHeight = drawAllDayBox( p, eventList, curDay, true, allDayBox );
00734 
00735     QRect dayBox( allDayBox );
00736     dayBox.setTop( allDayHeight /*allDayBox.bottom()*/ );
00737     dayBox.setBottom( height );
00738     drawAgendaDayBox( p, eventList, curDay, mIncludeAllEvents,
00739                       curStartTime, curEndTime, dayBox );
00740 
00741     QRect tlBox( dayBox );
00742     tlBox.setLeft( 0 );
00743     tlBox.setWidth( TIMELINE_WIDTH );
00744     drawTimeLine( p, curStartTime, curEndTime, tlBox );
00745 
00746     drawFooter( p, footerBox );
00747 
00748     curDay = curDay.addDays( 1 );
00749     if ( curDay <= mToDate ) mPrinter->newPage();
00750   } while ( curDay <= mToDate );
00751 }
00752 
00753 
00754 
00755 /**************************************************************
00756  *           Print Week
00757  **************************************************************/
00758 
00759 CalPrintWeek::CalPrintWeek() : CalPrintPluginBase()
00760 {
00761 }
00762 
00763 CalPrintWeek::~CalPrintWeek()
00764 {
00765 }
00766 
00767 QWidget *CalPrintWeek::createConfigWidget( QWidget *w )
00768 {
00769   return new CalPrintWeekConfig_Base( w );
00770 }
00771 
00772 void CalPrintWeek::readSettingsWidget()
00773 {
00774   CalPrintWeekConfig_Base *cfg =
00775       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00776   if ( cfg ) {
00777     mFromDate = cfg->mFromDate->date();
00778     mToDate = cfg->mToDate->date();
00779 
00780     mWeekPrintType = (eWeekPrintType)( cfg->mPrintType->id(
00781       cfg->mPrintType->selected() ) );
00782 
00783     mStartTime = cfg->mFromTime->time();
00784     mEndTime = cfg->mToTime->time();
00785 
00786     mIncludeTodos = cfg->mIncludeTodos->isChecked();
00787     mUseColors = cfg->mColors->isChecked();
00788   }
00789 }
00790 
00791 void CalPrintWeek::setSettingsWidget()
00792 {
00793   CalPrintWeekConfig_Base *cfg =
00794       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00795   if ( cfg ) {
00796     cfg->mFromDate->setDate( mFromDate );
00797     cfg->mToDate->setDate( mToDate );
00798 
00799     cfg->mPrintType->setButton( mWeekPrintType );
00800 
00801     cfg->mFromTime->setTime( mStartTime );
00802     cfg->mToTime->setTime( mEndTime );
00803 
00804     cfg->mIncludeTodos->setChecked( mIncludeTodos );
00805     cfg->mColors->setChecked( mUseColors );
00806   }
00807 }
00808 
00809 void CalPrintWeek::loadConfig()
00810 {
00811   if ( mConfig ) {
00812     QDate dt;
00813     QTime tm1( dayStart() );
00814     QDateTime startTm( dt, tm1  );
00815     QDateTime endTm( dt, tm1.addSecs( 43200 ) );
00816     mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time();
00817     mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time();
00818     mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
00819     mWeekPrintType =(eWeekPrintType)( mConfig->readNumEntry( "Print type", (int)Filofax ) );
00820   }
00821   setSettingsWidget();
00822 }
00823 
00824 void CalPrintWeek::saveConfig()
00825 {
00826   readSettingsWidget();
00827   if ( mConfig ) {
00828     mConfig->writeEntry( "Start time", QDateTime( QDate(), mStartTime ) );
00829     mConfig->writeEntry( "End time", QDateTime( QDate(), mEndTime ) );
00830     mConfig->writeEntry( "Include todos", mIncludeTodos );
00831     mConfig->writeEntry( "Print type", int( mWeekPrintType ) );
00832   }
00833 }
00834 
00835 KPrinter::Orientation CalPrintWeek::defaultOrientation()
00836 {
00837   if ( mWeekPrintType == Filofax ) return KPrinter::Portrait;
00838   else if ( mWeekPrintType == SplitWeek ) return KPrinter::Portrait;
00839   else return KPrinter::Landscape;
00840 }
00841 
00842 void CalPrintWeek::setDateRange( const QDate &from, const QDate &to )
00843 {
00844   CalPrintPluginBase::setDateRange( from, to );
00845   CalPrintWeekConfig_Base *cfg =
00846       dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget );
00847   if ( cfg ) {
00848     cfg->mFromDate->setDate( from );
00849     cfg->mToDate->setDate( to );
00850   }
00851 }
00852 
00853 void CalPrintWeek::print( QPainter &p, int width, int height )
00854 {
00855   QDate curWeek, fromWeek, toWeek;
00856 
00857   // correct begin and end to first and last day of week
00858   int weekdayCol = weekdayColumn( mFromDate.dayOfWeek() );
00859   fromWeek = mFromDate.addDays( -weekdayCol );
00860   weekdayCol = weekdayColumn( mFromDate.dayOfWeek() );
00861   toWeek = mToDate.addDays( 6 - weekdayCol );
00862 
00863   curWeek = fromWeek.addDays( 6 );
00864   KLocale *local = KGlobal::locale();
00865 
00866   QString line1, line2, title;
00867   QRect headerBox( 0, 0, width, headerHeight() );
00868   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
00869   height -= footerHeight();
00870 
00871   QRect weekBox( headerBox );
00872   weekBox.setTop( headerBox.bottom() + padding() );
00873   weekBox.setBottom( height );
00874 
00875   switch ( mWeekPrintType ) {
00876     case Filofax:
00877       do {
00878         line1 = local->formatDate( curWeek.addDays( -6 ) );
00879         line2 = local->formatDate( curWeek );
00880         if ( orientation() == KPrinter::Landscape ) {
00881           title = i18n("date from-to", "%1 - %2");
00882         } else {
00883           title = i18n("date from-\nto", "%1 -\n%2");;
00884         }
00885         title = title.arg( line1 ).arg( line2 );
00886         drawHeader( p, title, curWeek.addDays( -6 ), QDate(), headerBox );
00887 
00888         drawWeek( p, curWeek, weekBox );
00889 
00890         drawFooter( p, footerBox );
00891 
00892         curWeek = curWeek.addDays( 7 );
00893         if ( curWeek <= toWeek )
00894           mPrinter->newPage();
00895       } while ( curWeek <= toWeek );
00896       break;
00897 
00898     case Timetable:
00899     default:
00900       do {
00901         line1 = local->formatDate( curWeek.addDays( -6 ) );
00902         line2 = local->formatDate( curWeek );
00903         if ( orientation() == KPrinter::Landscape ) {
00904           title = i18n("date from - to (week number)", "%1 - %2 (Week %3)");
00905         } else {
00906           title = i18n("date from -\nto (week number)", "%1 -\n%2 (Week %3)");
00907         }
00908         title = title.arg( line1 ).arg( line2 ).arg( curWeek.weekNumber() );
00909         drawHeader( p, title, curWeek, QDate(), headerBox );
00910 
00911         QRect weekBox( headerBox );
00912         weekBox.setTop( headerBox.bottom() + padding() );
00913         weekBox.setBottom( height );
00914         drawTimeTable( p, fromWeek, curWeek, mStartTime, mEndTime, weekBox );
00915 
00916         drawFooter( p, footerBox );
00917 
00918         fromWeek = fromWeek.addDays( 7 );
00919         curWeek = fromWeek.addDays( 6 );
00920         if ( curWeek <= toWeek )
00921           mPrinter->newPage();
00922       } while ( curWeek <= toWeek );
00923       break;
00924 
00925     case SplitWeek: {
00926       QRect weekBox1( weekBox );
00927       // On the left side there are four days (mo-th) plus the timeline,
00928       // on the right there are only three days (fr-su) plus the timeline. Don't
00929       // use the whole width, but rather give them the same width as on the left.
00930       weekBox1.setRight( int( ( width - TIMELINE_WIDTH ) * 3. / 4. + TIMELINE_WIDTH ) );
00931       do {
00932         QDate endLeft( fromWeek.addDays( 3 ) );
00933         int hh = headerHeight();
00934 
00935         drawTimeTable( p, fromWeek, endLeft,
00936                        mStartTime, mEndTime, weekBox );
00937         mPrinter->newPage();
00938         drawSplitHeaderRight( p, fromWeek, curWeek, QDate(), width, hh );
00939         drawTimeTable( p, endLeft.addDays( 1 ), curWeek,
00940                        mStartTime, mEndTime, weekBox1 );
00941 
00942         drawFooter( p, footerBox );
00943 
00944         fromWeek = fromWeek.addDays( 7 );
00945         curWeek = fromWeek.addDays( 6 );
00946         if ( curWeek <= toWeek )
00947           mPrinter->newPage();
00948       } while ( curWeek <= toWeek );
00949       }
00950       break;
00951   }
00952 }
00953 
00954 
00955 
00956 
00957 /**************************************************************
00958  *           Print Month
00959  **************************************************************/
00960 
00961 CalPrintMonth::CalPrintMonth() : CalPrintPluginBase()
00962 {
00963 }
00964 
00965 CalPrintMonth::~CalPrintMonth()
00966 {
00967 }
00968 
00969 QWidget *CalPrintMonth::createConfigWidget( QWidget *w )
00970 {
00971   return new CalPrintMonthConfig_Base( w );
00972 }
00973 
00974 void CalPrintMonth::readSettingsWidget()
00975 {
00976   CalPrintMonthConfig_Base *cfg =
00977       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
00978   if ( cfg ) {
00979     mFromDate = QDate( cfg->mFromYear->value(), cfg->mFromMonth->currentItem()+1, 1 );
00980     mToDate = QDate( cfg->mToYear->value(), cfg->mToMonth->currentItem()+1, 1 );
00981 
00982     mWeekNumbers =  cfg->mWeekNumbers->isChecked();
00983     mRecurDaily = cfg->mRecurDaily->isChecked();
00984     mRecurWeekly = cfg->mRecurWeekly->isChecked();
00985     mIncludeTodos = cfg->mIncludeTodos->isChecked();
00986 //    mUseColors = cfg->mColors->isChecked();
00987   }
00988 }
00989 
00990 void CalPrintMonth::setSettingsWidget()
00991 {
00992   CalPrintMonthConfig_Base *cfg =
00993       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
00994   setDateRange( mFromDate, mToDate );
00995   if ( cfg ) {
00996     cfg->mWeekNumbers->setChecked( mWeekNumbers );
00997     cfg->mRecurDaily->setChecked( mRecurDaily );
00998     cfg->mRecurWeekly->setChecked( mRecurWeekly );
00999     cfg->mIncludeTodos->setChecked( mIncludeTodos );
01000 //    cfg->mColors->setChecked( mUseColors );
01001   }
01002 }
01003 
01004 void CalPrintMonth::loadConfig()
01005 {
01006   if ( mConfig ) {
01007     mWeekNumbers = mConfig->readBoolEntry( "Print week numbers", true );
01008     mRecurDaily = mConfig->readBoolEntry( "Print daily incidences", true );
01009     mRecurWeekly = mConfig->readBoolEntry( "Print weekly incidences", true );
01010     mIncludeTodos = mConfig->readBoolEntry( "Include todos", false );
01011   }
01012   setSettingsWidget();
01013 }
01014 
01015 void CalPrintMonth::saveConfig()
01016 {
01017   readSettingsWidget();
01018   if ( mConfig ) {
01019     mConfig->writeEntry( "Print week numbers", mWeekNumbers );
01020     mConfig->writeEntry( "Print daily incidences", mRecurDaily );
01021     mConfig->writeEntry( "Print weekly incidences", mRecurWeekly );
01022     mConfig->writeEntry( "Include todos", mIncludeTodos );
01023   }
01024 }
01025 
01026 void CalPrintMonth::setDateRange( const QDate &from, const QDate &to )
01027 {
01028   CalPrintPluginBase::setDateRange( from, to );
01029   CalPrintMonthConfig_Base *cfg =
01030       dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget );
01031   const KCalendarSystem *calSys = calendarSystem();
01032   if ( cfg && calSys ) {
01033     cfg->mFromMonth->clear();
01034     for ( int i=0; i<calSys->monthsInYear( mFromDate ); ++i ) {
01035       cfg->mFromMonth->insertItem( calSys->monthName( i+1, mFromDate.year() ) );
01036     }
01037     cfg->mToMonth->clear();
01038     for ( int i=0; i<calSys->monthsInYear( mToDate ); ++i ) {
01039       cfg->mToMonth->insertItem( calSys->monthName( i+1, mToDate.year() ) );
01040     }
01041   }
01042   if ( cfg ) {
01043     cfg->mFromMonth->setCurrentItem( from.month()-1 );
01044     cfg->mFromYear->setValue( to.year() );
01045     cfg->mToMonth->setCurrentItem( mToDate.month()-1 );
01046     cfg->mToYear->setValue( mToDate.year() );
01047   }
01048 }
01049 
01050 void CalPrintMonth::print( QPainter &p, int width, int height )
01051 {
01052   QDate curMonth, fromMonth, toMonth;
01053 
01054   fromMonth = mFromDate.addDays( -( mFromDate.day() - 1 ) );
01055   toMonth = mToDate.addDays( mToDate.daysInMonth() - mToDate.day() );
01056 
01057   curMonth = fromMonth;
01058   const KCalendarSystem *calSys = calendarSystem();
01059   if ( !calSys ) return;
01060 
01061   QRect headerBox( 0, 0, width, headerHeight() );
01062   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
01063   height -= footerHeight();
01064 
01065   QRect monthBox( 0, 0, width, height );
01066   monthBox.setTop( headerBox.bottom() + padding() );
01067 
01068   do {
01069     QString title( i18n("monthname year", "%1 %2") );
01070     title = title.arg( calSys->monthName( curMonth ) )
01071                  .arg( curMonth.year() );
01072     QDate tmp( fromMonth );
01073     int weekdayCol = weekdayColumn( tmp.dayOfWeek() );
01074     tmp = tmp.addDays( -weekdayCol );
01075 
01076     drawHeader( p, title, curMonth.addMonths( -1 ), curMonth.addMonths( 1 ),
01077                 headerBox );
01078     drawMonthTable( p, curMonth, mWeekNumbers, mRecurDaily, mRecurWeekly, monthBox );
01079 
01080     drawFooter( p, footerBox );
01081 
01082     curMonth = curMonth.addDays( curMonth.daysInMonth() );
01083     if ( curMonth <= toMonth ) mPrinter->newPage();
01084   } while ( curMonth <= toMonth );
01085 
01086 }
01087 
01088 
01089 
01090 
01091 /**************************************************************
01092  *           Print Todos
01093  **************************************************************/
01094 
01095 CalPrintTodos::CalPrintTodos() : CalPrintPluginBase()
01096 {
01097   mTodoSortField = TodoFieldUnset;
01098   mTodoSortDirection = TodoDirectionUnset;
01099 }
01100 
01101 CalPrintTodos::~CalPrintTodos()
01102 {
01103 }
01104 
01105 QWidget *CalPrintTodos::createConfigWidget( QWidget *w )
01106 {
01107   return new CalPrintTodoConfig_Base( w );
01108 }
01109 
01110 void CalPrintTodos::readSettingsWidget()
01111 {
01112   CalPrintTodoConfig_Base *cfg =
01113       dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget );
01114   if ( cfg ) {
01115     mPageTitle = cfg->mTitle->text();
01116 
01117     mTodoPrintType = (eTodoPrintType)( cfg->mPrintType->id(
01118       cfg->mPrintType->selected() ) );
01119 
01120     mFromDate = cfg->mFromDate->date();
01121     mToDate = cfg->mToDate->date();
01122 
01123     mIncludeDescription = cfg->mDescription->isChecked();
01124     mIncludePriority = cfg->mPriority->isChecked();
01125     mIncludeDueDate = cfg->mDueDate->isChecked();
01126     mIncludePercentComplete = cfg->mPercentComplete->isChecked();
01127     mConnectSubTodos = cfg->mConnectSubTodos->isChecked();
01128     mStrikeOutCompleted = cfg->mStrikeOutCompleted->isChecked();
01129 
01130     mTodoSortField = (eTodoSortField)cfg->mSortField->currentItem();
01131     mTodoSortDirection = (eTodoSortDirection)cfg->mSortDirection->currentItem();
01132   }
01133 }
01134 
01135 void CalPrintTodos::setSettingsWidget()
01136 {
01137 //   kdDebug(5850) << "CalPrintTodos::setSettingsWidget" << endl;
01138 
01139   CalPrintTodoConfig_Base *cfg =
01140       dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget );
01141   if ( cfg ) {
01142     cfg->mTitle->setText( mPageTitle );
01143 
01144     cfg->mPrintType->setButton( mTodoPrintType );
01145 
01146     cfg->mFromDate->setDate( mFromDate );
01147     cfg->mToDate->setDate( mToDate );
01148 
01149     cfg->mDescription->setChecked( mIncludeDescription );
01150     cfg->mPriority->setChecked( mIncludePriority );
01151     cfg->mDueDate->setChecked( mIncludeDueDate );
01152     cfg->mPercentComplete->setChecked( mIncludePercentComplete );
01153     cfg->mConnectSubTodos->setChecked( mConnectSubTodos );
01154     cfg->mStrikeOutCompleted->setChecked( mStrikeOutCompleted );
01155 
01156     if ( mTodoSortField != TodoFieldUnset ) {
01157       // do not insert if already done so.
01158       cfg->mSortField->insertItem( i18n("Summary") );
01159       cfg->mSortField->insertItem( i18n("Start Date") );
01160       cfg->mSortField->insertItem( i18n("Due Date") );
01161       cfg->mSortField->insertItem( i18n("Priority") );
01162       cfg->mSortField->insertItem( i18n("Percent Complete") );
01163       cfg->mSortField->setCurrentItem( (int)mTodoSortField );
01164     }
01165 
01166     if ( mTodoSortDirection != TodoDirectionUnset ) {
01167       // do not insert if already done so.
01168       cfg->mSortDirection->insertItem( i18n("Ascending") );
01169       cfg->mSortDirection->insertItem( i18n("Descending") );
01170       cfg->mSortDirection->setCurrentItem( (int)mTodoSortDirection );
01171     }
01172   }
01173 }
01174 
01175 void CalPrintTodos::loadConfig()
01176 {
01177   if ( mConfig ) {
01178     mPageTitle = mConfig->readEntry( "Page title", i18n("To-do list") );
01179     mTodoPrintType = (eTodoPrintType)mConfig->readNumEntry( "Print type", (int)TodosAll );
01180     mIncludeDescription = mConfig->readBoolEntry( "Include description", true );
01181     mIncludePriority = mConfig->readBoolEntry( "Include priority", true );
01182     mIncludeDueDate = mConfig->readBoolEntry( "Include due date", true );
01183     mIncludePercentComplete = mConfig->readBoolEntry( "Include percentage completed", true );
01184     mConnectSubTodos = mConfig->readBoolEntry( "Connect subtodos", true );
01185     mStrikeOutCompleted = mConfig->readBoolEntry( "Strike out completed summaries",  true );
01186     mTodoSortField = (eTodoSortField)mConfig->readNumEntry( "Sort field", (int)TodoFieldSummary );
01187     mTodoSortDirection = (eTodoSortDirection)mConfig->readNumEntry( "Sort direction", (int)TodoDirectionAscending );
01188   }
01189   setSettingsWidget();
01190 }
01191 
01192 void CalPrintTodos::saveConfig()
01193 {
01194   readSettingsWidget();
01195   if ( mConfig ) {
01196     mConfig->writeEntry( "Page title", mPageTitle );
01197     mConfig->writeEntry( "Print type", int( mTodoPrintType ) );
01198     mConfig->writeEntry( "Include description", mIncludeDescription );
01199     mConfig->writeEntry( "Include priority", mIncludePriority );
01200     mConfig->writeEntry( "Include due date", mIncludeDueDate );
01201     mConfig->writeEntry( "Include percentage completed", mIncludePercentComplete );
01202     mConfig->writeEntry( "Connect subtodos", mConnectSubTodos );
01203     mConfig->writeEntry( "Strike out completed summaries", mStrikeOutCompleted );
01204     mConfig->writeEntry( "Sort field", mTodoSortField );
01205     mConfig->writeEntry( "Sort direction", mTodoSortDirection );
01206   }
01207 }
01208 
01209 void CalPrintTodos::print( QPainter &p, int width, int height )
01210 {
01211   // TODO: Find a good way to guarantee a nicely designed output
01212   int pospriority = 10;
01213   int possummary = 60;
01214   int posdue = width - 65;
01215   int poscomplete = posdue - 70; //Complete column is to right of the Due column
01216   int lineSpacing = 15;
01217   int fontHeight = 10;
01218 
01219   QRect headerBox( 0, 0, width, headerHeight() );
01220   QRect footerBox( 0, height - footerHeight(), width, footerHeight() );
01221   height -= footerHeight();
01222 
01223   // Draw the First Page Header
01224   drawHeader( p, mPageTitle, mFromDate, QDate(), headerBox );
01225 
01226   // Draw the Column Headers
01227   int mCurrentLinePos = headerHeight() + 5;
01228   QString outStr;
01229   QFont oldFont( p.font() );
01230 
01231   p.setFont( QFont( "sans-serif", 10, QFont::Bold ) );
01232   lineSpacing = p.fontMetrics().lineSpacing();
01233   mCurrentLinePos += lineSpacing;
01234   if ( mIncludePriority ) {
01235     outStr += i18n( "Priority" );
01236     p.drawText( pospriority, mCurrentLinePos - 2, outStr );
01237   } else {
01238     possummary = 10;
01239     pospriority = -1;
01240   }
01241 
01242   outStr.truncate( 0 );
01243   outStr += i18n( "Summary" );
01244   p.drawText( possummary, mCurrentLinePos - 2, outStr );
01245 
01246   if ( mIncludePercentComplete ) {
01247     if ( !mIncludeDueDate ) //move Complete column to the right
01248       poscomplete = posdue; //if not print the Due Date column
01249     outStr.truncate( 0 );
01250     outStr += i18n( "Complete" );
01251     p.drawText( poscomplete, mCurrentLinePos - 2, outStr );
01252   } else {
01253     poscomplete = -1;
01254   }
01255 
01256   if ( mIncludeDueDate ) {
01257     outStr.truncate( 0 );
01258     outStr += i18n( "Due" );
01259     p.drawText( posdue, mCurrentLinePos - 2, outStr );
01260   } else {
01261     posdue = -1;
01262   }
01263 
01264   p.setFont( QFont( "sans-serif", 10 ) );
01265   fontHeight = p.fontMetrics().height();
01266 
01267   Todo::List todoList;
01268   Todo::List tempList;
01269   Todo::List::ConstIterator it;
01270 
01271   // Convert sort options to the corresponding enums
01272   TodoSortField sortField = TodoSortSummary;
01273   switch( mTodoSortField ) {
01274   case TodoFieldSummary:
01275     sortField = TodoSortSummary; break;
01276   case TodoFieldStartDate:
01277     sortField = TodoSortStartDate; break;
01278   case TodoFieldDueDate:
01279     sortField = TodoSortDueDate; break;
01280   case TodoFieldPriority:
01281     sortField = TodoSortPriority; break;
01282   case TodoFieldPercentComplete:
01283     sortField = TodoSortPercentComplete; break;
01284   case TodoFieldUnset:
01285     break;
01286   }
01287 
01288   SortDirection sortDirection;
01289   switch( mTodoSortDirection ) {
01290   case TodoDirectionAscending:
01291     sortDirection = SortDirectionAscending; break;
01292   case TodoDirectionDescending:
01293     sortDirection = SortDirectionDescending; break;
01294   case TodoDirectionUnset:
01295     break;
01296   }
01297 
01298   // Create list of to-dos which will be printed
01299   todoList = mCalendar->todos( sortField,  sortDirection );
01300   switch( mTodoPrintType ) {
01301   case TodosAll:
01302     break;
01303   case TodosUnfinished:
01304     for( it = todoList.begin(); it!= todoList.end(); ++it ) {
01305       if ( !(*it)->isCompleted() )
01306         tempList.append( *it );
01307     }
01308     todoList = tempList;
01309     break;
01310   case TodosDueRange:
01311     for( it = todoList.begin(); it!= todoList.end(); ++it ) {
01312       if ( (*it)->hasDueDate() ) {
01313         if ( (*it)->dtDue().date() >= mFromDate &&
01314              (*it)->dtDue().date() <= mToDate )
01315           tempList.append( *it );
01316       } else {
01317         tempList.append( *it );
01318       }
01319     }
01320     todoList = tempList;
01321     break;
01322   }
01323 
01324   // Print to-dos
01325   int count = 0;
01326   for ( it=todoList.begin(); it!=todoList.end(); ++it ) {
01327     Todo *currEvent = *it;
01328 
01329     // Skip sub-to-dos. They will be printed recursively in drawTodo()
01330     if ( !currEvent->relatedTo() ) {
01331       count++;
01332       drawTodo( count, currEvent, p,
01333                          sortField, sortDirection,
01334                          mConnectSubTodos,
01335                          mStrikeOutCompleted, mIncludeDescription,
01336                          pospriority, possummary, posdue, poscomplete,
01337                          0, 0, mCurrentLinePos, width, height, todoList );
01338     }
01339   }
01340 
01341   drawFooter( p, footerBox );
01342   p.setFont( oldFont );
01343 }
01344 
01345 #endif
KDE Home | KDE Accessibility Home | Description of Access Keys