mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
2239 lines
77 KiB
C++
2239 lines
77 KiB
C++
/*
|
|
Copyright (c) 1998 Preston Brown <pbrown@kde.org>
|
|
Copyright (C) 2003 Reinhold Kainhofer <reinhold@kainhofer.com>
|
|
Copyright (C) 2008 Ron Goodheart <rong.dev@gmail.com>
|
|
Copyright (c) 2012-2013 Allen Winter <winter@kde.org>
|
|
|
|
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.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "calprintpluginbase.h"
|
|
#include "cellitem.h"
|
|
#include "kcalprefs.h"
|
|
#include "utils.h"
|
|
|
|
#include <Akonadi/Item>
|
|
|
|
#include <KCalendarSystem>
|
|
#include <KConfigGroup>
|
|
#include <KDebug>
|
|
#include <KSystemTimeZones>
|
|
#include <KWordWrap>
|
|
|
|
#include <QAbstractTextDocumentLayout>
|
|
#include <QFrame>
|
|
#include <QLabel>
|
|
#include <QLayout>
|
|
#include <QPainter>
|
|
#include <QTextCursor>
|
|
#include <QTextDocument>
|
|
#include <QTextDocumentFragment>
|
|
#include <qmath.h> // qCeil krazy:exclude=camelcase since no QMath
|
|
|
|
using namespace CalendarSupport;
|
|
|
|
static QString cleanStr( const QString &instr )
|
|
{
|
|
QString ret = instr;
|
|
return ret.replace( QLatin1Char('\n'), QLatin1Char(' ') );
|
|
}
|
|
|
|
/******************************************************************
|
|
** The Todo positioning structure **
|
|
******************************************************************/
|
|
class CalPrintPluginBase::TodoParentStart
|
|
{
|
|
public:
|
|
TodoParentStart( const QRect &pt = QRect(), bool hasLine = false, bool page = true )
|
|
: mRect( pt ), mHasLine( hasLine ), mSamePage( page ) {}
|
|
|
|
QRect mRect;
|
|
bool mHasLine;
|
|
bool mSamePage;
|
|
};
|
|
|
|
/******************************************************************
|
|
** The Print item **
|
|
******************************************************************/
|
|
|
|
class PrintCellItem : public CellItem
|
|
{
|
|
public:
|
|
PrintCellItem( const KCalCore::Event::Ptr &event, const KDateTime &start, const KDateTime &end )
|
|
: mEvent( event ), mStart( start ), mEnd( end )
|
|
{
|
|
}
|
|
|
|
KCalCore::Event::Ptr event() const { return mEvent; }
|
|
|
|
QString label() const { return mEvent->summary(); }
|
|
|
|
KDateTime start() const { return mStart; }
|
|
KDateTime end() const { return mEnd; }
|
|
|
|
/** Calculate the start and end date/time of the recurrence that
|
|
happens on the given day */
|
|
bool overlaps( CellItem *o ) const
|
|
{
|
|
PrintCellItem *other = static_cast<PrintCellItem *>( o );
|
|
return !( other->start() >= end() || other->end() <= start() );
|
|
}
|
|
|
|
private:
|
|
KCalCore::Event::Ptr mEvent;
|
|
KDateTime mStart, mEnd;
|
|
};
|
|
|
|
/******************************************************************
|
|
** The Print plugin **
|
|
******************************************************************/
|
|
|
|
CalPrintPluginBase::CalPrintPluginBase()
|
|
: PrintPlugin(), mUseColors( true ), mPrintFooter( true ),
|
|
mHeaderHeight( -1 ), mSubHeaderHeight( SUBHEADER_HEIGHT ), mFooterHeight( -1 ),
|
|
mMargin( MARGIN_SIZE ), mPadding( PADDING_SIZE ), mCalSys( 0 )
|
|
{
|
|
}
|
|
|
|
CalPrintPluginBase::~CalPrintPluginBase()
|
|
{
|
|
}
|
|
|
|
QWidget *CalPrintPluginBase::createConfigWidget( 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( info(), wdg ) );
|
|
layout->addSpacing( 20 );
|
|
layout->addWidget(
|
|
new QLabel( i18n( "This printing style does not have any configuration options." ), wdg ) );
|
|
layout->addStretch();
|
|
return wdg;
|
|
}
|
|
|
|
void CalPrintPluginBase::doPrint( QPrinter *printer )
|
|
{
|
|
if ( !printer ) {
|
|
return;
|
|
}
|
|
mPrinter = printer;
|
|
QPainter p;
|
|
|
|
mPrinter->setColorMode( mUseColors ? QPrinter::Color : QPrinter::GrayScale );
|
|
|
|
p.begin( mPrinter );
|
|
// TODO: Fix the margins!!!
|
|
// the painter initially begins at 72 dpi per the Qt docs.
|
|
// we want half-inch margins.
|
|
int margins = margin();
|
|
p.setViewport( margins, margins,
|
|
p.viewport().width() - 2 * margins,
|
|
p.viewport().height() - 2 * margins );
|
|
// QRect vp( p.viewport() );
|
|
// vp.setRight( vp.right()*2 );
|
|
// vp.setBottom( vp.bottom()*2 );
|
|
// p.setWindow( vp );
|
|
int pageWidth = p.window().width();
|
|
int pageHeight = p.window().height();
|
|
// int pageWidth = p.viewport().width();
|
|
// int pageHeight = p.viewport().height();
|
|
|
|
print( p, pageWidth, pageHeight );
|
|
|
|
p.end();
|
|
mPrinter = 0;
|
|
}
|
|
|
|
void CalPrintPluginBase::doLoadConfig()
|
|
{
|
|
if ( mConfig ) {
|
|
KConfigGroup group( mConfig, groupName() );
|
|
mConfig->sync();
|
|
QDateTime dt = QDateTime::currentDateTime();
|
|
mFromDate = group.readEntry( "FromDate", dt ).date();
|
|
mToDate = group.readEntry( "ToDate", dt ).date();
|
|
mUseColors = group.readEntry( "UseColors", true );
|
|
mPrintFooter = group.readEntry( "PrintFooter", true );
|
|
loadConfig();
|
|
} else {
|
|
kDebug() << "No config available in loadConfig!!!!";
|
|
}
|
|
}
|
|
|
|
void CalPrintPluginBase::doSaveConfig()
|
|
{
|
|
if ( mConfig ) {
|
|
KConfigGroup group( mConfig, groupName() );
|
|
saveConfig();
|
|
QDateTime dt = QDateTime::currentDateTime(); // any valid QDateTime will do
|
|
dt.setDate( mFromDate );
|
|
group.writeEntry( "FromDate", dt );
|
|
dt.setDate( mToDate );
|
|
group.writeEntry( "ToDate", dt );
|
|
group.writeEntry( "UseColors", mUseColors );
|
|
group.writeEntry( "PrintFooter", mPrintFooter );
|
|
mConfig->sync();
|
|
} else {
|
|
kDebug() << "No config available in saveConfig!!!!";
|
|
}
|
|
}
|
|
|
|
bool CalPrintPluginBase::useColors() const
|
|
{
|
|
return mUseColors;
|
|
}
|
|
|
|
void CalPrintPluginBase::setUseColors( bool useColors )
|
|
{
|
|
mUseColors = useColors;
|
|
}
|
|
|
|
bool CalPrintPluginBase::printFooter() const
|
|
{
|
|
return mPrintFooter;
|
|
}
|
|
|
|
void CalPrintPluginBase::setPrintFooter( bool printFooter )
|
|
{
|
|
mPrintFooter = printFooter;
|
|
}
|
|
|
|
QPrinter::Orientation CalPrintPluginBase::orientation() const
|
|
{
|
|
return mPrinter ? mPrinter->orientation() : QPrinter::Portrait;
|
|
}
|
|
|
|
QColor CalPrintPluginBase::getTextColor( const QColor &c ) const
|
|
{
|
|
double luminance = ( c.red() * 0.299 ) + ( c.green() * 0.587 ) + ( c.blue() * 0.114 );
|
|
return ( luminance > 128.0 ) ? QColor( 0, 0, 0 ) : QColor( 255, 255, 255 );
|
|
}
|
|
|
|
QTime CalPrintPluginBase::dayStart() const
|
|
{
|
|
QTime start( 8, 0, 0 );
|
|
QDateTime dayBegins = KCalPrefs::instance()->dayBegins();
|
|
if ( dayBegins.isValid() ) {
|
|
start = dayBegins.time();
|
|
}
|
|
return start;
|
|
}
|
|
|
|
void CalPrintPluginBase::setColorsByIncidenceCategory( QPainter &p, const KCalCore::Incidence::Ptr &incidence ) const
|
|
{
|
|
QColor bgColor = categoryBgColor( incidence );
|
|
if ( bgColor.isValid() ) {
|
|
p.setBrush( bgColor );
|
|
}
|
|
QColor tColor( getTextColor( bgColor ) );
|
|
if ( tColor.isValid() ) {
|
|
p.setPen( tColor );
|
|
}
|
|
}
|
|
|
|
QColor CalPrintPluginBase::categoryColor( const QStringList &categories ) const
|
|
{
|
|
if ( categories.isEmpty() ) {
|
|
return KCalPrefs::instance()->unsetCategoryColor();
|
|
}
|
|
// FIXME: Correctly treat events with multiple categories
|
|
const QString cat = categories.first();
|
|
QColor bgColor;
|
|
if ( cat.isEmpty() ) {
|
|
bgColor = KCalPrefs::instance()->unsetCategoryColor();
|
|
} else {
|
|
bgColor = KCalPrefs::instance()->categoryColor( cat );
|
|
}
|
|
return bgColor;
|
|
}
|
|
|
|
QColor CalPrintPluginBase::categoryBgColor( const KCalCore::Incidence::Ptr &incidence ) const
|
|
{
|
|
if ( incidence ) {
|
|
QColor backColor = categoryColor( incidence->categories() );
|
|
if ( incidence->type() == KCalCore::Incidence::TypeTodo ) {
|
|
if ( ( incidence.staticCast<KCalCore::Todo>() )->isOverdue() ) {
|
|
backColor = QColor( 255, 100, 100 ); //was KOPrefs::instance()->todoOverdueColor();
|
|
}
|
|
}
|
|
return backColor;
|
|
} else {
|
|
return QColor();
|
|
}
|
|
}
|
|
|
|
QString CalPrintPluginBase::holidayString( const QDate &date ) const
|
|
{
|
|
QStringList lst = holiday( date );
|
|
return lst.join( i18nc( "@item:intext delimiter for joining holiday names", "," ) );
|
|
}
|
|
|
|
KCalCore::Event::Ptr CalPrintPluginBase::holidayEvent( const QDate &date ) const
|
|
{
|
|
QString hstring( holidayString( date ) );
|
|
if ( hstring.isEmpty() ) {
|
|
return KCalCore::Event::Ptr();
|
|
}
|
|
|
|
KCalCore::Event::Ptr holiday( new KCalCore::Event );
|
|
holiday->setSummary( hstring );
|
|
holiday->setCategories( i18n( "Holiday" ) );
|
|
|
|
KDateTime kdt( date, QTime(), KSystemTimeZones::local() );
|
|
holiday->setDtStart( kdt );
|
|
holiday->setDtEnd( kdt );
|
|
holiday->setAllDay( true );
|
|
|
|
return holiday;
|
|
}
|
|
|
|
const KCalendarSystem *CalPrintPluginBase::calendarSystem()
|
|
{
|
|
if ( !mCalSys ) {
|
|
mCalSys = KGlobal::locale()->calendar();
|
|
}
|
|
return mCalSys;
|
|
}
|
|
|
|
void CalPrintPluginBase::setCalendarSystem( const KCalendarSystem *calsys )
|
|
{
|
|
mCalSys = calsys;
|
|
}
|
|
|
|
int CalPrintPluginBase::headerHeight() const
|
|
{
|
|
if ( mHeaderHeight >= 0 ) {
|
|
return mHeaderHeight;
|
|
} else if ( orientation() == QPrinter::Portrait ) {
|
|
return PORTRAIT_HEADER_HEIGHT;
|
|
} else {
|
|
return LANDSCAPE_HEADER_HEIGHT;
|
|
}
|
|
}
|
|
|
|
void CalPrintPluginBase::setHeaderHeight( const int height )
|
|
{
|
|
mHeaderHeight = height;
|
|
}
|
|
|
|
int CalPrintPluginBase::subHeaderHeight() const
|
|
{
|
|
return mSubHeaderHeight;
|
|
}
|
|
|
|
void CalPrintPluginBase::setSubHeaderHeight( const int height )
|
|
{
|
|
mSubHeaderHeight = height;
|
|
}
|
|
|
|
int CalPrintPluginBase::footerHeight() const
|
|
{
|
|
if ( !mPrintFooter ) {
|
|
return 0;
|
|
}
|
|
|
|
if ( mFooterHeight >= 0 ) {
|
|
return mFooterHeight;
|
|
} else if ( orientation() == QPrinter::Portrait ) {
|
|
return PORTRAIT_FOOTER_HEIGHT;
|
|
} else {
|
|
return LANDSCAPE_FOOTER_HEIGHT;
|
|
}
|
|
}
|
|
|
|
void CalPrintPluginBase::setFooterHeight( const int height )
|
|
{
|
|
mFooterHeight = height;
|
|
}
|
|
|
|
int CalPrintPluginBase::margin() const
|
|
{
|
|
return mMargin;
|
|
}
|
|
|
|
void CalPrintPluginBase::setMargin( const int margin )
|
|
{
|
|
mMargin = margin;
|
|
}
|
|
|
|
int CalPrintPluginBase::padding() const
|
|
{
|
|
return mPadding;
|
|
}
|
|
|
|
void CalPrintPluginBase::setPadding( const int padding )
|
|
{
|
|
mPadding = padding;
|
|
}
|
|
|
|
int CalPrintPluginBase::borderWidth() const
|
|
{
|
|
return mBorder;
|
|
}
|
|
|
|
void CalPrintPluginBase::setBorderWidth( const int borderwidth )
|
|
{
|
|
mBorder = borderwidth;
|
|
}
|
|
|
|
void CalPrintPluginBase::drawBox( QPainter &p, int linewidth, const QRect &rect )
|
|
{
|
|
QPen pen( p.pen() );
|
|
QPen oldpen( pen );
|
|
// no border
|
|
if ( linewidth >= 0 ) {
|
|
pen.setWidth( linewidth );
|
|
p.setPen( pen );
|
|
} else {
|
|
p.setPen( Qt::NoPen );
|
|
}
|
|
p.drawRect( rect );
|
|
p.setPen( oldpen );
|
|
}
|
|
|
|
void CalPrintPluginBase::drawShadedBox( QPainter &p, int linewidth,
|
|
const QBrush &brush, const QRect &rect )
|
|
{
|
|
QBrush oldbrush( p.brush() );
|
|
p.setBrush( brush );
|
|
drawBox( p, linewidth, rect );
|
|
p.setBrush( oldbrush );
|
|
}
|
|
|
|
void CalPrintPluginBase::printEventString( QPainter &p, const QRect &box,
|
|
const QString &str, int flags )
|
|
{
|
|
QRect newbox( box );
|
|
newbox.adjust( 3, 1, -1, -1 );
|
|
p.drawText( newbox, ( flags == -1 ) ?
|
|
( Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap ) : flags, str );
|
|
}
|
|
|
|
void CalPrintPluginBase::showEventBox( QPainter &p, int linewidth, const QRect &box,
|
|
const KCalCore::Incidence::Ptr &incidence, const QString &str,
|
|
int flags )
|
|
{
|
|
QPen oldpen( p.pen() );
|
|
QBrush oldbrush( p.brush() );
|
|
QColor bgColor( categoryBgColor( incidence ) );
|
|
if ( mUseColors & bgColor.isValid() ) {
|
|
p.setBrush( bgColor );
|
|
} else {
|
|
p.setBrush( QColor( 232, 232, 232 ) );
|
|
}
|
|
drawBox( p, ( linewidth > 0 ) ? linewidth : EVENT_BORDER_WIDTH, box );
|
|
if ( mUseColors && bgColor.isValid() ) {
|
|
p.setPen( getTextColor( bgColor ) );
|
|
}
|
|
printEventString( p, box, str, flags );
|
|
p.setPen( oldpen );
|
|
p.setBrush( oldbrush );
|
|
}
|
|
|
|
void CalPrintPluginBase::drawSubHeaderBox( QPainter &p, const QString &str, const QRect &box )
|
|
{
|
|
drawShadedBox( p, BOX_BORDER_WIDTH, QColor( 232, 232, 232 ), box );
|
|
QFont oldfont( p.font() );
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 10, QFont::Bold ) );
|
|
p.drawText( box, Qt::AlignCenter | Qt::AlignVCenter, str );
|
|
p.setFont( oldfont );
|
|
}
|
|
|
|
void CalPrintPluginBase::drawVerticalBox( QPainter &p, int linewidth, const QRect &box,
|
|
const QString &str, int flags )
|
|
{
|
|
p.save();
|
|
p.rotate( -90 );
|
|
QRect rotatedBox( -box.top() - box.height(), box.left(), box.height(), box.width() );
|
|
showEventBox( p, linewidth, rotatedBox, KCalCore::Incidence::Ptr(), str,
|
|
( flags == -1 ) ? Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine : flags );
|
|
|
|
p.restore();
|
|
}
|
|
|
|
/*
|
|
* Return value: If expand, bottom of the printed box, otherwise vertical end
|
|
* of the printed contents inside the box.
|
|
*/
|
|
int CalPrintPluginBase::drawBoxWithCaption( QPainter &p, const QRect &allbox,
|
|
const QString &caption,
|
|
const QString &contents,
|
|
bool sameLine, bool expand,
|
|
const QFont &captionFont,
|
|
const QFont &textFont,
|
|
bool richContents )
|
|
{
|
|
QFont oldFont( p.font() );
|
|
// QFont captionFont( "sans-serif", 11, QFont::Bold );
|
|
// QFont textFont( "sans-serif", 11, QFont::Normal );
|
|
// QFont captionFont( "Tahoma", 11, QFont::Bold );
|
|
// QFont textFont( "Tahoma", 11, QFont::Normal );
|
|
|
|
QRect box( allbox );
|
|
|
|
// Bounding rectangle for caption, single-line, clip on the right
|
|
QRect captionBox( box.left() + padding(), box.top() + padding(), 0, 0 );
|
|
p.setFont( captionFont );
|
|
captionBox = p.boundingRect( captionBox,
|
|
Qt::AlignLeft | Qt::AlignTop | Qt::TextSingleLine,
|
|
caption );
|
|
p.setFont( oldFont );
|
|
if ( captionBox.right() > box.right() ) {
|
|
captionBox.setRight( box.right() );
|
|
}
|
|
if ( expand && captionBox.bottom() + padding() > box.bottom() ) {
|
|
box.setBottom( captionBox.bottom() + padding() );
|
|
}
|
|
|
|
// Bounding rectangle for the contents (if any), word break, clip on the bottom
|
|
QRect textBox( captionBox );
|
|
if ( !contents.isEmpty() ) {
|
|
if ( sameLine ) {
|
|
textBox.setLeft( captionBox.right() + padding() );
|
|
} else {
|
|
textBox.setTop( captionBox.bottom() + padding() );
|
|
}
|
|
textBox.setRight( box.right() );
|
|
}
|
|
drawBox( p, BOX_BORDER_WIDTH, box );
|
|
p.setFont( captionFont );
|
|
p.drawText( captionBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextSingleLine,
|
|
caption );
|
|
|
|
if ( !contents.isEmpty() ) {
|
|
if ( sameLine ) {
|
|
QString contentText = toPlainText( contents );
|
|
p.setFont( textFont );
|
|
p.drawText( textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextSingleLine,
|
|
contents );
|
|
} else {
|
|
QTextDocument rtb;
|
|
int borderWidth = 2 * BOX_BORDER_WIDTH;
|
|
if ( richContents ) {
|
|
rtb.setHtml( contents );
|
|
} else {
|
|
rtb.setPlainText( contents );
|
|
}
|
|
int boxHeight = allbox.height();
|
|
if ( !sameLine ) {
|
|
boxHeight -= captionBox.height();
|
|
}
|
|
rtb.setPageSize( QSize( textBox.width(), boxHeight ) );
|
|
rtb.setDefaultFont( textFont );
|
|
p.save();
|
|
p.translate( textBox.x() - borderWidth, textBox.y() );
|
|
QRect clipBox( 0, 0, box.width(), boxHeight );
|
|
rtb.drawContents( &p, clipBox );
|
|
p.restore();
|
|
textBox.setBottom( textBox.y() +
|
|
rtb.documentLayout()->documentSize().height() );
|
|
}
|
|
}
|
|
p.setFont( oldFont );
|
|
|
|
if ( expand ) {
|
|
return box.bottom();
|
|
} else {
|
|
return textBox.bottom();
|
|
}
|
|
}
|
|
|
|
int CalPrintPluginBase::drawHeader( QPainter &p, const QString &title,
|
|
const QDate &month1, const QDate &month2, const QRect &allbox,
|
|
bool expand, QColor backColor )
|
|
{
|
|
// print previous month for month view, print current for to-do, day and week
|
|
int smallMonthWidth = ( allbox.width() / 4 ) - 10;
|
|
if ( smallMonthWidth > 100 ) {
|
|
smallMonthWidth = 100;
|
|
}
|
|
|
|
QRect box( allbox );
|
|
QRect textRect( allbox );
|
|
|
|
QFont oldFont( p.font() );
|
|
QFont newFont( QLatin1String("sans-serif"), ( textRect.height() < 60 ) ? 16 : 18, QFont::Bold );
|
|
if ( expand ) {
|
|
p.setFont( newFont );
|
|
QRect boundingR =
|
|
p.boundingRect( textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, title );
|
|
p.setFont( oldFont );
|
|
int h = boundingR.height();
|
|
if ( h > allbox.height() ) {
|
|
box.setHeight( h );
|
|
textRect.setHeight( h );
|
|
}
|
|
}
|
|
|
|
if ( !backColor.isValid() ) {
|
|
backColor = QColor( 232, 232, 232 );
|
|
}
|
|
|
|
drawShadedBox( p, BOX_BORDER_WIDTH, backColor, box );
|
|
|
|
#if 0
|
|
// current month title left justified, prev month, next month right justified
|
|
QRect monthbox2( box.right()-10-smallMonthWidth, box.top(),
|
|
smallMonthWidth, box.height() );
|
|
if ( month2.isValid() ) {
|
|
drawSmallMonth( p, QDate( month2.year(), month2.month(), 1 ), monthbox2 );
|
|
textRect.setRight( monthbox2.left() );
|
|
}
|
|
QRect monthbox1( monthbox2.left()-10-smallMonthWidth, box.top(),
|
|
smallMonthWidth, box.height() );
|
|
if ( month1.isValid() ) {
|
|
drawSmallMonth( p, QDate( month1.year(), month1.month(), 1 ), monthbox1 );
|
|
textRect.setRight( monthbox1.left() );
|
|
}
|
|
|
|
// Set the margins
|
|
p.setFont( newFont );
|
|
textRect.adjust( 5, 0, 0, 0 );
|
|
p.drawText( textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, title );
|
|
p.setFont( oldFont );
|
|
#endif
|
|
// prev month left, current month centered, next month right
|
|
QRect monthbox2( box.right()-10-smallMonthWidth, box.top(),
|
|
smallMonthWidth, box.height() );
|
|
if ( month2.isValid() ) {
|
|
drawSmallMonth( p, QDate( month2.year(), month2.month(), 1 ), monthbox2 );
|
|
textRect.setRight( monthbox2.left() );
|
|
}
|
|
QRect monthbox1( box.left()+10, box.top(), smallMonthWidth, box.height() );
|
|
if ( month1.isValid() ) {
|
|
drawSmallMonth( p, QDate( month1.year(), month1.month(), 1 ), monthbox1 );
|
|
textRect.setLeft( monthbox1.right() );
|
|
}
|
|
|
|
// Set the margins
|
|
p.setFont( newFont );
|
|
p.drawText( textRect, Qt::AlignCenter | Qt::AlignVCenter | Qt::TextWordWrap, title );
|
|
p.setFont( oldFont );
|
|
|
|
return textRect.bottom();
|
|
}
|
|
|
|
int CalPrintPluginBase::drawFooter( QPainter &p, const QRect &footbox )
|
|
{
|
|
QFont oldfont( p.font() );
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 6 ) );
|
|
QFontMetrics fm( p.font() );
|
|
QString dateStr =
|
|
KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(), KLocale::LongDate );
|
|
p.drawText( footbox, Qt::AlignCenter | Qt::AlignVCenter | Qt::TextSingleLine,
|
|
i18nc( "print date: formatted-datetime", "printed: %1", dateStr ) );
|
|
p.setFont( oldfont );
|
|
|
|
return footbox.bottom();
|
|
}
|
|
|
|
void CalPrintPluginBase::drawSmallMonth( QPainter &p, const QDate &qd, const QRect &box )
|
|
{
|
|
int weekdayCol = weekdayColumn( qd.dayOfWeek() );
|
|
int month = qd.month();
|
|
QDate monthDate( QDate( qd.year(), qd.month(), 1 ) );
|
|
// correct begin of week
|
|
QDate monthDate2( monthDate.addDays( -weekdayCol ) );
|
|
|
|
double cellWidth = double( box.width() ) / double( 7 );
|
|
int rownr = 3 + ( qd.daysInMonth() + weekdayCol - 1 ) / 7;
|
|
// 3 Pixel after month name, 2 after day names, 1 after the calendar
|
|
double cellHeight = ( box.height() - 5 ) / rownr;
|
|
QFont oldFont( p.font() );
|
|
p.setFont( QFont( QLatin1String("sans-serif"), int(cellHeight-2), QFont::Normal ) );
|
|
|
|
// draw the title
|
|
if ( mCalSys ) {
|
|
QRect titleBox( box );
|
|
titleBox.setHeight( int( cellHeight + 1 ) );
|
|
p.drawText( titleBox, Qt::AlignTop | Qt::AlignHCenter, mCalSys->monthName( qd ) );
|
|
}
|
|
|
|
// draw days of week
|
|
QRect wdayBox( box );
|
|
wdayBox.setTop( int( box.top() + 3 + cellHeight ) );
|
|
wdayBox.setHeight( int( 2 * cellHeight ) - int( cellHeight ) );
|
|
|
|
if ( mCalSys ) {
|
|
for ( int col = 0; col < 7; ++col ) {
|
|
QString tmpStr = mCalSys->weekDayName( monthDate2 )[0].toUpper();
|
|
wdayBox.setLeft( int( box.left() + col * cellWidth ) );
|
|
wdayBox.setRight( int( box.left() + ( col + 1 ) * cellWidth ) );
|
|
p.drawText( wdayBox, Qt::AlignCenter, tmpStr );
|
|
monthDate2 = monthDate2.addDays( 1 );
|
|
}
|
|
}
|
|
|
|
// draw separator line
|
|
int calStartY = wdayBox.bottom() + 2;
|
|
p.drawLine( box.left(), calStartY, box.right(), calStartY );
|
|
monthDate = monthDate.addDays( -weekdayCol );
|
|
|
|
for ( int row = 0; row < (rownr-2); row++ ) {
|
|
for ( int col = 0; col < 7; col++ ) {
|
|
if ( monthDate.month() == month ) {
|
|
QRect dayRect( int( box.left() + col * cellWidth ),
|
|
int( calStartY + row * cellHeight ), 0, 0 );
|
|
dayRect.setRight( int( box.left() + ( col + 1 ) * cellWidth ) );
|
|
dayRect.setBottom( int( calStartY + ( row + 1 ) * cellHeight ) );
|
|
p.drawText( dayRect, Qt::AlignCenter, QString::number( monthDate.day() ) );
|
|
}
|
|
monthDate = monthDate.addDays(1);
|
|
}
|
|
}
|
|
p.setFont( oldFont );
|
|
}
|
|
|
|
/*
|
|
* This routine draws a header box over the main part of the calendar
|
|
* containing the days of the week.
|
|
*/
|
|
void CalPrintPluginBase::drawDaysOfWeek( QPainter &p,
|
|
const QDate &fromDate,
|
|
const QDate &toDate, const QRect &box )
|
|
{
|
|
double cellWidth = double( box.width() ) / double( fromDate.daysTo( toDate ) + 1 );
|
|
QDate cellDate( fromDate );
|
|
QRect dateBox( box );
|
|
int i = 0;
|
|
|
|
while ( cellDate <= toDate ) {
|
|
dateBox.setLeft( box.left() + int( i * cellWidth ) );
|
|
dateBox.setRight( box.left() + int( ( i + 1 ) * cellWidth ) );
|
|
drawDaysOfWeekBox( p, cellDate, dateBox );
|
|
cellDate = cellDate.addDays( 1 );
|
|
++i;
|
|
}
|
|
}
|
|
|
|
void CalPrintPluginBase::drawDaysOfWeekBox( QPainter &p, const QDate &qd, const QRect &box )
|
|
{
|
|
drawSubHeaderBox( p, ( mCalSys ) ? ( mCalSys->weekDayName( qd ) ) : QString(), box );
|
|
}
|
|
|
|
void CalPrintPluginBase::drawTimeLine( QPainter &p, const QTime &fromTime,
|
|
const QTime &toTime, const QRect &box )
|
|
{
|
|
drawBox( p, BOX_BORDER_WIDTH, box );
|
|
|
|
int totalsecs = fromTime.secsTo( toTime );
|
|
float minlen = (float)box.height() * 60. / (float)totalsecs;
|
|
float cellHeight = ( 60. * (float)minlen );
|
|
float currY = box.top();
|
|
// TODO: Don't use half of the width, but less, for the minutes!
|
|
int xcenter = box.left() + box.width() / 2;
|
|
|
|
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( xcenter, (int)yy, box.right(), (int)yy );
|
|
curTime = QTime( fromTime.hour() + 1, 0, 0 );
|
|
}
|
|
currY += ( float( fromTime.secsTo( curTime ) * minlen ) / 60. );
|
|
|
|
while ( curTime < endTime ) {
|
|
p.drawLine( box.left(), (int)currY, box.right(), (int)currY );
|
|
int newY = (int)( currY + cellHeight / 2. );
|
|
QString numStr;
|
|
if ( newY < box.bottom() ) {
|
|
QFont oldFont( p.font() );
|
|
// draw the time:
|
|
if ( !KGlobal::locale()->use12Clock() ) {
|
|
p.drawLine( xcenter, (int)newY, box.right(), (int)newY );
|
|
numStr.setNum( curTime.hour() );
|
|
if ( cellHeight > 30 ) {
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 14, QFont::Bold ) );
|
|
} else {
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 12, QFont::Bold ) );
|
|
}
|
|
p.drawText( box.left() + 4, (int)currY + 2, box.width() / 2 - 2, (int)cellHeight,
|
|
Qt::AlignTop | Qt::AlignRight, numStr );
|
|
p.setFont( QFont( QLatin1String("helvetica"), 10, QFont::Normal ) );
|
|
p.drawText( xcenter + 4, (int)currY+2, box.width() / 2 + 2, (int)( cellHeight / 2 ) - 3,
|
|
Qt::AlignTop | Qt::AlignLeft, QLatin1String("00") );
|
|
} else {
|
|
p.drawLine( box.left(), (int)newY, box.right(), (int)newY );
|
|
QTime time( curTime.hour(), 0 );
|
|
numStr = KGlobal::locale()->formatTime( time );
|
|
if ( box.width() < 60 ) {
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 7, QFont::Bold ) ); // for weekprint
|
|
} else {
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 12, QFont::Bold ) ); // for dayprint
|
|
}
|
|
p.drawText( box.left() + 2, (int)currY + 2, box.width() - 4, (int)cellHeight / 2 - 3,
|
|
Qt::AlignTop|Qt::AlignLeft, numStr );
|
|
}
|
|
currY += cellHeight;
|
|
p.setFont( oldFont );
|
|
} // enough space for half-hour line and time
|
|
if ( curTime.secsTo( endTime ) > 3600 ) {
|
|
curTime = curTime.addSecs( 3600 );
|
|
} else {
|
|
curTime = 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 ", ".
|
|
*/
|
|
int CalPrintPluginBase::drawAllDayBox( QPainter &p, const KCalCore::Event::List &eventList_,
|
|
const QDate &qd, bool expandable,
|
|
const QRect &box,
|
|
bool excludeConfidential,
|
|
bool excludePrivate )
|
|
{
|
|
KCalCore::Event::List::Iterator it;
|
|
int offset = box.top();
|
|
QString multiDayStr;
|
|
|
|
KCalCore::Event::List eventList = eventList_;
|
|
KCalCore::Event::Ptr hd = holidayEvent( qd );
|
|
if ( hd ) {
|
|
eventList.prepend( hd );
|
|
}
|
|
|
|
it = eventList.begin();
|
|
while ( it != eventList.end() ) {
|
|
KCalCore::Event::Ptr currEvent = *it;
|
|
if ( ( excludeConfidential && currEvent->secrecy() == KCalCore::Incidence::SecrecyConfidential ) ||
|
|
( excludePrivate && currEvent->secrecy() == KCalCore::Incidence::SecrecyPrivate ) ) {
|
|
continue;
|
|
}
|
|
if ( currEvent && currEvent->allDay() ) {
|
|
// set the colors according to the categories
|
|
if ( expandable ) {
|
|
QRect eventBox( box );
|
|
eventBox.setTop( offset );
|
|
showEventBox( p, EVENT_BORDER_WIDTH, eventBox, currEvent, currEvent->summary() );
|
|
offset += box.height();
|
|
} else {
|
|
if ( !multiDayStr.isEmpty() ) {
|
|
multiDayStr += QLatin1String(", ");
|
|
}
|
|
multiDayStr += currEvent->summary();
|
|
}
|
|
it = eventList.erase( it );
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
|
|
int ret = box.height();
|
|
QRect eventBox( box );
|
|
if ( !expandable ) {
|
|
if ( !multiDayStr.isEmpty() ) {
|
|
drawShadedBox( p, BOX_BORDER_WIDTH, QColor( 180, 180, 180 ), eventBox );
|
|
printEventString( p, eventBox, multiDayStr );
|
|
} else {
|
|
drawBox( p, BOX_BORDER_WIDTH, eventBox );
|
|
}
|
|
} else {
|
|
ret = offset - box.top();
|
|
eventBox.setBottom( ret );
|
|
drawBox( p, BOX_BORDER_WIDTH, eventBox );
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void CalPrintPluginBase::drawAgendaDayBox( QPainter &p, const KCalCore::Event::List &events,
|
|
const QDate &qd, bool expandable,
|
|
const QTime &fromTime,
|
|
const QTime &toTime,
|
|
const QRect &oldbox,
|
|
bool includeDescription,
|
|
bool excludeTime,
|
|
bool excludeConfidential,
|
|
bool excludePrivate,
|
|
const QList<QDate> &workDays )
|
|
{
|
|
QTime myFromTime, myToTime;
|
|
if ( fromTime.isValid() ) {
|
|
myFromTime = fromTime;
|
|
} else {
|
|
myFromTime = QTime( 0, 0, 0 );
|
|
}
|
|
if ( toTime.isValid() ) {
|
|
myToTime = toTime;
|
|
} else {
|
|
myToTime = QTime( 23, 59, 59 );
|
|
}
|
|
|
|
if ( !workDays.contains( qd ) ) {
|
|
drawShadedBox( p, BOX_BORDER_WIDTH, QColor( 232, 232, 232 ), oldbox );
|
|
} else {
|
|
drawBox( p, BOX_BORDER_WIDTH, oldbox );
|
|
}
|
|
QRect box( oldbox );
|
|
// Account for the border with and cut away that margin from the interior
|
|
// box.setRight( box.right()-BOX_BORDER_WIDTH );
|
|
|
|
if ( expandable ) {
|
|
// Adapt start/end times to include complete events
|
|
Q_FOREACH ( const KCalCore::Event::Ptr &event, events ) {
|
|
Q_ASSERT( event );
|
|
if ( ( excludeConfidential && event->secrecy() == KCalCore::Incidence::SecrecyConfidential ) ||
|
|
( excludePrivate && event->secrecy() == KCalCore::Incidence::SecrecyPrivate ) ) {
|
|
continue;
|
|
}
|
|
// skip items without times so that we do not adjust for all day items
|
|
if ( event->allDay() ) {
|
|
continue;
|
|
}
|
|
if ( event->dtStart().time() < myFromTime ) {
|
|
myFromTime = event->dtStart().time();
|
|
}
|
|
if ( event->dtEnd().time() > myToTime ) {
|
|
myToTime = event->dtEnd().time();
|
|
}
|
|
}
|
|
}
|
|
|
|
// calculate the height of a cell and of a minute
|
|
int totalsecs = myFromTime.secsTo( myToTime );
|
|
float minlen = box.height() * 60. / totalsecs;
|
|
float cellHeight = 60. * minlen;
|
|
float currY = box.top();
|
|
|
|
// print grid:
|
|
QTime curTime( QTime( myFromTime.hour(), 0, 0 ) );
|
|
currY += myFromTime.secsTo( curTime ) * minlen / 60;
|
|
|
|
while ( curTime < myToTime && curTime.isValid() ) {
|
|
if ( currY > box.top() ) {
|
|
p.drawLine( box.left(), int( currY ), box.right(), int( currY ) );
|
|
}
|
|
currY += cellHeight / 2;
|
|
if ( ( currY > box.top() ) && ( currY < box.bottom() ) ) {
|
|
// enough space for half-hour line
|
|
QPen oldPen( p.pen() );
|
|
p.setPen( QColor( 192, 192, 192 ) );
|
|
p.drawLine( box.left(), int( currY ), box.right(), int( currY ) );
|
|
p.setPen( oldPen );
|
|
}
|
|
if ( curTime.secsTo( myToTime ) > 3600 ) {
|
|
curTime = curTime.addSecs( 3600 );
|
|
} else {
|
|
curTime = myToTime;
|
|
}
|
|
currY += cellHeight / 2;
|
|
}
|
|
|
|
KDateTime startPrintDate = KDateTime( qd, myFromTime );
|
|
KDateTime endPrintDate = KDateTime( qd, myToTime );
|
|
|
|
// Calculate horizontal positions and widths of events taking into account
|
|
// overlapping events
|
|
|
|
QList<CellItem *> cells;
|
|
|
|
Akonadi::Item::List::ConstIterator itEvents;
|
|
foreach ( const KCalCore::Event::Ptr &event, events ) {
|
|
if ( event->allDay() ) {
|
|
continue;
|
|
}
|
|
QList<KDateTime> times = event->startDateTimesForDate( qd );
|
|
for ( QList<KDateTime>::ConstIterator it = times.constBegin();
|
|
it != times.constEnd(); ++it ) {
|
|
cells.append( new PrintCellItem( event, (*it), event->endDateForStart( *it ) ) );
|
|
}
|
|
}
|
|
|
|
QListIterator<CellItem *> it1( cells );
|
|
while ( it1.hasNext() ) {
|
|
CellItem *placeItem = it1.next();
|
|
CellItem::placeItem( cells, placeItem );
|
|
}
|
|
|
|
QListIterator<CellItem *> it2( cells );
|
|
while ( it2.hasNext() ) {
|
|
PrintCellItem *placeItem = static_cast<PrintCellItem *>( it2.next() );
|
|
drawAgendaItem( placeItem, p, startPrintDate, endPrintDate, minlen, box,
|
|
includeDescription, excludeTime );
|
|
}
|
|
}
|
|
|
|
void CalPrintPluginBase::drawAgendaItem( PrintCellItem *item, QPainter &p,
|
|
const KDateTime &startPrintDate,
|
|
const KDateTime &endPrintDate,
|
|
float minlen, const QRect &box,
|
|
bool includeDescription,
|
|
bool excludeTime )
|
|
{
|
|
KCalCore::Event::Ptr event = item->event();
|
|
|
|
// start/end of print area for event
|
|
KDateTime startTime = item->start();
|
|
KDateTime endTime = item->end();
|
|
if ( ( startTime < endPrintDate && endTime > startPrintDate ) ||
|
|
( endTime > startPrintDate && startTime < endPrintDate ) ) {
|
|
if ( startTime < startPrintDate ) {
|
|
startTime = startPrintDate;
|
|
}
|
|
if ( endTime > endPrintDate ) {
|
|
endTime = endPrintDate;
|
|
}
|
|
int currentWidth = box.width() / item->subCells();
|
|
int currentX = box.left() + item->subCell() * currentWidth;
|
|
int currentYPos =
|
|
int( box.top() + startPrintDate.secsTo( startTime ) * minlen / 60. );
|
|
int currentHeight =
|
|
int( box.top() + startPrintDate.secsTo( endTime ) * minlen / 60. ) - currentYPos;
|
|
|
|
QRect eventBox( currentX, currentYPos, currentWidth, currentHeight );
|
|
QString str;
|
|
if ( excludeTime ) {
|
|
if ( event->location().isEmpty() ) {
|
|
str = cleanStr( event->summary() );
|
|
} else {
|
|
str = i18nc( "summary, location", "%1, %2",
|
|
cleanStr( event->summary() ), cleanStr( event->location() ) );
|
|
}
|
|
} else {
|
|
if ( event->location().isEmpty() ) {
|
|
str = i18nc( "starttime - endtime summary",
|
|
"%1-%2 %3",
|
|
KGlobal::locale()->formatTime( item->start().toLocalZone().time() ),
|
|
KGlobal::locale()->formatTime( item->end().toLocalZone().time() ),
|
|
cleanStr( event->summary() ) );
|
|
} else {
|
|
str = i18nc( "starttime - endtime summary, location",
|
|
"%1-%2 %3, %4",
|
|
KGlobal::locale()->formatTime( item->start().toLocalZone().time() ),
|
|
KGlobal::locale()->formatTime( item->end().toLocalZone().time() ),
|
|
cleanStr( event->summary() ),
|
|
cleanStr( event->location() ) );
|
|
}
|
|
}
|
|
if ( includeDescription && !event->description().isEmpty() ) {
|
|
str += QLatin1Char('\n');
|
|
if ( event->descriptionIsRich() ) {
|
|
str += toPlainText( event->description() );
|
|
} else {
|
|
str += event->description();
|
|
}
|
|
}
|
|
QFont oldFont( p.font() );
|
|
if ( eventBox.height() < 24 ) {
|
|
if ( eventBox.height() < 12 ) {
|
|
if ( eventBox.height() < 8 ) {
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 4 ) );
|
|
} else {
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 5 ) );
|
|
}
|
|
} else {
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 6 ) );
|
|
}
|
|
} else {
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 8 ) );
|
|
}
|
|
showEventBox( p, EVENT_BORDER_WIDTH, eventBox, event, str );
|
|
p.setFont( oldFont );
|
|
}
|
|
}
|
|
|
|
void CalPrintPluginBase::drawDayBox( QPainter &p, const QDate &qd,
|
|
const QTime &fromTime, const QTime &toTime,
|
|
const QRect &box, bool fullDate,
|
|
bool printRecurDaily, bool printRecurWeekly,
|
|
bool singleLineLimit, bool showNoteLines,
|
|
bool includeDescription,
|
|
bool excludeConfidential,
|
|
bool excludePrivate )
|
|
{
|
|
QString dayNumStr;
|
|
const KLocale *local = KGlobal::locale();
|
|
|
|
QTime myFromTime, myToTime;
|
|
if ( fromTime.isValid() ) {
|
|
myFromTime = fromTime;
|
|
} else {
|
|
myFromTime = QTime( 0, 0, 0 );
|
|
}
|
|
if ( toTime.isValid() ) {
|
|
myToTime = toTime;
|
|
} else {
|
|
myToTime = QTime( 23, 59, 59 );
|
|
}
|
|
|
|
if ( fullDate && mCalSys ) {
|
|
dayNumStr = i18nc( "weekday, shortmonthname daynumber",
|
|
"%1, %2 <numid>%3</numid>",
|
|
mCalSys->weekDayName( qd ),
|
|
mCalSys->monthName( qd, KCalendarSystem::ShortName ),
|
|
qd.day() );
|
|
} else {
|
|
dayNumStr = QString::number( qd.day() );
|
|
}
|
|
|
|
QRect subHeaderBox( box );
|
|
subHeaderBox.setHeight( mSubHeaderHeight );
|
|
drawShadedBox( p, BOX_BORDER_WIDTH, p.background(), box );
|
|
drawShadedBox( p, 0, QColor( 232, 232, 232 ), subHeaderBox );
|
|
drawBox( p, BOX_BORDER_WIDTH, box );
|
|
QString hstring( holidayString( qd ) );
|
|
const QFont oldFont( p.font() );
|
|
|
|
QRect headerTextBox( subHeaderBox );
|
|
headerTextBox.setLeft( subHeaderBox.left() + 5 );
|
|
headerTextBox.setRight( subHeaderBox.right() - 5 );
|
|
if ( !hstring.isEmpty() ) {
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 8, QFont::Bold, true ) );
|
|
p.drawText( headerTextBox, Qt::AlignLeft | Qt::AlignVCenter, hstring );
|
|
}
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 10, QFont::Bold ) );
|
|
p.drawText( headerTextBox, Qt::AlignRight | Qt::AlignVCenter, dayNumStr );
|
|
|
|
const KCalCore::Event::List eventList =
|
|
mCalendar->events( qd, KSystemTimeZones::local(),
|
|
KCalCore::EventSortStartDate,
|
|
KCalCore::SortDirectionAscending );
|
|
|
|
QString timeText;
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 7 ) );
|
|
|
|
int textY = mSubHeaderHeight; // gives the relative y-coord of the next printed entry
|
|
unsigned int visibleEventsCounter = 0;
|
|
Q_FOREACH ( const KCalCore::Event::Ptr &currEvent, eventList ) {
|
|
Q_ASSERT( currEvent );
|
|
if ( !currEvent->allDay() ) {
|
|
if ( currEvent->dtEnd().toLocalZone().time() <= myFromTime ||
|
|
currEvent->dtStart().toLocalZone().time() > myToTime ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( ( !printRecurDaily && currEvent->recurrenceType() == KCalCore::Recurrence::rDaily ) ||
|
|
( !printRecurWeekly && currEvent->recurrenceType() == KCalCore::Recurrence::rWeekly ) ) {
|
|
continue;
|
|
}
|
|
if ( ( excludeConfidential && currEvent->secrecy() == KCalCore::Incidence::SecrecyConfidential ) ||
|
|
( excludePrivate && currEvent->secrecy() == KCalCore::Incidence::SecrecyPrivate ) ) {
|
|
continue;
|
|
}
|
|
if ( currEvent->allDay() || currEvent->isMultiDay() ) {
|
|
timeText.clear();
|
|
} else {
|
|
timeText = local->formatTime( currEvent->dtStart().toLocalZone().time() ) + QLatin1Char(' ');
|
|
}
|
|
p.save();
|
|
setColorsByIncidenceCategory( p, currEvent );
|
|
QString summaryStr = currEvent->summary();
|
|
if ( !currEvent->location().isEmpty() ) {
|
|
summaryStr = i18nc( "summary, location",
|
|
"%1, %2", summaryStr, currEvent->location() );
|
|
}
|
|
drawIncidence( p, box, timeText,
|
|
summaryStr, currEvent->description(),
|
|
textY, singleLineLimit, includeDescription,
|
|
currEvent->descriptionIsRich() );
|
|
p.restore();
|
|
visibleEventsCounter++;
|
|
|
|
if ( textY >= box.height() ) {
|
|
const QChar downArrow( 0x21e3 );
|
|
|
|
const unsigned int invisibleIncidences =
|
|
( eventList.count() - visibleEventsCounter ) + mCalendar->todos( qd ).count();
|
|
if ( invisibleIncidences > 0 ) {
|
|
const QString warningMsg = QString::fromLatin1( "%1 (%2)" ).arg( downArrow ).arg( invisibleIncidences );
|
|
|
|
QFontMetrics fm( p.font() );
|
|
QRect msgRect = fm.boundingRect( warningMsg );
|
|
msgRect.setRect( box.right() - msgRect.width() - 2,
|
|
box.bottom() - msgRect.height() - 2,
|
|
msgRect.width(), msgRect.height() );
|
|
|
|
p.save();
|
|
p.setPen( Qt::red ); //krazy:exclude=qenums we don't allow custom print colors
|
|
p.drawText( msgRect, Qt::AlignLeft, warningMsg );
|
|
p.restore();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( textY < box.height() ) {
|
|
KCalCore::Todo::List todos = mCalendar->todos( qd );
|
|
foreach ( const KCalCore::Todo::Ptr &todo, todos ) {
|
|
if ( !todo->allDay() ) {
|
|
if ( ( todo->hasDueDate() && todo->dtDue().toLocalZone().time() <= myFromTime ) ||
|
|
( todo->hasStartDate() && todo->dtStart().toLocalZone().time() > myToTime ) ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( ( !printRecurDaily && todo->recurrenceType() == KCalCore::Recurrence::rDaily ) ||
|
|
( !printRecurWeekly && todo->recurrenceType() == KCalCore::Recurrence::rWeekly ) ) {
|
|
continue;
|
|
}
|
|
if ( ( excludeConfidential && todo->secrecy() == KCalCore::Incidence::SecrecyConfidential ) ||
|
|
( excludePrivate && todo->secrecy() == KCalCore::Incidence::SecrecyPrivate ) ) {
|
|
continue;
|
|
}
|
|
if ( todo->hasStartDate() && !todo->allDay() ) {
|
|
timeText = KGlobal::locale()->formatTime( todo->dtStart().toLocalZone().time() ) + QLatin1Char(' ');
|
|
} else {
|
|
timeText.clear();
|
|
}
|
|
p.save();
|
|
setColorsByIncidenceCategory( p, todo );
|
|
QString summaryStr = todo->summary();
|
|
if ( !todo->location().isEmpty() ) {
|
|
summaryStr = i18nc( "summary, location",
|
|
"%1, %2", summaryStr, todo->location() );
|
|
}
|
|
|
|
QString str;
|
|
if ( todo->hasDueDate() ) {
|
|
if ( !todo->allDay() ) {
|
|
str = i18nc( "to-do summary (Due: datetime)", "%1 (Due: %2)",
|
|
summaryStr,
|
|
KGlobal::locale()->formatDateTime( todo->dtDue().toLocalZone() ) );
|
|
} else {
|
|
str = i18nc( "to-do summary (Due: date)", "%1 (Due: %2)",
|
|
summaryStr,
|
|
KGlobal::locale()->formatDate(
|
|
todo->dtDue().toLocalZone().date(), KLocale::ShortDate ) );
|
|
}
|
|
} else {
|
|
str = summaryStr;
|
|
}
|
|
drawIncidence( p, box, timeText,
|
|
i18n( "To-do: %1", str ), todo->description(),
|
|
textY, singleLineLimit, includeDescription,
|
|
todo->descriptionIsRich() );
|
|
p.restore();
|
|
}
|
|
}
|
|
if ( showNoteLines ) {
|
|
drawNoteLines( p, box, box.y() + textY );
|
|
}
|
|
|
|
p.setFont( oldFont );
|
|
}
|
|
|
|
void CalPrintPluginBase::drawIncidence( QPainter &p, const QRect &dayBox,
|
|
const QString &time,
|
|
const QString &summary,
|
|
const QString &description,
|
|
int &textY, bool singleLineLimit,
|
|
bool includeDescription,
|
|
bool richDescription )
|
|
{
|
|
kDebug() << "summary =" << summary << ", singleLineLimit=" << singleLineLimit;
|
|
|
|
int flags = Qt::AlignLeft | Qt::OpaqueMode;
|
|
QFontMetrics fm = p.fontMetrics();
|
|
const int borderWidth = p.pen().width() + 1;
|
|
QRect timeBound = p.boundingRect( dayBox.x() + borderWidth,
|
|
dayBox.y() + textY,
|
|
dayBox.width(), fm.lineSpacing(),
|
|
flags, time );
|
|
|
|
int summaryWidth = time.isEmpty() ? 0 : timeBound.width() + 3;
|
|
QRect summaryBound = QRect( dayBox.x() + borderWidth + summaryWidth,
|
|
dayBox.y() + textY + 1,
|
|
dayBox.width() - summaryWidth - ( borderWidth * 2 ),
|
|
dayBox.height() - textY );
|
|
|
|
QString summaryText = summary;
|
|
QString descText = toPlainText( description );
|
|
bool boxOverflow = false;
|
|
|
|
if ( singleLineLimit ) {
|
|
if ( includeDescription && !descText.isEmpty() ) {
|
|
summaryText += QLatin1String(", ") + descText;
|
|
}
|
|
int totalHeight = fm.lineSpacing() + borderWidth;
|
|
int textBoxHeight = ( totalHeight > ( dayBox.height() - textY ) ) ?
|
|
dayBox.height() - textY :
|
|
totalHeight;
|
|
summaryBound.setHeight( textBoxHeight );
|
|
QRect lineRect( dayBox.x() + borderWidth, dayBox.y() + textY,
|
|
dayBox.width() - ( borderWidth * 2 ), textBoxHeight );
|
|
drawBox( p, 1, lineRect );
|
|
if ( !time.isEmpty() ) {
|
|
p.drawText( timeBound, flags, time );
|
|
}
|
|
p.drawText( summaryBound, flags, summaryText );
|
|
} else {
|
|
QTextDocument textDoc;
|
|
QTextCursor textCursor( &textDoc );
|
|
if ( richDescription ) {
|
|
QTextCursor textCursor( &textDoc );
|
|
textCursor.insertText( summaryText );
|
|
if ( includeDescription && !description.isEmpty() ) {
|
|
textCursor.insertText( QLatin1String("\n") );
|
|
textCursor.insertHtml( description );
|
|
}
|
|
} else {
|
|
textCursor.insertText( summaryText );
|
|
if ( includeDescription && !descText.isEmpty() ) {
|
|
textCursor.insertText( QLatin1String("\n") );
|
|
textCursor.insertText( descText );
|
|
}
|
|
}
|
|
textDoc.setPageSize( QSize( summaryBound.width(), summaryBound.height() ) );
|
|
p.save();
|
|
QRect clipBox( 0, 0, summaryBound.width(), summaryBound.height() );
|
|
p.setFont( p.font() );
|
|
p.translate( summaryBound.x(), summaryBound.y() );
|
|
summaryBound.setHeight( textDoc.documentLayout()->documentSize().height() );
|
|
if ( summaryBound.bottom() > dayBox.bottom() ) {
|
|
summaryBound.setBottom( dayBox.bottom() );
|
|
}
|
|
clipBox.setHeight( summaryBound.height() );
|
|
p.restore();
|
|
|
|
p.save();
|
|
QRect backBox( timeBound.x(), timeBound.y(),
|
|
dayBox.width() - ( borderWidth * 2 ), clipBox.height() );
|
|
drawBox( p, 1, backBox );
|
|
|
|
if ( !time.isEmpty() ) {
|
|
if ( timeBound.bottom() > dayBox.bottom() ) {
|
|
timeBound.setBottom( dayBox.bottom() );
|
|
}
|
|
timeBound.moveTop ( timeBound.y() + ( summaryBound.height() - timeBound.height() ) / 2 );
|
|
p.drawText( timeBound, flags, time );
|
|
}
|
|
p.translate( summaryBound.x(), summaryBound.y() );
|
|
textDoc.drawContents( &p, clipBox );
|
|
p.restore();
|
|
boxOverflow = textDoc.pageCount() > 1;
|
|
}
|
|
if ( summaryBound.bottom() < dayBox.bottom() ) {
|
|
QPen oldPen( p.pen() );
|
|
p.setPen( QPen() );
|
|
p.drawLine( dayBox.x(), summaryBound.bottom(),
|
|
dayBox.x() + dayBox.width(), summaryBound.bottom() );
|
|
p.setPen( oldPen );
|
|
}
|
|
textY += summaryBound.height();
|
|
|
|
// show that we have overflowed the box
|
|
if ( boxOverflow ) {
|
|
QPolygon poly(3);
|
|
int x = dayBox.x() + dayBox.width();
|
|
int y = dayBox.y() + dayBox.height();
|
|
poly.setPoint( 0, x - 10, y );
|
|
poly.setPoint( 1, x, y - 10 );
|
|
poly.setPoint( 2, x, y );
|
|
QBrush oldBrush( p.brush() );
|
|
p.setBrush( QBrush( Qt::black ) );
|
|
p.drawPolygon(poly);
|
|
p.setBrush( oldBrush );
|
|
textY = dayBox.height();
|
|
}
|
|
}
|
|
|
|
void CalPrintPluginBase::drawWeek( QPainter &p, const QDate &qd,
|
|
const QTime &fromTime, const QTime &toTime,
|
|
const QRect &box,
|
|
bool singleLineLimit, bool showNoteLines,
|
|
bool includeDescription,
|
|
bool excludeConfidential,
|
|
bool excludePrivate )
|
|
{
|
|
QDate weekDate = qd;
|
|
const bool portrait = ( box.height() > box.width() );
|
|
int cellWidth;
|
|
int vcells;
|
|
if ( portrait ) {
|
|
cellWidth = box.width() / 2;
|
|
vcells=3;
|
|
} else {
|
|
cellWidth = box.width() / 6;
|
|
vcells=1;
|
|
}
|
|
const int cellHeight = box.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) ) {
|
|
// Saturday and sunday share a cell, so we have to special-case sunday
|
|
int hpos = ( ( i < 6 ) ? i : ( i - 1 ) ) / vcells;
|
|
int vpos = ( ( i < 6 ) ? i : ( i - 1 ) ) % vcells;
|
|
QRect dayBox(
|
|
box.left() + cellWidth * hpos,
|
|
box.top() + cellHeight * vpos + ( ( i == 6 ) ? ( cellHeight / 2 ) : 0 ),
|
|
cellWidth, ( i < 5 ) ? ( cellHeight ) : ( cellHeight / 2 ) );
|
|
drawDayBox( p, weekDate, fromTime, toTime, dayBox, true, true, true,
|
|
singleLineLimit, showNoteLines, includeDescription,
|
|
excludeConfidential, excludePrivate );
|
|
} // for i through all weekdays
|
|
}
|
|
|
|
void CalPrintPluginBase::drawDays( QPainter &p,
|
|
const QDate &start, const QDate &end,
|
|
const QTime &fromTime, const QTime &toTime,
|
|
const QRect &box,
|
|
bool singleLineLimit, bool showNoteLines,
|
|
bool includeDescription,
|
|
bool excludeConfidential, bool excludePrivate )
|
|
{
|
|
const int numberOfDays = start.daysTo( end ) + 1;
|
|
int vcells;
|
|
const bool portrait = ( box.height() > box.width() );
|
|
int cellWidth;
|
|
if ( portrait ) {
|
|
// 2 columns
|
|
vcells = qCeil( static_cast<double>( numberOfDays ) / 2.0 );
|
|
if ( numberOfDays > 1 ) {
|
|
cellWidth = box.width() / 2;
|
|
} else {
|
|
cellWidth = box.width();
|
|
}
|
|
} else {
|
|
// landscape: N columns
|
|
vcells = 1;
|
|
cellWidth = box.width() / numberOfDays;
|
|
}
|
|
const int cellHeight = box.height() / vcells;
|
|
QDate weekDate = start;
|
|
for ( int i = 0; i < numberOfDays; ++i, weekDate = weekDate.addDays(1) ) {
|
|
const int hpos = i / vcells;
|
|
const int vpos = i % vcells;
|
|
const QRect dayBox(
|
|
box.left() + cellWidth * hpos,
|
|
box.top() + cellHeight * vpos,
|
|
cellWidth, cellHeight );
|
|
drawDayBox( p, weekDate, fromTime, toTime, dayBox,
|
|
true, true, true, singleLineLimit,
|
|
showNoteLines, includeDescription, excludeConfidential,
|
|
excludePrivate );
|
|
} // for i through all selected days
|
|
}
|
|
|
|
void CalPrintPluginBase::drawTimeTable( QPainter &p,
|
|
const QDate &fromDate,
|
|
const QDate &toDate,
|
|
bool expandable,
|
|
const QTime &fromTime,
|
|
const QTime &toTime,
|
|
const QRect &box,
|
|
bool includeDescription,
|
|
bool excludeTime,
|
|
bool excludeConfidential,
|
|
bool excludePrivate )
|
|
{
|
|
QTime myFromTime = fromTime;
|
|
QTime myToTime = toTime;
|
|
if ( expandable ) {
|
|
QDate curDate( fromDate );
|
|
KDateTime::Spec timeSpec = KSystemTimeZones::local();
|
|
while ( curDate <= toDate ) {
|
|
KCalCore::Event::List eventList = mCalendar->events( curDate, timeSpec );
|
|
Q_FOREACH ( const KCalCore::Event::Ptr &event, eventList ) {
|
|
Q_ASSERT( event );
|
|
if ( event->allDay() ) {
|
|
continue;
|
|
}
|
|
if ( event->dtStart().time() < myFromTime ) {
|
|
myFromTime = event->dtStart().time();
|
|
}
|
|
if ( event->dtEnd().time() > myToTime ) {
|
|
myToTime = event->dtEnd().time();
|
|
}
|
|
}
|
|
curDate = curDate.addDays(1);
|
|
}
|
|
}
|
|
|
|
// timeline is 1 hour:
|
|
int alldayHeight = (int)( 3600. * box.height() / ( myFromTime.secsTo( myToTime ) + 3600. ) );
|
|
int timelineWidth = TIMELINE_WIDTH;
|
|
|
|
QRect dowBox( box );
|
|
dowBox.setLeft( box.left() + timelineWidth );
|
|
dowBox.setHeight( mSubHeaderHeight );
|
|
drawDaysOfWeek( p, fromDate, toDate, dowBox );
|
|
|
|
QRect tlBox( box );
|
|
tlBox.setWidth( timelineWidth );
|
|
tlBox.setTop( dowBox.bottom() + BOX_BORDER_WIDTH + alldayHeight );
|
|
drawTimeLine( p, myFromTime, myToTime, tlBox );
|
|
|
|
// draw each day
|
|
QDate curDate( fromDate );
|
|
KDateTime::Spec timeSpec = KSystemTimeZones::local();
|
|
int i=0;
|
|
double cellWidth = double( dowBox.width() ) / double( fromDate.daysTo( toDate ) + 1 );
|
|
const QList<QDate> workDays = CalendarSupport::workDays( fromDate, toDate );
|
|
while ( curDate <= toDate ) {
|
|
QRect allDayBox( dowBox.left()+int( i * cellWidth ), dowBox.bottom() + BOX_BORDER_WIDTH,
|
|
int( ( i + 1 ) * cellWidth ) - int( i * cellWidth ), alldayHeight );
|
|
QRect dayBox( allDayBox );
|
|
dayBox.setTop( tlBox.top() );
|
|
dayBox.setBottom( box.bottom() );
|
|
KCalCore::Event::List eventList = mCalendar->events( curDate, timeSpec,
|
|
KCalCore::EventSortStartDate,
|
|
KCalCore::SortDirectionAscending );
|
|
|
|
alldayHeight = drawAllDayBox( p, eventList, curDate, false, allDayBox,
|
|
excludeConfidential, excludePrivate );
|
|
drawAgendaDayBox( p, eventList, curDate, false, myFromTime, myToTime,
|
|
dayBox, includeDescription, excludeTime,
|
|
excludeConfidential, excludePrivate, workDays );
|
|
|
|
++i;
|
|
curDate = curDate.addDays(1);
|
|
}
|
|
}
|
|
|
|
class MonthEventStruct
|
|
{
|
|
public:
|
|
MonthEventStruct() : event(0) {}
|
|
MonthEventStruct( const KDateTime &s, const KDateTime &e, const KCalCore::Event::Ptr &ev )
|
|
{
|
|
event = ev;
|
|
start = s;
|
|
end = e;
|
|
if ( event->allDay() ) {
|
|
start = KDateTime( start.date(), QTime( 0, 0, 0 ) );
|
|
end = KDateTime( end.date().addDays(1), QTime( 0, 0, 0 ) ).addSecs(-1);
|
|
}
|
|
}
|
|
bool operator < ( const MonthEventStruct &mes ) { return start < mes.start; }
|
|
KDateTime start;
|
|
KDateTime end;
|
|
KCalCore::Event::Ptr event;
|
|
};
|
|
|
|
void CalPrintPluginBase::drawMonth( QPainter &p, const QDate &dt,
|
|
const QRect &box, int maxdays,
|
|
int subDailyFlags, int holidaysFlags,
|
|
bool excludeConfidential, bool excludePrivate )
|
|
{
|
|
p.save();
|
|
const KCalendarSystem *calsys = calendarSystem();
|
|
QRect subheaderBox( box );
|
|
subheaderBox.setHeight( subHeaderHeight() );
|
|
QRect borderBox( box );
|
|
borderBox.setTop( subheaderBox.bottom() + 1 );
|
|
drawSubHeaderBox( p, calsys->monthName( dt ), subheaderBox );
|
|
// correct for half the border width
|
|
int correction = ( BOX_BORDER_WIDTH/*-1*/ ) / 2;
|
|
QRect daysBox( borderBox );
|
|
daysBox.adjust( correction, correction, -correction, -correction );
|
|
|
|
int daysinmonth = calsys->daysInMonth( dt );
|
|
if ( maxdays <= 0 ) {
|
|
maxdays = daysinmonth;
|
|
}
|
|
|
|
int d;
|
|
float dayheight = float( daysBox.height() ) / float( maxdays );
|
|
|
|
QColor holidayColor( 240, 240, 240 );
|
|
QColor workdayColor( 255, 255, 255 );
|
|
int dayNrWidth = p.fontMetrics().width( QLatin1String("99") );
|
|
|
|
// Fill the remaining space (if a month has less days than others) with a crossed-out pattern
|
|
if ( daysinmonth<maxdays ) {
|
|
QRect dayBox( box.left(), daysBox.top() + qRound( dayheight * daysinmonth ), box.width(), 0 );
|
|
dayBox.setBottom( daysBox.bottom() );
|
|
p.fillRect( dayBox, Qt::DiagCrossPattern );
|
|
}
|
|
// Backgrounded boxes for each day, plus day numbers
|
|
QBrush oldbrush( p.brush() );
|
|
|
|
QList<QDate> workDays;
|
|
|
|
{
|
|
QDate startDate;
|
|
QDate endDate;
|
|
calsys->setDate( startDate, dt.year(), dt.month(), 1 );
|
|
calsys->setDate( endDate, dt.year(), dt.month(), daysinmonth );
|
|
|
|
workDays = CalendarSupport::workDays( startDate, endDate );
|
|
}
|
|
|
|
for ( d = 0; d < daysinmonth; ++d ) {
|
|
QDate day;
|
|
calsys->setDate( day, dt.year(), dt.month(), d+1 );
|
|
QRect dayBox(
|
|
daysBox.left()/*+rand()%50*/,
|
|
daysBox.top() + qRound( dayheight * d ), daysBox.width()/*-rand()%50*/, 0 );
|
|
// 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!
|
|
dayBox.setBottom( daysBox.top() + qRound( dayheight * ( d + 1 ) ) - 1 );
|
|
|
|
p.setBrush( workDays.contains( day ) ? workdayColor : holidayColor );
|
|
p.drawRect( dayBox );
|
|
QRect dateBox( dayBox );
|
|
dateBox.setWidth( dayNrWidth + 3 );
|
|
p.drawText( dateBox,
|
|
Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine,
|
|
QString::number( d + 1 ) );
|
|
}
|
|
p.setBrush( oldbrush );
|
|
int xstartcont = box.left() + dayNrWidth + 5;
|
|
|
|
QDate start, end;
|
|
calsys->setDate( start, dt.year(), dt.month(), 1 );
|
|
end = calsys->addMonths( start, 1 );
|
|
end = calsys->addDays( end, -1 );
|
|
|
|
const KCalCore::Event::List events = mCalendar->events( start, end );
|
|
QMap<int, QStringList> textEvents;
|
|
QList<CellItem *> timeboxItems;
|
|
|
|
// 1) For multi-day events, show boxes spanning several cells, use CellItem
|
|
// print the summary vertically
|
|
// 2) For sub-day events, print the concated summaries into the remaining
|
|
// space of the box (optional, depending on the given flags)
|
|
// 3) Draw some kind of timeline showing free and busy times
|
|
|
|
// Holidays
|
|
QList<KCalCore::Event::Ptr> holidays;
|
|
for ( QDate d( start ); d <= end; d = d.addDays(1) ) {
|
|
KCalCore::Event::Ptr e = holidayEvent( d );
|
|
if ( e ) {
|
|
holidays.append( e );
|
|
if ( holidaysFlags & TimeBoxes ) {
|
|
timeboxItems.append( new PrintCellItem( e, KDateTime( d, QTime( 0, 0, 0 ) ),
|
|
KDateTime( d.addDays(1), QTime( 0, 0, 0 ) ) ) );
|
|
}
|
|
if ( holidaysFlags & Text ) {
|
|
textEvents[d.day()] << e->summary();
|
|
}
|
|
}
|
|
}
|
|
|
|
QList<MonthEventStruct> monthentries;
|
|
|
|
KDateTime::Spec timeSpec = KSystemTimeZones::local();
|
|
Q_FOREACH ( const KCalCore::Event::Ptr &e, events ) {
|
|
if ( !e ) {
|
|
continue;
|
|
}
|
|
if ( ( excludeConfidential && e->secrecy() == KCalCore::Incidence::SecrecyConfidential ) ||
|
|
( excludePrivate && e->secrecy() == KCalCore::Incidence::SecrecyPrivate ) ) {
|
|
continue;
|
|
}
|
|
if ( e->recurs() ) {
|
|
if ( e->recursOn( start, timeSpec ) ) {
|
|
// This occurrence has possibly started before the beginning of the
|
|
// month, so obtain the start date before the beginning of the month
|
|
QList<KDateTime> starttimes = e->startDateTimesForDate( start );
|
|
QList<KDateTime>::ConstIterator it = starttimes.constBegin();
|
|
for ( ; it != starttimes.constEnd(); ++it ) {
|
|
monthentries.append( MonthEventStruct( *it, e->endDateForStart( *it ), e ) );
|
|
}
|
|
}
|
|
// Loop through all remaining days of the month and check if the event
|
|
// begins on that day (don't use Event::recursOn, as that will
|
|
// also return events that have started earlier. These start dates
|
|
// however, have already been treated!
|
|
KCalCore::Recurrence *recur = e->recurrence();
|
|
QDate d1( start.addDays(1) );
|
|
while ( d1 <= end ) {
|
|
if ( recur->recursOn( d1, timeSpec ) ) {
|
|
KCalCore::TimeList times( recur->recurTimesOn( d1, timeSpec ) );
|
|
for ( KCalCore::TimeList::ConstIterator it = times.constBegin();
|
|
it != times.constEnd(); ++it ) {
|
|
KDateTime d1start( d1, *it, timeSpec );
|
|
monthentries.append( MonthEventStruct( d1start, e->endDateForStart( d1start ), e ) );
|
|
}
|
|
}
|
|
d1 = d1.addDays(1);
|
|
}
|
|
} else {
|
|
monthentries.append( MonthEventStruct( e->dtStart(), e->dtEnd(), e ) );
|
|
}
|
|
}
|
|
|
|
// TODO: to port the month entries sorting
|
|
|
|
// qSort( monthentries.begin(), monthentries.end() );
|
|
|
|
QList<MonthEventStruct>::ConstIterator mit = monthentries.constBegin();
|
|
KDateTime endofmonth( end, QTime( 0, 0, 0 ) );
|
|
endofmonth = endofmonth.addDays(1);
|
|
for ( ; mit != monthentries.constEnd(); ++mit ) {
|
|
if ( (*mit).start.date() == (*mit).end.date() ) {
|
|
// Show also single-day events as time line boxes
|
|
if ( subDailyFlags & TimeBoxes ) {
|
|
timeboxItems.append(
|
|
new PrintCellItem( (*mit).event, (*mit).start, (*mit).end ) );
|
|
}
|
|
// Show as text in the box
|
|
if ( subDailyFlags & Text ) {
|
|
textEvents[(*mit).start.date().day()] << (*mit).event->summary();
|
|
}
|
|
} else {
|
|
// Multi-day events are always shown as time line boxes
|
|
KDateTime thisstart( (*mit).start );
|
|
KDateTime thisend( (*mit).end );
|
|
if ( thisstart.date() < start ) {
|
|
thisstart.setDate( start );
|
|
}
|
|
if ( thisend > endofmonth ) {
|
|
thisend = endofmonth;
|
|
}
|
|
timeboxItems.append(
|
|
new PrintCellItem( (*mit).event, thisstart, thisend ) );
|
|
}
|
|
}
|
|
|
|
// For Multi-day events, line them up nicely so that the boxes don't overlap
|
|
QListIterator<CellItem *> it1( timeboxItems );
|
|
while ( it1.hasNext() ) {
|
|
CellItem *placeItem = it1.next();
|
|
CellItem::placeItem( timeboxItems, placeItem );
|
|
}
|
|
KDateTime starttime( start, QTime( 0, 0, 0 ) );
|
|
int newxstartcont = xstartcont;
|
|
|
|
QFont oldfont( p.font() );
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 7 ) );
|
|
while ( it1.hasNext() ) {
|
|
PrintCellItem *placeItem = static_cast<PrintCellItem *>( it1.next() );
|
|
int minsToStart = starttime.secsTo( placeItem->start() ) / 60;
|
|
int minsToEnd = starttime.secsTo( placeItem->end() ) / 60;
|
|
|
|
QRect eventBox(
|
|
xstartcont + placeItem->subCell() * 17,
|
|
daysBox.top() + qRound(
|
|
double( minsToStart * daysBox.height() ) / double( maxdays * 24 * 60 ) ), 14, 0 );
|
|
eventBox.setBottom(
|
|
daysBox.top() + qRound(
|
|
double( minsToEnd * daysBox.height() ) / double( maxdays * 24 * 60 ) ) );
|
|
drawVerticalBox( p, 0, eventBox, placeItem->event()->summary() );
|
|
newxstartcont = qMax( newxstartcont, eventBox.right() );
|
|
}
|
|
xstartcont = newxstartcont;
|
|
|
|
// For Single-day events, simply print their summaries into the remaining
|
|
// space of the day's cell
|
|
for ( int d=0; d<daysinmonth; ++d ) {
|
|
QStringList dayEvents( textEvents[d+1] );
|
|
QString txt = dayEvents.join( QLatin1String(", ") );
|
|
QRect dayBox( xstartcont, daysBox.top() + qRound( dayheight * d ), 0, 0 );
|
|
dayBox.setRight( box.right() );
|
|
dayBox.setBottom( daysBox.top() + qRound( dayheight * ( d + 1 ) ) );
|
|
printEventString( p, dayBox, txt, Qt::AlignTop | Qt::AlignLeft | Qt::TextWrapAnywhere );
|
|
}
|
|
p.setFont( oldfont );
|
|
drawBox( p, BOX_BORDER_WIDTH, borderBox );
|
|
p.restore();
|
|
}
|
|
|
|
void CalPrintPluginBase::drawMonthTable( QPainter &p, const QDate &qd,
|
|
const QTime &fromTime, const QTime &toTime,
|
|
bool weeknumbers, bool recurDaily,
|
|
bool recurWeekly, bool singleLineLimit,
|
|
bool showNoteLines,
|
|
bool includeDescription,
|
|
bool excludeConfidential,
|
|
bool excludePrivate,
|
|
const QRect &box )
|
|
{
|
|
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);
|
|
|
|
if (weeknumbers) {
|
|
xoffset += 14;
|
|
}
|
|
|
|
int rows = ( weekdayCol + qd.daysInMonth() - 1 ) / 7 + 1;
|
|
double cellHeight = ( box.height() - yoffset ) / ( 1. * rows );
|
|
double cellWidth = ( box.width() - xoffset ) / 7.;
|
|
|
|
// Precalculate the grid...
|
|
// rows is at most 6, so using 8 entries in the array is fine, too!
|
|
int coledges[8], rowedges[8];
|
|
for ( int i = 0; i <= 7; ++i ) {
|
|
rowedges[i] = int( box.top() + yoffset + i * cellHeight );
|
|
coledges[i] = int( box.left() + xoffset + i * cellWidth );
|
|
}
|
|
|
|
if ( weeknumbers ) {
|
|
QFont oldFont( p.font() );
|
|
QFont newFont( p.font() );
|
|
newFont.setPointSize( 6 );
|
|
p.setFont( newFont );
|
|
QDate weekDate( monthDate );
|
|
for ( int row = 0; row<rows; ++row ) {
|
|
int calWeek = weekDate.weekNumber();
|
|
QRect rc( box.left(), rowedges[row],
|
|
coledges[0] - 3 - box.left(), rowedges[row + 1] - rowedges[row] );
|
|
p.drawText( rc, Qt::AlignRight | Qt::AlignVCenter, QString::number( calWeek ) );
|
|
weekDate = weekDate.addDays( 7 );
|
|
}
|
|
p.setFont( oldFont );
|
|
}
|
|
|
|
QRect daysOfWeekBox( box );
|
|
daysOfWeekBox.setHeight( mSubHeaderHeight );
|
|
daysOfWeekBox.setLeft( box.left() + xoffset );
|
|
drawDaysOfWeek( p, monthDate, monthDate.addDays( 6 ), daysOfWeekBox );
|
|
|
|
QColor back = p.background().color();
|
|
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.setBackground( back.darker( 120 ) );
|
|
darkbg = true;
|
|
}
|
|
QRect dayBox( coledges[col], rowedges[row],
|
|
coledges[col + 1] - coledges[col], rowedges[row + 1] - rowedges[row] );
|
|
drawDayBox( p, monthDate, fromTime, toTime, dayBox, false,
|
|
recurDaily, recurWeekly, singleLineLimit, showNoteLines,
|
|
includeDescription, excludeConfidential, excludePrivate );
|
|
if ( darkbg ) {
|
|
p.setBackground( back );
|
|
darkbg = false;
|
|
}
|
|
monthDate = monthDate.addDays(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CalPrintPluginBase::drawTodoLines( QPainter &p,
|
|
const QString &entry,
|
|
int x, int &y, int width,
|
|
int pageHeight, bool richTextEntry,
|
|
QList<TodoParentStart *> &startPoints,
|
|
bool connectSubTodos )
|
|
{
|
|
QString plainEntry = ( richTextEntry ) ? toPlainText( entry ) : entry;
|
|
|
|
QRect textrect( 0, 0, width, -1 );
|
|
int flags = Qt::AlignLeft;
|
|
QFontMetrics fm = p.fontMetrics();
|
|
|
|
QStringList lines = plainEntry.split( QLatin1Char( '\n' ) );
|
|
for ( int currentLine = 0; currentLine < lines.count(); currentLine++ ) {
|
|
// split paragraphs into lines
|
|
KWordWrap *ww = KWordWrap::formatText( fm, textrect, flags, lines[currentLine] );
|
|
QStringList textLine = ww->wrappedString().split( QLatin1Char( '\n' ) );
|
|
delete ww;
|
|
|
|
// print each individual line
|
|
for ( int lineCount = 0; lineCount < textLine.count(); lineCount++ ) {
|
|
if ( y >= pageHeight ) {
|
|
if ( connectSubTodos ) {
|
|
for ( int i = 0; i < startPoints.size(); ++i ) {
|
|
TodoParentStart *rct;
|
|
rct = startPoints.at( i );
|
|
int start = rct->mRect.bottom() + 1;
|
|
int center = rct->mRect.left() + ( rct->mRect.width() / 2 );
|
|
int to = y;
|
|
if ( !rct->mSamePage ) {
|
|
start = 0;
|
|
}
|
|
if ( rct->mHasLine ) {
|
|
p.drawLine( center, start, center, to );
|
|
}
|
|
rct->mSamePage = false;
|
|
}
|
|
}
|
|
y = 0;
|
|
mPrinter->newPage();
|
|
}
|
|
y += fm.height();
|
|
p.drawText( x, y, textLine[lineCount] );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CalPrintPluginBase::drawTodo( int &count, const KCalCore::Todo::Ptr &todo, QPainter &p,
|
|
KCalCore::TodoSortField sortField,
|
|
KCalCore::SortDirection sortDir,
|
|
bool connectSubTodos, bool strikeoutCompleted,
|
|
bool desc, int posPriority, int posSummary,
|
|
int posDueDt, int posPercentComplete,
|
|
int level, int x, int &y, int width,
|
|
int pageHeight, const KCalCore::Todo::List &todoList,
|
|
TodoParentStart *r, bool excludeConfidential,
|
|
bool excludePrivate )
|
|
{
|
|
QString outStr;
|
|
const KLocale *local = KGlobal::locale();
|
|
QRect rect;
|
|
TodoParentStart startpt;
|
|
// This list keeps all starting points of the parent to-dos so the connection
|
|
// lines of the tree can easily be drawn (needed if a new page is started)
|
|
static QList<TodoParentStart *> startPoints;
|
|
if ( level < 1 ) {
|
|
startPoints.clear();
|
|
}
|
|
|
|
y += 10;
|
|
|
|
// Compute the right hand side of the to-do box
|
|
int rhs = posPercentComplete;
|
|
if ( rhs < 0 ) {
|
|
rhs = posDueDt; //not printing percent completed
|
|
}
|
|
if ( rhs < 0 ) {
|
|
rhs = x + width; //not printing due dates either
|
|
}
|
|
|
|
int left = posSummary + ( level * 10 );
|
|
|
|
// If this is a sub-to-do, r will not be 0, and we want the LH side
|
|
// of the priority line up to the RH side of the parent to-do's priority
|
|
bool showPriority = posPriority >= 0;
|
|
int lhs = posPriority;
|
|
if ( r ) {
|
|
lhs = r->mRect.right() + 1;
|
|
}
|
|
|
|
outStr.setNum( todo->priority() );
|
|
rect = p.boundingRect( lhs, y + 10, 5, -1, Qt::AlignCenter, outStr );
|
|
// Make it a more reasonable size
|
|
rect.setWidth( 18 );
|
|
rect.setHeight( 18 );
|
|
|
|
// Draw a checkbox
|
|
p.setBrush( QBrush( Qt::NoBrush ) );
|
|
p.drawRect( rect );
|
|
if ( todo->isCompleted() ) {
|
|
// cross out the rectangle for completed to-dos
|
|
p.drawLine( rect.topLeft(), rect.bottomRight() );
|
|
p.drawLine( rect.topRight(), rect.bottomLeft() );
|
|
}
|
|
lhs = rect.right() + 3;
|
|
|
|
// Priority
|
|
if ( todo->priority() > 0 && showPriority ) {
|
|
p.drawText( rect, Qt::AlignCenter, outStr );
|
|
}
|
|
startpt.mRect = rect; //save for later
|
|
|
|
// Connect the dots
|
|
if ( r && level > 0 && connectSubTodos ) {
|
|
int bottom;
|
|
int center( r->mRect.left() + ( r->mRect.width() / 2 ) );
|
|
int to( rect.top() + ( rect.height() / 2 ) );
|
|
int endx( rect.left() );
|
|
p.drawLine( center, to, endx, to ); // side connector
|
|
if ( r->mSamePage ) {
|
|
bottom = r->mRect.bottom() + 1;
|
|
} else {
|
|
bottom = 0;
|
|
}
|
|
p.drawLine( center, bottom, center, to );
|
|
}
|
|
|
|
// summary
|
|
outStr = todo->summary();
|
|
rect = p.boundingRect( lhs, rect.top(), ( rhs - ( left + rect.width() + 5 ) ),
|
|
-1, Qt::TextWordWrap, outStr );
|
|
|
|
QRect newrect;
|
|
QFont newFont( p.font() );
|
|
QFont oldFont( p.font() );
|
|
if ( todo->isCompleted() && strikeoutCompleted ) {
|
|
newFont.setStrikeOut( true );
|
|
p.setFont( newFont );
|
|
}
|
|
p.drawText( rect, Qt::TextWordWrap, outStr, &newrect );
|
|
p.setFont( oldFont );
|
|
// due date
|
|
if ( todo->hasDueDate() && posDueDt >= 0 ) {
|
|
outStr = local->formatDate( todo->dtDue().toLocalZone().date(), KLocale::ShortDate );
|
|
rect = p.boundingRect( posDueDt, y, x + width, -1,
|
|
Qt::AlignTop | Qt::AlignLeft, outStr );
|
|
p.drawText( rect, Qt::AlignTop | Qt::AlignLeft, outStr );
|
|
}
|
|
|
|
// percentage completed
|
|
bool showPercentComplete = posPercentComplete >= 0;
|
|
if ( showPercentComplete ) {
|
|
int lwidth = 24;
|
|
int lheight = 12;
|
|
//first, draw the progress bar
|
|
int progress = (int)( ( lwidth * todo->percentComplete() ) / 100.0 + 0.5 );
|
|
|
|
p.setBrush( QBrush( Qt::NoBrush ) );
|
|
p.drawRect( posPercentComplete, y+3, lwidth, lheight );
|
|
if ( progress > 0 ) {
|
|
p.setBrush( QColor( 128, 128, 128 ) );
|
|
p.drawRect( posPercentComplete, y+3, progress, lheight );
|
|
}
|
|
|
|
//now, write the percentage
|
|
outStr = i18n( "%1%", todo->percentComplete() );
|
|
rect = p.boundingRect( posPercentComplete+lwidth+3, y, x + width, -1,
|
|
Qt::AlignTop | Qt::AlignLeft, outStr );
|
|
p.drawText( rect, Qt::AlignTop | Qt::AlignLeft, outStr );
|
|
}
|
|
|
|
y += 10;
|
|
|
|
// Make a list of all the sub-to-dos related to this to-do.
|
|
KCalCore::Todo::List t;
|
|
KCalCore::Incidence::List relations = mCalendar->childIncidences( todo->uid() );
|
|
|
|
foreach ( const KCalCore::Incidence::Ptr &incidence, relations ) {
|
|
// In the future, to-dos might also be related to events
|
|
// Manually check if the sub-to-do is in the list of to-dos to print
|
|
// The problem is that relations() does not apply filters, so
|
|
// we need to compare manually with the complete filtered list!
|
|
KCalCore::Todo::Ptr subtodo = incidence.dynamicCast<KCalCore::Todo>();
|
|
if ( !subtodo ) continue;
|
|
#ifdef AKONADI_PORT_DISABLED
|
|
if ( subtodo && todoList.contains( subtodo ) ) {
|
|
#else
|
|
bool subtodoOk = false;
|
|
if ( subtodo ) {
|
|
foreach ( const KCalCore::Todo::Ptr &tt, todoList ) {
|
|
if ( tt == subtodo ) {
|
|
subtodoOk = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( subtodoOk ) {
|
|
#endif
|
|
if ( ( excludeConfidential &&
|
|
subtodo->secrecy() == KCalCore::Incidence::SecrecyConfidential ) ||
|
|
( excludePrivate &&
|
|
subtodo->secrecy() == KCalCore::Incidence::SecrecyPrivate ) ) {
|
|
continue;
|
|
}
|
|
t.append( subtodo );
|
|
}
|
|
}
|
|
|
|
// has sub-todos?
|
|
startpt.mHasLine = ( relations.size() > 0 );
|
|
startPoints.append( &startpt );
|
|
|
|
// description
|
|
if ( !todo->description().isEmpty() && desc ) {
|
|
y = newrect.bottom() + 5;
|
|
drawTodoLines( p, todo->description(), left, y,
|
|
width - ( left + 10 - x ), pageHeight,
|
|
todo->descriptionIsRich(),
|
|
startPoints, connectSubTodos );
|
|
} else {
|
|
y += 10;
|
|
}
|
|
|
|
// Sort the sub-to-dos and print them
|
|
#ifdef AKONADI_PORT_DISABLED
|
|
KCalCore::Todo::List sl = mCalendar->sortTodos( &t, sortField, sortDir );
|
|
#else
|
|
KCalCore::Todo::List tl;
|
|
foreach ( const KCalCore::Todo::Ptr &todo, t ) {
|
|
tl.append( todo );
|
|
}
|
|
KCalCore::Todo::List sl = mCalendar->sortTodos( tl, sortField, sortDir );
|
|
#endif
|
|
|
|
int subcount = 0;
|
|
foreach ( const KCalCore::Todo::Ptr &isl, sl ) {
|
|
count++;
|
|
if ( ++subcount == sl.size() ) {
|
|
startpt.mHasLine = false;
|
|
}
|
|
drawTodo( count, isl, p, sortField, sortDir,
|
|
connectSubTodos, strikeoutCompleted,
|
|
desc, posPriority, posSummary, posDueDt, posPercentComplete,
|
|
level+1, x, y, width, pageHeight, todoList, &startpt,
|
|
excludeConfidential, excludePrivate );
|
|
}
|
|
startPoints.removeAll( &startpt );
|
|
}
|
|
|
|
int CalPrintPluginBase::weekdayColumn( int weekday )
|
|
{
|
|
int w = weekday + 7 - KGlobal::locale()->weekStartDay();
|
|
return w % 7;
|
|
}
|
|
|
|
void CalPrintPluginBase::drawTextLines( QPainter &p, const QString &entry,
|
|
int x, int &y, int width,
|
|
int pageHeight, bool richTextEntry )
|
|
{
|
|
QString plainEntry = ( richTextEntry ) ? toPlainText( entry ) : entry;
|
|
|
|
QRect textrect( 0, 0, width, -1 );
|
|
int flags = Qt::AlignLeft;
|
|
QFontMetrics fm = p.fontMetrics();
|
|
|
|
QStringList lines = plainEntry.split( QLatin1Char( '\n' ) );
|
|
for ( int currentLine = 0; currentLine < lines.count(); currentLine++ ) {
|
|
// split paragraphs into lines
|
|
KWordWrap *ww = KWordWrap::formatText( fm, textrect, flags, lines[currentLine] );
|
|
QStringList textLine = ww->wrappedString().split( QLatin1Char( '\n' ) );
|
|
delete ww;
|
|
// print each individual line
|
|
for ( int lineCount = 0; lineCount < textLine.count(); lineCount++ ) {
|
|
if ( y >= pageHeight ) {
|
|
y = 0;
|
|
mPrinter->newPage();
|
|
}
|
|
y += fm.height();
|
|
p.drawText( x, y, textLine[lineCount] );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CalPrintPluginBase::drawJournal( const KCalCore::Journal::Ptr &journal, QPainter &p,
|
|
int x, int &y, int width, int pageHeight )
|
|
{
|
|
QFont oldFont( p.font() );
|
|
p.setFont( QFont( QLatin1String("sans-serif"), 15 ) );
|
|
QString headerText;
|
|
QString dateText( KGlobal::locale()->formatDate( journal->dtStart().toLocalZone().date(),
|
|
KLocale::LongDate ) );
|
|
|
|
if ( journal->summary().isEmpty() ) {
|
|
headerText = dateText;
|
|
} else {
|
|
headerText = i18nc( "Description - date", "%1 - %2", journal->summary(), dateText );
|
|
}
|
|
|
|
QRect rect( p.boundingRect( x, y, width, -1, Qt::TextWordWrap, headerText ) );
|
|
if ( rect.bottom() > pageHeight ) {
|
|
// Start new page...
|
|
y = 0;
|
|
mPrinter->newPage();
|
|
rect = p.boundingRect( x, y, width, -1, Qt::TextWordWrap, headerText );
|
|
}
|
|
QRect newrect;
|
|
p.drawText( rect, Qt::TextWordWrap, headerText, &newrect );
|
|
p.setFont( oldFont );
|
|
|
|
y = newrect.bottom() + 4;
|
|
|
|
p.drawLine( x + 3, y, x + width - 6, y );
|
|
y += 5;
|
|
if ( !( journal->organizer()->fullName().isEmpty() ) ) {
|
|
drawTextLines( p, i18n( "Person: %1", journal->organizer()->fullName() ),
|
|
x, y, width, pageHeight, false );
|
|
y += 7;
|
|
}
|
|
if ( !( journal->description().isEmpty() ) ) {
|
|
drawTextLines( p, journal->description(), x, y, width, pageHeight,
|
|
journal->descriptionIsRich() );
|
|
y += 7;
|
|
}
|
|
y += 10;
|
|
}
|
|
|
|
void CalPrintPluginBase::drawSplitHeaderRight( QPainter &p, const QDate &fd,
|
|
const QDate &td, const QDate &,
|
|
int width, int height )
|
|
{
|
|
QFont oldFont( p.font() );
|
|
|
|
QPen oldPen( p.pen() );
|
|
QPen pen( Qt::black, 4 );
|
|
|
|
QString title;
|
|
if ( mCalSys ) {
|
|
if ( fd.month() == td.month() ) {
|
|
title = i18nc( "Date range: Month dayStart - dayEnd", "%1 %2 - %3",
|
|
mCalSys->monthName( fd.month(), KCalendarSystem::LongName ),
|
|
mCalSys->formatDate( fd, KLocale::Day, KLocale::LongNumber ),
|
|
mCalSys->formatDate( td, KLocale::Day, KLocale::LongNumber ) );
|
|
} else {
|
|
title = i18nc( "Date range: monthStart dayStart - monthEnd dayEnd", "%1 %2 - %3 %4",
|
|
mCalSys->monthName( fd.month(), KCalendarSystem::LongName ),
|
|
mCalSys->formatDate( fd, KLocale::Day, KLocale::LongNumber ),
|
|
mCalSys->monthName( td.month(), KCalendarSystem::LongName ),
|
|
mCalSys->formatDate( td, KLocale::Day, KLocale::LongNumber ) );
|
|
}
|
|
}
|
|
|
|
if ( height < 60 ) {
|
|
p.setFont( QFont( QLatin1String("Times"), 22 ) );
|
|
} else {
|
|
p.setFont( QFont( QLatin1String("Times"), 28 ) );
|
|
}
|
|
|
|
int lineSpacing = p.fontMetrics().lineSpacing();
|
|
p.drawText( 0, 0, width, lineSpacing,
|
|
Qt::AlignRight | Qt::AlignTop, title );
|
|
|
|
title.truncate(0);
|
|
|
|
p.setPen( pen );
|
|
p.drawLine( 300, lineSpacing, width, lineSpacing );
|
|
p.setPen( oldPen );
|
|
|
|
if ( height < 60 ) {
|
|
p.setFont( QFont( QLatin1String("Times"), 14, QFont::Bold, true ) );
|
|
} else {
|
|
p.setFont( QFont( QLatin1String("Times"), 18, QFont::Bold, true ) );
|
|
}
|
|
|
|
title += QString::number( fd.year() );
|
|
p.drawText( 0, lineSpacing, width, lineSpacing,
|
|
Qt::AlignRight | Qt::AlignTop, title );
|
|
|
|
p.setFont( oldFont );
|
|
}
|
|
|
|
void CalPrintPluginBase::drawNoteLines( QPainter &p, const QRect &box, int startY )
|
|
{
|
|
int lineHeight = int( p.fontMetrics().lineSpacing() * 1.5 );
|
|
int linePos = box.y();
|
|
int startPos = startY;
|
|
// adjust line to start at multiple from top of box for alignment
|
|
while ( linePos < startPos ) {
|
|
linePos += lineHeight;
|
|
}
|
|
QPen oldPen( p.pen() );
|
|
p.setPen( Qt::DotLine );
|
|
while ( linePos < box.bottom() ) {
|
|
p.drawLine( box.left() + padding(), linePos,
|
|
box.right() - padding(), linePos );
|
|
linePos += lineHeight;
|
|
}
|
|
p.setPen( oldPen );
|
|
}
|
|
|
|
QString CalPrintPluginBase::toPlainText( const QString &htmlText )
|
|
{
|
|
// this converts possible rich text to plain text
|
|
return QTextDocumentFragment::fromHtml( htmlText ).toPlainText();
|
|
}
|