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