korganizer

calprintpluginbase.cpp

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