-rw-r--r-- | korganizer/calprintbase.cpp | 1304 |
1 files changed, 1304 insertions, 0 deletions
diff --git a/korganizer/calprintbase.cpp b/korganizer/calprintbase.cpp new file mode 100644 index 0000000..af32ebc --- a/dev/null +++ b/korganizer/calprintbase.cpp @@ -0,0 +1,1304 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 1998 Preston Brown + Copyright (c) 2003 Reinhold Kainhofer <reinhold@kainhofer.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qpainter.h> +#include <qlayout.h> +#include <qframe.h> +#include <qlabel.h> +#include <qptrlist.h> +#include <qintdict.h> +#include <qfontmetrics.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> +#include <kconfig.h> +#include <kcalendarsystem.h> +#include <kprinter.h> + +#include <libkcal/todo.h> +#include <libkcal/event.h> +#include <libkcal/calendar.h> + +#include "koprefs.h" +#include "koglobals.h" +#ifndef KORG_NOPLUGINS +#include "kocore.h" +#endif +#include "cellitem.h" + +#include "calprintbase.h" + +#ifndef KORG_NOPRINTER +//#include "calprintbase.moc" + +int CalPrintBase::mHeaderHeight=90; +int CalPrintBase::mSubHeaderHeight=20; +int CalPrintBase::mMargin=36; + + + +class CalPrintBase::TodoParentStart +{ + public: + TodoParentStart( QRect pt = QRect(), bool page = true ) + : mRect( pt ), mSamePage( page ) {} + + QRect mRect; + bool mSamePage; +}; + +class PrintCellItem : public KOrg::CellItem +{ + public: + PrintCellItem( Event *event, const QDate &day ) + : mEvent( event ), mDay( day ) + { + } + + Event *event() const { return mEvent; } + + QString label() const { return mEvent->summary(); } + + bool overlaps( KOrg::CellItem *o ) const + { + PrintCellItem *other = static_cast<PrintCellItem *>( o ); + + QDateTime start = event()->dtStart(); + QDateTime end = event()->dtEnd(); + if ( event()->doesRecur() ) { + start.setDate( mDay ); + end.setDate( mDay ); + } + QDateTime otherStart = other->event()->dtStart(); + QDateTime otherEnd = other->event()->dtEnd(); + if ( other->event()->doesRecur() ) { + otherStart.setDate( mDay ); + otherEnd.setDate( mDay ); + } + +#if 0 + kdDebug() << "PrintCellItem::overlaps() " << event()->summary() + << " <-> " << other->event()->summary() << endl; + kdDebug() << " start : " << start.toString() << endl; + kdDebug() << " end : " << end.toString() << endl; + kdDebug() << " otherStart: " << otherStart.toString() << endl; + kdDebug() << " otherEnd : " << otherEnd.toString() << endl; +#endif + + return !( otherStart >= end || otherEnd <= start ); + } + + private: + Event *mEvent; + QDate mDay; +}; + +void setCategoryColors( QPainter &p, Incidence *incidence) +{ + QColor bgColor; + QStringList categories = incidence->categories(); + QString cat = categories.first(); + if (cat.isEmpty()) + bgColor = KOPrefs::instance()->mEventColor; + else + bgColor = *(KOPrefs::instance()->categoryColor(cat)); + QColor textColor = Qt::black;//getTextColor(bgColor); + p.setPen( textColor ); + p.setBrush( bgColor ); +} + + + +CalPrintBase::CalPrintBase( KPrinter *printer, Calendar *cal, KConfig *cfg ) + : QObject(), mPrinter( printer ), mCalendar( cal ), mConfig( cfg ) +{ +} + +CalPrintBase::~CalPrintBase() +{ +} + + + +QWidget *CalPrintBase::configWidget( QWidget *w ) +{ + QFrame *wdg = new QFrame( w ); + QVBoxLayout *layout = new QVBoxLayout( wdg ); + + QLabel *title = new QLabel( description(), wdg ); + QFont titleFont( title->font() ); + titleFont.setPointSize( 20 ); + titleFont.setBold( true ); + title->setFont( titleFont ); + + layout->addWidget( title ); + layout->addWidget( new QLabel( longDescription(), wdg ) ); + layout->addSpacing( 20 ); + layout->addWidget( new QLabel( i18n("This printing style does not " + "have any configuration options."), + wdg ) ); + layout->addStretch(); + return wdg; +} +#include <qapplication.h> +void CalPrintBase::doPrint() +{ + QPainter p; + + mPrinter->setColorMode( (mUseColors)?(KPrinter::Color):(KPrinter::GrayScale)); + //#define DUMMY_PRINTER +#ifdef DUMMY_PRINTER + + static QWidget* dummy = 0; + if ( ! dummy ) + dummy = new QWidget( ); + else { + delete dummy; + dummy = new QWidget( ); + + } + dummy->resize( 1024, 1024 ); + dummy->repaint(); + dummy->show(); + dummy->raise(); + dummy->setBackgroundColor( Qt::white); + qApp->processEvents(); + p.begin(dummy); +#else + p.begin(mPrinter); +#endif + // the painter initially begins at 72 dpi per the Qt docs. + // we want half-inch margins. + p.setViewport(mMargin, mMargin, + p.viewport().width()-mMargin, + p.viewport().height()-mMargin); + int pageWidth = p.viewport().width(); + int pageHeight = p.viewport().height(); + + print(p, pageWidth, pageHeight); + + p.end(); +} + +void CalPrintBase::doLoadConfig() +{ + if ( mConfig ) { + mConfig->setGroup(description()); + //KConfigGroupSaver saver( mConfig, description() ); + mConfig->sync(); + QDateTime currDate( QDate::currentDate() ); + mFromDate = mConfig->readDateTimeEntry( "FromDate", &currDate ).date(); + mToDate = mConfig->readDateTimeEntry( "ToDate" ).date(); + mUseColors = mConfig->readBoolEntry( "UseColors", false ); + loadConfig(); + } else { + qDebug("no config in CalPrintBase::doLoadConfig "); + } +} + +void CalPrintBase::doSaveConfig() +{ + if ( mConfig ) { + mConfig->setGroup(description()); + // KConfigGroupSaver saver( mConfig, description() ); + saveConfig(); + mConfig->writeEntry( "FromDate", QDateTime( mFromDate ) ); + mConfig->writeEntry( "ToDate", QDateTime( mToDate ) ); + mConfig->writeEntry( "UseColors", mUseColors ); + mConfig->sync(); + } else { + qDebug("no config in CalPrintBase::doSveConfig "); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void CalPrintBase::drawHeader( QPainter &p, QString title, + const QDate &month1, const QDate &month2, + int x, int y, int width, int height ) +{ + p.drawRect(x, y, width, height); + // p.fillRect( x+1, y+1, +// width-2,height-2, +// QBrush(Dense7Pattern) ); + + QString myOwner(mCalendar->getOwner()); + + int right=x+width; + + // print previous month for month view, print current for todo, day and week + int smallMonthWidth=width/4-10; + if (smallMonthWidth>100) smallMonthWidth=100; + if (month2.isValid()) { + right -= (10+smallMonthWidth); + drawSmallMonth(p, QDate(month2.year(), month2.month(), 1), + right, y+2, smallMonthWidth, height-4); + right-=10; + } + if (month1.isValid()) { + right -= (10+smallMonthWidth); + drawSmallMonth(p, QDate(month1.year(), month1.month(), 1), + right, y+2, smallMonthWidth, height-4); + right-=10; + } + + // Print the titles... + QFont font("helvetica", 18, QFont::Bold); + p.setFont(font); + QRect textRect( x+5, y+5, right-10-x, height-10 ); + p.drawText( textRect, Qt::AlignLeft | Qt::AlignTop | Qt::WordBreak, title ); +} + + +void CalPrintBase::drawSmallMonth(QPainter &p, const QDate &qd, + int x, int y, int width, int height) +{ + bool firstCol = true; + QDate monthDate(QDate(qd.year(), qd.month(), 1)); + QDate monthDate2; + int month = monthDate.month(); + + // draw the title + p.setFont(QFont("helvetica", 7, QFont::Bold)); + // int lineSpacing = p.fontMetrics().lineSpacing(); + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + p.drawText(x, y, width, height/4, AlignCenter, calSys->monthName( qd ) ); + + int cellWidth = width/7; + int cellHeight = height/8; + QString tmpStr; + + // correct begin of week + int weekdayCol = weekdayColumn( qd.dayOfWeek() ); + monthDate2 = monthDate.addDays(-weekdayCol); + + // draw days of week + p.setFont(QFont("helvetica", 7, QFont::Bold)); + for (int col = 0; col < 7; col++) { + // tmpStr.sprintf("%c",(const char*)monthDate2.dayName(monthDate2.dayOfWeek())); + tmpStr=calSys->weekDayName( monthDate2 )[0].upper(); + p.drawText(x+col*cellWidth, y+height/4, cellWidth, cellHeight, + AlignCenter, tmpStr); + monthDate2 = monthDate2.addDays(1); + } + + // draw separator line + p.drawLine(x, y+height/4+cellHeight, x+width, y+height/4+cellHeight); + + for (int row = 0; row < 5; row++) { + for (int col = 0; col < 7; col++) { + if (monthDate.month() != month) + break; + if (firstCol) { + firstCol = true; + col = weekdayColumn( monthDate.dayOfWeek() ); + } + p.drawText( x+col*cellWidth, + y+height/4+cellHeight+(row*cellHeight), + cellWidth, cellHeight, AlignCenter, + tmpStr.setNum(monthDate.day()) ); + monthDate = monthDate.addDays(1); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// + +/* + * This routine draws a header box over the main part of the calendar + * containing the days of the week. + */ +void CalPrintBase::drawDaysOfWeek(QPainter &p, + const QDate &fromDate, const QDate &toDate, + int x, int y, int width, int height) +{ + int cellWidth = width/(fromDate.daysTo( toDate )+1); + int currx=x; + QDate cellDate(fromDate); + + while (cellDate<=toDate) { + drawDaysOfWeekBox(p, cellDate, currx, y, cellWidth, height); + currx+=cellWidth; + cellDate = cellDate.addDays(1); + } +} + + +void CalPrintBase::drawDaysOfWeekBox(QPainter &p, const QDate &qd, + int x, int y, int width, int height) +{ + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + + p.setFont( QFont( "helvetica", 10, QFont::Bold ) ); + p.drawRect( x, y, width, height ); +// p.fillRect( x+1, y+1, +// width-2, height-2, +// QBrush( Dense7Pattern ) ); + p.drawText( x+5, y, width-10, height, AlignCenter | AlignVCenter, + calSys->weekDayName( qd ) ); +} + + +void CalPrintBase::drawTimeLine(QPainter &p, + const QTime &fromTime, const QTime &toTime, + int x, int y, int width, int height) +{ + p.drawRect(x, y, width, height); + + int totalsecs=fromTime.secsTo(toTime); + float minlen=(float)height*60./(float)totalsecs; + float cellHeight=(60.*(float)minlen); + float currY=y; + + QTime curTime( fromTime ); + QTime endTime( toTime ); + if ( fromTime.minute() > 30 ) + curTime = QTime( fromTime.hour()+1, 0, 0 ); + else if ( fromTime.minute() > 0 ) { + curTime = QTime( fromTime.hour(), 30, 0 ); + float yy = currY + minlen*(float)fromTime.secsTo( curTime )/60.; + p.drawLine( x+width/2, (int)yy, x+width, (int)yy ); + curTime = QTime( fromTime.hour()+1, 0, 0 ); + } + currY += ( fromTime.secsTo(curTime)*minlen/60 ); + + while ( curTime < endTime ) { + p.drawLine( x, (int)currY, x+width, (int)currY ); + int newY=(int)(currY+cellHeight/2.); + QString numStr; + if (newY < y+height) { + p.drawLine(x+width/2, (int)newY, x+width, (int)newY); + // draw the time: + if ( !KGlobal::locale()->use12Clock() ) { + numStr.setNum(curTime.hour()); + if (cellHeight > 30) { + p.setFont(QFont("helvetica", 16, QFont::Bold)); + } else { + p.setFont(QFont("helvetica", 12, QFont::Bold)); + } + p.drawText(x+2, (int)currY+2, width/2-2, (int)cellHeight, + AlignTop|AlignRight, numStr); + p.setFont(QFont("helvetica", 10, QFont::Normal)); + p.drawText(x+width/2, (int)currY+2, width/2+2, (int)(cellHeight/2)-3, + AlignTop | AlignLeft, "00"); + } else { + QTime time( curTime.hour(), 0 ); + numStr = KGlobal::locale()->formatTime( time ); + p.setFont(QFont("helvetica", 14, QFont::Bold)); + p.drawText(x+2, (int)currY+2, width-4, (int)cellHeight/2-3, + AlignTop|AlignLeft, numStr); + } + currY+=cellHeight; + } // enough space for half-hour line and time + if (curTime.secsTo(endTime)>3600) + curTime=curTime.addSecs(3600); + else curTime=endTime; + } // currTime<endTime +} + + +/////////////////////////////////////////////////////////////////////////////// + +/** prints the all-day box for the agenda print view. if expandable is set, + height is the cell height of a single cell, and the returned height will + be the total height used for the all-day events. If !expandable, only one + cell will be used, and multiple events are concatenated using ", ". +*/ +void CalPrintBase::drawAllDayBox(QPainter &p, Event::List &eventList, + const QDate &qd, bool expandable, + int x, int y, int width, int &height) +{ + Event::List::Iterator it, itold; + + int offset=y; + + //p.setBrush(QBrush(Dense7Pattern)); + QPen oldPen(p.pen()); + QColor oldBgColor(p.backgroundColor()); + QBrush oldBrush(p.brush()); + QString multiDayStr; + + it = eventList.begin(); +#ifndef KORG_NOPLUGINS + QString hstring(KOCore::self()->holiday(qd)); + if (!hstring.isEmpty()) { + Event*holiday=new Event(); + holiday->setDtStart(qd); + holiday->setDtEnd(qd); + holiday->setFloats(true); + holiday->setCategories(i18n("Holiday")); + eventList.prepend(holiday); + } +#endif + Event *currEvent = 0; + // First, print all floating events + while( it!=eventList.end() ) { + currEvent=*it; + itold=it; + ++it; + if ( currEvent->doesFloat() ) { + // set the colors according to the categories + QString text = currEvent->summary() ; + if ( ! currEvent->location().isEmpty() ) + text += " ("+currEvent->location()+")"; + if (expandable) { + if (mUseColors) + setCategoryColors(p, currEvent); + + p.drawRect( x, offset, width, height ); + + p.drawText( x+5, offset+5, width-10, height-10, + AlignCenter | AlignVCenter | AlignJustify | WordBreak, + text ); + // reset the colors + p.setBrush( oldBrush ); + p.setPen( oldPen ); + p.setBackgroundColor(oldBgColor); + + offset += height; + } else { + //if (!multiDayStr.isEmpty()) multiDayStr+=", "; + multiDayStr += text+"\n"; + } + eventList.remove( itold ); + } + } + + if (!expandable) { + p.drawRect(x, offset, width, height); + if (!multiDayStr.isEmpty()) { + // p.fillRect(x+1, offset+1, width-2, height-2, QBrush(Dense5Pattern) ); + p.drawText( x+5, offset+5, width-10, height-10, + AlignLeft | AlignTop | AlignJustify , + multiDayStr); + } + } else { + height=offset-y; + } +} + + +void CalPrintBase::drawAgendaDayBox( QPainter &p, Event::List &events, + const QDate &qd, bool expandable, + QTime &fromTime, QTime &toTime, + int x, int y, int width, int height ) +{ + p.drawRect( x, y, width, height ); + + Event *event; + + if ( expandable ) { + // Adapt start/end times to include complete events + Event::List::ConstIterator it; + for ( it = events.begin(); it != events.end(); ++it ) { + event = *it; + if ( event->dtStart().time() < fromTime ) + fromTime = event->dtStart().time(); + if ( event->dtEnd().time() > toTime ) + toTime = event->dtEnd().time(); + } + } + + // Show at least one hour + if ( fromTime.secsTo( toTime ) < 3600 ) { + fromTime = QTime( fromTime.hour(), 0, 0 ); + toTime = fromTime.addSecs( 3600 ); + } + + // calculate the height of a cell and of a minute + int totalsecs = fromTime.secsTo( toTime ); + float minlen = height * 60. / totalsecs; + float cellHeight = 60. * minlen; + float currY = y; + + // print grid: + QTime curTime( QTime( fromTime.hour(), 0, 0 ) ); + currY += fromTime.secsTo( curTime ) * minlen / 60; + + while ( curTime < toTime && curTime.isValid() ) { + if ( currY > y ) p.drawLine( x, int( currY ), x + width, int( currY ) ); + currY += cellHeight / 2; + if ( ( currY > y ) && ( currY < y + height ) ) { + QPen oldPen( p.pen() ); + p.setPen( QColor( 192, 192, 192 ) ); + p.drawLine( x, int( currY ), x + width, int( currY ) ); + p.setPen( oldPen ); + } // enough space for half-hour line + if ( curTime.secsTo( toTime ) > 3600 ) + curTime = curTime.addSecs( 3600 ); + else curTime = toTime; + currY += cellHeight / 2; + } + + QDateTime startPrintDate = QDateTime( qd, fromTime ); + QDateTime endPrintDate = QDateTime( qd, toTime ); + + // Calculate horizontal positions and widths of events taking into account + // overlapping events + + QPtrList<KOrg::CellItem> cells; + cells.setAutoDelete( true ); + + Event::List::ConstIterator itEvents; + for( itEvents = events.begin(); itEvents != events.end(); ++itEvents ) { + cells.append( new PrintCellItem( *itEvents, qd ) ); + } + + QPtrListIterator<KOrg::CellItem> it1( cells ); + for( it1.toFirst(); it1.current(); ++it1 ) { + KOrg::CellItem *placeItem = it1.current(); + + KOrg::CellItem::placeItem( cells, placeItem ); + } + + QPen oldPen = p.pen(); + QColor oldBgColor = p.backgroundColor(); + QBrush oldBrush = p.brush(); + + p.setFont( QFont( "helvetica", 10 ) ); + //p.setBrush( QBrush( Dense7Pattern ) ); + + for( it1.toFirst(); it1.current(); ++it1 ) { + PrintCellItem *placeItem = static_cast<PrintCellItem *>( it1.current() ); + + drawAgendaItem( placeItem, p, qd, startPrintDate, endPrintDate, minlen, x, + y, width ); + + p.setBrush( oldBrush ); + p.setPen( oldPen ); + p.setBackgroundColor( oldBgColor ); + } + + p.setBrush( QBrush( NoBrush ) ); +} + + +void CalPrintBase::drawAgendaItem( PrintCellItem *item, QPainter &p, + const QDate &qd, + const QDateTime &startPrintDate, + const QDateTime &endPrintDate, + float minlen, int x, int y, int width ) +{ + Event *event = item->event(); + + // set the colors according to the categories + if ( mUseColors ) setCategoryColors( p, event ); + else p.setBrush( Qt::white ); + // start/end of print area for event + QDateTime startTime = event->dtStart(); + QDateTime endTime = event->dtEnd(); + if ( event->doesRecur() ) { + startTime.setDate( qd ); + endTime.setDate( qd ); + } + if ( ( startTime < endPrintDate && endTime > startPrintDate ) || + ( endTime > startPrintDate && startTime < endPrintDate ) ) { + if ( startTime < startPrintDate ) startTime = startPrintDate; + if ( endTime > endPrintDate ) endTime = endPrintDate; + int eventLength = int( startTime.secsTo( endTime ) / 60. * minlen ); + int currentyPos = int( y + startPrintDate.secsTo( startTime ) * + minlen / 60. ); + int currentWidth = width / item->subCells(); + int currentX = x + item->subCell() * currentWidth; + QString text = KGlobal::locale()->formatTime(event->dtStart().time())+ + "-"+KGlobal::locale()->formatTime(event->dtEnd().time())+ + " "+event->summary(); + if ( !event->location().isEmpty() ) + text += " (" +event->location()+")"; + // p.save(); + QPen pe = p.pen(); + pe.setWidth( 2 ); + p.setPen( pe ); + p.drawRect( currentX, currentyPos+1, currentWidth+1, eventLength+1 ); + p.drawText( currentX+3, currentyPos+2, currentWidth-5, eventLength-3, + AlignLeft | AlignTop | AlignJustify | WordBreak, + text); + // p.restore(); + } +} + +void CalPrintBase::drawDayBox(QPainter &p, const QDate &qd, + int x, int y, int width, int height, + bool fullDate) +{ + QString dayNumStr; + QString ampm; + const KLocale*local = KGlobal::locale(); + + + // This has to be localized + if (fullDate) { + /*int index; + dayNumStr= qd.toString(); + index = dayNumStr.find(' '); + dayNumStr.remove(0, index); + index = dayNumStr.findRev(' '); + dayNumStr.truncate(index);*/ + + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + dayNumStr = i18n("weekday month date", "%1 %2 %3") + .arg( calSys->weekDayName( qd ) ) + .arg( calSys->monthName( qd ) ) + .arg( qd.day() ); +// dayNumStr = local->formatDate(qd); + } else { + dayNumStr = QString::number( qd.day() ); + } + + p.eraseRect( x, y, width, height ); + p.drawRect( x, y, width, height ); + // p.fillRect( x+1, y+1, width-2,height, QBrush(Dense7Pattern) ); + p.drawRect( x, y, width, mSubHeaderHeight ); + //p.fillRect( x+1, y+1, width-2, mSubHeaderHeight-2, QBrush(Dense7Pattern) ); + QString hstring; +#ifndef KORG_NOPLUGINS + hstring=KOCore::self()->holiday(qd); +#endif + + if (!hstring.isEmpty()) { + p.setFont( QFont( "helvetica", 8, QFont::Bold, true ) ); + + p.drawText( x+5, y, width-25, mSubHeaderHeight, AlignLeft | AlignVCenter, + hstring ); + } + p.setFont(QFont("helvetica", 10, QFont::Bold)); + p.drawText(x+5, y, width-10, mSubHeaderHeight, AlignRight | AlignVCenter, + dayNumStr); + Event::List eventList; + eventList.fill( mCalendar->events( qd, true )); + Todo::List todos; + todos.fill( mCalendar->todos( qd )); + QString outStr; + p.setFont( QFont( "helvetica", 8 ) ); + int lineSpacing = p.fontMetrics().lineSpacing(); + + int textY=mSubHeaderHeight+3; // gives the relative y-coord of the next printed entry + Event::List::ConstIterator it; + int entryCount = eventList.count() +todos.count(); + if ( p.fontMetrics().lineSpacing()* entryCount > height-textY ) { + if ( (p.fontMetrics().lineSpacing()-1) * entryCount > height-textY ) { + p.setFont( QFont( "helvetica", 7 ) ); + if ( (p.fontMetrics().lineSpacing()-1) * entryCount > height-textY ) + p.setFont( QFont( "helvetica", 6 ) ); + } + lineSpacing = p.fontMetrics().lineSpacing()-1; + } + // qDebug("fm %d %d %d ",p.fontMetrics().height(), eventList.count() , height-textY ); + for( it = eventList.begin(); it != eventList.end() && textY<height; ++it ) { + Event *currEvent = *it; + if (currEvent->doesFloat() || currEvent->isMultiDay()) + outStr = currEvent->summary(); + + else { + if ( fullDate ) { + outStr = KGlobal::locale()->formatTime( currEvent->dtStart().time())+ + "-"+KGlobal::locale()->formatTime( currEvent->dtEnd().time())+ + " "+ currEvent->summary(); + if ( ! currEvent->location().isEmpty() ) + outStr += " (" + currEvent->location()+")"; + } else { + QTime t1 = currEvent->dtStart().time(); + + outStr = local->formatTime(t1); + outStr += " " + currEvent->summary(); + } + + } // doesFloat + + p.drawText(x+5, y+textY, width-10, lineSpacing, + AlignLeft|AlignBottom, outStr); + textY+=lineSpacing; + } + + if ( textY<height ) { + + Todo::List::ConstIterator it2; + for( it2 = todos.begin(); it2 != todos.end() && textY<height; ++it2 ) { + Todo *todo = *it2; + QString text; + if (todo->hasDueDate()) { + if (!todo->doesFloat()) { + text += KGlobal::locale()->formatTime(todo->dtDue().time()); + text += " "; + } + } + text += i18n("To-Do: %1").arg(todo->summary()); + + p.drawText(x+5, y+textY, width-10, lineSpacing, + AlignLeft|AlignBottom, text); + textY+=lineSpacing; + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// + +void CalPrintBase::drawWeek(QPainter &p, const QDate &qd, + int x, int y, int width, int height) +{ + QDate weekDate = qd; + bool portrait = ( mPrinter->orientation() == KPrinter::Portrait ); + int cellWidth, cellHeight; + int vcells; + if (portrait) { + cellWidth = width/2; + vcells=3; + } else { + cellWidth = width/6; + vcells=1; + } + cellHeight = height/vcells; + + // correct begin of week + int weekdayCol = weekdayColumn( qd.dayOfWeek() ); + weekDate = qd.addDays( -weekdayCol ); + + for (int i = 0; i < 7; i++, weekDate = weekDate.addDays(1)) { + if (i<5) { + drawDayBox(p, weekDate, x+cellWidth*(int)(i/vcells), y+cellHeight*(i%vcells), + cellWidth, cellHeight, true); + } else if (i==5) { + drawDayBox(p, weekDate, x+cellWidth*(int)(i/vcells), y+cellHeight*(i%vcells), + cellWidth, cellHeight/2, true); + } else if (i==6) { + drawDayBox(p, weekDate, x+cellWidth*(int)((i-1)/vcells), + y+cellHeight*((i-1)%vcells)+cellHeight/2, cellWidth, cellHeight/2, true); + } + } // for i through all weekdays +} + + +void CalPrintBase::drawTimeTable(QPainter &p, + const QDate &fromDate, const QDate &toDate, + QTime &fromTime, QTime &toTime, + int x, int y, int width, int height) +{ + // timeline is 1.5 hours: + int alldayHeight = (int)( 3600.*height/(fromTime.secsTo(toTime)+3600.) ); + int timelineWidth = 60; + int cellWidth = (int)( (width-timelineWidth)/(fromDate.daysTo(toDate)+1) ); + int currY=y; + int currX=x; + + drawDaysOfWeek( p, fromDate, toDate, x+timelineWidth, currY, width-timelineWidth, mSubHeaderHeight); + currY+=mSubHeaderHeight; + drawTimeLine( p, fromTime, toTime, x, currY+alldayHeight, + timelineWidth, height-mSubHeaderHeight-alldayHeight ); + + currX=x+timelineWidth; + // draw each day + QDate curDate(fromDate); + while (curDate<=toDate) {Event::List eventList; + eventList.fill( mCalendar->events(curDate, true)); + drawAllDayBox( p, eventList, curDate, false, currX, currY, cellWidth, alldayHeight); + drawAgendaDayBox( p, eventList, curDate, false, fromTime, toTime, currX, + currY+alldayHeight, cellWidth, height-mSubHeaderHeight-alldayHeight ); + currX+=cellWidth; + curDate=curDate.addDays(1); + } + +} + + +/////////////////////////////////////////////////////////////////////////////// + +void CalPrintBase::drawMonth(QPainter &p, const QDate &qd, bool weeknumbers, + int x, int y, int width, int height) +{ + + int yoffset = mSubHeaderHeight; + int xoffset = 0; + + QDate monthDate(QDate(qd.year(), qd.month(), 1)); + QDate monthFirst(monthDate); + QDate monthLast(monthDate.addMonths(1).addDays(-1)); + + + int weekdayCol = weekdayColumn( monthDate.dayOfWeek() ); + monthDate = monthDate.addDays(-weekdayCol); + + int rows=(weekdayCol + qd.daysInMonth() - 1)/7 +1; + int cellHeight = (height-yoffset) / rows; + + if (weeknumbers) { + QFont oldFont(p.font()); + QFont newFont(p.font()); + newFont.setPointSize(7); + p.setFont(newFont); + xoffset += 18; + QDate weekDate(monthDate); + for (int row = 0; row<rows; row++) { + int calWeek = weekDate.weekNumber(); + QRect rc(x, y+yoffset+cellHeight*row, xoffset-1, cellHeight); + p.drawText( rc, AlignRight|AlignVCenter, QString::number(calWeek) ); + weekDate = weekDate.addDays(7); + } + p.setFont(oldFont); + } + + drawDaysOfWeek( p, monthDate, monthDate.addDays(6), x+xoffset, y, width-xoffset, mSubHeaderHeight ); + int cellWidth = (width-xoffset) / 7; + + QColor back = p.backgroundColor(); + bool darkbg = false; + for (int row = 0; row < rows; row++) { + for (int col = 0; col < 7; col++) { + // show days from previous/next month with a grayed background + if ( (monthDate < monthFirst) || (monthDate > monthLast) ) { + p.setBackgroundColor( QColor( 240, 240, 240) ); + darkbg = true; + } + drawDayBox(p, monthDate, x+xoffset+col*cellWidth, y+yoffset+row*cellHeight, cellWidth, cellHeight); + if ( darkbg ) { + p.setBackgroundColor( back ); + darkbg = false; + } + monthDate = monthDate.addDays(1); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// + +void CalPrintBase::drawTodo( bool completed, int &count, Todo * item, QPainter &p, bool connectSubTodos, + bool desc, int pospriority, int possummary, int posDueDt, int level, + int x, int &y, int width, int &height, int pageHeight, + TodoParentStart *r ) +{ + if ( !completed && item->isCompleted() ) + return; + QString outStr; +// int fontHeight = 10; + const KLocale *local = KGlobal::locale(); + int priority=item->priority(); + int posdue=posDueDt; + if (posdue<0) posdue=x+width; + QRect rect; + TodoParentStart startpt; + // This list keeps all starting points of the parent todos so the connection + // lines of the tree can easily be drawn (needed if a new page is started) + static QPtrList<TodoParentStart> startPoints; + if (level<1) { + startPoints.clear(); + } + + // size of item + outStr=item->summary(); + if ( ! item->location().isEmpty() ) + outStr += " ("+item->location()+")"; + if ( item->hasDueDate() && posDueDt>=0 ) { + outStr += " [" +local->formatDate(item->dtDue().date(),true)+"]"; + } + int left = possummary+(level*10); + rect = p.boundingRect(left, y, (posdue-left-5),-1, WordBreak, outStr); + if ( !item->description().isEmpty() && !desc ) { + outStr = item->description(); + rect = p.boundingRect( left+20, rect.bottom()+5, width-(left+10-x), -1, + WordBreak, outStr ); + } + // if too big make new page + if ( rect.bottom() > y+height) { + // first draw the connection lines from parent todos: + if (level > 0 && connectSubTodos) { + TodoParentStart *rct; + for ( rct = startPoints.first(); rct; rct = startPoints.next() ) { + int start; + int center = rct->mRect.left() + (rct->mRect.width()/2); + int to = p.viewport().bottom(); + + // draw either from start point of parent or from top of the page + if (rct->mSamePage) + start = rct->mRect.bottom() + 1; + else + start = p.viewport().top(); + p.moveTo( center, start ); + p.lineTo( center, to ); + rct->mSamePage=false; + } + } + y=0; + height=pageHeight-y; + mPrinter->newPage(); + } + + // If this is a sub-item, r will not be 0, and we want the LH side of the priority line up + //to the RH side of the parent item's priority + if (r && pospriority >= 0 ) { + pospriority = r->mRect.right() + 1; + } + + // Priority + outStr.setNum(priority); + rect = p.boundingRect(pospriority, y + 10, 5, -1, AlignCenter, outStr); + // Make it a more reasonable size + rect.setWidth(19); + rect.setHeight(19); + if ( priority > 0 && pospriority>=0 ) { + p.drawText(rect, AlignCenter, outStr); + p.drawRect(rect); + // cross out the rectangle for completed items + if ( item->isCompleted() ) { + p.drawLine( rect.topLeft(), rect.bottomRight() ); + p.drawLine( rect.topRight(), rect.bottomLeft() ); + } + } + startpt.mRect = rect; //save for later + + // Connect the dots + if (level > 0 && connectSubTodos) { + int bottom; + int center( r->mRect.left() + (r->mRect.width()/2)+1 ); + if (r->mSamePage ) + bottom = r->mRect.bottom();//lutz + 1; + else + bottom = 0; + int to( rect.top() + (rect.height()/2)+1 ); + int endx( rect.left() ); + p.moveTo(center, bottom); + p.lineTo(center, to); + p.lineTo(endx, to); + } + + // if completed, use strike out font + QFont ft=p.font(); + ft.setStrikeOut( item->isCompleted() ); + p.setFont( ft ); + // summary + outStr=item->summary(); + if ( ! item->location().isEmpty() ) + outStr += " ("+item->location()+")"; + if ( item->hasDueDate() && posDueDt>=0 ) { + outStr += " [" +local->formatDate(item->dtDue().date(),true)+"]"; + } + rect = p.boundingRect( left, rect.top(), (posdue-(left + rect.width() + 5)), + -1, WordBreak, outStr); + QRect newrect; + p.drawText( rect, WordBreak, outStr, -1, &newrect ); + ft.setStrikeOut(false); + p.setFont(ft); + + // due + // if ( item->hasDueDate() && posDueDt>=0 ) { +// outStr = local->formatDate(item->dtDue().date(),true); +// rect = p.boundingRect(posdue, y, x+width, -1, AlignTop|AlignLeft, outStr); +// p.drawText(rect, AlignTop|AlignLeft, outStr); +// } + + if ( !item->description().isEmpty() && desc ) { + y=newrect.bottom() + 5; + outStr = item->description(); + rect = p.boundingRect( left+20, y, x+width-(left+10), -1, + WordBreak, outStr ); + p.drawText( rect, WordBreak, outStr, -1, &newrect ); + } + + // Set the new line position + y=newrect.bottom() + 10; //set the line position + + // If the item has subitems, we need to call ourselves recursively + Incidence::List l;l.fill( item->relations()); + Incidence::List::ConstIterator it; + startPoints.append( &startpt ); + for( it = l.begin(); it != l.end(); ++it ) { + count++; + drawTodo( completed, count, static_cast<Todo *>( *it ), p, connectSubTodos, + desc, pospriority, possummary, posDueDt, level+1, + x, y, width, height, pageHeight, &startpt); + } + startPoints.remove(&startpt); +} + +int CalPrintBase::weekdayColumn( int weekday ) +{ + return ( weekday + 7 - KGlobal::locale()->weekStartDay() ) % 7; +} + +void CalPrintBase::drawSplitWeek( QPainter &p, const QDate &fd, + const QDate &td ) +{ + QDate curDay, fromDay, toDay, curWeek, fromWeek, toWeek; + + mPrinter->setOrientation(KPrinter::Portrait); + + int minus = 0; + if (KGlobal::locale()->weekStartsMonday()) { + // correct to monday + fromWeek = fd.addDays(-(fd.dayOfWeek()-1)); + // correct to sunday + toWeek = td.addDays(7-fd.dayOfWeek()); + minus = 1; + } else { + // correct to sunday + fromWeek = fd.addDays(-(fd.dayOfWeek()%7)); + // correct to saturday + toWeek = td.addDays(6-td.dayOfWeek()); + } + + fromDay = fd; + curDay = fd; + toDay = td; + p.setFont( QFont("Helvetica") ); + // the painter initially begins at 72 dpi per the Qt docs. + int pageWidth = p.viewport().width(); + int pageHeight = p.viewport().height(); + int margin=0; + mHeaderHeight = 110; + mSubHeaderHeight = 20; + + p.setViewport(margin, margin, + p.viewport().width()-margin, + p.viewport().height()-margin); + + curWeek = fromWeek.addDays(6); + + int columnWidth = int( pageWidth / 4.5 ); + + do { + + // if ( (curDay.dayOfWeek()-1)%7 < 3 ) + switch((curDay.dayOfWeek()-minus)%7){ + case 0: + drawSplitTimes( p, pageWidth, columnWidth, pageHeight ); + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 0.5 ) ); + break; + case 1: + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 1.5 ) ); + break; + case 2: + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 2.5 ) ); + break; + case 3: + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 3.5 ) ); + mPrinter->newPage(); + break; + case 4: + drawSplitTimes( p, int( pageWidth * ( 3.5/ 4.5 ) ), columnWidth, + pageHeight ); + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 0.5 ) ); + drawSplitHeaderRight( p, curWeek.addDays( -6 ), curWeek, + curWeek, pageWidth, mHeaderHeight ); + break; + case 5: + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 1.5 ) ); + break; + case 6: + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 2.5 ) ); + if ( curDay < toDay ) + mPrinter->newPage(); + curWeek = curWeek.addDays( 7 ); + break; + } + curDay = curDay.addDays(1); + + } while (curDay <= toDay); + +} + +void CalPrintBase::drawSplitHeaderRight( QPainter &p, const QDate &fd, + const QDate &td, + const QDate &, + int width, int ) +{ + int tempStore = mSubHeaderHeight; + mSubHeaderHeight+= mSubHeaderHeight; + KLocale *local = KGlobal::locale(); + QFont font("helvetica", 18, QFont::Bold); + QPen penA( black,0); + QPen penB( black,3); + p.setFont(font); + int lineSpacing = p.fontMetrics().lineSpacing(); + QString title; + QString myOwner(mCalendar->getOwner()); + if ( fd.month() == td.month() ) { + title = local->monthName(fd.month(), false) + ' ' + QString::number(fd.day()) + ' ' + + '-' + ' ' + QString::number(td.day()); + } else { + title = local->monthName(fd.month(), false) + ' ' + QString::number(fd.day()) + ' ' + + '-' + ' ' + local->monthName(td.month(), false) + ' ' + QString::number(td.day()); + } + +// Grrrrrrr! why can't I set the font to a serif font?!?!? + QFont serifFont("Helvetica", 30); +// serifFont.setFamily("Serif"); +// serifFont.setWeight(87); +// serifFont.setItalic(true); + p.setFont(serifFont); + QFontInfo info(p.font()); + + lineSpacing = p.fontMetrics().lineSpacing(); + p.drawText(0, lineSpacing * 0, width, lineSpacing, AlignRight |AlignTop, title ); + + title.truncate(0); + + p.setPen(penB ); + p.drawLine(200, lineSpacing * 1, width, lineSpacing * 1); + p.setPen(penA ); + + p.setFont(QFont("Helvetica", 20, QFont::Bold, TRUE)); + title += QString::number(fd.year()); + p.drawText(0, lineSpacing * 1, width, lineSpacing, AlignRight |AlignTop, title ); + mSubHeaderHeight = tempStore ; +} + +void CalPrintBase::drawSplitDay( QPainter &p, const QDate &qd, int width, + int height, int offsetLeft ) +{ + int tempStore = mSubHeaderHeight; + mSubHeaderHeight+= mSubHeaderHeight; + int startHour = KOPrefs::instance()->mDayBegins; + int endHour = 20; + int offset = mHeaderHeight + mSubHeaderHeight + 10; + Event::List eventList; eventList.fill( mCalendar->events( qd, true )); + Event::List::Iterator it; + Event *currEvent; + KLocale *local = KGlobal::locale(); + QString dayName; + + dayName = local->weekDayName(qd.dayOfWeek()) + ' ' + ' ' + QString::number(qd.day()); + //p.setBrush(QBrush(black)); +// width+1 to make sure there's a continuous, black bar across the top. + p.setPen( QPen(Qt::black,2)); + p.drawRect(offsetLeft, mHeaderHeight + 5, width +1, mSubHeaderHeight); + p.setPen( Qt::black); + p.setFont(QFont("helvetica", 12, QFont::Bold, true)); + p.drawText(offsetLeft, mHeaderHeight + 5, + width, mSubHeaderHeight, AlignHCenter | AlignVCenter, + dayName); + + p.setPen( QPen(Qt::black,2)); + p.setFont(QFont("helvetica", 12)); + p.setBrush(Qt::white); + it = eventList.begin(); + int allDays = 0; + /* + while( it != eventList.end() ) { + Event *currEvent = *it; + if ( currEvent->doesFloat() ) { + p.drawRect( offsetLeft, offset, width, 35 ); + p.drawText( offsetLeft + 5, offset + 10, width - 10, 30, + AlignLeft | AlignTop, currEvent->summary() ); + offset += 40; + allDays++; + it = eventList.remove( it ); + } else { + ++it; + } + } + */ + //p.setBrush(QBrush()); + int tmpEnd; + for ( it = eventList.begin(); it != eventList.end(); ++it ) { + Event *currEvent = *it; + tmpEnd = currEvent->dtEnd().time().hour(); + if (currEvent->dtEnd().time().minute() > 0) + tmpEnd++; + if (tmpEnd > endHour) + endHour = tmpEnd; + } + int hours = endHour - startHour; + int cellHeight = (height-offset) / hours; // hour increments. + + p.setFont(QFont("helvetica", 12)); + //p.setBrush(QBrush(Dense7Pattern)); + p.setBrush(Qt::white); + for ( it = eventList.begin(); it != eventList.end(); ++it ) { + Event *currEvent = *it; + int startTime = currEvent->dtStart().time().hour(); + int endTime = currEvent->dtEnd().time().hour(); + float minuteInc = cellHeight / 60.0; + if ((startTime >= startHour) && (endTime <= (startHour + hours))) { + startTime -= startHour; + int startMinuteOff = (int) (minuteInc * + currEvent->dtStart().time().minute()); + QString text = currEvent->summary() ; + if ( ! currEvent->location().isEmpty() ) + text += "\n("+currEvent->location()+")"; + int endMinuteOff = (int) (minuteInc * currEvent->dtEnd().time().minute()); + int cheight = (int) (minuteInc * + currEvent->dtStart().secsTo(currEvent->dtEnd()) / 60 ); + p.drawRect(offsetLeft+2, 1+offset+startMinuteOff+startTime*cellHeight, + width-4, cheight); + p.drawText(offsetLeft+12, offset+startMinuteOff+startTime*cellHeight+5, width-24, + cheight-10, AlignHCenter | AlignTop, text); + } + } + p.setBrush(QBrush(NoBrush)); + mSubHeaderHeight = tempStore ; +} + +void CalPrintBase::drawSplitTimes( QPainter &p, int width, int timeWidth, + int height ) +{ + int tempStore = mSubHeaderHeight; + mSubHeaderHeight+= mSubHeaderHeight; + int startHour = KOPrefs::instance()->mDayBegins; + int endHour = 20; + int offset = mHeaderHeight + mSubHeaderHeight + 10; + int hours = endHour - startHour; + int cellHeight = (height-offset) / hours; // hour increments. + + QString numStr; + for (int i = 0; i < hours; i++) { + p.setPen(QPen(black,1)); + p.drawLine(0, offset+i*cellHeight, width, offset+i*cellHeight); + p.setPen(QPen(gray,0)); + p.drawLine(37, offset+i*cellHeight+(cellHeight/2), + width, offset+i*cellHeight+(cellHeight/2)); + p.setPen(QPen(black,0)); + + if ( !KGlobal::locale()->use12Clock() ) { + numStr.setNum(i+startHour); + if (cellHeight > 40) { + p.setFont(QFont("helvetica", 16, QFont::Bold)); + } else { + p.setFont(QFont("helvetica", 14, QFont::Bold)); + } + p.drawText(0, offset+i*cellHeight, 33, cellHeight/2, + AlignTop|AlignRight, numStr); + p.setFont(QFont("helvetica", 12, QFont::Bold)); + p.drawText(37, offset+i*cellHeight, 45, cellHeight/2, + AlignTop | AlignLeft, "00"); + } else { + QTime time( i + startHour, 0 ); + numStr = KGlobal::locale()->formatTime( time ); + p.setFont(QFont("helvetica", 12, QFont::Bold)); + p.drawText(4, offset+i*cellHeight, 70, cellHeight/2, + AlignTop|AlignLeft, numStr); + } + } mSubHeaderHeight = tempStore ; +} + +#endif |