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