korganizer Library API Documentation

calprintbase.cpp

00001 /*
00002     This file is part of KOrganizer.
00003 
00004     Copyright (c) 1998 Preston Brown
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #include <qptrlist.h>
00031 #include <qintdict.h>
00032 #include <qsimplerichtext.h>
00033 
00034 #include <kglobal.h>
00035 #include <klocale.h>
00036 #include <kdebug.h>
00037 #include <kconfig.h>
00038 #include <kcalendarsystem.h>
00039 #include <kprinter.h>
00040 #include <kstringhandler.h>
00041 
00042 #include <libkcal/todo.h>
00043 #include <libkcal/event.h>
00044 #include <libkcal/calendar.h>
00045 
00046 #include "koprefs.h"
00047 #include "koglobals.h"
00048 #ifndef KORG_NOPLUGINS
00049 #include "kocore.h"
00050 #endif
00051 #include "cellitem.h"
00052 
00053 #include "calprintbase.h"
00054 
00055 #ifndef KORG_NOPRINTER
00056 #include "calprintbase.moc"
00057 
00058 int CalPrintBase::mHeaderHeight=72;
00059 int CalPrintBase::mSubHeaderHeight=20;
00060 int CalPrintBase::mMargin=36;
00061 
00062 
00063 class CalPrintBase::TodoParentStart
00064 {
00065   public:
00066     TodoParentStart( QRect pt = QRect(), bool page = true )
00067       : mRect( pt ), mSamePage( page ) {}
00068 
00069     QRect mRect;
00070     bool mSamePage;
00071 };
00072 
00073 class PrintCellItem : public KOrg::CellItem
00074 {
00075   public:
00076     PrintCellItem( Event *event, const QDate &day )
00077       : mEvent( event ), mDay( day )
00078     {
00079     }
00080   
00081     Event *event() const { return mEvent; }
00082 
00083     QString label() const { return mEvent->summary(); }
00084     
00085     bool overlaps( KOrg::CellItem *o ) const
00086     {
00087       PrintCellItem *other = static_cast<PrintCellItem *>( o );
00088 
00089       QDateTime start = event()->dtStart();
00090       QDateTime end = event()->dtEnd();
00091       if ( event()->doesRecur() ) {
00092         start.setDate( mDay );
00093         end.setDate( mDay );
00094       }
00095       QDateTime otherStart = other->event()->dtStart();
00096       QDateTime otherEnd = other->event()->dtEnd();
00097       if ( other->event()->doesRecur() ) {
00098         otherStart.setDate( mDay );
00099         otherEnd.setDate( mDay );
00100       }
00101 
00102 #if 0
00103       kdDebug() << "PrintCellItem::overlaps() " << event()->summary()
00104                 << " <-> " << other->event()->summary() << endl;
00105       kdDebug() << "  start     : " << start.toString() << endl;
00106       kdDebug() << "  end       : " << end.toString() << endl;
00107       kdDebug() << "  otherStart: " << otherStart.toString() << endl;
00108       kdDebug() << "  otherEnd  : " << otherEnd.toString() << endl;
00109 #endif
00110       
00111       return !( otherStart >= end || otherEnd <= start );
00112     }
00113     
00114   private:
00115     Event *mEvent;
00116     QDate mDay;
00117 };
00118 
00119 void setCategoryColors( QPainter &p, Incidence *incidence)
00120 {
00121   QColor bgColor;
00122   QStringList categories = incidence->categories();
00123   QString cat = categories.first();
00124   if (cat.isEmpty())
00125     bgColor = KOPrefs::instance()->mEventColor;
00126   else
00127     bgColor = *(KOPrefs::instance()->categoryColor(cat));
00128   QColor textColor = getTextColor(bgColor);
00129   p.setPen( textColor );
00130   p.setBrush( bgColor );
00131 }
00132 
00133 
00134 
00135 CalPrintBase::CalPrintBase( KPrinter *printer, Calendar *cal, KConfig *cfg )
00136   : QObject(), mPrinter( printer ), mCalendar( cal ), mConfig( cfg )
00137 {
00138 }
00139 
00140 CalPrintBase::~CalPrintBase()
00141 {
00142 }
00143 
00144 
00145 
00146 QWidget *CalPrintBase::configWidget( QWidget *w )
00147 {
00148   QFrame *wdg = new QFrame( w );
00149   QVBoxLayout *layout = new QVBoxLayout( wdg );
00150 
00151   QLabel *title = new QLabel( description(), wdg );
00152   QFont titleFont( title->font() );
00153   titleFont.setPointSize( 20 );
00154   titleFont.setBold( true );
00155   title->setFont( titleFont );
00156 
00157   layout->addWidget( title );
00158   layout->addWidget( new QLabel( longDescription(), wdg ) );
00159   layout->addSpacing( 20 );
00160   layout->addWidget( new QLabel( i18n("This printing style does not "
00161                                       "have any configuration options."),
00162                                  wdg ) );
00163   layout->addStretch();
00164   return wdg;
00165 }
00166 
00167 void CalPrintBase::doPrint()
00168 {
00169   QPainter p;
00170 
00171   mPrinter->setColorMode( (mUseColors)?(KPrinter::Color):(KPrinter::GrayScale));
00172 
00173   p.begin(mPrinter);
00174   // the painter initially begins at 72 dpi per the Qt docs.
00175   // we want half-inch margins.
00176   p.setViewport(mMargin, mMargin,
00177                 p.viewport().width()-mMargin,
00178                 p.viewport().height()-mMargin);
00179   int pageWidth = p.viewport().width();
00180   int pageHeight = p.viewport().height();
00181 
00182   print(p, pageWidth, pageHeight);
00183 
00184   p.end();
00185 }
00186 
00187 void CalPrintBase::doLoadConfig()
00188 {
00189   if ( mConfig ) {
00190     KConfigGroupSaver saver( mConfig, description() );
00191     mConfig->sync();
00192     QDateTime currDate( QDate::currentDate() );
00193     mFromDate = mConfig->readDateTimeEntry( "FromDate", &currDate ).date();
00194     mToDate = mConfig->readDateTimeEntry( "ToDate" ).date();
00195     mUseColors = mConfig->readBoolEntry( "UseColors", true );
00196     loadConfig();
00197   } else {
00198     kdDebug(5850) << "No config available in loadConfig!!!!" << endl;
00199   }
00200 }
00201 
00202 void CalPrintBase::doSaveConfig()
00203 {
00204   if ( mConfig ) {
00205     KConfigGroupSaver saver( mConfig, description() );
00206     saveConfig();
00207     mConfig->writeEntry( "FromDate", QDateTime( mFromDate ) );
00208     mConfig->writeEntry( "ToDate", QDateTime( mToDate ) );
00209     mConfig->writeEntry( "UseColors", mUseColors );
00210     mConfig->sync();
00211   } else {
00212     kdDebug(5850) << "No config available in saveConfig!!!!" << endl;
00213   }
00214 }
00215 
00217 
00218 void CalPrintBase::drawHeader( QPainter &p, QString title,
00219     const QDate &month1, const QDate &month2,
00220     int x, int y, int width, int height )
00221 {
00222   p.drawRect(x, y, width, height);
00223   p.fillRect( x+1, y+1,
00224               width-2,height-2,
00225               QBrush(Dense7Pattern) );
00226 
00227   QString myOwner(mCalendar->getOwner());
00228 
00229   int right=x+width;
00230 
00231   // print previous month for month view, print current for todo, day and week
00232   int smallMonthWidth=width/4-10;
00233   if (smallMonthWidth>100) smallMonthWidth=100;
00234   if (month2.isValid()) {
00235     right -= (10+smallMonthWidth);
00236     drawSmallMonth(p, QDate(month2.year(), month2.month(), 1),
00237                    right, y+2, smallMonthWidth, height-4);
00238     right-=10;
00239   }
00240   if (month1.isValid()) {
00241     right -= (10+smallMonthWidth);
00242     drawSmallMonth(p, QDate(month1.year(), month1.month(), 1),
00243                    right, y+2, smallMonthWidth, height-4);
00244     right-=10;
00245   }
00246 
00247   // Print the titles...
00248   QFont oldFont(p.font());
00249   p.setFont( QFont("helvetica", 18, QFont::Bold) );
00250   QRect textRect( x+5, y+5, right-10-x, height-10 );
00251   p.drawText( textRect, Qt::AlignLeft | Qt::AlignTop | Qt::WordBreak, title );
00252   p.setFont(oldFont);
00253 }
00254 
00255 
00256 void CalPrintBase::drawSmallMonth(QPainter &p, const QDate &qd,
00257     int x, int y, int width, int height)
00258 {
00259   bool firstCol = true;
00260   QDate monthDate(QDate(qd.year(), qd.month(), 1));
00261   QDate monthDate2;
00262   int month = monthDate.month();
00263 
00264   // draw the title
00265   QFont oldFont( p.font() );
00266   p.setFont(QFont("helvetica", 8, QFont::Bold));
00267   //  int lineSpacing = p.fontMetrics().lineSpacing();
00268   const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00269   p.drawText(x, y, width, height/4, AlignCenter, calSys->monthName( qd ) );
00270 
00271   int cellWidth = width/7;
00272   int cellHeight = height/8;
00273   QString tmpStr;
00274 
00275   // correct begin of week
00276   int weekdayCol = weekdayColumn( qd.dayOfWeek() );
00277   monthDate2 = monthDate.addDays(-weekdayCol);
00278 
00279   // draw days of week
00280    p.setFont(QFont("helvetica", 8, QFont::Bold));
00281   for (int col = 0; col < 7; col++) {
00282     // tmpStr.sprintf("%c",(const char*)monthDate2.dayName(monthDate2.dayOfWeek()));
00283     tmpStr=calSys->weekDayName( monthDate2 )[0].upper();
00284     p.drawText(x+col*cellWidth, y+height/4, cellWidth, cellHeight,
00285                AlignCenter, tmpStr);
00286     monthDate2 = monthDate2.addDays(1);
00287   }
00288 
00289   // draw separator line
00290   p.drawLine(x, y+height/4+cellHeight, x+width, y+height/4+cellHeight);
00291 
00292   for (int row = 0; row < 5; row++) {
00293     for (int col = 0; col < 7; col++) {
00294       if (monthDate.month() != month)
00295         break;
00296       if (firstCol) {
00297         firstCol = true;
00298         col = weekdayColumn( monthDate.dayOfWeek() );
00299       }
00300       p.drawText( x+col*cellWidth,
00301                   y+height/4+cellHeight+(row*cellHeight),
00302                   cellWidth, cellHeight, AlignCenter,
00303                   tmpStr.setNum(monthDate.day()) );
00304       monthDate = monthDate.addDays(1);
00305     }
00306   }
00307   p.setFont( oldFont );
00308 }
00309 
00310 
00312 
00313 /*
00314  * This routine draws a header box over the main part of the calendar
00315  * containing the days of the week.
00316  */
00317 void CalPrintBase::drawDaysOfWeek(QPainter &p,
00318     const QDate &fromDate, const QDate &toDate,
00319     int x, int y, int width, int height)
00320 {
00321   int cellWidth = width/(fromDate.daysTo( toDate )+1);
00322   int currx=x;
00323   QDate cellDate(fromDate);
00324 
00325   while (cellDate<=toDate) {
00326     drawDaysOfWeekBox(p, cellDate, currx, y, cellWidth, height);
00327     currx+=cellWidth;
00328     cellDate = cellDate.addDays(1);
00329   }
00330 }
00331 
00332 
00333 void CalPrintBase::drawDaysOfWeekBox(QPainter &p, const QDate &qd,
00334     int x, int y, int width, int height)
00335 {
00336   const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00337 
00338   QFont oldFont( p.font() );
00339   p.setFont( QFont( "helvetica", 10, QFont::Bold ) );
00340   p.drawRect( x, y, width, height );
00341   p.fillRect( x+1, y+1,
00342               width-2, height-2,
00343               QBrush( Dense7Pattern ) );
00344   p.drawText( x+5, y, width-10, height, AlignCenter | AlignVCenter,
00345              calSys->weekDayName( qd ) );
00346   p.setFont( oldFont );
00347 }
00348 
00349 
00350 void CalPrintBase::drawTimeLine(QPainter &p,
00351     const QTime &fromTime, const QTime &toTime,
00352     int x, int y, int width, int height)
00353 {
00354   p.drawRect(x, y, width, height);
00355 
00356   int totalsecs=fromTime.secsTo(toTime);
00357   float minlen=(float)height*60./(float)totalsecs;
00358   float cellHeight=(60.*(float)minlen);
00359   float currY=y;
00360 
00361   QTime curTime( fromTime );
00362   QTime endTime( toTime );
00363   if ( fromTime.minute() > 30 )
00364     curTime = QTime( fromTime.hour()+1, 0, 0 );
00365   else if ( fromTime.minute() > 0 ) {
00366     curTime = QTime( fromTime.hour(), 30, 0 );
00367     float yy = currY + minlen*(float)fromTime.secsTo( curTime )/60.;
00368     p.drawLine( x+width/2, (int)yy, x+width, (int)yy );
00369     curTime = QTime( fromTime.hour()+1, 0, 0 );
00370   }
00371   currY += ( fromTime.secsTo(curTime)*minlen/60 );
00372 
00373   while ( curTime < endTime ) {
00374     p.drawLine( x, (int)currY, x+width, (int)currY );
00375     int newY=(int)(currY+cellHeight/2.);
00376     QString numStr;
00377     if (newY < y+height) {
00378       QFont oldFont( p.font() );
00379       p.drawLine(x+width/2, (int)newY, x+width, (int)newY);
00380       // draw the time:
00381       if ( !KGlobal::locale()->use12Clock() ) {
00382         numStr.setNum(curTime.hour());
00383         if (cellHeight > 30) {
00384           p.setFont(QFont("helvetica", 16, QFont::Bold));
00385         } else {
00386           p.setFont(QFont("helvetica", 12, QFont::Bold));
00387         }
00388         p.drawText(x+2, (int)currY+2, width/2-2, (int)cellHeight,
00389                   AlignTop|AlignRight, numStr);
00390         p.setFont(QFont("helvetica", 10, QFont::Normal));
00391         p.drawText(x+width/2, (int)currY+2, width/2+2, (int)(cellHeight/2)-3,
00392                   AlignTop | AlignLeft, "00");
00393       } else {
00394         QTime time( curTime.hour(), 0 );
00395         numStr = KGlobal::locale()->formatTime( time );
00396         p.setFont(QFont("helvetica", 14, QFont::Bold));
00397         p.drawText(x+2, (int)currY+2, width-4, (int)cellHeight/2-3,
00398                   AlignTop|AlignLeft, numStr);
00399       }
00400       currY+=cellHeight;
00401     p.setFont( oldFont );
00402     } // enough space for half-hour line and time
00403     if (curTime.secsTo(endTime)>3600)
00404       curTime=curTime.addSecs(3600);
00405     else curTime=endTime;
00406   } // currTime<endTime
00407 }
00408 
00409 
00411 
00417 void CalPrintBase::drawAllDayBox(QPainter &p, Event::List &eventList,
00418     const QDate &qd, bool expandable,
00419     int x, int y, int width, int &height)
00420 {
00421   Event::List::Iterator it, itold;
00422 
00423   int offset=y;
00424 
00425   p.setBrush(QBrush(Dense7Pattern));
00426   QPen oldPen(p.pen());
00427   QColor oldBgColor(p.backgroundColor());
00428   QBrush oldBrush(p.brush());
00429   QString multiDayStr;
00430 
00431   it = eventList.begin();
00432 #ifndef KORG_NOPLUGINS
00433   QString hstring(KOCore::self()->holiday(qd));
00434   if (!hstring.isEmpty()) {
00435     Event*holiday=new Event();
00436     holiday->setDtStart(qd);
00437     holiday->setDtEnd(qd);
00438     holiday->setFloats(true);
00439     holiday->setCategories(i18n("Holiday"));
00440     eventList.prepend(holiday);
00441   }
00442 #endif
00443   Event *currEvent = 0;
00444   // First, print all floating events
00445   while( it!=eventList.end() ) {
00446     currEvent=*it;
00447     itold=it;
00448     ++it;
00449     if ( currEvent->doesFloat() ) {
00450       // set the colors according to the categories
00451       if (expandable) {
00452         if (mUseColors)
00453           setCategoryColors(p, currEvent);
00454 
00455         p.drawRect( x, offset, width, height );
00456         p.drawText( x+5, offset+5, width-10, height-10, 
00457                     AlignCenter | AlignVCenter | AlignJustify | WordBreak,
00458                     currEvent->summary() );
00459         // reset the colors
00460         p.setBrush( oldBrush );
00461         p.setPen( oldPen );
00462         p.setBackgroundColor(oldBgColor);
00463 
00464         offset += height;
00465       } else {
00466         if (!multiDayStr.isEmpty()) multiDayStr+=", ";
00467         multiDayStr += currEvent->summary()+"\n";
00468       }
00469       eventList.remove( itold );
00470     }
00471   }
00472 
00473   if (!expandable) {
00474     p.drawRect(x, offset, width, height);
00475     if (!multiDayStr.isEmpty()) {
00476       p.fillRect(x+1, offset+1, width-2, height-2, QBrush(Dense5Pattern) );
00477       p.drawText( x+5, offset+5, width-10, height-10, 
00478                   AlignCenter | AlignVCenter | AlignJustify | WordBreak, 
00479                   multiDayStr);
00480     }
00481   } else {
00482     height=offset-y;
00483   }
00484 }
00485 
00486 
00487 void CalPrintBase::drawAgendaDayBox( QPainter &p, Event::List &events,
00488                                      const QDate &qd, bool expandable,
00489                                      QTime &fromTime, QTime &toTime,
00490                                      int x, int y, int width, int height )
00491 {
00492   p.drawRect( x, y, width, height );
00493 
00494   Event *event;
00495 
00496   if ( expandable ) {
00497     // Adapt start/end times to include complete events
00498     Event::List::ConstIterator it;
00499     for ( it = events.begin(); it != events.end(); ++it ) {
00500       event = *it;
00501       if ( event->dtStart().time() < fromTime )
00502         fromTime = event->dtStart().time();
00503       if ( event->dtEnd().time() > toTime )
00504         toTime = event->dtEnd().time();
00505     }
00506   }
00507 
00508   // Show at least one hour
00509   if ( fromTime.secsTo( toTime ) < 3600 ) {
00510     fromTime = QTime( fromTime.hour(), 0, 0 );
00511     toTime = fromTime.addSecs( 3600 );
00512   }
00513 
00514   // calculate the height of a cell and of a minute
00515   int totalsecs = fromTime.secsTo( toTime );
00516   float minlen = height * 60. / totalsecs;
00517   float cellHeight = 60. * minlen;
00518   float currY = y;
00519 
00520   // print grid:
00521   QTime curTime( QTime( fromTime.hour(), 0, 0 ) );
00522   currY += fromTime.secsTo( curTime ) * minlen / 60;
00523 
00524   while ( curTime < toTime && curTime.isValid() ) {
00525     if ( currY > y ) p.drawLine( x, int( currY ), x + width, int( currY ) );
00526     currY += cellHeight / 2;
00527     if ( ( currY > y ) && ( currY < y + height ) ) {
00528       QPen oldPen( p.pen() );
00529       p.setPen( QColor( 192, 192, 192 ) );
00530       p.drawLine( x, int( currY ), x + width, int( currY ) );
00531       p.setPen( oldPen );
00532     } // enough space for half-hour line
00533     if ( curTime.secsTo( toTime ) > 3600 )
00534       curTime = curTime.addSecs( 3600 );
00535     else curTime = toTime;
00536     currY += cellHeight / 2;
00537   }
00538 
00539   QDateTime startPrintDate = QDateTime( qd, fromTime );
00540   QDateTime endPrintDate = QDateTime( qd, toTime );
00541 
00542   // Calculate horizontal positions and widths of events taking into account
00543   // overlapping events
00544 
00545   QPtrList<KOrg::CellItem> cells;
00546   cells.setAutoDelete( true );
00547 
00548   Event::List::ConstIterator itEvents;
00549   for( itEvents = events.begin(); itEvents != events.end(); ++itEvents ) {
00550     cells.append( new PrintCellItem( *itEvents, qd ) );
00551   }
00552 
00553   QPtrListIterator<KOrg::CellItem> it1( cells );
00554   for( it1.toFirst(); it1.current(); ++it1 ) {
00555     KOrg::CellItem *placeItem = it1.current();
00556 
00557     KOrg::CellItem::placeItem( cells, placeItem );
00558   }
00559 
00560   QPen oldPen( p.pen() );
00561   QColor oldBgColor( p.backgroundColor() );
00562   QBrush oldBrush( p.brush() );
00563   QFont oldFont( p.font() );
00564 
00565   p.setFont( QFont( "helvetica", 10 ) );
00566   p.setBrush( QBrush( Dense7Pattern ) );
00567 
00568   for( it1.toFirst(); it1.current(); ++it1 ) {
00569     PrintCellItem *placeItem = static_cast<PrintCellItem *>( it1.current() );
00570 
00571     drawAgendaItem( placeItem, p, qd, startPrintDate, endPrintDate, minlen, x,
00572                     y, width );
00573 
00574     p.setBrush( oldBrush );
00575     p.setPen( oldPen );
00576     p.setBackgroundColor( oldBgColor );
00577   }
00578   p.setFont( oldFont );
00579 //  p.setBrush( QBrush( NoBrush ) );
00580 }
00581 
00582 
00583 void CalPrintBase::drawAgendaItem( PrintCellItem *item, QPainter &p,
00584                                    const QDate &qd,
00585                                    const QDateTime &startPrintDate,
00586                                    const QDateTime &endPrintDate,
00587                                    float minlen, int x, int y, int width )
00588 {
00589   Event *event = item->event();
00590 
00591   // set the colors according to the categories
00592   if ( mUseColors ) setCategoryColors( p, event );
00593 
00594   // start/end of print area for event
00595   QDateTime startTime = event->dtStart();
00596   QDateTime endTime = event->dtEnd();
00597   if ( event->doesRecur() ) {
00598     startTime.setDate( qd );
00599     endTime.setDate( qd );
00600   }
00601   if ( ( startTime < endPrintDate && endTime > startPrintDate ) ||
00602        ( endTime > startPrintDate && startTime < endPrintDate ) ) {
00603     if ( startTime < startPrintDate ) startTime = startPrintDate;
00604     if ( endTime > endPrintDate ) endTime = endPrintDate;
00605     int eventLength = int( startTime.secsTo( endTime ) / 60. * minlen );
00606     int currentyPos = int( y + startPrintDate.secsTo( startTime ) *
00607                            minlen / 60. );
00608     int currentWidth = width / item->subCells();
00609     int currentX = x + item->subCell() * currentWidth;
00610 
00611     p.drawRect( currentX, currentyPos, currentWidth, eventLength );
00612     int offset = 4;
00613     // print the text vertically centered. If it doesn't fit inside the
00614     // box, align it at the top so the beginning is visible
00615     int flags = AlignLeft | WordBreak;
00616     QRect bound = p.boundingRect ( currentX + offset, currentyPos,
00617                                    currentWidth - 2 * offset, eventLength,
00618                                    flags, event->summary() );
00619     if ( bound.height() >= eventLength - 4 ) flags |= AlignTop;
00620     else flags |= AlignVCenter;
00621     p.drawText( currentX+offset, currentyPos+offset, currentWidth-2*offset,
00622                 eventLength-2*offset, flags, event->summary() );
00623   }
00624 }
00625 
00626 void CalPrintBase::drawDayBox(QPainter &p, const QDate &qd,
00627     int x, int y, int width, int height,
00628     bool fullDate)
00629 {
00630   QString dayNumStr;
00631   QString ampm;
00632   const KLocale*local = KGlobal::locale();
00633 
00634 
00635   // This has to be localized
00636   if (fullDate) {
00637     /*int index;
00638     dayNumStr= qd.toString();
00639     index = dayNumStr.find(' ');
00640     dayNumStr.remove(0, index);
00641     index = dayNumStr.findRev(' ');
00642     dayNumStr.truncate(index);*/
00643 
00644     const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00645     dayNumStr = i18n("weekday month date", "%1 %2 %3")
00646         .arg( calSys->weekDayName( qd ) )
00647         .arg( calSys->monthName( qd ) )
00648         .arg( qd.day() );
00649 //    dayNumStr = local->formatDate(qd);
00650   } else {
00651     dayNumStr = QString::number( qd.day() );
00652   }
00653 
00654   p.eraseRect( x, y, width, height );
00655   p.drawRect( x, y, width, height );
00656   // p.fillRect( x+1, y+1, width-2,height, QBrush(Dense7Pattern) );
00657   p.drawRect( x, y, width, mSubHeaderHeight );
00658   p.fillRect( x+1, y+1, width-2, mSubHeaderHeight-2, QBrush(Dense7Pattern) );
00659   QString hstring;
00660 #ifndef KORG_NOPLUGINS
00661   hstring=KOCore::self()->holiday(qd);
00662 #endif
00663   QFont oldFont( p.font() );
00664 
00665   if (!hstring.isEmpty()) {
00666     p.setFont( QFont( "helvetica", 8, QFont::Bold, true ) );
00667 
00668     p.drawText( x+5, y, width-25, mSubHeaderHeight, AlignLeft | AlignVCenter,
00669                 hstring );
00670   }
00671   p.setFont(QFont("helvetica", 10, QFont::Bold));
00672   p.drawText(x+5, y, width-10, mSubHeaderHeight, AlignRight | AlignVCenter,
00673              dayNumStr);
00674 
00675   Event::List eventList = mCalendar->events( qd, true );
00676   QString outStr;
00677   p.setFont( QFont( "helvetica", 8 ) );
00678   int lineSpacing = p.fontMetrics().lineSpacing();
00679 
00680   int textY=mSubHeaderHeight+3; // gives the relative y-coord of the next printed entry
00681   Event::List::ConstIterator it;
00682   for( it = eventList.begin(); it != eventList.end() && textY<height; ++it ) {
00683     Event *currEvent = *it;
00684     if (currEvent->doesFloat() || currEvent->isMultiDay())
00685       outStr = currEvent->summary();
00686 
00687     else {
00688       QTime t1 = currEvent->dtStart().time();
00689 
00690       outStr = local->formatTime(t1);
00691       outStr += " " + currEvent->summary();
00692       if ( !currEvent->location().isEmpty() )
00693         outStr += " (" + currEvent->location() + ")";
00694 
00695     } // doesFloat
00696 
00697     QSimpleRichText rt( outStr, p.font() );
00698     rt.setWidth( &p, width-10 );
00699     QRect clipRect( x+5, y+textY, rt.width(), rt.height() );
00700     rt.draw( &p, x+5, y+textY, clipRect, QColorGroup() );
00701     textY+=rt.height();
00702   }
00703 
00704   if ( textY<height ) {
00705     Todo::List todos = mCalendar->todos( qd );
00706     Todo::List::ConstIterator it2;
00707     for( it2 = todos.begin(); it2 != todos.end() && textY<height; ++it2 ) {
00708       Todo *todo = *it2;
00709       QString text;
00710       if (todo->hasDueDate()) {
00711         if (!todo->doesFloat()) {
00712           text += KGlobal::locale()->formatTime(todo->dtDue().time());
00713           text += " ";
00714         }
00715       }
00716       text += i18n("To-Do: %1").arg(todo->summary());
00717 
00718       p.drawText(x+5, y+textY, width-10, lineSpacing,
00719                 AlignLeft|AlignBottom, text);
00720       textY+=lineSpacing;
00721     }
00722   }
00723   p.setFont( oldFont );
00724 }
00725 
00726 
00728 
00729 void CalPrintBase::drawWeek(QPainter &p, const QDate &qd,
00730     int x, int y, int width, int height)
00731 {
00732   QDate weekDate = qd;
00733   bool portrait = ( mPrinter->orientation() == KPrinter::Portrait  );
00734   int cellWidth, cellHeight;
00735   int vcells;
00736   if (portrait) {
00737     cellWidth = width/2;
00738     vcells=3;
00739   } else {
00740     cellWidth = width/6;
00741     vcells=1;
00742   }
00743   cellHeight = height/vcells;
00744 
00745   // correct begin of week
00746   int weekdayCol = weekdayColumn( qd.dayOfWeek() );
00747   weekDate = qd.addDays( -weekdayCol );
00748 
00749   for (int i = 0; i < 7; i++, weekDate = weekDate.addDays(1)) {
00750     if (i<5) {
00751       drawDayBox(p, weekDate, x+cellWidth*(int)(i/vcells), y+cellHeight*(i%vcells),
00752         cellWidth, cellHeight, true);
00753     } else if (i==5) {
00754       drawDayBox(p, weekDate, x+cellWidth*(int)(i/vcells), y+cellHeight*(i%vcells),
00755         cellWidth, cellHeight/2, true);
00756     } else if (i==6) {
00757       drawDayBox(p, weekDate, x+cellWidth*(int)((i-1)/vcells),
00758         y+cellHeight*((i-1)%vcells)+cellHeight/2, cellWidth, cellHeight/2, true);
00759     }
00760   } // for i through all weekdays
00761 }
00762 
00763 
00764 void CalPrintBase::drawTimeTable(QPainter &p,
00765     const QDate &fromDate, const QDate &toDate,
00766     QTime &fromTime, QTime &toTime,
00767     int x, int y, int width, int height)
00768 {
00769   // timeline is 1.5 hours:
00770   int alldayHeight = (int)( 3600.*height/(fromTime.secsTo(toTime)+3600.) );
00771   int timelineWidth = 50;
00772   int cellWidth = (int)( (width-timelineWidth)/(fromDate.daysTo(toDate)+1) );
00773   int currY=y;
00774   int currX=x;
00775 
00776   drawDaysOfWeek( p, fromDate, toDate, x+timelineWidth, currY, width-timelineWidth, mSubHeaderHeight);
00777   currY+=mSubHeaderHeight;
00778   drawTimeLine( p, fromTime, toTime, x, currY+alldayHeight,
00779     timelineWidth, height-mSubHeaderHeight-alldayHeight );
00780 
00781   currX=x+timelineWidth;
00782   // draw each day
00783   QDate curDate(fromDate);
00784   while (curDate<=toDate) {
00785     Event::List eventList = mCalendar->events(curDate, true);
00786     drawAllDayBox( p, eventList, curDate, false, currX, currY, cellWidth, alldayHeight);
00787     drawAgendaDayBox( p, eventList, curDate, false, fromTime, toTime, currX,
00788       currY+alldayHeight, cellWidth, height-mSubHeaderHeight-alldayHeight );
00789     currX+=cellWidth;
00790     curDate=curDate.addDays(1);
00791   }
00792 
00793 }
00794 
00795 
00797 
00798 void CalPrintBase::drawMonth(QPainter &p, const QDate &qd, bool weeknumbers,
00799     int x, int y, int width, int height)
00800 {
00801   int yoffset = mSubHeaderHeight;
00802   int xoffset = 0;
00803   QDate monthDate(QDate(qd.year(), qd.month(), 1));
00804   QDate monthFirst(monthDate);
00805   QDate monthLast(monthDate.addMonths(1).addDays(-1));
00806   
00807 
00808   int weekdayCol = weekdayColumn( monthDate.dayOfWeek() );
00809   monthDate = monthDate.addDays(-weekdayCol);
00810 
00811   int rows=(weekdayCol + qd.daysInMonth() - 1)/7 +1;
00812   int cellHeight = (height-yoffset) / rows;
00813 
00814   if (weeknumbers) {
00815     QFont oldFont(p.font());
00816     QFont newFont(p.font());
00817     newFont.setPointSize(6);
00818     p.setFont(newFont);
00819     xoffset += 14;
00820     QDate weekDate(monthDate);
00821     for (int row = 0; row<rows; row++) {
00822       int calWeek = weekDate.weekNumber();
00823       QRect rc(x, y+yoffset+cellHeight*row, xoffset-1, cellHeight);
00824       p.drawText( rc, AlignRight|AlignVCenter, QString::number(calWeek) );
00825       weekDate = weekDate.addDays(7);
00826     }
00827     p.setFont(oldFont);
00828   }
00829 
00830   drawDaysOfWeek( p, monthDate, monthDate.addDays(6), x+xoffset, y, width-xoffset, mSubHeaderHeight );
00831   int cellWidth = (width-xoffset) / 7;
00832 
00833   QColor back = p.backgroundColor();
00834   bool darkbg = false;
00835   for (int row = 0; row < rows; row++) {
00836     for (int col = 0; col < 7; col++) {
00837       // show days from previous/next month with a grayed background
00838       if ( (monthDate < monthFirst) || (monthDate > monthLast) ) {
00839         p.setBackgroundColor( back.dark( 120 ) );
00840         darkbg = true;
00841       }
00842       drawDayBox(p, monthDate, x+xoffset+col*cellWidth, y+yoffset+row*cellHeight,
00843                  cellWidth, cellHeight);
00844       if ( darkbg ) {
00845         p.setBackgroundColor( back );
00846         darkbg = false;
00847       }
00848       monthDate = monthDate.addDays(1);
00849     }
00850   }
00851 }
00852 
00853 
00855 
00856 void CalPrintBase::drawTodo( int &count, Todo * item, QPainter &p, bool connectSubTodos,
00857     bool desc, int pospriority, int possummary, int posDueDt, int level,
00858     int x, int &y, int width, int pageHeight, const Todo::List &todoList,
00859     TodoParentStart *r )
00860 {
00861   QString outStr;
00862 //  int fontHeight = 10;
00863   const KLocale *local = KGlobal::locale();
00864   int priority=item->priority();
00865   int posdue=posDueDt;
00866   if (posdue<0) posdue=x+width;
00867   QRect rect;
00868   TodoParentStart startpt;
00869   // This list keeps all starting points of the parent todos so the connection
00870   // lines of the tree can easily be drawn (needed if a new page is started)
00871   static QPtrList<TodoParentStart> startPoints;
00872   if (level<1) {
00873     startPoints.clear();
00874   }
00875 
00876   // size of item
00877   outStr=item->summary();
00878   int left = possummary+(level*10);
00879   rect = p.boundingRect(left, y, (posdue-left-5),-1, WordBreak, outStr);
00880   if ( !item->description().isEmpty() && desc ) {
00881     outStr = item->description();
00882     rect = p.boundingRect( left+20, rect.bottom()+5, width-(left+10-x), -1,
00883                            WordBreak, outStr );
00884   }
00885   // if too big make new page
00886   if ( rect.bottom() > pageHeight) {
00887     // first draw the connection lines from parent todos:
00888     if (level > 0 && connectSubTodos) {
00889       TodoParentStart *rct;
00890       for ( rct = startPoints.first(); rct; rct = startPoints.next() ) {
00891         int start;
00892         int center = rct->mRect.left() + (rct->mRect.width()/2);
00893         int to = p.viewport().bottom();
00894 
00895         // draw either from start point of parent or from top of the page
00896         if (rct->mSamePage)
00897           start = rct->mRect.bottom() + 1;
00898         else
00899           start = p.viewport().top();
00900         p.moveTo( center, start );
00901         p.lineTo( center, to );
00902         rct->mSamePage=false;
00903       }
00904     }
00905     y=0;
00906     mPrinter->newPage();
00907   }
00908 
00909   // If this is a sub-item, r will not be 0, and we want the LH side of the priority line up
00910   //to the RH side of the parent item's priority
00911   bool showPriority = pospriority>=0;
00912   if (r) {
00913     pospriority = r->mRect.right() + 1;
00914   }
00915 
00916   outStr.setNum(priority);
00917   rect = p.boundingRect(pospriority, y + 10, 5, -1, AlignCenter, outStr);
00918   // Make it a more reasonable size
00919   rect.setWidth(18);
00920   rect.setHeight(18);
00921   
00922   // Priority
00923   if ( priority > 0 && showPriority ) {
00924     p.drawText(rect, AlignCenter, outStr);
00925     p.drawRect(rect);
00926     // cross out the rectangle for completed items
00927     if ( item->isCompleted() ) {
00928       p.drawLine( rect.topLeft(), rect.bottomRight() );
00929       p.drawLine( rect.topRight(), rect.bottomLeft() );
00930     }
00931   }
00932   startpt.mRect = rect; //save for later
00933 
00934   // Connect the dots
00935   if (level > 0 && connectSubTodos) {
00936     int bottom;
00937     int center( r->mRect.left() + (r->mRect.width()/2) );
00938     if (r->mSamePage )
00939       bottom = r->mRect.bottom() + 1;
00940     else
00941       bottom = 0;
00942     int to( rect.top() + (rect.height()/2) );
00943     int endx( rect.left() );
00944     p.moveTo(center, bottom);
00945     p.lineTo(center, to);
00946     p.lineTo(endx, to);
00947   }
00948 
00949   // if completed, use strike out font
00950   QFont ft( p.font() );
00951   ft.setStrikeOut( item->isCompleted() );
00952   p.setFont( ft );
00953   // summary
00954   outStr=item->summary();
00955   rect = p.boundingRect( left, rect.top(), (posdue-(left + rect.width() + 5)),
00956     -1, WordBreak, outStr);
00957   QRect newrect;
00958   p.drawText( rect, WordBreak, outStr, -1, &newrect );
00959   ft.setStrikeOut(false);
00960   p.setFont(ft);
00961 
00962   // due
00963   if ( item->hasDueDate() && posDueDt>=0 ) {
00964     outStr = local->formatDate(item->dtDue().date(),true);
00965     rect = p.boundingRect(posdue, y, x+width, -1, AlignTop|AlignLeft, outStr);
00966     p.drawText(rect, AlignTop|AlignLeft, outStr);
00967   }
00968 
00969   if ( !item->description().isEmpty() && desc ) {
00970     y=newrect.bottom() + 5;
00971     outStr = item->description();
00972     rect = p.boundingRect( left+20, y, x+width-(left+10), -1,
00973                            WordBreak, outStr );
00974     p.drawText( rect, WordBreak, outStr, -1, &newrect );
00975   }
00976 
00977   // Set the new line position
00978   y=newrect.bottom() + 10; //set the line position
00979 
00980   // If the item has subitems, we need to call ourselves recursively
00981   Incidence::List l = item->relations();
00982   Incidence::List::ConstIterator it;
00983   startPoints.append( &startpt );
00984   for( it = l.begin(); it != l.end(); ++it ) {
00985     count++;
00986     // In the future, todos might also be related to events
00987     // Manually check if the subtodo is in the list of todos to print
00988     // The problem is that relations() does not apply filters, so
00989     // we need to compare manually with the complete filtered list!
00990     Todo* subtodo = dynamic_cast<Todo *>( *it );
00991     if (subtodo && todoList.contains( subtodo ) ) {
00992       drawTodo( count, subtodo, p, connectSubTodos,
00993           desc, pospriority, possummary, posDueDt, level+1,
00994           x, y, width, pageHeight, todoList, &startpt);
00995     }
00996   }
00997   startPoints.remove(&startpt);
00998 }
00999 
01000 int CalPrintBase::weekdayColumn( int weekday )
01001 {
01002   return ( weekday + 7 - KGlobal::locale()->weekStartDay() ) % 7;
01003 }
01004 
01005 void CalPrintBase::drawSplitHeaderRight( QPainter &p, const QDate &fd,
01006                                          const QDate &td,
01007                                          const QDate &,
01008                                          int width, int )
01009 {
01010   QFont oldFont( p.font() );
01011   
01012   QPen oldPen( p.pen() );
01013   QPen pen( black,4);
01014   
01015   QString title;
01016   const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
01017   if ( fd.month() == td.month() ) {
01018     title = i18n("Date range: Month dayStart - dayEnd", "%1 %2 - %3")
01019       .arg( calSys->monthName( fd.month(), false ) )
01020       .arg( calSys->dayString( fd, false ) )
01021       .arg( calSys->dayString( td, false ) );
01022   } else {
01023     title = i18n("Date range: monthStart dayStart - monthEnd dayEnd", "%1 %2 - %3 %4")
01024       .arg( calSys->monthName( fd.month(), false ) )
01025       .arg( calSys->dayString( fd, false ) )
01026       .arg( calSys->monthName( td.month(), false ) )
01027       .arg( calSys->dayString( td, false ) );
01028   }
01029 
01030   QFont serifFont("Times", 30);
01031   p.setFont(serifFont);
01032 
01033   int lineSpacing = p.fontMetrics().lineSpacing();
01034   p.drawText(0, lineSpacing * 0, width, lineSpacing, AlignRight | AlignTop, title );
01035 
01036   title.truncate(0);
01037 
01038   p.setPen( pen );
01039   p.drawLine(300, lineSpacing * 1, width, lineSpacing * 1);
01040   p.setPen( oldPen );
01041 
01042   p.setFont(QFont("Times", 20, QFont::Bold, TRUE));
01043   int newlineSpacing = p.fontMetrics().lineSpacing();
01044   title += QString::number(fd.year());
01045   p.drawText( 0, lineSpacing * 1 + 4, width, newlineSpacing, AlignRight | AlignTop, title );
01046   
01047   p.setFont( oldFont );
01048 }
01049 
01050 #endif
KDE Logo
This file is part of the documentation for korganizer Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 25 11:20:57 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003