diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 (patch) | |
tree | 67208f7c145782a7e90b123b982ca78d88cc2c87 /korganizer/printing/calprintdefaultplugins.cpp | |
download | tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.tar.gz tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'korganizer/printing/calprintdefaultplugins.cpp')
-rw-r--r-- | korganizer/printing/calprintdefaultplugins.cpp | 1186 |
1 files changed, 1186 insertions, 0 deletions
diff --git a/korganizer/printing/calprintdefaultplugins.cpp b/korganizer/printing/calprintdefaultplugins.cpp new file mode 100644 index 000000000..d12df1e26 --- /dev/null +++ b/korganizer/printing/calprintdefaultplugins.cpp @@ -0,0 +1,1186 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 1998 Preston Brown <pbrown@kde.org> + Copyright (c) 2003 Reinhold Kainhofer <reinhold@kainhofer.com> + Copyright (c) 2003 Cornelius Schumacher <schumacher@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. +*/ + +#ifndef KORG_NOPRINTER + +#include <qpainter.h> +#include <qdatetimeedit.h> +#include <qcheckbox.h> +#include <qlineedit.h> +#include <qbuttongroup.h> + +#include <kdebug.h> +#include <kconfig.h> +#include <kcalendarsystem.h> +#include <knuminput.h> +#include <kcombobox.h> + +#include "calprintdefaultplugins.h" + +#include "calprintincidenceconfig_base.h" +#include "calprintdayconfig_base.h" +#include "calprintweekconfig_base.h" +#include "calprintmonthconfig_base.h" +#include "calprinttodoconfig_base.h" + + +/************************************************************** + * Print Incidence + **************************************************************/ + +CalPrintIncidence::CalPrintIncidence() : CalPrintPluginBase() +{ +} + +CalPrintIncidence::~CalPrintIncidence() +{ +} + +QWidget *CalPrintIncidence::createConfigWidget( QWidget *w ) +{ + return new CalPrintIncidenceConfig_Base( w ); +} + +void CalPrintIncidence::readSettingsWidget() +{ + CalPrintIncidenceConfig_Base *cfg = + dynamic_cast<CalPrintIncidenceConfig_Base*>( mConfigWidget ); + if ( cfg ) { + mUseColors = cfg->mColors->isChecked(); + mShowOptions = cfg->mShowDetails->isChecked(); + mShowSubitemsNotes = cfg->mShowSubitemsNotes->isChecked(); + mShowAttendees = cfg->mShowAttendees->isChecked(); + mShowAttachments = cfg->mShowAttachments->isChecked(); + } +} + +void CalPrintIncidence::setSettingsWidget() +{ + CalPrintIncidenceConfig_Base *cfg = + dynamic_cast<CalPrintIncidenceConfig_Base*>( mConfigWidget ); + if ( cfg ) { + cfg->mColors->setChecked( mUseColors ); + cfg->mShowDetails->setChecked(mShowOptions); + cfg->mShowSubitemsNotes->setChecked(mShowSubitemsNotes); + cfg->mShowAttendees->setChecked(mShowAttendees); + cfg->mShowAttachments->setChecked(mShowAttachments); + } +} + +void CalPrintIncidence::loadConfig() +{ + if ( mConfig ) { + mUseColors = mConfig->readBoolEntry( "Use Colors", false ); + mShowOptions = mConfig->readBoolEntry( "Show Options", false ); + mShowSubitemsNotes = mConfig->readBoolEntry( "Show Subitems and Notes", false ); + mShowAttendees = mConfig->readBoolEntry( "Use Attendees", false ); + mShowAttachments = mConfig->readBoolEntry( "Use Attachments", false ); + } + setSettingsWidget(); +} + +void CalPrintIncidence::saveConfig() +{ + readSettingsWidget(); + if ( mConfig ) { + mConfig->writeEntry( "Use Colors", mUseColors ); + mConfig->writeEntry( "Show Options", mShowOptions ); + mConfig->writeEntry( "Show Subitems and Notes", mShowSubitemsNotes ); + mConfig->writeEntry( "Use Attendees", mShowAttendees ); + mConfig->writeEntry( "Use Attachments", mShowAttachments ); + } +} + + +class TimePrintStringsVisitor : public IncidenceBase::Visitor +{ + public: + TimePrintStringsVisitor() {} + + bool act( IncidenceBase *incidence ) + { + return incidence->accept( *this ); + } + QString mStartCaption, mStartString; + QString mEndCaption, mEndString; + QString mDurationCaption, mDurationString; + + protected: + bool visit( Event *event ) { + if ( event->dtStart().isValid() ) { + mStartCaption = i18n("Start date: "); + // Show date/time or only date, depending on whether it's an all-day event +// TODO: Add shortfmt param to dtStartStr, dtEndStr and dtDueStr!!! + mStartString = (event->doesFloat()) ? (event->dtStartDateStr(false)) : (event->dtStartStr()); + } else { + mStartCaption = i18n("No start date"); + mStartString = QString::null; + } + + if ( event->hasEndDate() ) { + mEndCaption = i18n("End date: "); + mEndString = (event->doesFloat()) ? (event->dtEndDateStr(false)) : (event->dtEndStr()); + } else if ( event->hasDuration() ) { + mEndCaption = i18n("Duration: "); + int mins = event->duration() / 60; + if ( mins >= 60 ) { + mEndString += i18n( "1 hour ", "%n hours ", mins/60 ); + } + if ( mins%60 > 0 ) { + mEndString += i18n( "1 minute ", "%n minutes ", mins%60 ); + } + } else { + mEndCaption = i18n("No end date"); + mEndString = QString::null; + } + return true; + } + bool visit( Todo *todo ) { + if ( todo->hasStartDate() ) { + mStartCaption = i18n("Start date: "); + // Show date/time or only date, depending on whether it's an all-day event +// TODO: Add shortfmt param to dtStartStr, dtEndStr and dtDueStr!!! + mStartString = (todo->doesFloat()) ? (todo->dtStartDateStr(false)) : (todo->dtStartStr()); + } else { + mStartCaption = i18n("No start date"); + mStartString = QString::null; + } + + if ( todo->hasDueDate() ) { + mEndCaption = i18n("Due date: "); + mEndString = (todo->doesFloat()) ? (todo->dtDueDateStr(false)) : (todo->dtDueStr()); + } else { + mEndCaption = i18n("No due date"); + mEndString = QString::null; + } + return true; + } + bool visit( Journal *journal ) { + mStartCaption = i18n("Start date: "); +// TODO: Add shortfmt param to dtStartStr, dtEndStr and dtDueStr!!! + mStartString = (journal->doesFloat()) ? (journal->dtStartDateStr(false)) : (journal->dtStartStr()); + mEndCaption = QString::null; + mEndString = QString::null; + return true; + } +}; + +int CalPrintIncidence::printCaptionAndText( QPainter &p, const QRect &box, const QString &caption, const QString &text, QFont captionFont, QFont textFont ) +{ + QFontMetrics captionFM( captionFont ); + int textWd = captionFM.width( caption ); + QRect textRect( box ); + + QFont oldFont( p.font() ); + p.setFont( captionFont ); + p.drawText( box, Qt::AlignLeft|Qt::AlignTop|Qt::SingleLine, caption ); + + if ( !text.isEmpty() ) { + textRect.setLeft( textRect.left() + textWd ); + p.setFont( textFont ); + p.drawText( textRect, Qt::AlignLeft|Qt::AlignTop|Qt::SingleLine, text ); + } + p.setFont( oldFont ); + return textRect.bottom(); +} + +#include <qfontdatabase.h> +void CalPrintIncidence::print( QPainter &p, int width, int height ) +{ + KLocale *local = KGlobal::locale(); + + QFont oldFont(p.font()); + QFont textFont( "sans-serif", 11, QFont::Normal ); + QFont captionFont( "sans-serif", 11, QFont::Bold ); + p.setFont( textFont ); + int lineHeight = p.fontMetrics().lineSpacing(); + QString cap, txt; + + + Incidence::List::ConstIterator it; + for ( it=mSelectedIncidences.begin(); it!=mSelectedIncidences.end(); ++it ) { + // don't do anything on a 0-pointer! + if ( !(*it) ) continue; + if ( it != mSelectedIncidences.begin() ) mPrinter->newPage(); + + + // PAGE Layout (same for landscape and portrait! astonishingly, it looks good with both!): + // +-----------------------------------+ + // | Header: Summary | + // +===================================+ + // | start: ______ end: _________ | + // | repeats: ___________________ | + // | reminder: __________________ | + // +-----------------------------------+ + // | Location: ______________________ | + // +------------------------+----------+ + // | Description: | Notes or | + // | | Subitems | + // | | | + // | | | + // | | | + // | | | + // | | | + // | | | + // | | | + // | | | + // +------------------------+----------+ + // | Attachments: | Settings | + // | | | + // +------------------------+----------+ + // | Attendees: | + // | | + // +-----------------------------------+ + // | Categories: _____________________ | + // +-----------------------------------+ + + QRect box( 0, 0, width, height ); + QRect titleBox( box ); + titleBox.setHeight( headerHeight() ); + // Draw summary as header, no small calendars in title bar, expand height if needed + int titleBottom = drawHeader( p, (*it)->summary(), QDate(), QDate(), titleBox, true ); + titleBox.setBottom( titleBottom ); + + QRect timesBox( titleBox ); + timesBox.setTop( titleBox.bottom() + padding() ); + timesBox.setHeight( height / 8 ); + + TimePrintStringsVisitor stringVis; + int h = timesBox.top(); + if ( stringVis.act(*it) ) { + QRect textRect( timesBox.left()+padding(), timesBox.top()+padding(), 0, lineHeight ); + textRect.setRight( timesBox.center().x() ); + h = printCaptionAndText( p, textRect, stringVis.mStartCaption, stringVis.mStartString, captionFont, textFont ); + + textRect.setLeft( textRect.right() ); + textRect.setRight( timesBox.right() - padding() ); + h = QMAX( printCaptionAndText( p, textRect, stringVis.mEndCaption, stringVis.mEndString, captionFont, textFont ), h ); + } + + + if ( (*it)->doesRecur() ) { + QRect recurBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight ); + // TODO: Convert the recurrence to a string and print it out! + QString recurString( "TODO: Convert Repeat to String!" ); + h = QMAX( printCaptionAndText( p, recurBox, i18n("Repeats: "), recurString, captionFont, textFont ), h ); + } + + QRect alarmBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight ); + Alarm::List alarms = (*it)->alarms(); + if ( alarms.count() == 0 ) { + cap = i18n("No reminders"); + txt = QString::null; + } else { + cap = i18n("Reminder: ", "%n reminders: ", alarms.count() ); + + QStringList alarmStrings; + KCal::Alarm::List::ConstIterator it; + for ( it = alarms.begin(); it != alarms.end(); ++it ) { + Alarm *alarm = *it; + + // Alarm offset, copied from koeditoralarms.cpp: + QString offsetstr; + int offset = 0; + if ( alarm->hasStartOffset() ) { + offset = alarm->startOffset().asSeconds(); + if ( offset < 0 ) { + offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the start"); + offset = -offset; + } else { + offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the start"); + } + } else if ( alarm->hasEndOffset() ) { + offset = alarm->endOffset().asSeconds(); + if ( offset < 0 ) { + offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the end"); + offset = -offset; + } else { + offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the end"); + } + } + + offset = offset / 60; // make minutes + int useoffset = offset; + + if ( offset % (24*60) == 0 && offset>0 ) { // divides evenly into days? + useoffset = offset / (24*60); + offsetstr = offsetstr.arg( i18n("1 day", "%n days", useoffset ) ); + } else if (offset % 60 == 0 && offset>0 ) { // divides evenly into hours? + useoffset = offset / 60; + offsetstr = offsetstr.arg( i18n("1 hour", "%n hours", useoffset ) ); + } else { + useoffset = offset; + offsetstr = offsetstr.arg( i18n("1 minute", "%n minutes", useoffset ) ); + } + alarmStrings << offsetstr; + } + txt = alarmStrings.join( i18n("Spacer for the joined list of categories", ", ") ); + + } + h = QMAX( printCaptionAndText( p, alarmBox, cap, txt, captionFont, textFont ), h ); + + + QRect organizerBox( timesBox.left()+padding(), h+padding(), timesBox.right()-padding(), lineHeight ); + h = QMAX( printCaptionAndText( p, organizerBox, i18n("Organizer: "), (*it)->organizer().fullName(), captionFont, textFont ), h ); + + // Finally, draw the frame around the time information... + timesBox.setBottom( QMAX( timesBox.bottom(), h+padding() ) ); + drawBox( p, BOX_BORDER_WIDTH, timesBox ); + + + QRect locationBox( timesBox ); + locationBox.setTop( timesBox.bottom() + padding() ); + locationBox.setHeight( 0 ); + int locationBottom = drawBoxWithCaption( p, locationBox, i18n("Location: "), + (*it)->location(), /*sameLine=*/true, /*expand=*/true, captionFont, textFont ); + locationBox.setBottom( locationBottom ); + + + // Now start constructing the boxes from the bottom: + QRect categoriesBox( locationBox ); + categoriesBox.setBottom( box.bottom() ); + categoriesBox.setTop( categoriesBox.bottom() - lineHeight - 2*padding() ); + + + QRect attendeesBox( box.left(), categoriesBox.top()-padding()-box.height()/9, box.width(), box.height()/9 ); + if ( !mShowAttendees ) { + attendeesBox.setTop( categoriesBox.top() ); + } + QRect attachmentsBox( box.left(), attendeesBox.top()-padding()-box.height()/9, box.width()*3/4 - padding(), box.height()/9 ); + QRect optionsBox( attachmentsBox.right() + padding(), attachmentsBox.top(), 0, 0 ); + optionsBox.setRight( box.right() ); + optionsBox.setBottom( attachmentsBox.bottom() ); + QRect notesBox( optionsBox.left(), locationBox.bottom() + padding(), optionsBox.width(), 0 ); + notesBox.setBottom( optionsBox.top() - padding() ); + + // TODO: Adjust boxes depending on the show options... +// if ( !mShowOptions ) { +// optionsBox.left() +// bool mShowOptions; +// // bool mShowSubitemsNotes; +// bool mShowAttendees; +// bool mShowAttachments; + + + QRect descriptionBox( notesBox ); + descriptionBox.setLeft( box.left() ); + descriptionBox.setRight( mShowOptions?(attachmentsBox.right()):(box.right()) ); + + drawBoxWithCaption( p, descriptionBox, i18n("Description:"), + (*it)->description(), /*sameLine=*/false, + /*expand=*/false, captionFont, textFont ); + + if ( mShowSubitemsNotes ) { + if ( (*it)->relations().isEmpty() || (*it)->type() != "Todo" ) { + int notesPosition = drawBoxWithCaption( p, notesBox, i18n("Notes:"), + QString::null, /*sameLine=*/false, /*expand=*/false, + captionFont, textFont ); + QPen oldPen( p.pen() ); + p.setPen( Qt::DotLine ); + while ( (notesPosition += int(1.5*lineHeight)) < notesBox.bottom() ) { + p.drawLine( notesBox.left()+padding(), notesPosition, notesBox.right()-padding(), notesPosition ); + } + p.setPen( oldPen ); + } else { + int subitemsStart = drawBoxWithCaption( p, notesBox, i18n("Subitems:"), + (*it)->description(), /*sameLine=*/false, + /*expand=*/false, captionFont, textFont ); + // TODO: Draw subitems + } + } + + if ( mShowAttachments ) { + int attachStart = drawBoxWithCaption( p, attachmentsBox, + i18n("Attachments:"), QString::null, /*sameLine=*/false, + /*expand=*/false, captionFont, textFont ); + // TODO: Print out the attachments somehow + } + + if ( mShowAttendees ) { + Attendee::List attendees = (*it)->attendees(); + QString attendeeCaption; + if ( attendees.count() == 0 ) + attendeeCaption = i18n("No Attendees"); + else + attendeeCaption = i18n("1 Attendee:", "%n Attendees:", attendees.count() ); + QString attendeeString; + for ( Attendee::List::ConstIterator ait = attendees.begin(); ait != attendees.end(); ++ait ) { + if ( !attendeeString.isEmpty() ) attendeeString += "\n"; + attendeeString += i18n("Formatting of an attendee: " + "'Name (Role): Status', e.g. 'Reinhold Kainhofer " + "<reinhold@kainhofer.com> (Participant): Awaiting Response'", + "%1 (%2): %3") + .arg( (*ait)->fullName() ) + .arg( (*ait)->roleStr() ).arg( (*ait)->statusStr() ); + } + drawBoxWithCaption( p, attendeesBox, i18n("Attendees:"), attendeeString, + /*sameLine=*/false, /*expand=*/false, captionFont, textFont ); + } + + if ( mShowOptions ) { + QString optionsString; + if ( !(*it)->statusStr().isEmpty() ) { + optionsString += i18n("Status: %1").arg( (*it)->statusStr() ); + optionsString += "\n"; + } + if ( !(*it)->secrecyStr().isEmpty() ) { + optionsString += i18n("Secrecy: %1").arg( (*it)->secrecyStr() ); + optionsString += "\n"; + } + if ( (*it)->type() == "Event" ) { + Event *e = static_cast<Event*>(*it); + if ( e->transparency() == Event::Opaque ) { + optionsString += i18n("Show as: Busy"); + } else { + optionsString += i18n("Show as: Free"); + } + optionsString += "\n"; + } else if ( (*it)->type() == "Todo" ) { + Todo *t = static_cast<Todo*>(*it); + if ( t->isOverdue() ) { + optionsString += i18n("This task is overdue!"); + optionsString += "\n"; + } + } else if ( (*it)->type() == "Journal" ) { + //TODO: Anything Journal-specific? + } + drawBoxWithCaption( p, optionsBox, i18n("Settings: "), + optionsString, /*sameLine=*/false, /*expand=*/false, captionFont, textFont ); + } + + drawBoxWithCaption( p, categoriesBox, i18n("Categories: "), + (*it)->categories().join( i18n("Spacer for the joined list of categories", ", ") ), + /*sameLine=*/true, /*expand=*/false, captionFont, textFont ); + } + p.setFont( oldFont ); +} + +/************************************************************** + * Print Day + **************************************************************/ + +CalPrintDay::CalPrintDay() : CalPrintPluginBase() +{ +} + +CalPrintDay::~CalPrintDay() +{ +} + +QWidget *CalPrintDay::createConfigWidget( QWidget *w ) +{ + return new CalPrintDayConfig_Base( w ); +} + +void CalPrintDay::readSettingsWidget() +{ + CalPrintDayConfig_Base *cfg = + dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget ); + if ( cfg ) { + mFromDate = cfg->mFromDate->date(); + mToDate = cfg->mToDate->date(); + + mStartTime = cfg->mFromTime->time(); + mEndTime = cfg->mToTime->time(); + mIncludeAllEvents = cfg->mIncludeAllEvents->isChecked(); + + mIncludeTodos = cfg->mIncludeTodos->isChecked(); + mUseColors = cfg->mColors->isChecked(); + } +} + +void CalPrintDay::setSettingsWidget() +{ + CalPrintDayConfig_Base *cfg = + dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget ); + if ( cfg ) { + cfg->mFromDate->setDate( mFromDate ); + cfg->mToDate->setDate( mToDate ); + + cfg->mFromTime->setTime( mStartTime ); + cfg->mToTime->setTime( mEndTime ); + cfg->mIncludeAllEvents->setChecked( mIncludeAllEvents ); + + cfg->mIncludeTodos->setChecked( mIncludeTodos ); + cfg->mColors->setChecked( mUseColors ); + } +} + +void CalPrintDay::loadConfig() +{ + if ( mConfig ) { + QDate dt; + QTime tm1( dayStart() ); + QDateTime startTm( dt, tm1 ); + QDateTime endTm( dt, tm1.addSecs( 12 * 60 * 60 ) ); + mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time(); + mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time(); + mIncludeTodos = mConfig->readBoolEntry( "Include todos", false ); + mIncludeAllEvents = mConfig->readBoolEntry( "Include all events", false ); + } + setSettingsWidget(); +} + +void CalPrintDay::saveConfig() +{ + readSettingsWidget(); + if ( mConfig ) { + mConfig->writeEntry( "Start time", QDateTime( QDate(), mStartTime ) ); + mConfig->writeEntry( "End time", QDateTime( QDate(), mEndTime ) ); + mConfig->writeEntry( "Include todos", mIncludeTodos ); + mConfig->writeEntry( "Include all events", mIncludeAllEvents ); + } +} + +void CalPrintDay::setDateRange( const QDate& from, const QDate& to ) +{ + CalPrintPluginBase::setDateRange( from, to ); + CalPrintDayConfig_Base *cfg = + dynamic_cast<CalPrintDayConfig_Base*>( mConfigWidget ); + if ( cfg ) { + cfg->mFromDate->setDate( from ); + cfg->mToDate->setDate( to ); + } +} + +void CalPrintDay::print( QPainter &p, int width, int height ) +{ + QDate curDay( mFromDate ); + + do { + QTime curStartTime( mStartTime ); + QTime curEndTime( mEndTime ); + + // For an invalid time range, simply show one hour, starting at the hour + // before the given start time + if ( curEndTime <= curStartTime ) { + curStartTime = QTime( curStartTime.hour(), 0, 0 ); + curEndTime = curStartTime.addSecs( 3600 ); + } + + KLocale *local = KGlobal::locale(); + QRect headerBox( 0, 0, width, headerHeight() ); + drawHeader( p, local->formatDate( curDay ), curDay, QDate(), headerBox ); + + + Event::List eventList = mCalendar->events( curDay, + EventSortStartDate, + SortDirectionAscending ); + + p.setFont( QFont( "sans-serif", 12 ) ); + + // TODO: Find a good way to determine the height of the all-day box + QRect allDayBox( TIMELINE_WIDTH + padding(), headerBox.bottom() + padding(), + 0, height / 20 ); + allDayBox.setRight( width ); + int allDayHeight = drawAllDayBox( p, eventList, curDay, true, allDayBox ); + + QRect dayBox( allDayBox ); + dayBox.setTop( allDayHeight /*allDayBox.bottom()*/ ); + dayBox.setBottom( height ); + drawAgendaDayBox( p, eventList, curDay, mIncludeAllEvents, + curStartTime, curEndTime, dayBox ); + + QRect tlBox( dayBox ); + tlBox.setLeft( 0 ); + tlBox.setWidth( TIMELINE_WIDTH ); + drawTimeLine( p, curStartTime, curEndTime, tlBox ); + curDay = curDay.addDays( 1 ); + if ( curDay <= mToDate ) mPrinter->newPage(); + } while ( curDay <= mToDate ); +} + + + +/************************************************************** + * Print Week + **************************************************************/ + +CalPrintWeek::CalPrintWeek() : CalPrintPluginBase() +{ +} + +CalPrintWeek::~CalPrintWeek() +{ +} + +QWidget *CalPrintWeek::createConfigWidget( QWidget *w ) +{ + return new CalPrintWeekConfig_Base( w ); +} + +void CalPrintWeek::readSettingsWidget() +{ + CalPrintWeekConfig_Base *cfg = + dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget ); + if ( cfg ) { + mFromDate = cfg->mFromDate->date(); + mToDate = cfg->mToDate->date(); + + mWeekPrintType = (eWeekPrintType)( cfg->mPrintType->id( + cfg->mPrintType->selected() ) ); + + mStartTime = cfg->mFromTime->time(); + mEndTime = cfg->mToTime->time(); + + mIncludeTodos = cfg->mIncludeTodos->isChecked(); + mUseColors = cfg->mColors->isChecked(); + } +} + +void CalPrintWeek::setSettingsWidget() +{ + CalPrintWeekConfig_Base *cfg = + dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget ); + if ( cfg ) { + cfg->mFromDate->setDate( mFromDate ); + cfg->mToDate->setDate( mToDate ); + + cfg->mPrintType->setButton( mWeekPrintType ); + + cfg->mFromTime->setTime( mStartTime ); + cfg->mToTime->setTime( mEndTime ); + + cfg->mIncludeTodos->setChecked( mIncludeTodos ); + cfg->mColors->setChecked( mUseColors ); + } +} + +void CalPrintWeek::loadConfig() +{ + if ( mConfig ) { + QDate dt; + QTime tm1( dayStart() ); + QDateTime startTm( dt, tm1 ); + QDateTime endTm( dt, tm1.addSecs( 43200 ) ); + mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time(); + mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time(); + mIncludeTodos = mConfig->readBoolEntry( "Include todos", false ); + mWeekPrintType =(eWeekPrintType)( mConfig->readNumEntry( "Print type", (int)Filofax ) ); + } + setSettingsWidget(); +} + +void CalPrintWeek::saveConfig() +{ + readSettingsWidget(); + if ( mConfig ) { + mConfig->writeEntry( "Start time", QDateTime( QDate(), mStartTime ) ); + mConfig->writeEntry( "End time", QDateTime( QDate(), mEndTime ) ); + mConfig->writeEntry( "Include todos", mIncludeTodos ); + mConfig->writeEntry( "Print type", int( mWeekPrintType ) ); + } +} + +KPrinter::Orientation CalPrintWeek::defaultOrientation() +{ + if ( mWeekPrintType == Filofax ) return KPrinter::Portrait; + else if ( mWeekPrintType == SplitWeek ) return KPrinter::Portrait; + else return KPrinter::Landscape; +} + +void CalPrintWeek::setDateRange( const QDate &from, const QDate &to ) +{ + CalPrintPluginBase::setDateRange( from, to ); + CalPrintWeekConfig_Base *cfg = + dynamic_cast<CalPrintWeekConfig_Base*>( mConfigWidget ); + if ( cfg ) { + cfg->mFromDate->setDate( from ); + cfg->mToDate->setDate( to ); + } +} + +void CalPrintWeek::print( QPainter &p, int width, int height ) +{ + QDate curWeek, fromWeek, toWeek; + + // correct begin and end to first and last day of week + int weekdayCol = weekdayColumn( mFromDate.dayOfWeek() ); + fromWeek = mFromDate.addDays( -weekdayCol ); + weekdayCol = weekdayColumn( mFromDate.dayOfWeek() ); + toWeek = mToDate.addDays( 6 - weekdayCol ); + + curWeek = fromWeek.addDays( 6 ); + KLocale *local = KGlobal::locale(); + + QString line1, line2, title; + QRect headerBox( 0, 0, width, headerHeight() ); + QRect weekBox( headerBox ); + weekBox.setTop( headerBox.bottom() + padding() ); + weekBox.setBottom( height ); + + switch ( mWeekPrintType ) { + case Filofax: + do { + line1 = local->formatDate( curWeek.addDays( -6 ) ); + line2 = local->formatDate( curWeek ); + if ( orientation() == KPrinter::Landscape ) { + title = i18n("date from-to", "%1 - %2"); + } else { + title = i18n("date from-\nto", "%1 -\n%2");; + } + title = title.arg( line1 ).arg( line2 ); + drawHeader( p, title, curWeek.addDays( -6 ), QDate(), headerBox ); + drawWeek( p, curWeek, weekBox ); + curWeek = curWeek.addDays( 7 ); + if ( curWeek <= toWeek ) + mPrinter->newPage(); + } while ( curWeek <= toWeek ); + break; + + case Timetable: + default: + do { + line1 = local->formatDate( curWeek.addDays( -6 ) ); + line2 = local->formatDate( curWeek ); + if ( orientation() == KPrinter::Landscape ) { + title = i18n("date from - to (week number)", "%1 - %2 (Week %3)"); + } else { + title = i18n("date from -\nto (week number)", "%1 -\n%2 (Week %3)"); + } + title = title.arg( line1 ).arg( line2 ).arg( curWeek.weekNumber() ); + drawHeader( p, title, curWeek, QDate(), headerBox ); + QRect weekBox( headerBox ); + weekBox.setTop( headerBox.bottom() + padding() ); + weekBox.setBottom( height ); + + drawTimeTable( p, fromWeek, curWeek, mStartTime, mEndTime, weekBox ); + fromWeek = fromWeek.addDays( 7 ); + curWeek = fromWeek.addDays( 6 ); + if ( curWeek <= toWeek ) + mPrinter->newPage(); + } while ( curWeek <= toWeek ); + break; + + case SplitWeek: { + QRect weekBox1( weekBox ); + // On the left side there are four days (mo-th) plus the timeline, + // on the right there are only three days (fr-su) plus the timeline. Don't + // use the whole width, but rather give them the same width as on the left. + weekBox1.setRight( int( ( width - TIMELINE_WIDTH ) * 3. / 4. + TIMELINE_WIDTH ) ); + do { + QDate endLeft( fromWeek.addDays( 3 ) ); + int hh = headerHeight(); + + drawTimeTable( p, fromWeek, endLeft, + mStartTime, mEndTime, weekBox ); + mPrinter->newPage(); + drawSplitHeaderRight( p, fromWeek, curWeek, QDate(), width, hh ); + drawTimeTable( p, endLeft.addDays( 1 ), curWeek, + mStartTime, mEndTime, weekBox1 ); + + fromWeek = fromWeek.addDays( 7 ); + curWeek = fromWeek.addDays( 6 ); + if ( curWeek <= toWeek ) + mPrinter->newPage(); + } while ( curWeek <= toWeek ); + } + break; + } +} + + + + +/************************************************************** + * Print Month + **************************************************************/ + +CalPrintMonth::CalPrintMonth() : CalPrintPluginBase() +{ +} + +CalPrintMonth::~CalPrintMonth() +{ +} + +QWidget *CalPrintMonth::createConfigWidget( QWidget *w ) +{ + return new CalPrintMonthConfig_Base( w ); +} + +void CalPrintMonth::readSettingsWidget() +{ + CalPrintMonthConfig_Base *cfg = + dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget ); + if ( cfg ) { + mFromDate = QDate( cfg->mFromYear->value(), cfg->mFromMonth->currentItem()+1, 1 ); + mToDate = QDate( cfg->mToYear->value(), cfg->mToMonth->currentItem()+1, 1 ); + + mWeekNumbers = cfg->mWeekNumbers->isChecked(); + mRecurDaily = cfg->mRecurDaily->isChecked(); + mRecurWeekly = cfg->mRecurWeekly->isChecked(); + mIncludeTodos = cfg->mIncludeTodos->isChecked(); +// mUseColors = cfg->mColors->isChecked(); + } +} + +void CalPrintMonth::setSettingsWidget() +{ + CalPrintMonthConfig_Base *cfg = + dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget ); + setDateRange( mFromDate, mToDate ); + if ( cfg ) { + cfg->mWeekNumbers->setChecked( mWeekNumbers ); + cfg->mRecurDaily->setChecked( mRecurDaily ); + cfg->mRecurWeekly->setChecked( mRecurWeekly ); + cfg->mIncludeTodos->setChecked( mIncludeTodos ); +// cfg->mColors->setChecked( mUseColors ); + } +} + +void CalPrintMonth::loadConfig() +{ + if ( mConfig ) { + mWeekNumbers = mConfig->readBoolEntry( "Print week numbers", true ); + mRecurDaily = mConfig->readBoolEntry( "Print daily incidences", true ); + mRecurWeekly = mConfig->readBoolEntry( "Print weekly incidences", true ); + mIncludeTodos = mConfig->readBoolEntry( "Include todos", false ); + } + setSettingsWidget(); +} + +void CalPrintMonth::saveConfig() +{ + readSettingsWidget(); + if ( mConfig ) { + mConfig->writeEntry( "Print week numbers", mWeekNumbers ); + mConfig->writeEntry( "Print daily incidences", mRecurDaily ); + mConfig->writeEntry( "Print weekly incidences", mRecurWeekly ); + mConfig->writeEntry( "Include todos", mIncludeTodos ); + } +} + +void CalPrintMonth::setDateRange( const QDate &from, const QDate &to ) +{ + CalPrintPluginBase::setDateRange( from, to ); + CalPrintMonthConfig_Base *cfg = + dynamic_cast<CalPrintMonthConfig_Base *>( mConfigWidget ); + const KCalendarSystem *calSys = calendarSystem(); + if ( cfg && calSys ) { + cfg->mFromMonth->clear(); + for ( int i=0; i<calSys->monthsInYear( mFromDate ); ++i ) { + cfg->mFromMonth->insertItem( calSys->monthName( i+1, mFromDate.year() ) ); + } + cfg->mToMonth->clear(); + for ( int i=0; i<calSys->monthsInYear( mToDate ); ++i ) { + cfg->mToMonth->insertItem( calSys->monthName( i+1, mToDate.year() ) ); + } + } + if ( cfg ) { + cfg->mFromMonth->setCurrentItem( from.month()-1 ); + cfg->mFromYear->setValue( to.year() ); + cfg->mToMonth->setCurrentItem( mToDate.month()-1 ); + cfg->mToYear->setValue( mToDate.year() ); + } +} + +void CalPrintMonth::print( QPainter &p, int width, int height ) +{ + QDate curMonth, fromMonth, toMonth; + + fromMonth = mFromDate.addDays( -( mFromDate.day() - 1 ) ); + toMonth = mToDate.addDays( mToDate.daysInMonth() - mToDate.day() ); + + curMonth = fromMonth; + const KCalendarSystem *calSys = calendarSystem(); + if ( !calSys ) return; + + QRect headerBox( 0, 0, width, headerHeight() ); + QRect monthBox( 0, 0, width, height ); + monthBox.setTop( headerBox.bottom() + padding() ); + + do { + QString title( i18n("monthname year", "%1 %2") ); + title = title.arg( calSys->monthName( curMonth ) ) + .arg( curMonth.year() ); + QDate tmp( fromMonth ); + int weekdayCol = weekdayColumn( tmp.dayOfWeek() ); + tmp = tmp.addDays( -weekdayCol ); + + drawHeader( p, title, curMonth.addMonths( -1 ), curMonth.addMonths( 1 ), + headerBox ); + drawMonthTable( p, curMonth, mWeekNumbers, mRecurDaily, mRecurWeekly, monthBox ); + curMonth = curMonth.addDays( curMonth.daysInMonth() ); + if ( curMonth <= toMonth ) mPrinter->newPage(); + } while ( curMonth <= toMonth ); + +} + + + + +/************************************************************** + * Print Todos + **************************************************************/ + +CalPrintTodos::CalPrintTodos() : CalPrintPluginBase() +{ + mTodoSortField = TodoFieldUnset; + mTodoSortDirection = TodoDirectionUnset; +} + +CalPrintTodos::~CalPrintTodos() +{ +} + +QWidget *CalPrintTodos::createConfigWidget( QWidget *w ) +{ + return new CalPrintTodoConfig_Base( w ); +} + +void CalPrintTodos::readSettingsWidget() +{ + CalPrintTodoConfig_Base *cfg = + dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget ); + if ( cfg ) { + mPageTitle = cfg->mTitle->text(); + + mTodoPrintType = (eTodoPrintType)( cfg->mPrintType->id( + cfg->mPrintType->selected() ) ); + + mFromDate = cfg->mFromDate->date(); + mToDate = cfg->mToDate->date(); + + mIncludeDescription = cfg->mDescription->isChecked(); + mIncludePriority = cfg->mPriority->isChecked(); + mIncludeDueDate = cfg->mDueDate->isChecked(); + mIncludePercentComplete = cfg->mPercentComplete->isChecked(); + mConnectSubTodos = cfg->mConnectSubTodos->isChecked(); + mStrikeOutCompleted = cfg->mStrikeOutCompleted->isChecked(); + + mTodoSortField = (eTodoSortField)cfg->mSortField->currentItem(); + mTodoSortDirection = (eTodoSortDirection)cfg->mSortDirection->currentItem(); + } +} + +void CalPrintTodos::setSettingsWidget() +{ +// kdDebug(5850) << "CalPrintTodos::setSettingsWidget" << endl; + + CalPrintTodoConfig_Base *cfg = + dynamic_cast<CalPrintTodoConfig_Base *>( mConfigWidget ); + if ( cfg ) { + cfg->mTitle->setText( mPageTitle ); + + cfg->mPrintType->setButton( mTodoPrintType ); + + cfg->mFromDate->setDate( mFromDate ); + cfg->mToDate->setDate( mToDate ); + + cfg->mDescription->setChecked( mIncludeDescription ); + cfg->mPriority->setChecked( mIncludePriority ); + cfg->mDueDate->setChecked( mIncludeDueDate ); + cfg->mPercentComplete->setChecked( mIncludePercentComplete ); + cfg->mConnectSubTodos->setChecked( mConnectSubTodos ); + cfg->mStrikeOutCompleted->setChecked( mStrikeOutCompleted ); + + if ( mTodoSortField != TodoFieldUnset ) { + // do not insert if already done so. + cfg->mSortField->insertItem( i18n("Summary") ); + cfg->mSortField->insertItem( i18n("Start Date") ); + cfg->mSortField->insertItem( i18n("Due Date") ); + cfg->mSortField->insertItem( i18n("Priority") ); + cfg->mSortField->insertItem( i18n("Percent Complete") ); + cfg->mSortField->setCurrentItem( (int)mTodoSortField ); + } + + if ( mTodoSortDirection != TodoDirectionUnset ) { + // do not insert if already done so. + cfg->mSortDirection->insertItem( i18n("Ascending") ); + cfg->mSortDirection->insertItem( i18n("Descending") ); + cfg->mSortDirection->setCurrentItem( (int)mTodoSortDirection ); + } + } +} + +void CalPrintTodos::loadConfig() +{ + if ( mConfig ) { + mPageTitle = mConfig->readEntry( "Page title", i18n("To-do list") ); + mTodoPrintType = (eTodoPrintType)mConfig->readNumEntry( "Print type", (int)TodosAll ); + mIncludeDescription = mConfig->readBoolEntry( "Include description", true ); + mIncludePriority = mConfig->readBoolEntry( "Include priority", true ); + mIncludeDueDate = mConfig->readBoolEntry( "Include due date", true ); + mIncludePercentComplete = mConfig->readBoolEntry( "Include percentage completed", true ); + mConnectSubTodos = mConfig->readBoolEntry( "Connect subtodos", true ); + mStrikeOutCompleted = mConfig->readBoolEntry( "Strike out completed summaries", true ); + mTodoSortField = (eTodoSortField)mConfig->readNumEntry( "Sort field", (int)TodoFieldSummary ); + mTodoSortDirection = (eTodoSortDirection)mConfig->readNumEntry( "Sort direction", (int)TodoDirectionAscending ); + } + setSettingsWidget(); +} + +void CalPrintTodos::saveConfig() +{ + readSettingsWidget(); + if ( mConfig ) { + mConfig->writeEntry( "Page title", mPageTitle ); + mConfig->writeEntry( "Print type", int( mTodoPrintType ) ); + mConfig->writeEntry( "Include description", mIncludeDescription ); + mConfig->writeEntry( "Include priority", mIncludePriority ); + mConfig->writeEntry( "Include due date", mIncludeDueDate ); + mConfig->writeEntry( "Include percentage completed", mIncludePercentComplete ); + mConfig->writeEntry( "Connect subtodos", mConnectSubTodos ); + mConfig->writeEntry( "Strike out completed summaries", mStrikeOutCompleted ); + mConfig->writeEntry( "Sort field", mTodoSortField ); + mConfig->writeEntry( "Sort direction", mTodoSortDirection ); + } +} + +void CalPrintTodos::print( QPainter &p, int width, int height ) +{ + // TODO: Find a good way to guarantee a nicely designed output + int pospriority = 10; + int possummary = 60; + int posdue = width - 65; + int poscomplete = posdue - 70; //Complete column is to right of the Due column + int lineSpacing = 15; + int fontHeight = 10; + + // Draw the First Page Header + drawHeader( p, mPageTitle, mFromDate, QDate(), + QRect( 0, 0, width, headerHeight() ) ); + + // Draw the Column Headers + int mCurrentLinePos = headerHeight() + 5; + QString outStr; + QFont oldFont( p.font() ); + + p.setFont( QFont( "sans-serif", 10, QFont::Bold ) ); + lineSpacing = p.fontMetrics().lineSpacing(); + mCurrentLinePos += lineSpacing; + if ( mIncludePriority ) { + outStr += i18n( "Priority" ); + p.drawText( pospriority, mCurrentLinePos - 2, outStr ); + } else { + possummary = 10; + pospriority = -1; + } + + outStr.truncate( 0 ); + outStr += i18n( "Summary" ); + p.drawText( possummary, mCurrentLinePos - 2, outStr ); + + if ( mIncludePercentComplete ) { + if ( !mIncludeDueDate ) //move Complete column to the right + poscomplete = posdue; //if not print the Due Date column + outStr.truncate( 0 ); + outStr += i18n( "Complete" ); + p.drawText( poscomplete, mCurrentLinePos - 2, outStr ); + } else { + poscomplete = -1; + } + + if ( mIncludeDueDate ) { + outStr.truncate( 0 ); + outStr += i18n( "Due" ); + p.drawText( posdue, mCurrentLinePos - 2, outStr ); + } else { + posdue = -1; + } + + p.setFont( QFont( "sans-serif", 10 ) ); + fontHeight = p.fontMetrics().height(); + + Todo::List todoList; + Todo::List tempList; + Todo::List::ConstIterator it; + + // Convert sort options to the corresponding enums + TodoSortField sortField = TodoSortSummary; + switch( mTodoSortField ) { + case TodoFieldSummary: + sortField = TodoSortSummary; break; + case TodoFieldStartDate: + sortField = TodoSortStartDate; break; + case TodoFieldDueDate: + sortField = TodoSortDueDate; break; + case TodoFieldPriority: + sortField = TodoSortPriority; break; + case TodoFieldPercentComplete: + sortField = TodoSortPercentComplete; break; + case TodoFieldUnset: + break; + } + + SortDirection sortDirection; + switch( mTodoSortDirection ) { + case TodoDirectionAscending: + sortDirection = SortDirectionAscending; break; + case TodoDirectionDescending: + sortDirection = SortDirectionDescending; break; + case TodoDirectionUnset: + break; + } + + // Create list of to-dos which will be printed + todoList = mCalendar->todos( sortField, sortDirection ); + switch( mTodoPrintType ) { + case TodosAll: + break; + case TodosUnfinished: + for( it = todoList.begin(); it!= todoList.end(); ++it ) { + if ( !(*it)->isCompleted() ) + tempList.append( *it ); + } + todoList = tempList; + break; + case TodosDueRange: + for( it = todoList.begin(); it!= todoList.end(); ++it ) { + if ( (*it)->hasDueDate() ) { + if ( (*it)->dtDue().date() >= mFromDate && + (*it)->dtDue().date() <= mToDate ) + tempList.append( *it ); + } else { + tempList.append( *it ); + } + } + todoList = tempList; + break; + } + + // Print to-dos + int count = 0; + for ( it=todoList.begin(); it!=todoList.end(); ++it ) { + Todo *currEvent = *it; + + // Skip sub-to-dos. They will be printed recursively in drawTodo() + if ( !currEvent->relatedTo() ) { + count++; + drawTodo( count, currEvent, p, + sortField, sortDirection, + mConnectSubTodos, + mStrikeOutCompleted, mIncludeDescription, + pospriority, possummary, posdue, poscomplete, + 0, 0, mCurrentLinePos, width, height, todoList ); + } + } + p.setFont( oldFont ); +} + + +#endif |