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, const QRect &box, Incidence *incidence, const QString &str, int flags )
00395 {
00396   QPen oldpen( p.pen() );
00397   QBrush oldbrush( p.brush() );
00398   QColor bgColor( categoryBgColor( incidence ) );
00399   if ( mUseColors & bgColor.isValid() ) {
00400     p.setBrush( bgColor );
00401   } else {
00402     p.setBrush( QColor( 232, 232, 232 ) );
00403   }
00404   drawBox( p, EVENT_BORDER_WIDTH, box );
00405 
00406   if ( mUseColors && bgColor.isValid() ) {
00407     p.setPen( textColor( bgColor ) );
00408   }
00409   printEventString( p, box, str, flags );
00410   p.setPen( oldpen );
00411   p.setBrush( oldbrush );
00412 }
00413 
00414 
00415 void CalPrintPluginBase::drawSubHeaderBox(QPainter &p, const QString &str,
00416     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, const QRect &box, const QString &str )
00426 {
00427   p.save();
00428   p.rotate( -90 );
00429   QRect rotatedBox( -box.top()-box.height(), box.left(), box.height(), box.width() );
00430   showEventBox( p, rotatedBox, 0, str, Qt::AlignLeft | Qt::AlignVCenter | Qt::SingleLine );
00431 
00432   p.restore();
00433 }
00434 
00435 
00436 
00438 // Return value: If expand, bottom of the printed box, otherwise vertical end
00439 // of the printed contents inside the box.
00440 
00441 int CalPrintPluginBase::drawBoxWithCaption( QPainter &p, const QRect &allbox,
00442         const QString &caption, const QString &contents, bool sameLine, bool expand, const QFont &captionFont, const QFont &textFont )
00443 {
00444   QFont oldFont( p.font() );
00445 //   QFont captionFont( "sans-serif", 11, QFont::Bold );
00446 //   QFont textFont( "sans-serif", 11, QFont::Normal );
00447 //   QFont captionFont( "Tahoma", 11, QFont::Bold );
00448 //   QFont textFont( "Tahoma", 11, QFont::Normal );
00449 
00450 
00451   QRect box( allbox );
00452 
00453   // Bounding rectangle for caption, single-line, clip on the right
00454   QRect captionBox( box.left() + padding(), box.top() + padding(), 0, 0 );
00455   p.setFont( captionFont );
00456   captionBox = p.boundingRect( captionBox, Qt::AlignLeft | Qt::AlignTop | Qt::SingleLine, caption );
00457   p.setFont( oldFont );
00458   if ( captionBox.right() > box.right() )
00459     captionBox.setRight( box.right() );
00460   if ( expand && captionBox.bottom() + padding() > box.bottom() )
00461     box.setBottom( captionBox.bottom() + padding() );
00462 
00463   // Bounding rectangle for the contents (if any), word break, clip on the bottom
00464   QRect textBox( captionBox );
00465   if ( !contents.isEmpty() ) {
00466     if ( sameLine ) {
00467       textBox.setLeft( captionBox.right() + padding() );
00468     } else {
00469       textBox.setTop( captionBox.bottom() + padding() );
00470     }
00471     textBox.setRight( box.right() );
00472     textBox.setHeight( 0 );
00473     p.setFont( textFont );
00474     textBox = p.boundingRect( textBox, Qt::WordBreak | Qt::AlignTop | Qt::AlignLeft, contents );
00475     p.setFont( oldFont );
00476     if ( textBox.bottom() + padding() > box.bottom() ) {
00477       if ( expand ) {
00478         box.setBottom( textBox.bottom() + padding() );
00479       } else {
00480         textBox.setBottom( box.bottom() );
00481       }
00482     }
00483   }
00484 
00485   drawBox( p, BOX_BORDER_WIDTH, box );
00486   p.setFont( captionFont );
00487   p.drawText( captionBox, Qt::AlignLeft | Qt::AlignTop | Qt::SingleLine, caption );
00488   if ( !contents.isEmpty() ) {
00489     p.setFont( textFont );
00490     p.drawText( textBox, Qt::WordBreak | Qt::AlignTop | Qt::AlignLeft, contents );
00491   }
00492   p.setFont( oldFont );
00493 
00494   if ( expand ) {
00495     return box.bottom();
00496   } else {
00497     return textBox.bottom();
00498   }
00499 }
00500 
00501 
00503 
00504 int CalPrintPluginBase::drawHeader( QPainter &p, QString title,
00505     const QDate &month1, const QDate &month2, const QRect &allbox, bool expand )
00506 {
00507   // print previous month for month view, print current for to-do, day and week
00508   int smallMonthWidth = (allbox.width()/4) - 10;
00509   if (smallMonthWidth>100) smallMonthWidth=100;
00510 
00511   int right = allbox.right();
00512   if ( month1.isValid() ) right -= (20+smallMonthWidth);
00513   if ( month2.isValid() ) right -= (20+smallMonthWidth);
00514   QRect box( allbox );
00515   QRect textRect( allbox );
00516   textRect.addCoords( 5, 0, 0, 0 );
00517   textRect.setRight( right );
00518 
00519 
00520   QFont oldFont( p.font() );
00521   QFont newFont("sans-serif", (textRect.height()<60)?16:18, QFont::Bold);
00522   if ( expand ) {
00523     p.setFont( newFont );
00524     QRect boundingR = p.boundingRect( textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::WordBreak, title );
00525     p.setFont( oldFont );
00526     int h = boundingR.height();
00527     if ( h > allbox.height() ) {
00528       box.setHeight( h );
00529       textRect.setHeight( h );
00530     }
00531   }
00532 
00533   drawShadedBox( p, BOX_BORDER_WIDTH, QColor( 232, 232, 232 ), box );
00534 
00535   QRect monthbox( box.right()-10-smallMonthWidth, box.top(), smallMonthWidth, box.height() );
00536   if (month2.isValid()) {
00537     drawSmallMonth( p, QDate(month2.year(), month2.month(), 1), monthbox );
00538     monthbox.moveBy( -20 - smallMonthWidth, 0 );
00539   }
00540   if (month1.isValid()) {
00541     drawSmallMonth( p, QDate(month1.year(), month1.month(), 1), monthbox );
00542     monthbox.moveBy( -20 - smallMonthWidth, 0 );
00543   }
00544 
00545   // Set the margins
00546   p.setFont( newFont );
00547   p.drawText( textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::WordBreak, title );
00548   p.setFont( oldFont );
00549 
00550   return textRect.bottom();
00551 }
00552 
00553 
00554 int CalPrintPluginBase::drawFooter( QPainter &p, QRect &footbox )
00555 {
00556   QFont oldfont( p.font() );
00557   p.setFont( QFont( "sans-serif", 6 ) );
00558   QFontMetrics fm( p.font() );
00559   QString dateStr = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(), false );
00560   p.drawText( footbox, Qt::AlignCenter | Qt::AlignVCenter | Qt::SingleLine,
00561               i18n( "print date: formatted-datetime", "printed: %1" ).arg( dateStr ) );
00562   p.setFont( oldfont );
00563 
00564   return footbox.bottom();
00565 }
00566 
00567 void CalPrintPluginBase::drawSmallMonth(QPainter &p, const QDate &qd,
00568     const QRect &box )
00569 {
00570 
00571   int weekdayCol = weekdayColumn( qd.dayOfWeek() );
00572   int month = qd.month();
00573   QDate monthDate(QDate(qd.year(), qd.month(), 1));
00574   // correct begin of week
00575   QDate monthDate2( monthDate.addDays( -weekdayCol ) );
00576 
00577   double cellWidth = double(box.width())/double(7);
00578   int rownr = 3 + ( qd.daysInMonth() + weekdayCol - 1 ) / 7;
00579   // 3 Pixel after month name, 2 after day names, 1 after the calendar
00580   double cellHeight = (box.height() - 5) / rownr;
00581   QFont oldFont( p.font() );
00582   p.setFont(QFont("sans-serif", int(cellHeight-1), QFont::Normal));
00583 
00584   // draw the title
00585   if ( mCalSys ) {
00586     QRect titleBox( box );
00587     titleBox.setHeight( int(cellHeight+1) );
00588     p.drawText( titleBox, Qt::AlignTop | Qt::AlignHCenter, mCalSys->monthName( qd ) );
00589   }
00590 
00591   // draw days of week
00592   QRect wdayBox( box );
00593   wdayBox.setTop( int( box.top() + 3 + cellHeight ) );
00594   wdayBox.setHeight( int(2*cellHeight)-int(cellHeight) );
00595 
00596   if ( mCalSys ) {
00597     for (int col = 0; col < 7; ++col) {
00598       QString tmpStr = mCalSys->weekDayName( monthDate2 )[0].upper();
00599       wdayBox.setLeft( int(box.left() + col*cellWidth) );
00600       wdayBox.setRight( int(box.left() + (col+1)*cellWidth) );
00601       p.drawText( wdayBox, Qt::AlignCenter, tmpStr );
00602       monthDate2 = monthDate2.addDays( 1 );
00603     }
00604   }
00605 
00606   // draw separator line
00607   int calStartY = wdayBox.bottom() + 2;
00608   p.drawLine( box.left(), calStartY, box.right(), calStartY );
00609   monthDate = monthDate.addDays( -weekdayCol );
00610 
00611   for ( int row = 0; row < (rownr-2); row++ ) {
00612     for ( int col = 0; col < 7; col++ ) {
00613       if ( monthDate.month() == month ) {
00614         QRect dayRect( int( box.left() + col*cellWidth ), int( calStartY + row*cellHeight ), 0, 0 );
00615         dayRect.setRight( int( box.left() + (col+1)*cellWidth ) );
00616         dayRect.setBottom( int( calStartY + (row+1)*cellHeight ) );
00617         p.drawText( dayRect, Qt::AlignCenter, QString::number( monthDate.day() ) );
00618       }
00619       monthDate = monthDate.addDays(1);
00620     }
00621   }
00622   p.setFont( oldFont );
00623 }
00624 
00625 
00626 
00627 
00628 
00630 
00631 /*
00632  * This routine draws a header box over the main part of the calendar
00633  * containing the days of the week.
00634  */
00635 void CalPrintPluginBase::drawDaysOfWeek(QPainter &p,
00636     const QDate &fromDate, const QDate &toDate, const QRect &box )
00637 {
00638   double cellWidth = double(box.width()) / double(fromDate.daysTo( toDate )+1);
00639   QDate cellDate( fromDate );
00640   QRect dateBox( box );
00641   int i = 0;
00642 
00643   while ( cellDate <= toDate ) {
00644     dateBox.setLeft( box.left() + int(i*cellWidth) );
00645     dateBox.setRight( box.left() + int((i+1)*cellWidth) );
00646     drawDaysOfWeekBox(p, cellDate, dateBox );
00647     cellDate = cellDate.addDays(1);
00648     i++;
00649   }
00650 }
00651 
00652 
00653 void CalPrintPluginBase::drawDaysOfWeekBox(QPainter &p, const QDate &qd,
00654     const QRect &box )
00655 {
00656   drawSubHeaderBox( p, (mCalSys)?(mCalSys->weekDayName( qd )):(QString::null), box );
00657 }
00658 
00659 
00660 void CalPrintPluginBase::drawTimeLine( QPainter &p, const QTime &fromTime,
00661                                        const QTime &toTime, const QRect &box )
00662 {
00663   drawBox( p, BOX_BORDER_WIDTH, box );
00664 
00665   int totalsecs = fromTime.secsTo( toTime );
00666   float minlen = (float)box.height() * 60. / (float)totalsecs;
00667   float cellHeight = ( 60. * (float)minlen );
00668   float currY = box.top();
00669   // TODO: Don't use half of the width, but less, for the minutes!
00670   int xcenter = box.left() + box.width() / 2;
00671 
00672   QTime curTime( fromTime );
00673   QTime endTime( toTime );
00674   if ( fromTime.minute() > 30 ) {
00675     curTime = QTime( fromTime.hour()+1, 0, 0 );
00676   } else if ( fromTime.minute() > 0 ) {
00677     curTime = QTime( fromTime.hour(), 30, 0 );
00678     float yy = currY + minlen * (float)fromTime.secsTo( curTime ) / 60.;
00679     p.drawLine( xcenter, (int)yy, box.right(), (int)yy );
00680     curTime = QTime( fromTime.hour() + 1, 0, 0 );
00681   }
00682   currY += ( float( fromTime.secsTo( curTime ) * minlen ) / 60. );
00683 
00684   while ( curTime < endTime ) {
00685     p.drawLine( box.left(), (int)currY, box.right(), (int)currY );
00686     int newY = (int)( currY + cellHeight / 2. );
00687     QString numStr;
00688     if ( newY < box.bottom() ) {
00689       QFont oldFont( p.font() );
00690       // draw the time:
00691       if ( !KGlobal::locale()->use12Clock() ) {
00692         p.drawLine( xcenter, (int)newY, box.right(), (int)newY );
00693         numStr.setNum( curTime.hour() );
00694         if  ( cellHeight > 30 ) {
00695           p.setFont( QFont( "sans-serif", 14, QFont::Bold ) );
00696         } else {
00697           p.setFont( QFont( "sans-serif", 12, QFont::Bold ) );
00698         }
00699         p.drawText( box.left() + 4, (int)currY + 2, box.width() / 2 - 2, (int)cellHeight,
00700                     Qt::AlignTop | Qt::AlignRight, numStr );
00701         p.setFont( QFont ( "helvetica", 10, QFont::Normal ) );
00702         p.drawText( xcenter + 4, (int)currY + 2, box.width() / 2 + 2, (int)(cellHeight / 2 ) - 3,
00703                     Qt::AlignTop | Qt::AlignLeft, "00" );
00704       } else {
00705         p.drawLine( box.left(), (int)newY, box.right(), (int)newY );
00706         QTime time( curTime.hour(), 0 );
00707         numStr = KGlobal::locale()->formatTime( time );
00708         if ( box.width() < 60 ) {
00709           p.setFont( QFont( "sans-serif", 7, QFont::Bold ) ); // for weekprint
00710         } else {
00711           p.setFont( QFont( "sans-serif", 12, QFont::Bold ) ); // for dayprint
00712         }
00713         p.drawText( box.left() + 2, (int)currY + 2, box.width() - 4, (int)cellHeight / 2 - 3,
00714                     Qt::AlignTop|Qt::AlignLeft, numStr );
00715       }
00716       currY += cellHeight;
00717       p.setFont( oldFont );
00718     } // enough space for half-hour line and time
00719     if ( curTime.secsTo( endTime ) > 3600 ) {
00720       curTime = curTime.addSecs( 3600 );
00721     } else {
00722       curTime = endTime;
00723     }
00724   } // currTime<endTime
00725 }
00726 
00733 int CalPrintPluginBase::drawAllDayBox(QPainter &p, Event::List &eventList,
00734     const QDate &qd, bool expandable, const QRect &box )
00735 {
00736   Event::List::Iterator it, itold;
00737 
00738   int offset=box.top();
00739 
00740   QString multiDayStr;
00741 
00742   Event*hd = holiday( qd );
00743   if ( hd ) eventList.prepend( hd );
00744 
00745   it = eventList.begin();
00746   Event *currEvent = 0;
00747   // First, print all floating events
00748   while( it!=eventList.end() ) {
00749     currEvent=*it;
00750     itold=it;
00751     ++it;
00752     if ( currEvent && currEvent->doesFloat() ) {
00753       // set the colors according to the categories
00754       if ( expandable ) {
00755         QRect eventBox( box );
00756         eventBox.setTop( offset );
00757         showEventBox( p, eventBox, currEvent, currEvent->summary() );
00758         offset += box.height();
00759       } else {
00760         if ( !multiDayStr.isEmpty() ) multiDayStr += ", ";
00761         multiDayStr += currEvent->summary();
00762       }
00763       eventList.remove( itold );
00764     }
00765   }
00766   if ( hd ) delete hd;
00767 
00768   int ret = box.height();
00769   QRect eventBox( box );
00770   if (!expandable) {
00771     if (!multiDayStr.isEmpty()) {
00772       drawShadedBox( p, BOX_BORDER_WIDTH, QColor( 128, 128, 128 ), eventBox );
00773       printEventString( p, eventBox, multiDayStr );
00774     } else {
00775       drawBox( p, BOX_BORDER_WIDTH, eventBox );
00776     }
00777   } else {
00778     ret = offset - box.top();
00779     eventBox.setBottom( ret );
00780     drawBox( p, BOX_BORDER_WIDTH, eventBox );
00781   }
00782   return ret;
00783 }
00784 
00785 
00786 void CalPrintPluginBase::drawAgendaDayBox( QPainter &p, Event::List &events,
00787                                      const QDate &qd, bool expandable,
00788                                      QTime &fromTime, QTime &toTime,
00789                                      const QRect &oldbox )
00790 {
00791   if ( !isWorkingDay( qd ) ) {
00792     drawShadedBox( p, BOX_BORDER_WIDTH, QColor( 232, 232, 232 ), oldbox );
00793   } else {
00794     drawBox( p, BOX_BORDER_WIDTH, oldbox );
00795   }
00796   QRect box( oldbox );
00797   // Account for the border with and cut away that margin from the interior
00798 //   box.setRight( box.right()-BOX_BORDER_WIDTH );
00799 
00800   Event *event;
00801 
00802   if ( expandable ) {
00803     // Adapt start/end times to include complete events
00804     Event::List::ConstIterator it;
00805     for ( it = events.begin(); it != events.end(); ++it ) {
00806       event = *it;
00807       if ( event->dtStart().time() < fromTime )
00808         fromTime = event->dtStart().time();
00809       if ( event->dtEnd().time() > toTime )
00810         toTime = event->dtEnd().time();
00811     }
00812   }
00813 
00814   // Show at least one hour
00815 //   if ( fromTime.secsTo( toTime ) < 3600 ) {
00816 //     fromTime = QTime( fromTime.hour(), 0, 0 );
00817 //     toTime = fromTime.addSecs( 3600 );
00818 //   }
00819 
00820   // calculate the height of a cell and of a minute
00821   int totalsecs = fromTime.secsTo( toTime );
00822   float minlen = box.height() * 60. / totalsecs;
00823   float cellHeight = 60. * minlen;
00824   float currY = box.top();
00825 
00826   // print grid:
00827   QTime curTime( QTime( fromTime.hour(), 0, 0 ) );
00828   currY += fromTime.secsTo( curTime ) * minlen / 60;
00829 
00830   while ( curTime < toTime && curTime.isValid() ) {
00831     if ( currY > box.top() )
00832       p.drawLine( box.left(), int( currY ), box.right(), int( currY ) );
00833     currY += cellHeight / 2;
00834     if ( ( currY > box.top() ) && ( currY < box.bottom() ) ) {
00835       // enough space for half-hour line
00836       QPen oldPen( p.pen() );
00837       p.setPen( QColor( 192, 192, 192 ) );
00838       p.drawLine( box.left(), int( currY ), box.right(), int( currY ) );
00839       p.setPen( oldPen );
00840     }
00841     if ( curTime.secsTo( toTime ) > 3600 )
00842       curTime = curTime.addSecs( 3600 );
00843     else curTime = toTime;
00844     currY += cellHeight / 2;
00845   }
00846 
00847   QDateTime startPrintDate = QDateTime( qd, fromTime );
00848   QDateTime endPrintDate = QDateTime( qd, toTime );
00849 
00850   // Calculate horizontal positions and widths of events taking into account
00851   // overlapping events
00852 
00853   QPtrList<KOrg::CellItem> cells;
00854   cells.setAutoDelete( true );
00855 
00856   Event::List::ConstIterator itEvents;
00857   for( itEvents = events.begin(); itEvents != events.end(); ++itEvents ) {
00858     QValueList<QDateTime> times = (*itEvents)->startDateTimesForDate( qd );
00859     for ( QValueList<QDateTime>::ConstIterator it = times.begin();
00860           it != times.end(); ++it ) {
00861       cells.append( new PrintCellItem( *itEvents, (*it), (*itEvents)->endDateForStart( *it ) ) );
00862     }
00863   }
00864 
00865   QPtrListIterator<KOrg::CellItem> it1( cells );
00866   for( it1.toFirst(); it1.current(); ++it1 ) {
00867     KOrg::CellItem *placeItem = it1.current();
00868     KOrg::CellItem::placeItem( cells, placeItem );
00869   }
00870 
00871 //   p.setFont( QFont( "sans-serif", 10 ) );
00872 
00873   for( it1.toFirst(); it1.current(); ++it1 ) {
00874     PrintCellItem *placeItem = static_cast<PrintCellItem *>( it1.current() );
00875     drawAgendaItem( placeItem, p, startPrintDate, endPrintDate, minlen, box );
00876   }
00877 //   p.setFont( oldFont );
00878 }
00879 
00880 
00881 
00882 void CalPrintPluginBase::drawAgendaItem( PrintCellItem *item, QPainter &p,
00883                                    const QDateTime &startPrintDate,
00884                                    const QDateTime &endPrintDate,
00885                                    float minlen, const QRect &box )
00886 {
00887   Event *event = item->event();
00888 
00889   // start/end of print area for event
00890   QDateTime startTime = item->start();
00891   QDateTime endTime = item->end();
00892   if ( ( startTime < endPrintDate && endTime > startPrintDate ) ||
00893        ( endTime > startPrintDate && startTime < endPrintDate ) ) {
00894     if ( startTime < startPrintDate ) startTime = startPrintDate;
00895     if ( endTime > endPrintDate ) endTime = endPrintDate;
00896     int currentWidth = box.width() / item->subCells();
00897     int currentX = box.left() + item->subCell() * currentWidth;
00898     int currentYPos = int( box.top() + startPrintDate.secsTo( startTime ) *
00899                            minlen / 60. );
00900     int currentHeight = int( box.top() + startPrintDate.secsTo( endTime ) * minlen / 60. ) - currentYPos;
00901 
00902     QRect eventBox( currentX, currentYPos, currentWidth, currentHeight );
00903     QString str;
00904     if ( event->location().isEmpty() ) {
00905       str = i18n( "starttime - endtime summary",
00906                   "%1-%2 %3" ).
00907             arg( KGlobal::locale()->formatTime( startTime.time() ) ).
00908             arg( KGlobal::locale()->formatTime( endTime.time() ) ).
00909             arg( cleanStr( event->summary() ) );
00910     } else {
00911       str = i18n( "starttime - endtime summary, location",
00912                   "%1-%2 %3, %4" ).
00913             arg( KGlobal::locale()->formatTime( startTime.time() ) ).
00914             arg( KGlobal::locale()->formatTime( endTime.time() ) ).
00915             arg( cleanStr( event->summary() ) ).
00916             arg( cleanStr( event->location() ) );
00917     }
00918     showEventBox( p, eventBox, event, str );
00919   }
00920 }
00921 
00922 //TODO TODO TODO
00923 void CalPrintPluginBase::drawDayBox( QPainter &p, const QDate &qd,
00924     const QRect &box,
00925     bool fullDate, bool printRecurDaily, bool printRecurWeekly )
00926 {
00927   QString dayNumStr;
00928   const KLocale*local = KGlobal::locale();
00929 
00930   // This has to be localized
00931   if ( fullDate && mCalSys ) {
00932 
00933     dayNumStr = i18n("weekday month date", "%1 %2 %3")
00934         .arg( mCalSys->weekDayName( qd ) )
00935         .arg( mCalSys->monthName( qd ) )
00936         .arg( qd.day() );
00937 //    dayNumStr = local->formatDate(qd);
00938   } else {
00939     dayNumStr = QString::number( qd.day() );
00940   }
00941 
00942   QRect subHeaderBox( box );
00943   subHeaderBox.setHeight( mSubHeaderHeight );
00944   drawShadedBox( p, BOX_BORDER_WIDTH, p.backgroundColor(), box );
00945   drawShadedBox( p, 0, QColor( 232, 232, 232 ), subHeaderBox );
00946   drawBox( p, BOX_BORDER_WIDTH, box );
00947   QString hstring( holidayString( qd ) );
00948   QFont oldFont( p.font() );
00949 
00950   QRect headerTextBox( subHeaderBox );
00951   headerTextBox.setLeft( subHeaderBox.left()+5 );
00952   headerTextBox.setRight( subHeaderBox.right()-5 );
00953   if (!hstring.isEmpty()) {
00954     p.setFont( QFont( "sans-serif", 8, QFont::Bold, true ) );
00955 
00956     p.drawText( headerTextBox, Qt::AlignLeft | Qt::AlignVCenter, hstring );
00957   }
00958   p.setFont(QFont("sans-serif", 10, QFont::Bold));
00959   p.drawText( headerTextBox, Qt::AlignRight | Qt::AlignVCenter, dayNumStr);
00960 
00961   Event::List eventList = mCalendar->events( qd,
00962                                              EventSortStartDate,
00963                                              SortDirectionAscending );
00964   QString timeText;
00965   p.setFont( QFont( "sans-serif", 8 ) );
00966 
00967   int textY=mSubHeaderHeight+3; // gives the relative y-coord of the next printed entry
00968   Event::List::ConstIterator it;
00969 
00970   for( it = eventList.begin(); it != eventList.end() && textY<box.height(); ++it ) {
00971     Event *currEvent = *it;
00972     if ( ( !printRecurDaily  && currEvent->recurrenceType() == Recurrence::rDaily  ) ||
00973          ( !printRecurWeekly && currEvent->recurrenceType() == Recurrence::rWeekly ) ) {
00974       continue;
00975     }
00976     if ( currEvent->doesFloat() || currEvent->isMultiDay() ) {
00977       timeText = "";
00978     } else {
00979       timeText = local->formatTime( currEvent->dtStart().time() );
00980     }
00981 
00982     QString str;
00983     if ( !currEvent->location().isEmpty() ) {
00984       str = i18n( "summary, location", "%1, %2" ).
00985             arg( currEvent->summary() ).arg( currEvent->location() );
00986     } else {
00987       str = currEvent->summary();
00988     }
00989     drawIncidence( p, box, timeText, str, textY );
00990   }
00991 
00992   if ( textY < box.height() ) {
00993     Todo::List todos = mCalendar->todos( qd );
00994     Todo::List::ConstIterator it2;
00995     for ( it2 = todos.begin(); it2 != todos.end() && textY <box.height(); ++it2 ) {
00996       Todo *todo = *it2;
00997       if ( ( !printRecurDaily  && todo->recurrenceType() == Recurrence::rDaily  ) ||
00998            ( !printRecurWeekly && todo->recurrenceType() == Recurrence::rWeekly ) ) {
00999         continue;
01000       }
01001       if ( todo->hasStartDate() && !todo->doesFloat() ) {
01002         timeText = KGlobal::locale()->formatTime( todo->dtStart().time() ) + " ";
01003       } else {
01004         timeText = "";
01005       }
01006       QString summaryStr;
01007       if ( !todo->location().isEmpty() ) {
01008         summaryStr = i18n( "summary, location", "%1, %2" ).
01009                      arg( todo->summary() ).arg( todo->location() );
01010       } else {
01011         summaryStr = todo->summary();
01012       }
01013       QString str;
01014       if ( todo->hasDueDate() ) {
01015         if ( !todo->doesFloat() ) {
01016           str = i18n( "%1 (Due: %2)" ).
01017                 arg( summaryStr ).
01018                 arg( KGlobal::locale()->formatDateTime( todo->dtDue() ) );
01019         } else {
01020           str = i18n( "%1 (Due: %2)" ).
01021                 arg( summaryStr ).
01022                 arg( KGlobal::locale()->formatDate( todo->dtDue().date(), true ) );
01023         }
01024       } else {
01025         str = summaryStr;
01026       }
01027       drawIncidence( p, box, timeText, i18n("To-do: %1").arg( str ), textY );
01028     }
01029   }
01030 
01031   p.setFont( oldFont );
01032 }
01033 
01034 // TODO TODO TODO
01035 void CalPrintPluginBase::drawIncidence( QPainter &p, const QRect &dayBox, const QString &time, const QString &summary, int &textY )
01036 {
01037   kdDebug(5850) << "summary = " << summary << endl;
01038 
01039   int flags = Qt::AlignLeft;
01040   QFontMetrics fm = p.fontMetrics();
01041   QRect timeBound = p.boundingRect( dayBox.x() + 5, dayBox.y() + textY,
01042                                     dayBox.width() - 10, fm.lineSpacing(),
01043                                     flags, time );
01044   p.drawText( timeBound, flags, time );
01045 
01046   int summaryWidth = time.isEmpty() ? 0 : timeBound.width() + 4;
01047   QRect summaryBound = QRect( dayBox.x() + 5 + summaryWidth, dayBox.y() + textY,
01048                               dayBox.width() - summaryWidth -5, dayBox.height() );
01049 
01050   KWordWrap *ww = KWordWrap::formatText( fm, summaryBound, flags, summary );
01051   ww->drawText( &p, dayBox.x() + 5 + summaryWidth, dayBox.y() + textY, flags );
01052 
01053   textY += ww->boundingRect().height();
01054 
01055   delete ww;
01056 }
01057 
01058 
01060 
01061 void CalPrintPluginBase::drawWeek(QPainter &p, const QDate &qd, const QRect &box )
01062 {
01063   QDate weekDate = qd;
01064   bool portrait = ( box.height() > box.width() );
01065   int cellWidth, cellHeight;
01066   int vcells;
01067   if (portrait) {
01068     cellWidth = box.width()/2;
01069     vcells=3;
01070   } else {
01071     cellWidth = box.width()/6;
01072     vcells=1;
01073   }
01074   cellHeight = box.height()/vcells;
01075 
01076   // correct begin of week
01077   int weekdayCol = weekdayColumn( qd.dayOfWeek() );
01078   weekDate = qd.addDays( -weekdayCol );
01079 
01080   for (int i = 0; i < 7; i++, weekDate = weekDate.addDays(1)) {
01081     // Saturday and sunday share a cell, so we have to special-case sunday
01082     int hpos = ((i<6)?i:(i-1)) / vcells;
01083     int vpos = ((i<6)?i:(i-1)) % vcells;
01084     QRect dayBox( box.left()+cellWidth*hpos, box.top()+cellHeight*vpos + ((i==6)?(cellHeight/2):0),
01085         cellWidth, (i<5)?(cellHeight):(cellHeight/2) );
01086     drawDayBox(p, weekDate, dayBox, true);
01087   } // for i through all weekdays
01088 }
01089 
01090 
01091 void CalPrintPluginBase::drawTimeTable(QPainter &p,
01092     const QDate &fromDate, const QDate &toDate,
01093     QTime &fromTime, QTime &toTime,
01094     const QRect &box)
01095 {
01096   // timeline is 1 hour:
01097   int alldayHeight = (int)( 3600.*box.height()/(fromTime.secsTo(toTime)+3600.) );
01098   int timelineWidth = TIMELINE_WIDTH;
01099 
01100   QRect dowBox( box );
01101   dowBox.setLeft( box.left() + timelineWidth );
01102   dowBox.setHeight( mSubHeaderHeight );
01103   drawDaysOfWeek( p, fromDate, toDate, dowBox );
01104 
01105   QRect tlBox( box );
01106   tlBox.setWidth( timelineWidth );
01107   tlBox.setTop( dowBox.bottom() + BOX_BORDER_WIDTH + alldayHeight );
01108   drawTimeLine( p, fromTime, toTime, tlBox );
01109 
01110   // draw each day
01111   QDate curDate(fromDate);
01112   int i=0;
01113   double cellWidth = double(dowBox.width()) / double(fromDate.daysTo(toDate)+1);
01114   while (curDate<=toDate) {
01115     QRect allDayBox( dowBox.left()+int(i*cellWidth), dowBox.bottom() + BOX_BORDER_WIDTH,
01116                      int((i+1)*cellWidth)-int(i*cellWidth), alldayHeight );
01117     QRect dayBox( allDayBox );
01118     dayBox.setTop( tlBox.top() );
01119     dayBox.setBottom( box.bottom() );
01120     Event::List eventList = mCalendar->events(curDate,
01121                                               EventSortStartDate,
01122                                               SortDirectionAscending);
01123     alldayHeight = drawAllDayBox( p, eventList, curDate, false, allDayBox );
01124     drawAgendaDayBox( p, eventList, curDate, false, fromTime, toTime, dayBox );
01125     i++;
01126     curDate=curDate.addDays(1);
01127   }
01128 
01129 }
01130 
01131 
01133 
01134 class MonthEventStruct
01135 {
01136   public:
01137     MonthEventStruct() : event(0) {}
01138     MonthEventStruct( const QDateTime &s, const QDateTime &e, Event *ev)
01139     {
01140       event = ev;
01141       start = s;
01142       end = e;
01143       if ( event->doesFloat() ) {
01144         start = QDateTime( start.date(), QTime(0,0,0) );
01145         end = QDateTime( end.date().addDays(1), QTime(0,0,0) ).addSecs(-1);
01146       }
01147     }
01148     bool operator<(const MonthEventStruct &mes) { return start < mes.start; }
01149     QDateTime start;
01150     QDateTime end;
01151     Event *event;
01152 };
01153 
01154 void CalPrintPluginBase::drawMonth( QPainter &p, const QDate &dt, const QRect &box, int maxdays, int subDailyFlags, int holidaysFlags )
01155 {
01156   const KCalendarSystem *calsys = calendarSystem();
01157   QRect subheaderBox( box );
01158   subheaderBox.setHeight( subHeaderHeight() );
01159   QRect borderBox( box );
01160   borderBox.setTop( subheaderBox.bottom()+1 );
01161   drawSubHeaderBox( p, calsys->monthName(dt), subheaderBox );
01162   // correct for half the border width
01163   int correction = (BOX_BORDER_WIDTH/*-1*/)/2;
01164   QRect daysBox( borderBox );
01165   daysBox.addCoords( correction, correction, -correction, -correction );
01166 
01167   int daysinmonth = calsys->daysInMonth( dt );
01168   if ( maxdays <= 0 ) maxdays = daysinmonth;
01169 
01170   int d;
01171   float dayheight = float(daysBox.height()) / float( maxdays );
01172 
01173   QColor holidayColor( 240, 240, 240 );
01174   QColor workdayColor( 255, 255, 255 );
01175   int dayNrWidth = p.fontMetrics().width( "99" );
01176 
01177   // Fill the remaining space (if a month has less days than others) with a crossed-out pattern
01178   if ( daysinmonth<maxdays ) {
01179     QRect dayBox( box.left(), daysBox.top() + round(dayheight*daysinmonth), box.width(), 0 );
01180     dayBox.setBottom( daysBox.bottom() );
01181     p.fillRect( dayBox, Qt::DiagCrossPattern );
01182   }
01183   // Backgrounded boxes for each day, plus day numbers
01184   QBrush oldbrush( p.brush() );
01185   for ( d = 0; d < daysinmonth; ++d ) {
01186     QDate day;
01187     calsys->setYMD( day, dt.year(), dt.month(), d+1 );
01188     QRect dayBox( daysBox.left()/*+rand()%50*/, daysBox.top() + round(dayheight*d), daysBox.width()/*-rand()%50*/, 0 );
01189     // 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!
01190     dayBox.setBottom( daysBox.top()+round(dayheight*(d+1)) - 1 );
01191 
01192     p.setBrush( isWorkingDay( day )?workdayColor:holidayColor );
01193     p.drawRect( dayBox );
01194     QRect dateBox( dayBox );
01195     dateBox.setWidth( dayNrWidth+3 );
01196     p.drawText( dateBox, Qt::AlignRight | Qt::AlignVCenter | Qt::SingleLine,
01197                 QString::number(d+1) );
01198   }
01199   p.setBrush( oldbrush );
01200   int xstartcont = box.left() + dayNrWidth + 5;
01201 
01202   QDate start, end;
01203   calsys->setYMD( start, dt.year(), dt.month(), 1 );
01204   end = calsys->addMonths( start, 1 );
01205   end = calsys->addDays( end, -1 );
01206 
01207   Event::List events = mCalendar->events( start, end );
01208   QMap<int, QStringList> textEvents;
01209   QPtrList<KOrg::CellItem> timeboxItems;
01210   timeboxItems.setAutoDelete( true );
01211 
01212 
01213   // 1) For multi-day events, show boxes spanning several cells, use CellItem
01214   //    print the summary vertically
01215   // 2) For sub-day events, print the concated summaries into the remaining
01216   //    space of the box (optional, depending on the given flags)
01217   // 3) Draw some kind of timeline showing free and busy times
01218 
01219   // Holidays
01220   Event::List holidays;
01221   holidays.setAutoDelete( true );
01222   for ( QDate d(start); d <= end; d = d.addDays(1) ) {
01223     Event *e = holiday( d );
01224     if ( e ) {
01225       holidays.append( e );
01226       if ( holidaysFlags & TimeBoxes ) {
01227         timeboxItems.append( new PrintCellItem( e, QDateTime(d, QTime(0,0,0) ),
01228             QDateTime( d.addDays(1), QTime(0,0,0) ) ) );
01229       }
01230       if ( holidaysFlags & Text ) {
01231         textEvents[ d.day() ] << e->summary();
01232       }
01233     }
01234   }
01235 
01236   QValueList<MonthEventStruct> monthentries;
01237 
01238   for ( Event::List::ConstIterator evit = events.begin();
01239         evit != events.end(); ++evit ) {
01240     Event *e = (*evit);
01241     if (!e) continue;
01242     if ( e->doesRecur() ) {
01243       if ( e->recursOn( start ) ) {
01244         // This occurrence has possibly started before the beginning of the
01245         // month, so obtain the start date before the beginning of the month
01246         QValueList<QDateTime> starttimes = e->startDateTimesForDate( start );
01247         QValueList<QDateTime>::ConstIterator it = starttimes.begin();
01248         for ( ; it != starttimes.end(); ++it ) {
01249           monthentries.append( MonthEventStruct( *it, e->endDateForStart( *it ), e ) );
01250         }
01251       }
01252       // Loop through all remaining days of the month and check if the event
01253       // begins on that day (don't use Event::recursOn, as that will
01254       // also return events that have started earlier. These start dates
01255       // however, have already been treated!
01256       Recurrence *recur = e->recurrence();
01257       QDate d1( start.addDays(1) );
01258       while ( d1 <= end ) {
01259         if ( recur->recursOn(d1) ) {
01260           TimeList times( recur->recurTimesOn( d1 ) );
01261           for ( TimeList::ConstIterator it = times.begin();
01262                 it != times.end(); ++it ) {
01263             QDateTime d1start( d1, *it );
01264             monthentries.append( MonthEventStruct( d1start, e->endDateForStart( d1start ), e ) );
01265           }
01266         }
01267         d1 = d1.addDays(1);
01268       }
01269     } else {
01270       monthentries.append( MonthEventStruct( e->dtStart(), e->dtEnd(), e ) );
01271     }
01272   }
01273   qHeapSort( monthentries );
01274 
01275   QValueList<MonthEventStruct>::ConstIterator mit = monthentries.begin();
01276   QDateTime endofmonth( end, QTime(0,0,0) );
01277   endofmonth = endofmonth.addDays(1);
01278   for ( ; mit != monthentries.end(); ++mit ) {
01279     if ( (*mit).start.date() == (*mit).end.date() ) {
01280       // Show also single-day events as time line boxes
01281       if ( subDailyFlags & TimeBoxes ) {
01282         timeboxItems.append( new PrintCellItem( (*mit).event, (*mit).start, (*mit).end ) );
01283       }
01284       // Show as text in the box
01285       if ( subDailyFlags & Text ) {
01286         textEvents[ (*mit).start.date().day() ] << (*mit).event->summary();
01287       }
01288     } else {
01289       // Multi-day events are always shown as time line boxes
01290       QDateTime thisstart( (*mit).start );
01291       QDateTime thisend( (*mit).end );
01292       if ( thisstart.date()<start ) thisstart = start;
01293       if ( thisend>endofmonth ) thisend = endofmonth;
01294       timeboxItems.append( new PrintCellItem( (*mit).event, thisstart, thisend ) );
01295     }
01296   }
01297 
01298   // For Multi-day events, line them up nicely so that the boxes don't overlap
01299   QPtrListIterator<KOrg::CellItem> it1( timeboxItems );
01300   for( it1.toFirst(); it1.current(); ++it1 ) {
01301     KOrg::CellItem *placeItem = it1.current();
01302     KOrg::CellItem::placeItem( timeboxItems, placeItem );
01303   }
01304   QDateTime starttime( start, QTime( 0, 0, 0 ) );
01305   int newxstartcont = xstartcont;
01306 
01307   QFont oldfont( p.font() );
01308   p.setFont( QFont( "sans-serif", 7 ) );
01309   for( it1.toFirst(); it1.current(); ++it1 ) {
01310     PrintCellItem *placeItem = static_cast<PrintCellItem *>( it1.current() );
01311     int minsToStart = starttime.secsTo( placeItem->start() )/60;
01312     int minsToEnd = starttime.secsTo( placeItem->end() )/60;
01313 
01314     QRect eventBox( xstartcont + placeItem->subCell()*17,
01315            daysBox.top() + round( double( minsToStart*daysBox.height()) / double(maxdays*24*60) ),
01316            14, 0 );
01317     eventBox.setBottom( daysBox.top() + round( double( minsToEnd*daysBox.height()) / double(maxdays*24*60) ) );
01318     drawVerticalBox( p, eventBox, placeItem->event()->summary() );
01319     newxstartcont = QMAX( newxstartcont, eventBox.right() );
01320   }
01321   xstartcont = newxstartcont;
01322 
01323   // For Single-day events, simply print their summaries into the remaining
01324   // space of the day's cell
01325   for ( int d=0; d<daysinmonth; ++d ) {
01326     QStringList dayEvents( textEvents[d+1] );
01327     QString txt = dayEvents.join(", ");
01328     QRect dayBox( xstartcont, daysBox.top()+round(dayheight*d), 0, 0 );
01329     dayBox.setRight( box.right() );
01330     dayBox.setBottom( daysBox.top()+round(dayheight*(d+1)) );
01331     printEventString(p, dayBox, txt, Qt::AlignTop | Qt::AlignLeft | Qt::BreakAnywhere );
01332   }
01333   p.setFont( oldfont );
01334 //   p.setBrush( Qt::NoBrush );
01335   drawBox( p, BOX_BORDER_WIDTH, borderBox );
01336   p.restore();
01337 }
01338 
01340 
01341 void CalPrintPluginBase::drawMonthTable(QPainter &p, const QDate &qd, bool weeknumbers,
01342                                bool recurDaily, bool recurWeekly,
01343                                const QRect &box)
01344 {
01345   int yoffset = mSubHeaderHeight;
01346   int xoffset = 0;
01347   QDate monthDate(QDate(qd.year(), qd.month(), 1));
01348   QDate monthFirst(monthDate);
01349   QDate monthLast(monthDate.addMonths(1).addDays(-1));
01350 
01351 
01352   int weekdayCol = weekdayColumn( monthDate.dayOfWeek() );
01353   monthDate = monthDate.addDays(-weekdayCol);
01354 
01355   if (weeknumbers) {
01356     xoffset += 14;
01357   }
01358 
01359   int rows=(weekdayCol + qd.daysInMonth() - 1)/7 +1;
01360   double cellHeight = ( box.height() - yoffset ) / (1.*rows);
01361   double cellWidth = ( box.width() - xoffset ) / 7.;
01362 
01363   // Precalculate the grid...
01364   // rows is at most 6, so using 8 entries in the array is fine, too!
01365   int coledges[8], rowedges[8];
01366   for ( int i = 0; i <= 7; i++ ) {
01367     rowedges[i] = int( box.top() + yoffset + i*cellHeight );
01368     coledges[i] = int( box.left() + xoffset + i*cellWidth );
01369   }
01370 
01371   if (weeknumbers) {
01372     QFont oldFont(p.font());
01373     QFont newFont(p.font());
01374     newFont.setPointSize(6);
01375     p.setFont(newFont);
01376     QDate weekDate(monthDate);
01377     for (int row = 0; row<rows; ++row ) {
01378       int calWeek = weekDate.weekNumber();
01379       QRect rc( box.left(), rowedges[row], coledges[0] - 3 - box.left(), rowedges[row+1]-rowedges[row] );
01380       p.drawText( rc, Qt::AlignRight | Qt::AlignVCenter, QString::number( calWeek ) );
01381       weekDate = weekDate.addDays( 7 );
01382     }
01383     p.setFont( oldFont );
01384   }
01385 
01386   QRect daysOfWeekBox( box );
01387   daysOfWeekBox.setHeight( mSubHeaderHeight );
01388   daysOfWeekBox.setLeft( box.left()+xoffset );
01389   drawDaysOfWeek( p, monthDate, monthDate.addDays( 6 ), daysOfWeekBox );
01390 
01391   QColor back = p.backgroundColor();
01392   bool darkbg = false;
01393   for ( int row = 0; row < rows; ++row ) {
01394     for ( int col = 0; col < 7; ++col ) {
01395       // show days from previous/next month with a grayed background
01396       if ( (monthDate < monthFirst) || (monthDate > monthLast) ) {
01397         p.setBackgroundColor( back.dark( 120 ) );
01398         darkbg = true;
01399       }
01400       QRect dayBox( coledges[col], rowedges[row], coledges[col+1]-coledges[col], rowedges[row+1]-rowedges[row] );
01401       drawDayBox(p, monthDate, dayBox, false, recurDaily, recurWeekly );
01402       if ( darkbg ) {
01403         p.setBackgroundColor( back );
01404         darkbg = false;
01405       }
01406       monthDate = monthDate.addDays(1);
01407     }
01408   }
01409 }
01410 
01411 
01413 
01414 void CalPrintPluginBase::drawTodo( int &count, Todo *todo, QPainter &p,
01415                                TodoSortField sortField, SortDirection sortDir,
01416                                bool connectSubTodos, bool strikeoutCompleted,
01417                                bool desc, int posPriority, int posSummary,
01418                                int posDueDt, int posPercentComplete,
01419                                int level, int x, int &y, int width,
01420                                int pageHeight, const Todo::List &todoList,
01421                                TodoParentStart *r )
01422 {
01423   QString outStr;
01424   const KLocale *local = KGlobal::locale();
01425   QRect rect;
01426   TodoParentStart startpt;
01427 
01428   // This list keeps all starting points of the parent to-dos so the connection
01429   // lines of the tree can easily be drawn (needed if a new page is started)
01430   static QPtrList<TodoParentStart> startPoints;
01431   if ( level < 1 ) {
01432     startPoints.clear();
01433   }
01434 
01435   // Compute the right hand side of the to-do box
01436   int rhs = posPercentComplete;
01437   if ( rhs < 0 ) rhs = posDueDt; //not printing percent completed
01438   if ( rhs < 0 ) rhs = x+width;  //not printing due dates either
01439 
01440   // size of to-do
01441   outStr=todo->summary();
01442   int left = posSummary + ( level*10 );
01443   rect = p.boundingRect( left, y, ( rhs-left-5 ), -1, Qt::WordBreak, outStr );
01444   if ( !todo->description().isEmpty() && desc ) {
01445     outStr = todo->description();
01446     rect = p.boundingRect( left+20, rect.bottom()+5, width-(left+10-x), -1,
01447                            Qt::WordBreak, outStr );
01448   }
01449   // if too big make new page
01450   if ( rect.bottom() > pageHeight ) {
01451     // first draw the connection lines from parent to-dos:
01452     if ( level > 0 && connectSubTodos ) {
01453       TodoParentStart *rct;
01454       for ( rct = startPoints.first(); rct; rct = startPoints.next() ) {
01455         int start;
01456         int center = rct->mRect.left() + (rct->mRect.width()/2);
01457         int to = p.viewport().bottom();
01458 
01459         // draw either from start point of parent or from top of the page
01460         if ( rct->mSamePage )
01461           start = rct->mRect.bottom() + 1;
01462         else
01463           start = p.viewport().top();
01464         p.moveTo( center, start );
01465         p.lineTo( center, to );
01466         rct->mSamePage = false;
01467       }
01468     }
01469     y=0;
01470     mPrinter->newPage();
01471   }
01472 
01473   // If this is a sub-to-do, r will not be 0, and we want the LH side
01474   // of the priority line up to the RH side of the parent to-do's priority
01475   bool showPriority = posPriority>=0;
01476   int lhs = posPriority;
01477   if ( r ) {
01478     lhs = r->mRect.right() + 1;
01479   }
01480 
01481   outStr.setNum( todo->priority() );
01482   rect = p.boundingRect( lhs, y + 10, 5, -1, Qt::AlignCenter, outStr );
01483   // Make it a more reasonable size
01484   rect.setWidth(18);
01485   rect.setHeight(18);
01486 
01487   // Draw a checkbox
01488   p.setBrush( QBrush( Qt::NoBrush ) );
01489   p.drawRect( rect );
01490   if ( todo->isCompleted() ) {
01491     // cross out the rectangle for completed to-dos
01492     p.drawLine( rect.topLeft(), rect.bottomRight() );
01493     p.drawLine( rect.topRight(), rect.bottomLeft() );
01494   }
01495   lhs = rect.right() + 3;
01496 
01497   // Priority
01498   if ( todo->priority() > 0 && showPriority ) {
01499     p.drawText( rect, Qt::AlignCenter, outStr );
01500   }
01501   startpt.mRect = rect; //save for later
01502 
01503   // Connect the dots
01504   if ( level > 0 && connectSubTodos ) {
01505     int bottom;
01506     int center( r->mRect.left() + (r->mRect.width()/2) );
01507     if ( r->mSamePage )
01508       bottom = r->mRect.bottom() + 1;
01509     else
01510       bottom = 0;
01511     int to( rect.top() + (rect.height()/2) );
01512     int endx( rect.left() );
01513     p.moveTo( center, bottom );
01514     p.lineTo( center, to );
01515     p.lineTo( endx, to );
01516   }
01517 
01518   // summary
01519   outStr=todo->summary();
01520   rect = p.boundingRect( lhs, rect.top(), (rhs-(left + rect.width() + 5)),
01521                          -1, Qt::WordBreak, outStr );
01522 
01523   QRect newrect;
01524   //FIXME: the following code prints underline rather than strikeout text
01525 #if 0
01526   QFont f( p.font() );
01527   if ( todo->isCompleted() && strikeoutCompleted ) {
01528     f.setStrikeOut( true );
01529     p.setFont( f );
01530   }
01531   p.drawText( rect, Qt::WordBreak, outStr, -1, &newrect );
01532   f.setStrikeOut( false );
01533   p.setFont( f );
01534 #endif
01535   //TODO: Remove this section when the code above is fixed
01536   p.drawText( rect, Qt::WordBreak, outStr, -1, &newrect );
01537   if ( todo->isCompleted() && strikeoutCompleted ) {
01538     // strike out the summary text if to-do is complete
01539     // Note: we tried to use a strike-out font and for unknown reasons the
01540     // result was underline instead of strike-out, so draw the lines ourselves.
01541     int delta = p.fontMetrics().lineSpacing();
01542     int lines = ( rect.height() / delta ) + 1;
01543     for ( int i=0; i<lines; i++ ) {
01544       p.moveTo( rect.left(),  rect.top() + ( delta/2 ) + ( i*delta ) );
01545       p.lineTo( rect.right(), rect.top() + ( delta/2 ) + ( i*delta ) );
01546     }
01547   }
01548 
01549   // due date
01550   if ( todo->hasDueDate() && posDueDt>=0 ) {
01551     outStr = local->formatDate( todo->dtDue().date(), true );
01552     rect = p.boundingRect( posDueDt, y, x + width, -1,
01553                            Qt::AlignTop | Qt::AlignLeft, outStr );
01554     p.drawText( rect, Qt::AlignTop | Qt::AlignLeft, outStr );
01555   }
01556 
01557   // percentage completed
01558   bool showPercentComplete = posPercentComplete>=0;
01559   if ( showPercentComplete ) {
01560     int lwidth = 24;
01561     int lheight = 12;
01562     //first, draw the progress bar
01563     int progress = (int)(( lwidth*todo->percentComplete())/100.0 + 0.5);
01564 
01565     p.setBrush( QBrush( Qt::NoBrush ) );
01566     p.drawRect( posPercentComplete, y+3, lwidth, lheight );
01567     if ( progress > 0 ) {
01568       p.setBrush( QColor( 128, 128, 128 ) );
01569       p.drawRect( posPercentComplete, y+3, progress, lheight );
01570     }
01571 
01572     //now, write the percentage
01573     outStr = i18n( "%1%" ).arg( todo->percentComplete() );
01574     rect = p.boundingRect( posPercentComplete+lwidth+3, y, x + width, -1,
01575                            Qt::AlignTop | Qt::AlignLeft, outStr );
01576     p.drawText( rect, Qt::AlignTop | Qt::AlignLeft, outStr );
01577   }
01578 
01579   // description
01580   if ( !todo->description().isEmpty() && desc ) {
01581     y = newrect.bottom() + 5;
01582     outStr = todo->description();
01583     rect = p.boundingRect( left+20, y, x+width-(left+10), -1,
01584                            Qt::WordBreak, outStr );
01585     p.drawText( rect, Qt::WordBreak, outStr, -1, &newrect );
01586   }
01587 
01588   // Set the new line position
01589   y = newrect.bottom() + 10; //set the line position
01590 
01591   // If the to-do has sub-to-dos, we need to call ourselves recursively
01592 #if 0
01593   Incidence::List l = todo->relations();
01594   Incidence::List::ConstIterator it;
01595   startPoints.append( &startpt );
01596   for( it = l.begin(); it != l.end(); ++it ) {
01597     count++;
01598     // In the future, to-dos might also be related to events
01599     // Manually check if the sub-to-do is in the list of to-dos to print
01600     // The problem is that relations() does not apply filters, so
01601     // we need to compare manually with the complete filtered list!
01602     Todo* subtodo = dynamic_cast<Todo *>( *it );
01603     if (subtodo && todoList.contains( subtodo ) ) {
01604       drawTodo( count, subtodo, p, connectSubTodos, strikeoutCompleted,
01605                 desc, posPriority, posSummary, posDueDt, posPercentComplete,
01606                 level+1, x, y, width, pageHeight, todoList, &startpt );
01607     }
01608   }
01609 #endif
01610   // Make a list of all the sub-to-dos related to this to-do.
01611   Todo::List t;
01612   Incidence::List l = todo->relations();
01613   Incidence::List::ConstIterator it;
01614   for( it=l.begin(); it!=l.end(); ++it ) {
01615     // In the future, to-dos might also be related to events
01616     // Manually check if the sub-to-do is in the list of to-dos to print
01617     // The problem is that relations() does not apply filters, so
01618     // we need to compare manually with the complete filtered list!
01619     Todo* subtodo = dynamic_cast<Todo *>( *it );
01620     if ( subtodo && todoList.contains( subtodo ) ) {
01621       t.append( subtodo );
01622     }
01623   }
01624 
01625   // Sort the sub-to-dos and then print them
01626   Todo::List sl = mCalendar->sortTodos( &t, sortField, sortDir );
01627   Todo::List::ConstIterator isl;
01628   startPoints.append( &startpt );
01629   for( isl = sl.begin(); isl != sl.end(); ++isl ) {
01630     count++;
01631     drawTodo( count, ( *isl ), p, sortField, sortDir,
01632               connectSubTodos, strikeoutCompleted,
01633               desc, posPriority, posSummary, posDueDt, posPercentComplete,
01634               level+1, x, y, width, pageHeight, todoList, &startpt );
01635   }
01636   startPoints.remove( &startpt );
01637 }
01638 
01639 int CalPrintPluginBase::weekdayColumn( int weekday )
01640 {
01641   return ( weekday + 7 - KGlobal::locale()->weekStartDay() ) % 7;
01642 }
01643 
01644 void CalPrintPluginBase::drawJournalField( QPainter &p, QString field, QString text,
01645                                        int x, int &y, int width, int pageHeight )
01646 {
01647   if ( text.isEmpty() ) return;
01648 
01649   QString entry( field.arg( text ) );
01650 
01651   QRect rect( p.boundingRect( x, y, width, -1, Qt::WordBreak, entry) );
01652   if ( rect.bottom() > pageHeight) {
01653     // Start new page...
01654     // FIXME: If it's a multi-line text, draw a few lines on this page, and the
01655     // remaining lines on the next page.
01656     y=0;
01657     mPrinter->newPage();
01658     rect = p.boundingRect( x, y, width, -1, Qt::WordBreak, entry);
01659   }
01660   QRect newrect;
01661   p.drawText( rect, Qt::WordBreak, entry, -1, &newrect );
01662   y = newrect.bottom() + 7;
01663 }
01664 
01665 void CalPrintPluginBase::drawJournal( Journal * journal, QPainter &p, int x, int &y,
01666                                   int width, int pageHeight )
01667 {
01668   QFont oldFont( p.font() );
01669   p.setFont( QFont( "sans-serif", 15 ) );
01670   QString headerText;
01671   QString dateText( KGlobal::locale()->
01672         formatDate( journal->dtStart().date(), false ) );
01673 
01674   if ( journal->summary().isEmpty() ) {
01675     headerText = dateText;
01676   } else {
01677     headerText = i18n("Description - date", "%1 - %2")
01678                      .arg( journal->summary() )
01679                      .arg( dateText );
01680   }
01681 
01682   QRect rect( p.boundingRect( x, y, width, -1, Qt::WordBreak, headerText) );
01683   if ( rect.bottom() > pageHeight) {
01684     // Start new page...
01685     y=0;
01686     mPrinter->newPage();
01687     rect = p.boundingRect( x, y, width, -1, Qt::WordBreak, headerText );
01688   }
01689   QRect newrect;
01690   p.drawText( rect, Qt::WordBreak, headerText, -1, &newrect );
01691   p.setFont( oldFont );
01692 
01693   y = newrect.bottom() + 4;
01694 
01695   p.drawLine( x + 3, y, x + width - 6, y );
01696   y += 5;
01697 
01698   drawJournalField( p, i18n("Person: %1"), journal->organizer().fullName(), x, y, width, pageHeight );
01699   drawJournalField( p, i18n("%1"), journal->description(), x, y, width, pageHeight );
01700   y += 10;
01701 }
01702 
01703 
01704 void CalPrintPluginBase::drawSplitHeaderRight( QPainter &p, const QDate &fd,
01705                                            const QDate &td,
01706                                            const QDate &,
01707                                            int width, int )
01708 {
01709   QFont oldFont( p.font() );
01710 
01711   QPen oldPen( p.pen() );
01712   QPen pen( Qt::black, 4 );
01713 
01714   QString title;
01715   if ( mCalSys ) {
01716     if ( fd.month() == td.month() ) {
01717       title = i18n("Date range: Month dayStart - dayEnd", "%1 %2 - %3")
01718         .arg( mCalSys->monthName( fd.month(), false ) )
01719         .arg( mCalSys->dayString( fd, false ) )
01720         .arg( mCalSys->dayString( td, false ) );
01721     } else {
01722       title = i18n("Date range: monthStart dayStart - monthEnd dayEnd", "%1 %2 - %3 %4")
01723         .arg( mCalSys->monthName( fd.month(), false ) )
01724         .arg( mCalSys->dayString( fd, false ) )
01725         .arg( mCalSys->monthName( td.month(), false ) )
01726         .arg( mCalSys->dayString( td, false ) );
01727     }
01728   }
01729 
01730   QFont serifFont("Times", 30);
01731   p.setFont(serifFont);
01732 
01733   int lineSpacing = p.fontMetrics().lineSpacing();
01734   p.drawText( 0, lineSpacing * 0, width, lineSpacing,
01735               Qt::AlignRight | Qt::AlignTop, title );
01736 
01737   title.truncate(0);
01738 
01739   p.setPen( pen );
01740   p.drawLine(300, lineSpacing * 1, width, lineSpacing * 1);
01741   p.setPen( oldPen );
01742 
01743   p.setFont(QFont("Times", 20, QFont::Bold, TRUE));
01744   int newlineSpacing = p.fontMetrics().lineSpacing();
01745   title += QString::number(fd.year());
01746   p.drawText( 0, lineSpacing * 1 + 4, width, newlineSpacing,
01747               Qt::AlignRight | Qt::AlignTop, title );
01748 
01749   p.setFont( oldFont );
01750 }
01751 
01752 #endif
KDE Home | KDE Accessibility Home | Description of Access Keys