korganizer

calprintpluginbase.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 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020 
00021     As a special exception, permission is given to link this program
00022     with any edition of Qt, and distribute the resulting executable,
00023     without including the source code for Qt in the source distribution.
00024 */
00025 
00026 #include <qpainter.h>
00027 #include <qlayout.h>
00028 #include <qframe.h>
00029 #include <qlabel.h>
00030 
00031 #include <kdebug.h>
00032 #include <kconfig.h>
00033 #include <kcalendarsystem.h>
00034 #include <kwordwrap.h>
00035 
00036 #include "calprintpluginbase.h"
00037 #include "cellitem.h"
00038 
00039 #ifndef KORG_NOPRINTER
00040 
00041 inline int round(const double x)
00042 {
00043   return int(x > 0.0 ? x + 0.5 : x - 0.5);
00044 }
00045 
00046 static QString cleanStr( const QString &instr )
00047 {
00048   QString ret = instr;
00049   return ret.replace( '\n', ' ' );
00050 }
00051 
00052 /******************************************************************
00053  **              The Todo positioning structure                  **
00054  ******************************************************************/
00055 class CalPrintPluginBase::TodoParentStart
00056 {
00057   public:
00058     TodoParentStart( QRect pt = QRect(), bool page = true )
00059       : mRect( pt ), mSamePage( page ) {}
00060 
00061     QRect mRect;
00062     bool mSamePage;
00063 };
00064 
00065 
00066 /******************************************************************
00067  **                     The Print item                           **
00068  ******************************************************************/
00069 
00070 
00071 class PrintCellItem : public KOrg::CellItem
00072 {
00073   public:
00074     PrintCellItem( Event *event, const QDateTime &start, const QDateTime &end )
00075       : mEvent( event ), mStart( start), mEnd( end )
00076     {
00077     }
00078 
00079     Event *event() const { return mEvent; }
00080 
00081     QString label() const { return mEvent->summary(); }
00082 
00083     QDateTime start() const { return mStart; }
00084     QDateTime end() const { return mEnd; }
00085 
00088     bool overlaps( KOrg::CellItem *o ) const
00089     {
00090       PrintCellItem *other = static_cast<PrintCellItem *>( o );
00091 
00092 #if 0
00093       kdDebug(5850) << "PrintCellItem::overlaps() " << event()->summary()
00094                     << " <-> " << other->event()->summary() << endl;
00095       kdDebug(5850) << "  start     : " << start.toString() << endl;
00096       kdDebug(5850) << "  end       : " << end.toString() << endl;
00097       kdDebug(5850) << "  otherStart: " << otherStart.toString() << endl;
00098       kdDebug(5850) << "  otherEnd  : " << otherEnd.toString() << endl;
00099 #endif
00100 
00101       return !( other->start() >= end() || other->end() <= start() );
00102     }
00103 
00104   private:
00105     Event *mEvent;
00106     QDateTime mStart, mEnd;
00107 };
00108 
00109 
00110 
00111 
00112 /******************************************************************
00113  **                    The Print plugin                          **
00114  ******************************************************************/
00115 
00116 
00117 CalPrintPluginBase::CalPrintPluginBase() : PrintPlugin(), mUseColors( true ),
00118     mHeaderHeight( -1 ), mSubHeaderHeight( SUBHEADER_HEIGHT ), mFooterHeight( -1 ),
00119     mMargin( MARGIN_SIZE ), mPadding( PADDING_SIZE), mCalSys( 0 )
00120 {
00121 }
00122 CalPrintPluginBase::~CalPrintPluginBase()
00123 {
00124 }
00125 
00126 
00127 
00128 QWidget *CalPrintPluginBase::createConfigWidget( QWidget *w )
00129 {
00130   QFrame *wdg = new QFrame( w );
00131   QVBoxLayout *layout = new QVBoxLayout( wdg );
00132 
00133   QLabel *title = new QLabel( description(), wdg );
00134   QFont titleFont( title->font() );
00135   titleFont.setPointSize( 20 );
00136   titleFont.setBold( true );
00137   title->setFont( titleFont );
00138 
00139   layout->addWidget( title );
00140   layout->addWidget( new QLabel( info(), wdg ) );
00141   layout->addSpacing( 20 );
00142   layout->addWidget( new QLabel( i18n("This printing style does not "
00143                                       "have any configuration options."),
00144                                  wdg ) );
00145   layout->addStretch();
00146   return wdg;
00147 }
00148 
00149 void CalPrintPluginBase::doPrint( KPrinter *printer )
00150 {
00151   if ( !printer ) return;
00152   mPrinter = printer;
00153   QPainter p;
00154 
00155   mPrinter->setColorMode( mUseColors?(KPrinter::Color):(KPrinter::GrayScale) );
00156 
00157   p.begin( mPrinter );
00158   // TODO: Fix the margins!!!
00159   // the painter initially begins at 72 dpi per the Qt docs.
00160   // we want half-inch margins.
00161   int margins = margin();
00162   p.setViewport( margins, margins,
00163                  p.viewport().width() - 2*margins,
00164                  p.viewport().height() - 2*margins );
00165 //   QRect vp( p.viewport() );
00166 // vp.setRight( vp.right()*2 );
00167 // vp.setBottom( vp.bottom()*2 );
00168 //   p.setWindow( vp );
00169   int pageWidth = p.window().width();
00170   int pageHeight = p.window().height();
00171 //   int pageWidth = p.viewport().width();
00172 //   int pageHeight = p.viewport().height();
00173 
00174   print( p, pageWidth, pageHeight );
00175 
00176   p.end();
00177   mPrinter = 0;
00178 }
00179 
00180 void CalPrintPluginBase::doLoadConfig()
00181 {
00182   if ( mConfig ) {
00183     KConfigGroupSaver saver( mConfig, description() );
00184     mConfig->sync();
00185     QDateTime currDate( QDate::currentDate() );
00186     mFromDate = mConfig->readDateTimeEntry( "FromDate", &currDate ).date();
00187     mToDate = mConfig->readDateTimeEntry( "ToDate" ).date();
00188     mUseColors = mConfig->readBoolEntry( "UseColors", true );
00189     setUseColors( mUseColors );
00190     loadConfig();
00191   } else {
00192     kdDebug(5850) << "No config available in loadConfig!!!!" << endl;
00193   }
00194 }
00195 
00196 void CalPrintPluginBase::doSaveConfig()
00197 {
00198   if ( mConfig ) {
00199     KConfigGroupSaver saver( mConfig, description() );
00200     saveConfig();
00201     mConfig->writeEntry( "FromDate", QDateTime( mFromDate ) );
00202     mConfig->writeEntry( "ToDate", QDateTime( mToDate ) );
00203     mConfig->writeEntry( "UseColors", mUseColors );
00204     mConfig->sync();
00205   } else {
00206     kdDebug(5850) << "No config available in saveConfig!!!!" << endl;
00207   }
00208 }
00209 
00210 
00211 
00212 
00213 void CalPrintPluginBase::setKOrgCoreHelper( KOrg::CoreHelper*helper )
00214 {
00215   PrintPlugin::setKOrgCoreHelper( helper );
00216   if ( helper )
00217     setCalendarSystem( helper->calendarSystem() );
00218 }
00219 
00220 bool CalPrintPluginBase::useColors() const
00221 {
00222   return mUseColors;
00223 }
00224 void CalPrintPluginBase::setUseColors( bool useColors )
00225 {
00226   mUseColors = useColors;
00227 }
00228 
00229 KPrinter::Orientation CalPrintPluginBase::orientation() const
00230 {
00231   return (mPrinter)?(mPrinter->orientation()):(KPrinter::Portrait);
00232 }
00233 
00234 
00235 
00236 QTime CalPrintPluginBase::dayStart()
00237 {
00238   QTime start( 8,0,0 );
00239   if ( mCoreHelper ) start = mCoreHelper->dayStart();
00240   return start;
00241 }
00242 
00243 void CalPrintPluginBase::setCategoryColors( QPainter &p, Incidence *incidence )
00244 {
00245   QColor bgColor = categoryBgColor( incidence );
00246   if ( bgColor.isValid() )
00247     p.setBrush( bgColor );
00248   QColor tColor( textColor( bgColor ) );
00249   if ( tColor.isValid() )
00250     p.setPen( tColor );
00251 }
00252 
00253 QColor CalPrintPluginBase::categoryBgColor( Incidence *incidence )
00254 {
00255   if (mCoreHelper && incidence)
00256     return mCoreHelper->categoryColor( incidence->categories() );
00257   else
00258     return QColor();
00259 }
00260 
00261 QColor CalPrintPluginBase::textColor( const QColor &color )
00262 {
00263   return (mCoreHelper)?(mCoreHelper->textColor( color )):QColor();
00264 }
00265 
00266 bool CalPrintPluginBase::isWorkingDay( const QDate &dt )
00267 {
00268   return (mCoreHelper)?( mCoreHelper->isWorkingDay( dt ) ):true;
00269 }
00270 
00271 QString CalPrintPluginBase::holidayString( const QDate &dt )
00272 {
00273   return (mCoreHelper)?(mCoreHelper->holidayString(dt)):(QString::null);
00274 }
00275 
00276 
00277 Event *CalPrintPluginBase::holiday( const QDate &dt )
00278 {
00279   QString hstring( holidayString( dt ) );
00280   if ( !hstring.isEmpty() ) {
00281     Event*holiday=new Event();
00282     holiday->setSummary( hstring );
00283     holiday->setDtStart( dt );
00284     holiday->setDtEnd( dt );
00285     holiday->setFloats( true );
00286     holiday->setCategories( i18n("Holiday") );
00287     return holiday;
00288   }
00289   return 0;
00290 }
00291 
00292 const KCalendarSystem *CalPrintPluginBase::calendarSystem() const
00293 {
00294   return mCalSys;
00295 }
00296 void CalPrintPluginBase::setCalendarSystem( const KCalendarSystem *calsys )
00297 {
00298   mCalSys = calsys;
00299 }
00300 
00301 int CalPrintPluginBase::headerHeight() const
00302 {
00303   if ( mHeaderHeight >= 0 )
00304     return mHeaderHeight;
00305   else if ( orientation() == KPrinter::Portrait )
00306     return PORTRAIT_HEADER_HEIGHT;
00307   else
00308     return LANDSCAPE_HEADER_HEIGHT;
00309 }
00310 void CalPrintPluginBase::setHeaderHeight( const int height )
00311 {
00312   mHeaderHeight = height;
00313 }
00314 
00315 int CalPrintPluginBase::subHeaderHeight() const
00316 {
00317   return mSubHeaderHeight;
00318 }
00319 void CalPrintPluginBase::setSubHeaderHeight( const int height )
00320 {
00321   mSubHeaderHeight = height;
00322 }
00323 
00324 int CalPrintPluginBase::footerHeight() const
00325 {
00326   if ( mFooterHeight >= 0 )
00327     return mFooterHeight;
00328   else if ( orientation() == KPrinter::Portrait )
00329     return PORTRAIT_FOOTER_HEIGHT;
00330   else
00331     return LANDSCAPE_FOOTER_HEIGHT;
00332 }
00333 void CalPrintPluginBase::setFooterHeight( const int height )
00334 {
00335   mFooterHeight = height;
00336 }
00337 
00338 int CalPrintPluginBase::margin() const
00339 {
00340   return mMargin;
00341 }
00342 void CalPrintPluginBase::setMargin( const int margin )
00343 {
00344   mMargin = margin;
00345 }
00346 
00347 int CalPrintPluginBase::padding() const
00348 {
00349   return mPadding;
00350 }
00351 void CalPrintPluginBase::setPadding( const int padding )
00352 {
00353   mPadding = padding;
00354 }
00355 
00356 int CalPrintPluginBase::borderWidth() const
00357 {
00358   return mBorder;
00359 }
00360 void CalPrintPluginBase::setBorderWidth( const int borderwidth )
00361 {
00362   mBorder = borderwidth;
00363 }
00364 
00365 
00366 
00367 
00368 void CalPrintPluginBase::drawBox( QPainter &p, int linewidth, const QRect &rect )
00369 {
00370   QPen pen( p.pen() );
00371   QPen oldpen( pen );
00372   pen.setWidth( linewidth );
00373   p.setPen( pen );
00374   p.drawRect( rect );
00375   p.setPen( oldpen );
00376 }
00377 
00378 void CalPrintPluginBase::drawShadedBox( QPainter &p, int linewidth, const QBrush &brush, const QRect &rect )
00379 {
00380   QBrush oldbrush( p.brush() );
00381   p.setBrush( brush );
00382   drawBox( p, linewidth, rect );
00383   p.setBrush( oldbrush );
00384 }
00385 
00386 void CalPrintPluginBase::printEventString( QPainter &p, const QRect &box, const QString &str, int flags )
00387 {
00388   QRect newbox( box );
00389   newbox.addCoords( 3, 1, -1, -1 );
00390   p.drawText( newbox, (flags==-1)?(Qt::AlignTop | Qt::AlignJustify | Qt::BreakAnywhere):flags, str );
00391 }
00392 
00393 
00394 void CalPrintPluginBase::showEventBox( QPainter &p, int linewidth, const QRect &box,
00395                                        Incidence *incidence, const QString &str, int flags )
00396 {
00397   QPen oldpen( p.pen() );
00398   QBrush oldbrush( p.brush() );
00399   QColor bgColor( categoryBgColor( incidence ) );
00400   if ( mUseColors & bgColor.isValid() ) {
00401     p.setBrush( bgColor );
00402   } else {
00403     p.setBrush( QColor( 232, 232, 232 ) );
00404   }
00405   drawBox( p, ( linewidth > 0 ) ? linewidth : EVENT_BORDER_WIDTH, box );
00406 
00407   if ( mUseColors && bgColor.isValid() ) {
00408     p.setPen( textColor( bgColor ) );
00409   }
00410   printEventString( p, box, str, flags );
00411   p.setPen( oldpen );
00412   p.setBrush( oldbrush );
00413 }
00414 
00415 
00416 void CalPrintPluginBase::drawSubHeaderBox(QPainter &p, const QString &str, const QRect &box )
00417 {
00418   drawShadedBox( p, BOX_BORDER_WIDTH, QColor( 232, 232, 232 ), box );
00419   QFont oldfont( p.font() );
00420   p.setFont( QFont( "sans-serif", 10, QFont::Bold ) );
00421   p.drawText( box, Qt::AlignCenter | Qt::AlignVCenter, str );
00422   p.setFont( oldfont );
00423 }
00424 
00425 void CalPrintPluginBase::drawVerticalBox( QPainter &p, int linewidth, const QRect &box,
00426                                           const QString &str, int flags )
00427 {
00428   p.save();
00429   p.rotate( -90 );
00430   QRect rotatedBox( -box.top()-box.height(), box.left(), box.height(), box.width() );
00431   showEventBox( p, linewidth, rotatedBox, 0, str,
00432                 ( flags == -1 ) ? Qt::AlignLeft | Qt::AlignVCenter | Qt::SingleLine : flags );
00433 
00434   p.restore();
00435 }
00436 
00437 
00438 
00440 // Return value: If expand, bottom of the printed box, otherwise vertical end
00441 // of the printed contents inside the box.
00442 
00443 int CalPrintPluginBase::drawBoxWithCaption( QPainter &p, const QRect &allbox,
00444         const QString &caption, const QString &contents, bool sameLine, bool expand, const QFont &captionFont, const QFont &textFont )
00445 {
00446   QFont oldFont( p.font() );
00447 //   QFont captionFont( "sans-serif", 11, QFont::Bold );
00448 //   QFont textFont( "sans-serif", 11, QFont::Normal );
00449 //   QFont captionFont( "Tahoma", 11, QFont::Bold );
00450 //   QFont textFont( "Tahoma", 11, QFont::Normal );
00451 
00452 
00453   QRect box( allbox );
00454 
00455   // Bounding rectangle for caption, single-line, clip on the right
00456   QRect captionBox( box.left() + padding(), box.top() + padding(), 0, 0 );
00457   p.setFont( captionFont );
00458   captionBox = p.boundingRect( captionBox, Qt::AlignLeft | Qt::AlignTop | Qt::SingleLine, caption );
00459   p.setFont( oldFont );
00460   if ( captionBox.right() > box.right() )
00461     captionBox.setRight( box.right() );
00462   if ( expand && captionBox.bottom() + padding() > box.bottom() )
00463     box.setBottom( captionBox.bottom() + padding() );
00464 
00465   // Bounding rectangle for the contents (if any), word break, clip on the bottom
00466   QRect textBox( captionBox );
00467   if ( !contents.isEmpty() ) {
00468     if ( sameLine ) {
00469       textBox.setLeft( captionBox.right() + padding() );
00470     } else {
00471       textBox.setTop( captionBox.bottom() + padding() );
00472     }
00473     textBox.setRight( box.right() );
00474     textBox.setHeight( 0 );
00475     p.setFont( textFont );
00476     textBox = p.boundingRect( textBox, Qt::WordBreak | Qt::AlignTop | Qt::AlignLeft, contents );
00477     p.setFont( oldFont );
00478     if ( textBox.bottom() + padding() > box.bottom() ) {
00479       if ( expand ) {
00480         box.setBottom( textBox.bottom() + padding() );
00481       } else {
00482         textBox.setBottom( box.bottom() );
00483       }
00484     }
00485   }
00486 
00487   drawBox( p, BOX_BORDER_WIDTH, box );
00488   p.setFont( captionFont );
00489   p.drawText( captionBox, Qt::AlignLeft | Qt::AlignTop | Qt::SingleLine, caption );
00490   if ( !contents.isEmpty() ) {
00491     p.setFont( textFont );
00492     p.drawText( textBox, Qt::WordBreak | Qt::AlignTop | Qt::AlignLeft, contents );
00493   }
00494   p.setFont( oldFont );
00495 
00496   if ( expand ) {
00497     return box.bottom();
00498   } else {
00499     return textBox.bottom();
00500   }
00501 }
00502 
00503 
00505 
00506 int CalPrintPluginBase::drawHeader( QPainter &p, QString title,
00507     const QDate &month1, const QDate &month2, const QRect &allbox, bool expand )
00508 {
00509   // print previous month for month view, print current for to-do, day and week
00510   int smallMonthWidth = (allbox.width()/4) - 10;
00511   if (smallMonthWidth>100) smallMonthWidth=100;
00512 
00513   int right = allbox.right();
00514   if ( month1.isValid() ) right -= (20+smallMonthWidth);
00515   if ( month2.isValid() ) right -= (20+smallMonthWidth);
00516   QRect box( allbox );
00517   QRect textRect( allbox );
00518   textRect.addCoords( 5, 0, 0, 0 );
00519   textRect.setRight( right );
00520 
00521 
00522   QFont oldFont( p.font() );
00523   QFont newFont("sans-serif", (textRect.height()<60)?16:18, QFont::Bold);
00524   if ( expand ) {
00525     p.setFont( newFont );
00526     QRect boundingR = p.boundingRect( textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::WordBreak, title );
00527     p.setFont( oldFont );
00528     int h = boundingR.height();
00529     if ( h > allbox.height() ) {
00530       box.setHeight( h );
00531       textRect.setHeight( h );
00532     }
00533   }
00534 
00535   drawShadedBox( p, BOX_BORDER_WIDTH, QColor( 232, 232, 232 ), box );
00536 
00537   QRect monthbox( box.right()-10-smallMonthWidth, box.top(), smallMonthWidth, box.height() );
00538   if (month2.isValid()) {
00539     drawSmallMonth( p, QDate(month2.year(), month2.month(), 1), monthbox );
00540     monthbox.moveBy( -20 - smallMonthWidth, 0 );
00541   }
00542   if (month1.isValid()) {
00543     drawSmallMonth( p, QDate(month1.year(), month1.month(), 1), monthbox );
00544     monthbox.moveBy( -20 - smallMonthWidth, 0 );
00545   }
00546 
00547   // Set the margins
00548   p.setFont( newFont );
00549   p.drawText( textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::WordBreak, title );
00550   p.setFont( oldFont );
00551 
00552   return textRect.bottom();
00553 }
00554 
00555 
00556 int CalPrintPluginBase::drawFooter( QPainter &p, QRect &footbox )
00557 {
00558   QFont oldfont( p.font() );
00559   p.setFont( QFont( "sans-serif", 6 ) );
00560   QFontMetrics fm( p.font() );
00561   QString dateStr = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(), false );
00562   p.drawText( footbox, Qt::AlignCenter | Qt::AlignVCenter | Qt::SingleLine,
00563               i18n( "print date: formatted-datetime", "printed: %1" ).arg( dateStr ) );
00564   p.setFont( oldfont );
00565 
00566   return footbox.bottom();
00567 }
00568 
00569 void CalPrintPluginBase::drawSmallMonth(QPainter &p, const QDate &qd,
00570     const QRect &box )
00571 {
00572 
00573   int weekdayCol = weekdayColumn( qd.dayOfWeek() );
00574   int month = qd.month();
00575   QDate monthDate(QDate(qd.year(), qd.month(), 1));
00576   // correct begin of week
00577   QDate monthDate2( monthDate.addDays( -weekdayCol ) );
00578 
00579   double cellWidth = double(box.width())/double(7);
00580   int rownr = 3 + ( qd.daysInMonth() + weekdayCol - 1 ) / 7;
00581   // 3 Pixel after month name, 2 after day names, 1 after the calendar
00582   double cellHeight = (box.height() - 5) / rownr;
00583   QFont oldFont( p.font() );
00584   p.setFont(QFont("sans-serif", int(cellHeight-1), QFont::Normal));
00585 
00586   // draw the title
00587   if ( mCalSys ) {
00588     QRect titleBox( box );
00589     titleBox.setHeight( int(cellHeight+1) );
00590     p.drawText( titleBox, Qt::AlignTop | Qt::AlignHCenter, mCalSys->monthName( qd ) );
00591   }
00592 
00593   // draw days of week
00594   QRect wdayBox( box );
00595   wdayBox.setTop( int( box.top() + 3 + cellHeight ) );
00596   wdayBox.setHeight( int(2*cellHeight)-int(cellHeight) );
00597 
00598   if ( mCalSys ) {
00599     for (int col = 0; col < 7; ++col) {
00600       QString tmpStr = mCalSys->weekDayName( monthDate2 )[0].upper();
00601       wdayBox.setLeft( int(box.left() + col*cellWidth) );
00602       wdayBox.setRight( int(box.left() + (col+1)*cellWidth) );
00603       p.drawText( wdayBox, Qt::AlignCenter, tmpStr );
00604       monthDate2 = monthDate2.addDays( 1 );
00605     }
00606   }
00607 
00608   // draw separator line
00609   int calStartY = wdayBox.bottom() + 2;
00610   p.drawLine( box.left(), calStartY, box.right(), calStartY );
00611   monthDate = monthDate.addDays( -weekdayCol );
00612 
00613   for ( int row = 0; row < (rownr-2); row++ ) {
00614     for ( int col = 0; col < 7; col++ ) {
00615       if ( monthDate.month() == month ) {
00616         QRect dayRect( int( box.left() + col*cellWidth ), int( calStartY + row*cellHeight ), 0, 0 );
00617         dayRect.setRight( int( box.left() + (col+1)*cellWidth ) );
00618         dayRect.setBottom( int( calStartY + (row+1)*cellHeight ) );
00619         p.drawText( dayRect, Qt::AlignCenter, QString::number( monthDate.day() ) );
00620       }
00621       monthDate = monthDate.addDays(1);
00622     }
00623   }
00624   p.setFont( oldFont );
00625 }
00626 
00627 
00628 
00629 
00630 
00632 
00633 /*
00634  * This routine draws a header box over the main part of the calendar
00635  * containing the days of the week.
00636  */
00637 void CalPrintPluginBase::drawDaysOfWeek(QPainter &p,
00638     const QDate &fromDate, const QDate &toDate, const QRect &box )
00639 {
00640   double cellWidth = double(box.width()) / double(fromDate.daysTo( toDate )+1);
00641   QDate cellDate( fromDate );
00642   QRect dateBox( box );
00643   int i = 0;
00644 
00645   while ( cellDate <= toDate ) {
00646     dateBox.setLeft( box.left() + int(i*cellWidth) );
00647     dateBox.setRight( box.left() + int((i+1)*cellWidth) );
00648     drawDaysOfWeekBox(p, cellDate, dateBox );
00649     cellDate = cellDate.addDays(1);
00650     i++;
00651   }
00652 }
00653 
00654 
00655 void CalPrintPluginBase::drawDaysOfWeekBox(QPainter &p, const QDate &qd,
00656     const QRect &box )
00657 {
00658   drawSubHeaderBox( p, (mCalSys)?(mCalSys->weekDayName( qd )):(QString::null), box );
00659 }
00660 
00661 
00662 void CalPrintPluginBase::drawTimeLine( QPainter &p, const QTime &fromTime,
00663                                        const QTime &toTime, const QRect &box )
00664 {
00665   drawBox( p, BOX_BORDER_WIDTH, box );
00666 
00667   int totalsecs = fromTime.secsTo( toTime );
00668   float minlen = (float)box.height() * 60. / (float)totalsecs;
00669   float cellHeight = ( 60. * (float)minlen );
00670   float currY = box.top();
00671   // TODO: Don't use half of the width, but less, for the minutes!
00672   int xcenter = box.left() + box.width() / 2;
00673 
00674   QTime curTime( fromTime );
00675   QTime endTime( toTime );
00676   if ( fromTime.minute() > 30 ) {
00677     curTime = QTime( fromTime.hour()+1, 0, 0 );
00678   } else if ( fromTime.minute() > 0 ) {
00679     curTime = QTime( fromTime.hour(), 30, 0 );
00680     float yy = currY + minlen * (float)fromTime.secsTo( curTime ) / 60.;
00681     p.drawLine( xcenter, (int)yy, box.right(), (int)yy );
00682     curTime = QTime( fromTime.hour() + 1, 0, 0 );
00683   }
00684   currY += ( float( fromTime.secsTo( curTime ) * minlen ) / 60. );
00685 
00686   while ( curTime < endTime ) {
00687     p.drawLine( box.left(), (int)currY, box.right(), (int)currY );
00688     int newY = (int)( currY + cellHeight / 2. );
00689     QString numStr;
00690     if ( newY < box.bottom() ) {
00691       QFont oldFont( p.font() );
00692       // draw the time:
00693       if ( !KGlobal::locale()->use12Clock() ) {
00694         p.drawLine( xcenter, (int)newY, box.right(), (int)newY );
00695         numStr.setNum( curTime.hour() );
00696         if  ( cellHeight > 30 ) {
00697           p.setFont( QFont( "sans-serif", 14, QFont::Bold ) );
00698         } else {
00699           p.setFont( QFont( "sans-serif", 12, QFont::Bold ) );
00700         }
00701         p.drawText( box.left() + 4, (int)currY + 2, box.width() / 2 - 2, (int)cellHeight,
00702                     Qt::AlignTop | Qt::AlignRight, numStr );
00703         p.setFont( QFont ( "helvetica", 10, QFont::Normal ) );
00704         p.drawText( xcenter + 4, (int)currY + 2, box.width() / 2 + 2, (int)(cellHeight / 2 ) - 3,
00705                     Qt::AlignTop | Qt::AlignLeft, "00" );
00706       } else {
00707         p.drawLine( box.left(), (int)newY, box.right(), (int)newY );
00708         QTime time( curTime.hour(), 0 );
00709         numStr = KGlobal::locale()->formatTime( time );
00710         if ( box.width() < 60 ) {
00711           p.setFont( QFont( "sans-serif", 7, QFont::Bold ) ); // for weekprint
00712         } else {
00713           p.setFont( QFont( "sans-serif", 12, QFont::Bold ) ); // for dayprint
00714         }
00715         p.drawText( box.left() + 2, (int)currY + 2, box.width() - 4, (int)cellHeight / 2 - 3,
00716                     Qt::AlignTop|Qt::AlignLeft, numStr );
00717       }
00718       currY += cellHeight;
00719       p.setFont( oldFont );
00720     } // enough space for half-hour line and time
00721     if ( curTime.secsTo( endTime ) > 3600 ) {
00722       curTime = curTime.addSecs( 3600 );
00723     } else {
00724       curTime = endTime;
00725     }
00726   } // currTime<endTime
00727 }
00728 
00735 int CalPrintPluginBase::drawAllDayBox(QPainter &p, Event::List &eventList,
00736     const QDate &qd, bool expandable, const QRect &box )
00737 {
00738   Event::List::Iterator it, itold;
00739 
00740   int offset=box.top();
00741 
00742   QString multiDayStr;
00743 
00744   Event*hd = holiday( qd );
00745   if ( hd ) eventList.prepend( hd );
00746 
00747   it = eventList.begin();
00748   Event *currEvent = 0;
00749   // First, print all floating events
00750   while( it!=eventList.end() ) {
00751     currEvent=*it;
00752     itold=it;
00753     ++it;
00754     if ( currEvent && currEvent->doesFloat() ) {
00755       // set the colors according to the categories
00756       if ( expandable ) {
00757         QRect eventBox( box );
00758         eventBox.setTop( offset );
00759         showEventBox( p, EVENT_BORDER_WIDTH, eventBox, currEvent, currEvent->summary() );
00760         offset += box.height();
00761       } else {
00762         if ( !multiDayStr.isEmpty() ) multiDayStr += ", ";
00763         multiDayStr += currEvent->summary();
00764       }
00765       eventList.remove( itold );
00766     }
00767   }
00768   if ( hd ) delete hd;
00769 
00770   int ret = box.height();
00771   QRect eventBox( box );
00772   if (!expandable) {
00773     if (!multiDayStr.isEmpty()) {
00774       drawShadedBox( p, BOX_BORDER_WIDTH, QColor( 128, 128, 128 ), eventBox );
00775       printEventString( p, eventBox, multiDayStr );
00776     } else {
00777       drawBox( p, BOX_BORDER_WIDTH, eventBox );
00778     }
00779   } else {
00780     ret = offset - box.top();
00781     eventBox.setBottom( ret );
00782     drawBox( p, BOX_BORDER_WIDTH, eventBox );
00783   }
00784   return ret;
00785 }
00786 
00787 
00788 void CalPrintPluginBase::drawAgendaDayBox( QPainter &p, Event::List &events,
00789                                      const QDate &qd, bool expandable,
00790                                      QTime &fromTime, QTime &toTime,
00791                                      const QRect &oldbox )
00792 {
00793   if ( !isWorkingDay( qd ) ) {
00794     drawShadedBox( p, BOX_BORDER_WIDTH, QColor( 232, 232, 232 ), oldbox );
00795   } else {
00796     drawBox( p, BOX_BORDER_WIDTH, oldbox );
00797   }
00798   QRect box( oldbox );
00799   // Account for the border with and cut away that margin from the interior
00800 //   box.setRight( box.right()-BOX_BORDER_WIDTH );
00801 
00802   Event *event;
00803 
00804   if ( expandable ) {
00805     // Adapt start/end times to include complete events
00806     Event::List::ConstIterator it;
00807     for ( it = events.begin(); it != events.end(); ++it ) {
00808       event = *it;
00809       if ( event->dtStart().time() < fromTime )
00810         fromTime = event->dtStart().time();
00811       if ( event->dtEnd().time() > toTime )
00812         toTime = event->dtEnd().time();
00813     }
00814   }
00815 
00816   // Show at least one hour
00817 //   if ( fromTime.secsTo( toTime ) < 3600 ) {
00818 //     fromTime = QTime( fromTime.hour(), 0, 0 );
00819 //     toTime = fromTime.addSecs( 3600 );
00820 //   }
00821 
00822   // calculate the height of a cell and of a minute
00823   int totalsecs = fromTime.secsTo( toTime );
00824   float minlen = box.height() * 60. / totalsecs;
00825   float cellHeight = 60. * minlen;
00826   float currY = box.top();
00827 
00828   // print grid:
00829   QTime curTime( QTime( fromTime.hour(), 0, 0 ) );
00830   currY += fromTime.secsTo( curTime ) * minlen / 60;
00831 
00832   while ( curTime < toTime && curTime.isValid() ) {
00833     if ( currY > box.top() )
00834       p.drawLine( box.left(), int( currY ), box.right(), int( currY ) );
00835     currY += cellHeight / 2;
00836     if ( ( currY > box.top() ) && ( currY < box.bottom() ) ) {
00837       // enough space for half-hour line
00838       QPen oldPen( p.pen() );
00839       p.setPen( QColor( 192, 192, 192 ) );
00840       p.drawLine( box.left(), int( currY ), box.right(), int( currY ) );
00841       p.setPen( oldPen );
00842     }
00843     if ( curTime.secsTo( toTime ) > 3600 )
00844       curTime = curTime.addSecs( 3600 );
00845     else curTime = toTime;
00846     currY += cellHeight / 2;
00847   }
00848 
00849   QDateTime startPrintDate = QDateTime( qd, fromTime );
00850   QDateTime endPrintDate = QDateTime( qd, toTime );
00851 
00852   // Calculate horizontal positions and widths of events taking into account
00853   // overlapping events
00854 
00855   QPtrList<KOrg::CellItem> cells;
00856   cells.setAutoDelete( true );
00857 
00858   Event::List::ConstIterator itEvents;
00859   for( itEvents = events.begin(); itEvents != events.end(); ++itEvents ) {
00860     QValueList<QDateTime> times = (*itEvents)->startDateTimesForDate( qd );
00861     for ( QValueList<QDateTime>::ConstIterator it = times.begin();
00862           it != times.end(); ++it ) {
00863       cells.append( new PrintCellItem( *itEvents, (*it), (*itEvents)->endDateForStart( *it ) ) );
00864     }
00865   }
00866 
00867   QPtrListIterator<KOrg::CellItem> it1( cells );
00868   for( it1.toFirst(); it1.current(); ++it1 ) {
00869     KOrg::CellItem *placeItem = it1.current();
00870     KOrg::CellItem::placeItem( cells, placeItem );
00871   }
00872 
00873 //   p.setFont( QFont( "sans-serif", 10 ) );
00874 
00875   for( it1.toFirst(); it1.current(); ++it1 ) {
00876     PrintCellItem *placeItem = static_cast<PrintCellItem *>( it1.current() );
00877     drawAgendaItem( placeItem, p, startPrintDate, endPrintDate, minlen, box );
00878   }
00879 //   p.setFont( oldFont );
00880 }
00881 
00882 
00883 
00884 void CalPrintPluginBase::drawAgendaItem( PrintCellItem *item, QPainter &p,
00885                                    const QDateTime &startPrintDate,
00886                                    const QDateTime &endPrintDate,
00887                                    float minlen, const QRect &box )
00888 {
00889   Event *event = item->event();
00890 
00891   // start/end of print area for event
00892   QDateTime startTime = item->start();
00893   QDateTime endTime = item->end();
00894   if ( ( startTime < endPrintDate && endTime > startPrintDate ) ||
00895        ( endTime > startPrintDate && startTime < endPrintDate ) ) {
00896     if ( startTime < startPrintDate ) startTime = startPrintDate;
00897     if ( endTime > endPrintDate ) endTime = endPrintDate;
00898     int currentWidth = box.width() / item->subCells();
00899     int currentX = box.left() + item->subCell() * currentWidth;
00900     int currentYPos = int( box.top() + startPrintDate.secsTo( startTime ) *
00901                            minlen / 60. );
00902     int currentHeight = int( box.top() + startPrintDate.secsTo( endTime ) * minlen / 60. ) - currentYPos;
00903 
00904     QRect eventBox( currentX, currentYPos, currentWidth, currentHeight );
00905     QString str;
00906     if ( event->location().isEmpty() ) {
00907       str = i18n( "starttime - endtime summary",
00908                   "%1-%2 %3" ).
00909             arg( KGlobal::locale()->formatTime( startTime.time() ) ).
00910             arg( KGlobal::locale()->formatTime( endTime.time() ) ).
00911             arg( cleanStr( event->summary() ) );
00912     } else {
00913       str = i18n( "starttime - endtime summary, location",
00914                   "%1-%2 %3, %4" ).
00915             arg( KGlobal::locale()->formatTime( startTime.time() ) ).
00916             arg( KGlobal::locale()->formatTime( endTime.time() ) ).
00917             arg( cleanStr( event->summary() ) ).
00918             arg( cleanStr( event->location() ) );
00919     }
00920     showEventBox( p, EVENT_BORDER_WIDTH, eventBox, event, str );
00921   }
00922 }
00923 
00924 //TODO TODO TODO
00925 void CalPrintPluginBase::drawDayBox( QPainter &p, const QDate &qd,
00926     const QRect &box,
00927     bool fullDate, bool printRecurDaily, bool printRecurWeekly )
00928 {
00929   QString dayNumStr;
00930   const KLocale*local = KGlobal::locale();
00931 
00932   // This has to be localized
00933   if ( fullDate && mCalSys ) {
00934 
00935     dayNumStr = i18n("weekday month date", "%1 %2 %3")
00936         .arg( mCalSys->weekDayName( qd ) )
00937         .arg( mCalSys->monthName( qd ) )
00938         .arg( qd.day() );
00939 //    dayNumStr = local->formatDate(qd);
00940   } else {
00941     dayNumStr = QString::number( qd.day() );
00942   }
00943 
00944   QRect subHeaderBox( box );
00945   subHeaderBox.setHeight( mSubHeaderHeight );
00946   drawShadedBox( p, BOX_BORDER_WIDTH, p.backgroundColor(), box );
00947   drawShadedBox( p, 0, QColor( 232, 232, 232 ), subHeaderBox );
00948   drawBox( p, BOX_BORDER_WIDTH, box );
00949   QString hstring( holidayString( qd ) );
00950   QFont oldFont( p.font() );
00951 
00952   QRect headerTextBox( subHeaderBox );
00953   headerTextBox.setLeft( subHeaderBox.left()+5 );
00954   headerTextBox.setRight( subHeaderBox.right()-5 );
00955   if (!hstring.isEmpty()) {
00956     p.setFont( QFont( "sans-serif", 8, QFont::Bold, true ) );
00957 
00958     p.drawText( headerTextBox, Qt::AlignLeft | Qt::AlignVCenter, hstring );
00959   }
00960   p.setFont(QFont("sans-serif", 10, QFont::Bold));
00961   p.drawText( headerTextBox, Qt::AlignRight | Qt::AlignVCenter, dayNumStr);
00962 
00963   Event::List eventList = mCalendar->events( qd,
00964                                              EventSortStartDate,
00965                                              SortDirectionAscending );
00966   QString timeText;
00967   p.setFont( QFont( "sans-serif", 8 ) );
00968 
00969   int textY=mSubHeaderHeight+3; // gives the relative y-coord of the next printed entry
00970   Event::List::ConstIterator it;
00971 
00972   unsigned int visibleEventsCounter = 0;
00973   for( it = eventList.begin(); it != eventList.end() && textY<box.height(); ++it ) {
00974     Event *currEvent = *it;
00975     if ( ( !printRecurDaily  && currEvent->recurrenceType() == Recurrence::rDaily  ) ||
00976          ( !printRecurWeekly && currEvent->recurrenceType() == Recurrence::rWeekly ) ) {
00977       continue;
00978     }
00979     if ( currEvent->doesFloat() || currEvent->isMultiDay() ) {
00980       timeText = "";
00981     } else {
00982       timeText = local->formatTime( currEvent->dtStart().time() );
00983     }
00984 
00985     QString str;
00986     if ( !currEvent->location().isEmpty() ) {
00987       str = i18n( "summary, location", "%1, %2" ).
00988             arg( currEvent->summary() ).arg( currEvent->location() );
00989     } else {
00990       str = currEvent->summary();
00991     }
00992     drawIncidence( p, box, timeText, str, textY );
00993     visibleEventsCounter++;
00994 
00995     if ( textY >= box.height() ) {
00996       const QChar downArrow( 0x21e3 );
00997       const unsigned int invisibleIncidences = ((eventList.count() - visibleEventsCounter) + mCalendar->todos( qd ).count());
00998       const QString warningMsg = QString( "%1 (%2)" ).arg( downArrow ).arg( invisibleIncidences );
00999 
01000       QFontMetrics fm( p.font() );
01001       QRect msgRect = fm.boundingRect( warningMsg );
01002       msgRect.setRect( box.right() - msgRect.width() - 2, box.bottom() - msgRect.height() - 2, msgRect.width(), msgRect.height() );
01003 
01004       p.save();
01005       p.setPen( Qt::red );
01006       p.drawText( msgRect, Qt::AlignLeft, warningMsg );
01007       p.restore();
01008     }
01009   }
01010 
01011   if ( textY < box.height() ) {
01012     Todo::List todos = mCalendar->todos( qd );
01013     Todo::List::ConstIterator it2;
01014     for ( it2 = todos.begin(); it2 != todos.end() && textY <box.height(); ++it2 ) {
01015       Todo *todo = *it2;
01016       if ( ( !printRecurDaily  && todo->recurrenceType() == Recurrence::rDaily  ) ||
01017            ( !printRecurWeekly && todo->recurrenceType() == Recurrence::rWeekly ) ) {
01018         continue;
01019       }
01020       if ( todo->hasStartDate() && !todo->doesFloat() ) {
01021         timeText = KGlobal::locale()->formatTime( todo->dtStart().time() ) + " ";
01022       } else {
01023         timeText = "";
01024       }
01025       QString summaryStr;
01026       if ( !todo->location().isEmpty() ) {
01027         summaryStr = i18n( "summary, location", "%1, %2" ).
01028                      arg( todo->summary() ).arg( todo->location() );
01029       } else {
01030         summaryStr = todo->summary();
01031       }
01032       QString str;
01033       if ( todo->hasDueDate() ) {
01034         if ( !todo->doesFloat() ) {
01035           str = i18n( "%1 (Due: %2)" ).
01036                 arg( summaryStr ).
01037                 arg( KGlobal::locale()->formatDateTime( todo->dtDue() ) );
01038         } else {
01039           str = i18n( "%1 (Due: %2)" ).
01040                 arg( summaryStr ).
01041                 arg( KGlobal::locale()->formatDate( todo->dtDue().date(), true ) );
01042         }
01043       } else {
01044         str = summaryStr;
01045       }
01046       drawIncidence( p, box, timeText, i18n("To-do: %1").arg( str ), textY );
01047     }
01048   }
01049 
01050   p.setFont( oldFont );
01051 }
01052 
01053 // TODO TODO TODO
01054 void CalPrintPluginBase::drawIncidence( QPainter &p, const QRect &dayBox, const QString &time, const QString &summary, int &textY )
01055 {
01056   kdDebug(5850) << "summary = " << summary << endl;
01057 
01058   int flags = Qt::AlignLeft;
01059   QFontMetrics fm = p.fontMetrics();
01060   QRect timeBound = p.boundingRect( dayBox.x() + 5, dayBox.y() + textY,
01061                                     dayBox.width() - 10, fm.lineSpacing(),
01062                                     flags, time );
01063   p.drawText( timeBound, flags, time );
01064 
01065   int summaryWidth = time.isEmpty() ? 0 : timeBound.width() + 4;
01066   QRect summaryBound = QRect( dayBox.x() + 5 + summaryWidth, dayBox.y() + textY,
01067                               dayBox.width() - summaryWidth -5, dayBox.height() );
01068 
01069   KWordWrap *ww = KWordWrap::formatText( fm, summaryBound, flags, summary );
01070   ww->drawText( &p, dayBox.x() + 5 + summaryWidth, dayBox.y() + textY, flags );
01071 
01072   textY += ww->boundingRect().height();
01073 
01074   delete ww;
01075 }
01076 
01077 
01079 
01080 void CalPrintPluginBase::drawWeek(QPainter &p, const QDate &qd, const QRect &box )
01081 {
01082   QDate weekDate = qd;
01083   bool portrait = ( box.height() > box.width() );
01084   int cellWidth, cellHeight;
01085   int vcells;
01086   if (portrait) {
01087     cellWidth = box.width()/2;
01088     vcells=3;
01089   } else {
01090     cellWidth = box.width()/6;
01091     vcells=1;
01092   }
01093   cellHeight = box.height()/vcells;
01094 
01095   // correct begin of week
01096   int weekdayCol = weekdayColumn( qd.dayOfWeek() );
01097   weekDate = qd.addDays( -weekdayCol );
01098 
01099   for (int i = 0; i < 7; i++, weekDate = weekDate.addDays(1)) {
01100     // Saturday and sunday share a cell, so we have to special-case sunday
01101     int hpos = ((i<6)?i:(i-1)) / vcells;
01102     int vpos = ((i<6)?i:(i-1)) % vcells;
01103     QRect dayBox( box.left()+cellWidth*hpos, box.top()+cellHeight*vpos + ((i==6)?(cellHeight/2):0),
01104         cellWidth, (i<5)?(cellHeight):(cellHeight/2) );
01105     drawDayBox(p, weekDate, dayBox, true);
01106   } // for i through all weekdays
01107 }
01108 
01109 
01110 void CalPrintPluginBase::drawTimeTable(QPainter &p,
01111     const QDate &fromDate, const QDate &toDate,
01112     QTime &fromTime, QTime &toTime,
01113     const QRect &box)
01114 {
01115   // timeline is 1 hour:
01116   int alldayHeight = (int)( 3600.*box.height()/(fromTime.secsTo(toTime)+3600.) );
01117   int timelineWidth = TIMELINE_WIDTH;
01118 
01119   QRect dowBox( box );
01120   dowBox.setLeft( box.left() + timelineWidth );
01121   dowBox.setHeight( mSubHeaderHeight );
01122   drawDaysOfWeek( p, fromDate, toDate, dowBox );
01123 
01124   QRect tlBox( box );
01125   tlBox.setWidth( timelineWidth );
01126   tlBox.setTop( dowBox.bottom() + BOX_BORDER_WIDTH + alldayHeight );
01127   drawTimeLine( p, fromTime, toTime, tlBox );
01128 
01129   // draw each day
01130   QDate curDate(fromDate);
01131   int i=0;
01132   double cellWidth = double(dowBox.width()) / double(fromDate.daysTo(toDate)+1);
01133   while (curDate<=toDate) {
01134     QRect allDayBox( dowBox.left()+int(i*cellWidth), dowBox.bottom() + BOX_BORDER_WIDTH,
01135                      int((i+1)*cellWidth)-int(i*cellWidth), alldayHeight );
01136     QRect dayBox( allDayBox );
01137     dayBox.setTop( tlBox.top() );
01138     dayBox.setBottom( box.bottom() );
01139     Event::List eventList = mCalendar->events(curDate,
01140                                               EventSortStartDate,
01141                                               SortDirectionAscending);
01142     alldayHeight = drawAllDayBox( p, eventList, curDate, false, allDayBox );
01143     drawAgendaDayBox( p, eventList, curDate, false, fromTime, toTime, dayBox );
01144     i++;
01145     curDate=curDate.addDays(1);
01146   }
01147 
01148 }
01149 
01150 
01152 
01153 class MonthEventStruct
01154 {
01155   public:
01156     MonthEventStruct() : event(0) {}
01157     MonthEventStruct( const QDateTime &s, const QDateTime &e, Event *ev)
01158     {
01159       event = ev;
01160       start = s;
01161       end = e;
01162       if ( event->doesFloat() ) {
01163         start = QDateTime( start.date(), QTime(0,0,0) );
01164         end = QDateTime( end.date().addDays(1), QTime(0,0,0) ).addSecs(-1);
01165       }
01166     }
01167     bool operator<(const MonthEventStruct &mes) { return start < mes.start; }
01168     QDateTime start;
01169     QDateTime end;
01170     Event *event;
01171 };
01172 
01173 void CalPrintPluginBase::drawMonth( QPainter &p, const QDate &dt, const QRect &box, int maxdays, int subDailyFlags, int holidaysFlags )
01174 {
01175   const KCalendarSystem *calsys = calendarSystem();
01176   QRect subheaderBox( box );
01177   subheaderBox.setHeight( subHeaderHeight() );
01178   QRect borderBox( box );
01179   borderBox.setTop( subheaderBox.bottom()+1 );
01180   drawSubHeaderBox( p, calsys->monthName(dt), subheaderBox );
01181   // correct for half the border width
01182   int correction = (BOX_BORDER_WIDTH/*-1*/)/2;
01183   QRect daysBox( borderBox );
01184   daysBox.addCoords( correction, correction, -correction, -correction );
01185 
01186   int daysinmonth = calsys->daysInMonth( dt );
01187   if ( maxdays <= 0 ) maxdays = daysinmonth;
01188 
01189   int d;
01190   float dayheight = float(daysBox.height()) / float( maxdays );
01191 
01192   QColor holidayColor( 240, 240, 240 );
01193   QColor workdayColor( 255, 255, 255 );
01194   int dayNrWidth = p.fontMetrics().width( "99" );
01195 
01196   // Fill the remaining space (if a month has less days than others) with a crossed-out pattern
01197   if ( daysinmonth<maxdays ) {
01198     QRect dayBox( box.left(), daysBox.top() + round(dayheight*daysinmonth), box.width(), 0 );
01199     dayBox.setBottom( daysBox.bottom() );
01200     p.fillRect( dayBox, Qt::DiagCrossPattern );
01201   }
01202   // Backgrounded boxes for each day, plus day numbers
01203   QBrush oldbrush( p.brush() );
01204   for ( d = 0; d < daysinmonth; ++d ) {
01205     QDate day;
01206     calsys->setYMD( day, dt.year(), dt.month(), d+1 );
01207     QRect dayBox( daysBox.left()/*+rand()%50*/, daysBox.top() + round(dayheight*d), daysBox.width()/*-rand()%50*/, 0 );
01208     // FIXME: When using a border width of 0 for event boxes, don't let the rectangles overlap, i.e. subtract 1 from the top or bottom!
01209     dayBox.setBottom( daysBox.top()+round(dayheight*(d+1)) - 1 );
01210 
01211     p.setBrush( isWorkingDay( day )?workdayColor:holidayColor );
01212     p.drawRect( dayBox );
01213     QRect dateBox( dayBox );
01214     dateBox.setWidth( dayNrWidth+3 );
01215     p.drawText( dateBox, Qt::AlignRight | Qt::AlignVCenter | Qt::SingleLine,
01216                 QString::number(d+1) );
01217   }
01218   p.setBrush( oldbrush );
01219   int xstartcont = box.left() + dayNrWidth + 5;
01220 
01221   QDate start, end;
01222   calsys->setYMD( start, dt.year(), dt.month(), 1 );
01223   end = calsys->addMonths( start, 1 );
01224   end = calsys->addDays( end, -1 );
01225 
01226   Event::List events = mCalendar->events( start, end );
01227   QMap<int, QStringList> textEvents;
01228   QPtrList<KOrg::CellItem> timeboxItems;
01229   timeboxItems.setAutoDelete( true );
01230 
01231 
01232   // 1) For multi-day events, show boxes spanning several cells, use CellItem
01233   //    print the summary vertically
01234   // 2) For sub-day events, print the concated summaries into the remaining
01235   //    space of the box (optional, depending on the given flags)
01236   // 3) Draw some kind of timeline showing free and busy times
01237 
01238   // Holidays
01239   Event::List holidays;
01240   holidays.setAutoDelete( true );
01241   for ( QDate d(start); d <= end; d = d.addDays(1) ) {
01242     Event *e = holiday( d );
01243     if ( e ) {
01244       holidays.append( e );
01245       if ( holidaysFlags & TimeBoxes ) {
01246         timeboxItems.append( new PrintCellItem( e, QDateTime(d, QTime(0,0,0) ),
01247             QDateTime( d.addDays(1), QTime(0,0,0) ) ) );
01248       }
01249       if ( holidaysFlags & Text ) {
01250         textEvents[ d.day() ] << e->summary();
01251       }
01252     }
01253   }
01254 
01255   QValueList<MonthEventStruct> monthentries;
01256 
01257   for ( Event::List::ConstIterator evit = events.begin();
01258         evit != events.end(); ++evit ) {
01259     Event *e = (*evit);
01260     if (!e) continue;
01261     if ( e->doesRecur() ) {
01262       if ( e->recursOn( start ) ) {
01263         // This occurrence has possibly started before the beginning of the
01264         // month, so obtain the start date before the beginning of the month
01265         QValueList<QDateTime> starttimes = e->startDateTimesForDate( start );
01266         QValueList<QDateTime>::ConstIterator it = starttimes.begin();
01267         for ( ; it != starttimes.end(); ++it ) {
01268           monthentries.append( MonthEventStruct( *it, e->endDateForStart( *it ), e ) );
01269         }
01270       }
01271       // Loop through all remaining days of the month and check if the event
01272       // begins on that day (don't use Event::recursOn, as that will
01273       // also return events that have started earlier. These start dates
01274       // however, have already been treated!
01275       Recurrence *recur = e->recurrence();
01276       QDate d1( start.addDays(1) );
01277       while ( d1 <= end ) {
01278         if ( recur->recursOn(d1) ) {
01279           TimeList times( recur->recurTimesOn( d1 ) );
01280           for ( TimeList::ConstIterator it = times.begin();
01281                 it != times.end(); ++it ) {
01282             QDateTime d1start( d1, *it );
01283             monthentries.append( MonthEventStruct( d1start, e->endDateForStart( d1start ), e ) );
01284           }
01285         }
01286         d1 = d1.addDays(1);
01287       }
01288     } else {
01289       monthentries.append( MonthEventStruct( e->dtStart(), e->dtEnd(), e ) );
01290     }
01291   }
01292   qHeapSort( monthentries );
01293 
01294   QValueList<MonthEventStruct>::ConstIterator mit = monthentries.begin();
01295   QDateTime endofmonth( end, QTime(0,0,0) );
01296   endofmonth = endofmonth.addDays(1);
01297   for ( ; mit != monthentries.end(); ++mit ) {
01298     if ( (*mit).start.date() == (*mit).end.date() ) {
01299       // Show also single-day events as time line boxes
01300       if ( subDailyFlags & TimeBoxes ) {
01301         timeboxItems.append( new PrintCellItem( (*mit).event, (*mit).start, (*mit).end ) );
01302       }
01303       // Show as text in the box
01304       if ( subDailyFlags & Text ) {
01305         textEvents[ (*mit).start.date().day() ] << (*mit).event->summary();
01306       }
01307     } else {
01308       // Multi-day events are always shown as time line boxes
01309       QDateTime thisstart( (*mit).start );
01310       QDateTime thisend( (*mit).end );
01311       if ( thisstart.date()<start ) thisstart = start;
01312       if ( thisend>endofmonth ) thisend = endofmonth;
01313       timeboxItems.append( new PrintCellItem( (*mit).event, thisstart, thisend ) );
01314     }
01315   }
01316 
01317   // For Multi-day events, line them up nicely so that the boxes don't overlap
01318   QPtrListIterator<KOrg::CellItem> it1( timeboxItems );
01319   for( it1.toFirst(); it1.current(); ++it1 ) {
01320     KOrg::CellItem *placeItem = it1.current();
01321     KOrg::CellItem::placeItem( timeboxItems, placeItem );
01322   }
01323   QDateTime starttime( start, QTime( 0, 0, 0 ) );
01324   int newxstartcont = xstartcont;
01325 
01326   QFont oldfont( p.font() );
01327   p.setFont( QFont( "sans-serif", 7 ) );
01328   for( it1.toFirst(); it1.current(); ++it1 ) {
01329     PrintCellItem *placeItem = static_cast<PrintCellItem *>( it1.current() );
01330     int minsToStart = starttime.secsTo( placeItem->start() )/60;
01331     int minsToEnd = starttime.secsTo( placeItem->end() )/60;
01332 
01333     QRect eventBox( xstartcont + placeItem->subCell()*17,
01334            daysBox.top() + round( double( minsToStart*daysBox.height()) / double(maxdays*24*60) ),
01335            14, 0 );
01336     eventBox.setBottom( daysBox.top() + round( double( minsToEnd*daysBox.height()) / double(maxdays*24*60) ) );
01337     drawVerticalBox( p, 0, eventBox, placeItem->event()->summary() );
01338     newxstartcont = QMAX( newxstartcont, eventBox.right() );
01339   }
01340   xstartcont = newxstartcont;
01341 
01342   // For Single-day events, simply print their summaries into the remaining
01343   // space of the day's cell
01344   for ( int d=0; d<daysinmonth; ++d ) {
01345     QStringList dayEvents( textEvents[d+1] );
01346     QString txt = dayEvents.join(", ");
01347     QRect dayBox( xstartcont, daysBox.top()+round(dayheight*d), 0, 0 );
01348     dayBox.setRight( box.right() );
01349     dayBox.setBottom( daysBox.top()+round(dayheight*(d+1)) );
01350     printEventString(p, dayBox, txt, Qt::AlignTop | Qt::AlignLeft | Qt::BreakAnywhere );
01351   }
01352   p.setFont( oldfont );
01353 //   p.setBrush( Qt::NoBrush );
01354   drawBox( p, BOX_BORDER_WIDTH, borderBox );
01355   p.restore();
01356 }
01357 
01359 
01360 void CalPrintPluginBase::drawMonthTable(QPainter &p, const QDate &qd, bool weeknumbers,
01361                                bool recurDaily, bool recurWeekly,
01362                                const QRect &box)
01363 {
01364   int yoffset = mSubHeaderHeight;
01365   int xoffset = 0;
01366   QDate monthDate(QDate(qd.year(), qd.month(), 1));
01367   QDate monthFirst(monthDate);
01368   QDate monthLast(monthDate.addMonths(1).addDays(-1));
01369 
01370 
01371   int weekdayCol = weekdayColumn( monthDate.dayOfWeek() );
01372   monthDate = monthDate.addDays(-weekdayCol);
01373 
01374   if (weeknumbers) {
01375     xoffset += 14;
01376   }
01377 
01378   int rows=(weekdayCol + qd.daysInMonth() - 1)/7 +1;
01379   double cellHeight = ( box.height() - yoffset ) / (1.*rows);
01380   double cellWidth = ( box.width() - xoffset ) / 7.;
01381 
01382   // Precalculate the grid...
01383   // rows is at most 6, so using 8 entries in the array is fine, too!
01384   int coledges[8], rowedges[8];
01385   for ( int i = 0; i <= 7; i++ ) {
01386     rowedges[i] = int( box.top() + yoffset + i*cellHeight );
01387     coledges[i] = int( box.left() + xoffset + i*cellWidth );
01388   }
01389 
01390   if (weeknumbers) {
01391     QFont oldFont(p.font());
01392     QFont newFont(p.font());
01393     newFont.setPointSize(6);
01394     p.setFont(newFont);
01395     QDate weekDate(monthDate);
01396     for (int row = 0; row<rows; ++row ) {
01397       int calWeek = weekDate.weekNumber();
01398       QRect rc( box.left(), rowedges[row], coledges[0] - 3 - box.left(), rowedges[row+1]-rowedges[row] );
01399       p.drawText( rc, Qt::AlignRight | Qt::AlignVCenter, QString::number( calWeek ) );
01400       weekDate = weekDate.addDays( 7 );
01401     }
01402     p.setFont( oldFont );
01403   }
01404 
01405   QRect daysOfWeekBox( box );
01406   daysOfWeekBox.setHeight( mSubHeaderHeight );
01407   daysOfWeekBox.setLeft( box.left()+xoffset );
01408   drawDaysOfWeek( p, monthDate, monthDate.addDays( 6 ), daysOfWeekBox );
01409 
01410   QColor back = p.backgroundColor();
01411   bool darkbg = false;
01412   for ( int row = 0; row < rows; ++row ) {
01413     for ( int col = 0; col < 7; ++col ) {
01414       // show days from previous/next month with a grayed background
01415       if ( (monthDate < monthFirst) || (monthDate > monthLast) ) {
01416         p.setBackgroundColor( back.dark( 120 ) );
01417         darkbg = true;
01418       }
01419       QRect dayBox( coledges[col], rowedges[row], coledges[col+1]-coledges[col], rowedges[row+1]-rowedges[row] );
01420       drawDayBox(p, monthDate, dayBox, false, recurDaily, recurWeekly );
01421       if ( darkbg ) {
01422         p.setBackgroundColor( back );
01423         darkbg = false;
01424       }
01425       monthDate = monthDate.addDays(1);
01426     }
01427   }
01428 }
01429 
01430 
01432 
01433 void CalPrintPluginBase::drawTodo( int &count, Todo *todo, QPainter &p,
01434                                TodoSortField sortField, SortDirection sortDir,
01435                                bool connectSubTodos, bool strikeoutCompleted,
01436                                bool desc, int posPriority, int posSummary,
01437                                int posDueDt, int posPercentComplete,
01438                                int level, int x, int &y, int width,
01439                                int pageHeight, const Todo::List &todoList,
01440                                TodoParentStart *r )
01441 {
01442   QString outStr;
01443   const KLocale *local = KGlobal::locale();
01444   QRect rect;
01445   TodoParentStart startpt;
01446 
01447   // This list keeps all starting points of the parent to-dos so the connection
01448   // lines of the tree can easily be drawn (needed if a new page is started)
01449   static QPtrList<TodoParentStart> startPoints;
01450   if ( level < 1 ) {
01451     startPoints.clear();
01452   }
01453 
01454   // Compute the right hand side of the to-do box
01455   int rhs = posPercentComplete;
01456   if ( rhs < 0 ) rhs = posDueDt; //not printing percent completed
01457   if ( rhs < 0 ) rhs = x+width;  //not printing due dates either
01458 
01459   // size of to-do
01460   outStr=todo->summary();
01461   int left = posSummary + ( level*10 );
01462   rect = p.boundingRect( left, y, ( rhs-left-5 ), -1, Qt::WordBreak, outStr );
01463   if ( !todo->description().isEmpty() && desc ) {
01464     outStr = todo->description();
01465     rect = p.boundingRect( left+20, rect.bottom()+5, width-(left+10-x), -1,
01466                            Qt::WordBreak, outStr );
01467   }
01468   // if too big make new page
01469   if ( rect.bottom() > pageHeight ) {
01470     // first draw the connection lines from parent to-dos:
01471     if ( level > 0 && connectSubTodos ) {
01472       TodoParentStart *rct;
01473       for ( rct = startPoints.first(); rct; rct = startPoints.next() ) {
01474         int start;
01475         int center = rct->mRect.left() + (rct->mRect.width()/2);
01476         int to = p.viewport().bottom();
01477 
01478         // draw either from start point of parent or from top of the page
01479         if ( rct->mSamePage )
01480           start = rct->mRect.bottom() + 1;
01481         else
01482           start = p.viewport().top();
01483         p.moveTo( center, start );
01484         p.lineTo( center, to );
01485         rct->mSamePage = false;
01486       }
01487     }
01488     y=0;
01489     mPrinter->newPage();
01490   }
01491 
01492   // If this is a sub-to-do, r will not be 0, and we want the LH side
01493   // of the priority line up to the RH side of the parent to-do's priority
01494   bool showPriority = posPriority>=0;
01495   int lhs = posPriority;
01496   if ( r ) {
01497     lhs = r->mRect.right() + 1;
01498   }
01499 
01500   outStr.setNum( todo->priority() );
01501   rect = p.boundingRect( lhs, y + 10, 5, -1, Qt::AlignCenter, outStr );
01502   // Make it a more reasonable size
01503   rect.setWidth(18);
01504   rect.setHeight(18);
01505 
01506   // Draw a checkbox
01507   p.setBrush( QBrush( Qt::NoBrush ) );
01508   p.drawRect( rect );
01509   if ( todo->isCompleted() ) {
01510     // cross out the rectangle for completed to-dos
01511     p.drawLine( rect.topLeft(), rect.bottomRight() );
01512     p.drawLine( rect.topRight(), rect.bottomLeft() );
01513   }
01514   lhs = rect.right() + 3;
01515 
01516   // Priority
01517   if ( todo->priority() > 0 && showPriority ) {
01518     p.drawText( rect, Qt::AlignCenter, outStr );
01519   }
01520   startpt.mRect = rect; //save for later
01521 
01522   // Connect the dots
01523   if ( level > 0 && connectSubTodos ) {
01524     int bottom;
01525     int center( r->mRect.left() + (r->mRect.width()/2) );
01526     if ( r->mSamePage )
01527       bottom = r->mRect.bottom() + 1;
01528     else
01529       bottom = 0;
01530     int to( rect.top() + (rect.height()/2) );
01531     int endx( rect.left() );
01532     p.moveTo( center, bottom );
01533     p.lineTo( center, to );
01534     p.lineTo( endx, to );
01535   }
01536 
01537   // summary
01538   outStr=todo->summary();
01539   rect = p.boundingRect( lhs, rect.top(), (rhs-(left + rect.width() + 5)),
01540                          -1, Qt::WordBreak, outStr );
01541 
01542   QRect newrect;
01543   //FIXME: the following code prints underline rather than strikeout text
01544 #if 0
01545   QFont f( p.font() );
01546   if ( todo->isCompleted() && strikeoutCompleted ) {
01547     f.setStrikeOut( true );
01548     p.setFont( f );
01549   }
01550   p.drawText( rect, Qt::WordBreak, outStr, -1, &newrect );
01551   f.setStrikeOut( false );
01552   p.setFont( f );
01553 #endif
01554   //TODO: Remove this section when the code above is fixed
01555   p.drawText( rect, Qt::WordBreak, outStr, -1, &newrect );
01556   if ( todo->isCompleted() && strikeoutCompleted ) {
01557     // strike out the summary text if to-do is complete
01558     // Note: we tried to use a strike-out font and for unknown reasons the
01559     // result was underline instead of strike-out, so draw the lines ourselves.
01560     int delta = p.fontMetrics().lineSpacing();
01561     int lines = ( rect.height() / delta ) + 1;
01562     for ( int i=0; i<lines; i++ ) {
01563       p.moveTo( rect.left(),  rect.top() + ( delta/2 ) + ( i*delta ) );
01564       p.lineTo( rect.right(), rect.top() + ( delta/2 ) + ( i*delta ) );
01565     }
01566   }
01567 
01568   // due date
01569   if ( todo->hasDueDate() && posDueDt>=0 ) {
01570     outStr = local->formatDate( todo->dtDue().date(), true );
01571     rect = p.boundingRect( posDueDt, y, x + width, -1,
01572                            Qt::AlignTop | Qt::AlignLeft, outStr );
01573     p.drawText( rect, Qt::AlignTop | Qt::AlignLeft, outStr );
01574   }
01575 
01576   // percentage completed
01577   bool showPercentComplete = posPercentComplete>=0;
01578   if ( showPercentComplete ) {
01579     int lwidth = 24;
01580     int lheight = 12;
01581     //first, draw the progress bar
01582     int progress = (int)(( lwidth*todo->percentComplete())/100.0 + 0.5);
01583 
01584     p.setBrush( QBrush( Qt::NoBrush ) );
01585     p.drawRect( posPercentComplete, y+3, lwidth, lheight );
01586     if ( progress > 0 ) {
01587       p.setBrush( QColor( 128, 128, 128 ) );
01588       p.drawRect( posPercentComplete, y+3, progress, lheight );
01589     }
01590 
01591     //now, write the percentage
01592     outStr = i18n( "%1%" ).arg( todo->percentComplete() );
01593     rect = p.boundingRect( posPercentComplete+lwidth+3, y, x + width, -1,
01594                            Qt::AlignTop | Qt::AlignLeft, outStr );
01595     p.drawText( rect, Qt::AlignTop | Qt::AlignLeft, outStr );
01596   }
01597 
01598   // description
01599   if ( !todo->description().isEmpty() && desc ) {
01600     y = newrect.bottom() + 5;
01601     outStr = todo->description();
01602     rect = p.boundingRect( left+20, y, x+width-(left+10), -1,
01603                            Qt::WordBreak, outStr );
01604     p.drawText( rect, Qt::WordBreak, outStr, -1, &newrect );
01605   }
01606 
01607   // Set the new line position
01608   y = newrect.bottom() + 10; //set the line position
01609 
01610   // If the to-do has sub-to-dos, we need to call ourselves recursively
01611 #if 0
01612   Incidence::List l = todo->relations();
01613   Incidence::List::ConstIterator it;
01614   startPoints.append( &startpt );
01615   for( it = l.begin(); it != l.end(); ++it ) {
01616     count++;
01617     // In the future, to-dos might also be related to events
01618     // Manually check if the sub-to-do is in the list of to-dos to print
01619     // The problem is that relations() does not apply filters, so
01620     // we need to compare manually with the complete filtered list!
01621     Todo* subtodo = dynamic_cast<Todo *>( *it );
01622     if (subtodo && todoList.contains( subtodo ) ) {
01623       drawTodo( count, subtodo, p, connectSubTodos, strikeoutCompleted,
01624                 desc, posPriority, posSummary, posDueDt, posPercentComplete,
01625                 level+1, x, y, width, pageHeight, todoList, &startpt );
01626     }
01627   }
01628 #endif
01629   // Make a list of all the sub-to-dos related to this to-do.
01630   Todo::List t;
01631   Incidence::List l = todo->relations();
01632   Incidence::List::ConstIterator it;
01633   for( it=l.begin(); it!=l.end(); ++it ) {
01634     // In the future, to-dos might also be related to events
01635     // Manually check if the sub-to-do is in the list of to-dos to print
01636     // The problem is that relations() does not apply filters, so
01637     // we need to compare manually with the complete filtered list!
01638     Todo* subtodo = dynamic_cast<Todo *>( *it );
01639     if ( subtodo && todoList.contains( subtodo ) ) {
01640       t.append( subtodo );
01641     }
01642   }
01643 
01644   // Sort the sub-to-dos and then print them
01645   Todo::List sl = mCalendar->sortTodos( &t, sortField, sortDir );
01646   Todo::List::ConstIterator isl;
01647   startPoints.append( &startpt );
01648   for( isl = sl.begin(); isl != sl.end(); ++isl ) {
01649     count++;
01650     drawTodo( count, ( *isl ), p, sortField, sortDir,
01651               connectSubTodos, strikeoutCompleted,
01652               desc, posPriority, posSummary, posDueDt, posPercentComplete,
01653               level+1, x, y, width, pageHeight, todoList, &startpt );
01654   }
01655   startPoints.remove( &startpt );
01656 }
01657 
01658 int CalPrintPluginBase::weekdayColumn( int weekday )
01659 {
01660   return ( weekday + 7 - KGlobal::locale()->weekStartDay() ) % 7;
01661 }
01662 
01663 void CalPrintPluginBase::drawJournalField( QPainter &p, QString field, QString text,
01664                                        int x, int &y, int width, int pageHeight )
01665 {
01666   if ( text.isEmpty() ) return;
01667 
01668   QString entry( field.arg( text ) );
01669 
01670   QRect rect( p.boundingRect( x, y, width, -1, Qt::WordBreak, entry) );
01671   if ( rect.bottom() > pageHeight) {
01672     // Start new page...
01673     // FIXME: If it's a multi-line text, draw a few lines on this page, and the
01674     // remaining lines on the next page.
01675     y=0;
01676     mPrinter->newPage();
01677     rect = p.boundingRect( x, y, width, -1, Qt::WordBreak, entry);
01678   }
01679   QRect newrect;
01680   p.drawText( rect, Qt::WordBreak, entry, -1, &newrect );
01681   y = newrect.bottom() + 7;
01682 }
01683 
01684 void CalPrintPluginBase::drawJournal( Journal * journal, QPainter &p, int x, int &y,
01685                                   int width, int pageHeight )
01686 {
01687   QFont oldFont( p.font() );
01688   p.setFont( QFont( "sans-serif", 15 ) );
01689   QString headerText;
01690   QString dateText( KGlobal::locale()->
01691         formatDate( journal->dtStart().date(), false ) );
01692 
01693   if ( journal->summary().isEmpty() ) {
01694     headerText = dateText;
01695   } else {
01696     headerText = i18n("Description - date", "%1 - %2")
01697                      .arg( journal->summary() )
01698                      .arg( dateText );
01699   }
01700 
01701   QRect rect( p.boundingRect( x, y, width, -1, Qt::WordBreak, headerText) );
01702   if ( rect.bottom() > pageHeight) {
01703     // Start new page...
01704     y=0;
01705     mPrinter->newPage();
01706     rect = p.boundingRect( x, y, width, -1, Qt::WordBreak, headerText );
01707   }
01708   QRect newrect;
01709   p.drawText( rect, Qt::WordBreak, headerText, -1, &newrect );
01710   p.setFont( oldFont );
01711 
01712   y = newrect.bottom() + 4;
01713 
01714   p.drawLine( x + 3, y, x + width - 6, y );
01715   y += 5;
01716 
01717   drawJournalField( p, i18n("Person: %1"), journal->organizer().fullName(), x, y, width, pageHeight );
01718   drawJournalField( p, i18n("%1"), journal->description(), x, y, width, pageHeight );
01719   y += 10;
01720 }
01721 
01722 
01723 void CalPrintPluginBase::drawSplitHeaderRight( QPainter &p, const QDate &fd,
01724                                            const QDate &td,
01725                                            const QDate &,
01726                                            int width, int )
01727 {
01728   QFont oldFont( p.font() );
01729 
01730   QPen oldPen( p.pen() );
01731   QPen pen( Qt::black, 4 );
01732 
01733   QString title;
01734   if ( mCalSys ) {
01735     if ( fd.month() == td.month() ) {
01736       title = i18n("Date range: Month dayStart - dayEnd", "%1 %2 - %3")
01737         .arg( mCalSys->monthName( fd.month(), false ) )
01738         .arg( mCalSys->dayString( fd, false ) )
01739         .arg( mCalSys->dayString( td, false ) );
01740     } else {
01741       title = i18n("Date range: monthStart dayStart - monthEnd dayEnd", "%1 %2 - %3 %4")
01742         .arg( mCalSys->monthName( fd.month(), false ) )
01743         .arg( mCalSys->dayString( fd, false ) )
01744         .arg( mCalSys->monthName( td.month(), false ) )
01745         .arg( mCalSys->dayString( td, false ) );
01746     }
01747   }
01748 
01749   QFont serifFont("Times", 30);
01750   p.setFont(serifFont);
01751 
01752   int lineSpacing = p.fontMetrics().lineSpacing();
01753   p.drawText( 0, lineSpacing * 0, width, lineSpacing,
01754               Qt::AlignRight | Qt::AlignTop, title );
01755 
01756   title.truncate(0);
01757 
01758   p.setPen( pen );
01759   p.drawLine(300, lineSpacing * 1, width, lineSpacing * 1);
01760   p.setPen( oldPen );
01761 
01762   p.setFont(QFont("Times", 20, QFont::Bold, TRUE));
01763   int newlineSpacing = p.fontMetrics().lineSpacing();
01764   title += QString::number(fd.year());
01765   p.drawText( 0, lineSpacing * 1 + 4, width, newlineSpacing,
01766               Qt::AlignRight | Qt::AlignTop, title );
01767 
01768   p.setFont( oldFont );
01769 }
01770 
01771 #endif
KDE Home | KDE Accessibility Home | Description of Access Keys