• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

PIMPrint Library

  • sources
  • kde-4.14
  • kdepim
  • pimprint
  • calendar
calprintbase.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the PimPrint library.
3 
4  Copyright (C) 2012-2013 Allen Winter <winter@kde.org>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License as published by the Free Software Foundation; either
9  version 2 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 */
21 
22 #include "calprintbase.h"
23 
24 #include <calendarsupport/kcalprefs.h>
25 #include <calendarsupport/utils.h>
26 
27 #include <KCalendarSystem>
28 #include <KGlobal>
29 #include <KSystemTimeZones>
30 
31 #include <QAbstractTextDocumentLayout>
32 #include <QPrinter>
33 #include <QTextCursor>
34 #include <QTextDocument>
35 #include <QTextDocumentFragment>
36 #ifndef Q_MOC_RUN
37 #include <boost/concept_check.hpp>
38 #endif
39 
40 using namespace PimPrint::Calendar;
41 
42 //TODO: compute default page height and width based QPainter window
43 static int sPortraitPageHeight = 792; // page height, for portrait orientation
44 static int sLandscapePageHeight = 612; // page height, for landscape orientation
45 
46 static int sPortraitHeaderHeight = 72; // header height, for portrait orientation
47 static int sLandscapeHeaderHeight = 54; // header height, for landscape orientation
48 static int sSubHeaderHeight = 20; // subheader height, for all orientations
49 
50 static int sPortraitFooterHeight = 16; // footer height, for portrait orientation
51 static int sLandscapeFooterHeight = 14; // footer height, for landscape orientation
52 
53 static int sMarginSize = 36; // margins, for all orientations (.5 inch)
54 static int sPaddingSize = 7; // padding between the various top-level boxes
55 
56 static int sBoxBorderWidth = 2; // width of the border of all top-level boxes
57 static int sItemBoxBorderWidth = 0; // width of the border of all item boxes
58 static int sTimeLineWidth = 50; // width of timeline (eg. day and timetable)
59 
64 //@cond PRIVATE
65 class PimPrint::Calendar::CalPrintBase::Private
66 {
67 public:
68  Private()
69  : mPrinter(0),
70  mPageHeight(-1),
71  mPageWidth(-1),
72  mCalendar(0),
73  mCalSystem(0),
74  mPrintStyle(CalPrintBase::None),
75  mHeaderHeight(-1),
76  mSubHeaderHeight(sSubHeaderHeight),
77  mFooterHeight(-1),
78  mMargins(sMarginSize),
79  mPadding(sPaddingSize),
80  mBoxBorderWidth(sBoxBorderWidth),
81  mItemBoxBorderWidth(sItemBoxBorderWidth),
82  mTimeLineWidth(sTimeLineWidth),
83  mInfoOptions(0),
84  mTypeOptions(0),
85  mRangeOptions(0),
86  mExtraOptions(0),
87  mUseColor(true),
88  mUseLandscape(false),
89  mPrintFooter(false)
90  {
91  }
92 
93  QPrinter *mPrinter; // the QPrinter
94  QPainter mPainter; // the QPainter
95  int mPageHeight; // page height, depends on page orientation
96  int mPageWidth; // page height, depends on page orientation
97  KCalCore::Calendar::Ptr mCalendar; // the Calendar
98  KCalendarSystem *mCalSystem; // the Calendar System
99  CalPrintBase::Style mPrintStyle; // the style to print
100  int mHeaderHeight; // height of header, depends on page orientation
101  int mSubHeaderHeight; // subheader height, same for all orientations
102  int mFooterHeight; // height of footer, depends on page orientation
103  int mMargins; // margins, for all orientations
104  int mPadding; // padding between the various top-level boxes
105  int mBoxBorderWidth; // width of the border of all top-level boxes
106  int mItemBoxBorderWidth; // width of the border of all item boxes
107  int mTimeLineWidth; // width of timelines
108 
109  InfoOptions mInfoOptions; // flags for information to print.
110  TypeOptions mTypeOptions; // flags for types to print.
111  RangeOptions mRangeOptions; // flags for time ranges to print.
112  ExtraOptions mExtraOptions; // flags for extra stuff to print.
113  bool mUseColor; // flag, print in color
114  bool mUseLandscape; // flag, print in landscape orientation
115  bool mPrintFooter; // flag, print footer
116 };
117 //@endcond
118 
119 CalPrintBase::CalPrintBase(QPrinter *printer)
120  : d(new PimPrint::Calendar::CalPrintBase::Private)
121 {
122  init(printer);
123 }
124 
125 CalPrintBase::~CalPrintBase()
126 {
127  finish();
128  delete d;
129 }
130 
131 void CalPrintBase::init(QPrinter *printer) const
132 {
133  if (!printer) {
134  return;
135  }
136 
137  // Init printer
138  d->mPrinter = printer;
139  d->mPrinter->setColorMode(QPrinter::GrayScale);
140 
141  // Init painter
142  d->mPainter.begin(d->mPrinter);
143 
144  // FIXME: allow each margin to be set individually.
145  // the painter initially begins at 72 dpi per the Qt docs.
146  // Currently hard-coding half-inch margins (36 dpi)
147  const int margin = margins();
148  d->mPainter.setViewport(margin, margin,
149  d->mPainter.viewport().width() - 2 * margin,
150  d->mPainter.viewport().height() - 2 * margin);
151 
152  // Init page
153  setPageHeight(d->mPainter.window().height());
154  setPageWidth(d->mPainter.window().width());
155 }
156 
157 void CalPrintBase::finish() const
158 {
159  d->mPainter.end();
160  d->mPrinter = 0;
161 }
162 
163 void CalPrintBase::setThePrinter(QPrinter *printer)
164 {
165  d->mPrinter = printer;
166 }
167 
168 QPrinter *CalPrintBase::thePrinter() const
169 {
170  return d->mPrinter;
171 }
172 
173 void CalPrintBase::setPrintCalendar(const KCalCore::Calendar::Ptr &calendar)
174 {
175  d->mCalendar = calendar;
176 }
177 
178 KCalCore::Calendar::Ptr CalPrintBase::printCalendar() const
179 {
180  return d->mCalendar;
181 }
182 
183 void CalPrintBase::setCalendarSystem(KCalendarSystem *calSystem)
184 {
185  d->mCalSystem = calSystem;
186 }
187 
188 KCalendarSystem *CalPrintBase::calendarSystem() const
189 {
190  return d->mCalSystem;
191 }
192 
193 void CalPrintBase::setPrintStyle(const Style style)
194 {
195  d->mPrintStyle = style;
196 }
197 
198 CalPrintBase::Style CalPrintBase::printStyle() const
199 {
200  return d->mPrintStyle;
201 }
202 
203 void CalPrintBase::setPageHeight(const int height) const
204 {
205  d->mPageHeight = height;
206 }
207 
208 int CalPrintBase::pageHeight() const
209 {
210  if (d->mPageHeight >= 0) {
211  return d->mPageHeight;
212  } else if (!d->mUseLandscape) {
213  return sPortraitPageHeight; //TODO: replace with p.window().height()
214  } else {
215  return sLandscapePageHeight; //TODO: replace with p.window().width()
216  }
217 }
218 
219 void CalPrintBase::setPageWidth(const int width) const
220 {
221  d->mPageWidth = width;
222 }
223 
224 int CalPrintBase::pageWidth() const
225 {
226  if (d->mPageWidth >= 0) {
227  return d->mPageWidth;
228  } else if (d->mUseLandscape) {
229  return sPortraitPageHeight; //TODO: replace with p.window().height()
230  } else {
231  return sLandscapePageHeight; //TODO: replace with p.windows().width()
232  }
233 }
234 
235 void CalPrintBase::setUseLandscape(const bool useLandscape)
236 {
237  d->mUseLandscape = useLandscape;
238 }
239 
240 bool CalPrintBase::useLandscape() const
241 {
242  return d->mUseLandscape;
243 }
244 
245 void CalPrintBase::setUseColor(const bool useColor)
246 {
247  d->mUseColor = useColor;
248 }
249 
250 bool CalPrintBase::useColor() const
251 {
252  return d->mUseColor;
253 }
254 
255 void CalPrintBase::setHeaderHeight(const int height)
256 {
257  d->mHeaderHeight = height;
258 }
259 
260 int CalPrintBase::headerHeight() const
261 {
262  if (d->mHeaderHeight >= 0) {
263  return d->mHeaderHeight;
264  } else if (!d->mUseLandscape) {
265  return sPortraitHeaderHeight;
266  } else {
267  return sLandscapeHeaderHeight;
268  }
269 }
270 
271 void CalPrintBase::setSubHeaderHeight(const int height)
272 {
273  d->mSubHeaderHeight = height;
274 }
275 
276 int CalPrintBase::subHeaderHeight() const
277 {
278  return d->mSubHeaderHeight;
279 }
280 
281 void CalPrintBase::setFooterHeight(const int height)
282 {
283  d->mFooterHeight = height;
284 }
285 
286 int CalPrintBase::footerHeight() const
287 {
288  if (!d->mPrintFooter) {
289  return 0;
290  }
291 
292  if (d->mFooterHeight >= 0) {
293  return d->mFooterHeight;
294  } else if (!d->mUseLandscape) {
295  return sPortraitFooterHeight;
296  } else {
297  return sLandscapeFooterHeight;
298  }
299 }
300 
301 void CalPrintBase::setPadding(const int padding)
302 {
303  d->mPadding = padding;
304 }
305 
306 int CalPrintBase::padding() const
307 {
308  return d->mPadding;
309 }
310 
311 int CalPrintBase::margins() const
312 {
313  return d->mMargins;
314 }
315 
316 int CalPrintBase::boxBorderWidth() const
317 {
318  return d->mBoxBorderWidth;
319 }
320 
321 int CalPrintBase::itemBoxBorderWidth() const
322 {
323  return d->mItemBoxBorderWidth;
324 }
325 
326 int CalPrintBase::timeLineWidth() const
327 {
328  return d->mTimeLineWidth;
329 }
330 
331 void CalPrintBase::setInfoOptions(CalPrintBase::InfoOptions flags)
332 {
333  d->mInfoOptions = flags;
334 }
335 
336 CalPrintBase::InfoOptions CalPrintBase::infoOptions() const
337 {
338  return d->mInfoOptions;
339 }
340 
341 void CalPrintBase::setTypeOptions(CalPrintBase::TypeOptions flags)
342 {
343  d->mTypeOptions = flags;
344 }
345 
346 CalPrintBase::TypeOptions CalPrintBase::typeOptions() const
347 {
348  return d->mTypeOptions;
349 }
350 
351 void CalPrintBase::setRangeOptions(CalPrintBase::RangeOptions flags)
352 {
353  d->mRangeOptions = flags;
354 }
355 
356 CalPrintBase::RangeOptions CalPrintBase::rangeOptions() const
357 {
358  return d->mRangeOptions;
359 }
360 
361 void CalPrintBase::setExtraOptions(CalPrintBase::ExtraOptions flags)
362 {
363  d->mExtraOptions = flags;
364 }
365 
366 CalPrintBase::ExtraOptions CalPrintBase::extraOptions() const
367 {
368  return d->mExtraOptions;
369 }
370 
371 void CalPrintBase::drawBox(QPainter &p, const int linewidth, const QRect &rect) const
372 {
373  QPen pen(p.pen());
374  QPen oldpen(pen);
375  // no border
376  if (linewidth >= 0) {
377  pen.setWidth(linewidth);
378  p.setPen(pen);
379  } else {
380  p.setPen(Qt::NoPen);
381  }
382  p.drawRect(rect);
383  p.setPen(oldpen);
384 }
385 
386 void CalPrintBase::drawShadedBox(QPainter &p, const int linewidth,
387  const QBrush &brush, const QRect &rect) const
388 {
389  QBrush oldbrush(p.brush());
390  p.setBrush(brush);
391  drawBox(p, linewidth, rect);
392  p.setBrush(oldbrush);
393 }
394 
395 void CalPrintBase::drawItemString(QPainter &p, const QRect &box,
396  const QString &str, int flags) const
397 {
398  QRect newbox(box);
399  newbox.adjust(3, 1, -1, -1);
400  p.drawText(newbox, (flags == -1) ?
401  (Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap) : flags, str);
402 }
403 
404 void CalPrintBase::drawItemBox(QPainter &p, const int linewidth, const QRect &box,
405  const KCalCore::Incidence::Ptr &incidence,
406  const QString &str, int flags) const
407 {
408  QPen oldpen(p.pen());
409  QBrush oldbrush(p.brush());
410  QColor bgColor(categoryBgColor(incidence));
411  if (d->mUseColor & bgColor.isValid()) {
412  p.setBrush(bgColor);
413  } else {
414  p.setBrush(QColor(232, 232, 232));
415  }
416  drawBox(p, (linewidth > 0) ? linewidth : itemBoxBorderWidth(), box);
417  if (d->mUseColor && bgColor.isValid()) {
418  p.setPen(getTextColor(bgColor));
419  }
420  drawItemString(p, box, str, flags);
421  p.setPen(oldpen);
422  p.setBrush(oldbrush);
423 }
424 
425 void CalPrintBase::drawVerticalBox(QPainter &p, const int linewidth,
426  const QRect &box,
427  const QString &str, int flags) const
428 {
429  p.save();
430  p.rotate(-90);
431  QRect rotatedBox(-box.top() - box.height(), box.left(), box.height(), box.width());
432  drawItemBox(p, linewidth, rotatedBox, KCalCore::Incidence::Ptr(), str,
433  (flags == -1) ? Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine : flags);
434 
435  p.restore();
436 }
437 
438 void CalPrintBase::drawSmallMonth(QPainter &p, const QDate &date, const QRect &box) const
439 {
440  int weekdayCol = weekdayColumn(date.dayOfWeek());
441  int month = date.month();
442  QDate monthDate(QDate(date.year(), date.month(), 1));
443  // correct begin of week
444  QDate monthDate2(monthDate.addDays(-weekdayCol));
445 
446  double cellWidth = double(box.width()) / double(7);
447  int rownr = 3 + (date.daysInMonth() + weekdayCol - 1) / 7;
448  // 3 Pixel after month name, 2 after day names, 1 after the calendar
449  double cellHeight = (box.height() - 5) / rownr;
450  QFont oldFont(p.font());
451  //TODO: option for the small month font?
452  p.setFont(QFont("sans-serif", int(cellHeight - 2), QFont::Normal));
453 
454  // draw the title
455  KCalendarSystem *calSys = calendarSystem();
456  if (calSys) {
457  QRect titleBox(box);
458  titleBox.setHeight(int(cellHeight + 1));
459  p.drawText(titleBox, Qt::AlignTop | Qt::AlignHCenter, calSys->monthName(date));
460  }
461 
462  // draw days of week
463  QRect wdayBox(box);
464  wdayBox.setTop(int(box.top() + 3 + cellHeight));
465  wdayBox.setHeight(int(2 * cellHeight) - int(cellHeight));
466 
467  if (calSys) {
468  for (int col = 0; col < 7; ++col) {
469  QString tmpStr = calSys->weekDayName(monthDate2)[0].toUpper();
470  wdayBox.setLeft(int(box.left() + col * cellWidth));
471  wdayBox.setRight(int(box.left() + (col + 1) * cellWidth));
472  p.drawText(wdayBox, Qt::AlignCenter, tmpStr);
473  monthDate2 = monthDate2.addDays(1);
474  }
475  }
476 
477  // draw separator line
478  int calStartY = wdayBox.bottom() + 2;
479  p.drawLine(box.left(), calStartY, box.right(), calStartY);
480  monthDate = monthDate.addDays(-weekdayCol);
481 
482  for (int row = 0; row < (rownr - 2); row++) {
483  for (int col = 0; col < 7; col++) {
484  if (monthDate.month() == month) {
485  QRect dayRect(int(box.left() + col * cellWidth),
486  int(calStartY + row * cellHeight), 0, 0);
487  dayRect.setRight(int(box.left() + (col + 1) * cellWidth));
488  dayRect.setBottom(int(calStartY + (row + 1) * cellHeight));
489  p.drawText(dayRect, Qt::AlignCenter, QString::number(monthDate.day()));
490  }
491  monthDate = monthDate.addDays(1);
492  }
493  }
494  p.setFont(oldFont);
495 }
496 
497 int CalPrintBase::drawHeader(QPainter &p, const QRect &allbox,
498  const QString &title,
499  const QDate &leftMonth, const QDate &rightMonth,
500  const bool expand,
501  const QColor &backColor) const
502 {
503  // print previous month for month view, print current for to-do, day and week
504  int smallMonthWidth = (allbox.width() / 4) - 10;
505  if (smallMonthWidth > 100) {
506  smallMonthWidth = 100;
507  }
508 
509  QRect box(allbox);
510  QRect textRect(allbox);
511 
512  QFont oldFont(p.font());
513  //TODO: option for the header font?
514  QFont newFont("sans-serif", (textRect.height() < 60) ? 16 : 18, QFont::Bold);
515  if (expand) {
516  p.setFont(newFont);
517  QRect boundingR =
518  p.boundingRect(textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, title);
519  p.setFont(oldFont);
520  int h = boundingR.height();
521  if (h > allbox.height()) {
522  box.setHeight(h);
523  textRect.setHeight(h);
524  }
525  }
526 
527  QBrush backBrush;
528  if (!backColor.isValid()) {
529  backBrush.setColor(QColor(232, 232, 232));
530  } else {
531  backBrush.setColor(backColor);
532  }
533 
534  drawShadedBox(p, boxBorderWidth(), backBrush, box);
535 
536  // prev month left, current month centered, next month right
537  if (rightMonth.isValid()) {
538  const QRect rightMonthBox(box.right() - 10 - smallMonthWidth, box.top(),
539  smallMonthWidth, box.height());
540  drawSmallMonth(p, QDate(rightMonth.year(), rightMonth.month(), 1), rightMonthBox);
541  textRect.setRight(rightMonthBox.left());
542  }
543  if (leftMonth.isValid()) {
544  const QRect leftMonthBox(box.left() + 10, box.top(),
545  smallMonthWidth, box.height());
546  drawSmallMonth(p, QDate(leftMonth.year(), leftMonth.month(), 1), leftMonthBox);
547  textRect.setLeft(leftMonthBox.right());
548  }
549 
550  // Set the margins
551  p.setFont(newFont);
552  p.drawText(textRect, Qt::AlignCenter | Qt::AlignVCenter | Qt::TextWordWrap, title);
553  p.setFont(oldFont);
554 
555  return textRect.bottom();
556 }
557 
558 void CalPrintBase::drawSubHeader(QPainter &p, const QRect &box, const QString &str) const
559 {
560  drawShadedBox(p, boxBorderWidth(), QColor(232, 232, 232), box);
561  QFont oldfont(p.font());
562  //TODO: option for the subheader font?
563  p.setFont(QFont("sans-serif", 10, QFont::Bold));
564  p.drawText(box, Qt::AlignCenter | Qt::AlignVCenter, str);
565  p.setFont(oldfont);
566 }
567 
568 int CalPrintBase::drawFooter(QPainter &p, const QRect &footbox) const
569 {
570  QFont oldfont(p.font());
571  //TODO: option for the footer font?
572  p.setFont(QFont("sans-serif", 6));
573  QFontMetrics fm(p.font());
574  QString dateStr =
575  KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(), KLocale::LongDate);
576  p.drawText(footbox, Qt::AlignCenter | Qt::AlignVCenter | Qt::TextSingleLine,
577  i18nc("print date: formatted-datetime", "printed: %1", dateStr));
578  p.setFont(oldfont);
579 
580  return footbox.bottom();
581 }
582 
583 void CalPrintBase::drawTimeLine(QPainter &p,
584  const QTime &startTime, const QTime &endTime,
585  const QRect &box) const
586 {
587  drawBox(p, boxBorderWidth(), box);
588 
589  int totalsecs = startTime.secsTo(endTime);
590  float minlen = (float)box.height() * 60. / (float)totalsecs;
591  float cellHeight = (60. * (float)minlen);
592  float currY = box.top();
593  // TODO: Don't use half of the width, but less, for the minutes!
594  int xcenter = box.left() + box.width() / 2;
595 
596  QTime curTime(startTime);
597  if (startTime.minute() > 30) {
598  curTime = QTime(startTime.hour() + 1, 0, 0);
599  } else if (startTime.minute() > 0) {
600  curTime = QTime(startTime.hour(), 30, 0);
601  float yy = currY + minlen * (float)startTime.secsTo(curTime) / 60.;
602  p.drawLine(xcenter, (int)yy, box.right(), (int)yy);
603  curTime = QTime(startTime.hour() + 1, 0, 0);
604  }
605  currY += (float(startTime.secsTo(curTime) * minlen) / 60.);
606 
607  while (curTime < endTime) {
608  p.drawLine(box.left(), (int)currY, box.right(), (int)currY);
609  int newY = (int)(currY + cellHeight / 2.);
610  QString numStr;
611  if (newY < box.bottom()) {
612  QFont oldFont(p.font());
613  // draw the time:
614  if (!KGlobal::locale()->use12Clock()) {
615  p.drawLine(xcenter, (int)newY, box.right(), (int)newY);
616  numStr.setNum(curTime.hour());
617  //TODO: option for this font?
618  if (cellHeight > 30) {
619  p.setFont(QFont("sans-serif", 14, QFont::Bold));
620  } else {
621  p.setFont(QFont("sans-serif", 12, QFont::Bold));
622  }
623  p.drawText(box.left() + 4, (int)currY + 2,
624  box.width() / 2 - 2, (int)cellHeight,
625  Qt::AlignTop | Qt::AlignRight, numStr);
626  //TODO: option for this font?
627  p.setFont(QFont("helvetica", 10, QFont::Normal));
628  p.drawText(xcenter + 4, (int)currY + 2,
629  box.width() / 2 + 2, (int)(cellHeight / 2) - 3,
630  Qt::AlignTop | Qt::AlignLeft, "00");
631  } else {
632  p.drawLine(box.left(), (int)newY, box.right(), (int)newY);
633  QTime time(curTime.hour(), 0);
634  numStr = KGlobal::locale()->formatTime(time);
635  //TODO: option for this font?
636  if (box.width() < 60) {
637  p.setFont(QFont("sans-serif", 7, QFont::Bold)); // for weekprint
638  } else {
639  p.setFont(QFont("sans-serif", 12, QFont::Bold)); // for dayprint
640  }
641  p.drawText(box.left() + 2, (int)currY + 2, box.width() - 4, (int)cellHeight / 2 - 3,
642  Qt::AlignTop | Qt::AlignLeft, numStr);
643  }
644  currY += cellHeight;
645  p.setFont(oldFont);
646  } // enough space for half-hour line and time
647  if (curTime.secsTo(endTime) > 3600) {
648  curTime = curTime.addSecs(3600);
649  } else {
650  curTime = endTime;
651  }
652  }
653 }
654 
655 void CalPrintBase::drawTimeTable(QPainter &p, const QRect &box,
656  const QDate &startDate, const QDate &endDate,
657  const QTime &startTime, const QTime &endTime,
658  bool expandAll) const
659 {
660  QTime myStartTime = startTime;
661  QTime myEndTime = endTime;
662  if (expandAll) {
663  QDate curDate(startDate);
664  KDateTime::Spec timeSpec = KSystemTimeZones::local();
665  while (curDate <= endDate) {
666  KCalCore::Event::List eventList = printCalendar()->events(curDate, timeSpec);
667  Q_FOREACH (const KCalCore::Event::Ptr &event, eventList) {
668  Q_ASSERT(event);
669  if (event->allDay()) {
670  continue;
671  }
672  if (event->dtStart().time() < myStartTime) {
673  myStartTime = event->dtStart().time();
674  }
675  if (event->dtEnd().time() > myEndTime) {
676  myEndTime = event->dtEnd().time();
677  }
678  }
679  curDate = curDate.addDays(1);
680  }
681  }
682 
683  // timeline is 1 hour:
684  int alldayHeight = (int)(3600. * box.height() / (myStartTime.secsTo(myEndTime) + 3600.));
685 
686  QRect dowBox(box);
687  dowBox.setLeft(box.left() + timeLineWidth());
688  dowBox.setHeight(d->mSubHeaderHeight);
689  drawDaysOfWeek(p, dowBox, startDate, endDate);
690 
691  QRect tlBox(box);
692  tlBox.setWidth(timeLineWidth());
693  tlBox.setTop(dowBox.bottom() + boxBorderWidth() + alldayHeight);
694  drawTimeLine(p, myStartTime, myEndTime, tlBox);
695 
696  // draw each day
697  QDate curDate(startDate);
698  KDateTime::Spec timeSpec = KSystemTimeZones::local();
699  int i = 0;
700  double cellWidth = double(dowBox.width()) / double(startDate.daysTo(endDate) + 1);
701  const QList<QDate> workDays = CalendarSupport::workDays(startDate, endDate);
702  while (curDate <= endDate) {
703  QRect allDayBox(dowBox.left() + int(i * cellWidth),
704  dowBox.bottom() + boxBorderWidth(),
705  int((i + 1) * cellWidth) - int(i * cellWidth),
706  alldayHeight);
707  QRect dayBox(allDayBox);
708  dayBox.setTop(tlBox.top());
709  dayBox.setBottom(box.bottom());
710  KCalCore::Event::List eventList =
711  printCalendar()->events(curDate, timeSpec,
712  KCalCore::EventSortStartDate,
713  KCalCore::SortDirectionAscending);
714 
715  alldayHeight = drawAllDayBox(p, allDayBox, curDate, eventList);
716 
717  drawAgendaDayBox(p, dayBox, curDate, eventList, myStartTime, myEndTime, workDays);
718 
719  i++;
720  curDate = curDate.addDays(1);
721  }
722 }
723 
724 void CalPrintBase::drawAgendaDayBox(QPainter &p,
725  const QRect &box,
726  const QDate &date,
727  const KCalCore::Event::List &eventList,
728  const QTime &startTime,
729  const QTime &endTime,
730  const QList<QDate> &workDays) const
731 {
732  QTime myFromTime, myToTime;
733  if (startTime.isValid()) {
734  myFromTime = startTime;
735  } else {
736  myFromTime = QTime(0, 0, 0);
737  }
738  if (endTime.isValid()) {
739  myToTime = endTime;
740  } else {
741  myToTime = QTime(23, 59, 59);
742  }
743 
744  if (!workDays.contains(date)) {
745  drawShadedBox(p, boxBorderWidth(), QColor(232, 232, 232), box);
746  } else {
747  drawBox(p, boxBorderWidth(), box);
748  }
749 
750  const bool printConf = typeOptions().testFlag(
751  CalPrintBase::TypeConfidential); //TODO should be false by default
752  const bool printPrivate = typeOptions().testFlag(
753  CalPrintBase::TypePrivate); //TODO should be false by default
754 
755  if (rangeOptions().testFlag(CalPrintBase::RangeTimeExpand)) {//TODO should be false by default
756  // Adapt start/end times to include complete events
757  Q_FOREACH (const KCalCore::Event::Ptr &event, eventList) {
758  Q_ASSERT(event);
759  if ((!printConf && event->secrecy() == KCalCore::Incidence::SecrecyConfidential) ||
760  (!printPrivate && event->secrecy() == KCalCore::Incidence::SecrecyPrivate)) {
761  continue;
762  }
763  // skip items without times so that we do not adjust for all day items
764  if (event->allDay()) {
765  continue;
766  }
767  if (event->dtStart().time() < myFromTime) {
768  myFromTime = event->dtStart().time();
769  }
770  if (event->dtEnd().time() > myToTime) {
771  myToTime = event->dtEnd().time();
772  }
773  }
774  }
775 
776  // calculate the height of a cell and of a minute
777  int totalsecs = myFromTime.secsTo(myToTime);
778  float minlen = box.height() * 60. / totalsecs;
779  float cellHeight = 60. * minlen;
780  float currY = box.top();
781 
782  // print grid:
783  QTime curTime(QTime(myFromTime.hour(), 0, 0));
784  currY += myFromTime.secsTo(curTime) * minlen / 60;
785 
786  while (curTime < myToTime && curTime.isValid()) {
787  if (currY > box.top()) {
788  p.drawLine(box.left(), int(currY), box.right(), int(currY));
789  }
790  currY += cellHeight / 2;
791  if ((currY > box.top()) && (currY < box.bottom())) {
792  // enough space for half-hour line
793  QPen oldPen(p.pen());
794  p.setPen(QColor(192, 192, 192)); //TODO: define this color
795  p.drawLine(box.left(), int(currY), box.right(), int(currY));
796 
797  p.setPen(oldPen);
798  }
799  if (curTime.secsTo(myToTime) > 3600) {
800  curTime = curTime.addSecs(3600);
801  } else {
802  curTime = myToTime;
803  }
804  currY += cellHeight / 2;
805  }
806 
807  KDateTime startPrintDate = KDateTime(date, myFromTime);
808  KDateTime endPrintDate = KDateTime(date, myToTime);
809 
810  // Calculate horizontal positions and widths of events taking into account
811  // overlapping events
812 
813  QList<CellItem *> cells;
814 
815  Q_FOREACH (const KCalCore::Event::Ptr &event, eventList) {
816  if (event->allDay()) {
817  continue;
818  }
819  QList<KDateTime>::ConstIterator it;
820  QList<KDateTime> times = event->startDateTimesForDate(date);
821  for (it = times.constBegin(); it != times.constEnd(); ++it) {
822  cells.append(new PrintCellItem(event, (*it), event->endDateForStart(*it)));
823  }
824  }
825 
826  QListIterator<CellItem *> it1(cells);
827  while (it1.hasNext()) {
828  CellItem *placeItem = it1.next();
829  CellItem::placeItem(cells, placeItem);
830 
831  }
832 
833  QListIterator<CellItem *> it2(cells);
834  while (it2.hasNext()) {
835  PrintCellItem *placeItem = static_cast<PrintCellItem *>(it2.next());
836  drawAgendaItem(placeItem, p, startPrintDate, endPrintDate, minlen, box);
837  }
838 }
839 
840 void CalPrintBase::drawAgendaItem(PrintCellItem *item, QPainter &p,
841  const KDateTime &startPrintDate,
842  const KDateTime &endPrintDate,
843  float minlen, const QRect &box) const
844 {
845  KCalCore::Event::Ptr event = item->event();
846 
847  // start/end of print area for event
848  KDateTime startTime = item->start();
849  KDateTime endTime = item->end();
850  if ((startTime < endPrintDate && endTime > startPrintDate) ||
851  (endTime > startPrintDate && startTime < endPrintDate)) {
852  if (startTime < startPrintDate) {
853  startTime = startPrintDate;
854  }
855  if (endTime > endPrintDate) {
856  endTime = endPrintDate;
857  }
858  int currentWidth = box.width() / item->subCells();
859  int currentX = box.left() + item->subCell() * currentWidth;
860  int currentYPos =
861  int(box.top() + startPrintDate.secsTo(startTime) * minlen / 60.);
862  int currentHeight =
863  int(box.top() + startPrintDate.secsTo(endTime) * minlen / 60.) - currentYPos;
864 
865  QRect eventBox(currentX, currentYPos, currentWidth, currentHeight);
866  QString str;
867  if (!infoOptions().testFlag(CalPrintBase::InfoTimeRange)) {
868  if (event->location().isEmpty()) {
869  str = cleanString(event->summary());
870  } else {
871  str = i18nc("summary, location", "%1, %2",
872  cleanString(event->summary()),
873  cleanString(event->location()));
874  }
875  } else {
876  if (event->location().isEmpty()) {
877  str = i18nc("starttime - endtime summary",
878  "%1-%2 %3",
879  KGlobal::locale()->formatTime(item->start().toLocalZone().time()),
880  KGlobal::locale()->formatTime(item->end().toLocalZone().time()),
881  cleanString(event->summary()));
882  } else {
883  str = i18nc("starttime - endtime summary, location",
884  "%1-%2 %3, %4",
885  KGlobal::locale()->formatTime(item->start().toLocalZone().time()),
886  KGlobal::locale()->formatTime(item->end().toLocalZone().time()),
887  cleanString(event->summary()),
888  cleanString(event->location()));
889  }
890  }
891  if (infoOptions().testFlag(CalPrintBase::InfoDescription) &&
892  !event->description().isEmpty()) {
893  str += '\n';
894  if (event->descriptionIsRich()) {
895  str += toPlainText(event->description());
896  } else {
897  str += event->description();
898  }
899  }
900  QFont oldFont(p.font());
901  //TODO: font option?
902  if (eventBox.height() < 24) {
903  if (eventBox.height() < 12) {
904  if (eventBox.height() < 8) {
905  p.setFont(QFont("sans-serif", 4));
906  } else {
907  p.setFont(QFont("sans-serif", 5));
908  }
909  } else {
910  p.setFont(QFont("sans-serif", 6));
911  }
912  } else {
913  p.setFont(QFont("sans-serif", 8));
914  }
915  drawItemBox(p, itemBoxBorderWidth(), eventBox, event, str);
916  p.setFont(oldFont);
917  }
918 }
919 
920 void CalPrintBase::drawDaysOfWeekBox(QPainter &p, const QRect &box, const QDate &date) const
921 {
922  KCalendarSystem *calSys = calendarSystem();
923  drawSubHeader(p, box, (calSys) ? (calSys->weekDayName(date)) : QString());
924 }
925 
926 void CalPrintBase::drawDaysOfWeek(QPainter &p, const QRect &box,
927  const QDate &fromDate, const QDate &toDate) const
928 {
929  double cellWidth = double(box.width()) / double(fromDate.daysTo(toDate) + 1);
930  QDate cellDate(fromDate);
931  QRect dateBox(box);
932  int i = 0;
933 
934  while (cellDate <= toDate) {
935  dateBox.setLeft(box.left() + int(i * cellWidth));
936  dateBox.setRight(box.left() + int((i + 1) * cellWidth));
937  drawDaysOfWeekBox(p, dateBox, cellDate);
938  cellDate = cellDate.addDays(1);
939  i++;
940  }
941 }
942 
943 int CalPrintBase::drawAllDayBox(QPainter &p, const QRect &box,
944  const QDate &date, const KCalCore::Event::List &eventList,
945  bool expandAll) const
946 {
947  KCalCore::Event::List::Iterator it;
948  int offset = box.top();
949  QString multiDayStr;
950 
951  KCalCore::Event::List evList = eventList;
952  KCalCore::Event::Ptr hd = holidayEvent(date);
953  if (hd) {
954  evList.prepend(hd);
955  }
956 
957  const bool printConf = typeOptions().testFlag(
958  CalPrintBase::TypeConfidential); //TODO should be false by default
959  const bool printPrivate = typeOptions().testFlag(
960  CalPrintBase::TypePrivate); //TODO should be false by default
961 
962  it = evList.begin();
963  while (it != evList.end()) {
964  KCalCore::Event::Ptr currEvent = *it;
965  if ((!printConf && currEvent->secrecy() == KCalCore::Incidence::SecrecyConfidential) ||
966  (!printPrivate && currEvent->secrecy() == KCalCore::Incidence::SecrecyPrivate)) {
967  continue;
968  }
969  if (currEvent && currEvent->allDay()) {
970  // set the colors according to the categories
971  if (expandAll) {
972  QRect eventBox(box);
973  eventBox.setTop(offset);
974  drawItemBox(p, itemBoxBorderWidth(), eventBox, currEvent, currEvent->summary());
975  offset += box.height();
976  } else {
977  if (!multiDayStr.isEmpty()) {
978  multiDayStr += ", ";
979  }
980  multiDayStr += currEvent->summary();
981  }
982  it = evList.erase(it);
983  } else {
984  ++it;
985  }
986  }
987 
988  int ret = box.height();
989  QRect eventBox(box);
990  if (!expandAll) {
991  if (!multiDayStr.isEmpty()) {
992  drawShadedBox(p, boxBorderWidth(), QColor(180, 180, 180), eventBox);
993  drawItemString(p, eventBox, multiDayStr);
994  } else {
995  drawBox(p, boxBorderWidth(), eventBox);
996  }
997  } else {
998  ret = offset - box.top();
999  eventBox.setBottom(ret);
1000  drawBox(p, boxBorderWidth(), eventBox);
1001  }
1002  return ret;
1003 }
1004 
1005 void CalPrintBase::drawDayIncidence(QPainter &p, const QRect &dayBox,
1006  const QString &time,
1007  const QString &summary,
1008  const QString &description,
1009  int &textY,
1010  bool richDescription) const
1011 {
1012  kDebug() << "summary =" << summary;
1013 
1014  int flags = Qt::AlignLeft | Qt::OpaqueMode;
1015  QFontMetrics fm = p.fontMetrics();
1016  const int borderWidth = p.pen().width() + 1;
1017  QRect timeBound = p.boundingRect(dayBox.x() + borderWidth,
1018  dayBox.y() + textY,
1019  dayBox.width(), fm.lineSpacing(),
1020  flags, time);
1021 
1022  int summaryWidth = time.isEmpty() ? 0 : timeBound.width() + 3;
1023  QRect summaryBound = QRect(dayBox.x() + borderWidth + summaryWidth,
1024  dayBox.y() + textY + 1,
1025  dayBox.width() - summaryWidth - (borderWidth * 2),
1026  dayBox.height() - textY);
1027 
1028  QString summaryText = summary;
1029  QString descText = toPlainText(description);
1030  bool boxOverflow = false;
1031 
1032  const bool includeDescription = infoOptions().testFlag(
1033  CalPrintBase::InfoDescription); // TODO false by default
1034 
1035  if (extraOptions().testFlag(CalPrintBase::ExtraSingleLine)) {//TODO should be true by default
1036  if (includeDescription && !descText.isEmpty()) {
1037  summaryText += ", " + descText;
1038  }
1039  int totalHeight = fm.lineSpacing() + borderWidth;
1040  int textBoxHeight = (totalHeight > (dayBox.height() - textY)) ?
1041  dayBox.height() - textY :
1042  totalHeight;
1043  summaryBound.setHeight(textBoxHeight);
1044  QRect lineRect(dayBox.x() + borderWidth, dayBox.y() + textY,
1045  dayBox.width() - (borderWidth * 2), textBoxHeight);
1046  drawBox(p, 1, lineRect);
1047  if (!time.isEmpty()) {
1048  p.drawText(timeBound, flags, time);
1049  }
1050  p.drawText(summaryBound, flags, summaryText);
1051  } else {
1052  QTextDocument textDoc;
1053  QTextCursor textCursor(&textDoc);
1054  if (richDescription) {
1055  QTextCursor textCursor(&textDoc);
1056  textCursor.insertText(summaryText);
1057  if (includeDescription && !description.isEmpty()) {
1058  textCursor.insertText("\n");
1059  textCursor.insertHtml(description);
1060  }
1061  } else {
1062  textCursor.insertText(summaryText);
1063  if (includeDescription && !descText.isEmpty()) {
1064  textCursor.insertText("\n");
1065  textCursor.insertText(descText);
1066  }
1067  }
1068  textDoc.setPageSize(QSize(summaryBound.width(), summaryBound.height()));
1069  p.save();
1070  QRect clipBox(0, 0, summaryBound.width(), summaryBound.height());
1071  p.setFont(p.font());
1072  p.translate(summaryBound.x(), summaryBound.y());
1073  summaryBound.setHeight(textDoc.documentLayout()->documentSize().height());
1074  if (summaryBound.bottom() > dayBox.bottom()) {
1075  summaryBound.setBottom(dayBox.bottom());
1076  }
1077  clipBox.setHeight(summaryBound.height());
1078  p.restore();
1079 
1080  p.save();
1081  QRect backBox(timeBound.x(), timeBound.y(),
1082  dayBox.width() - (borderWidth * 2), clipBox.height());
1083  drawBox(p, 1, backBox);
1084 
1085  if (!time.isEmpty()) {
1086  if (timeBound.bottom() > dayBox.bottom()) {
1087  timeBound.setBottom(dayBox.bottom());
1088  }
1089  timeBound.moveTop(timeBound.y() + (summaryBound.height() - timeBound.height()) / 2);
1090  p.drawText(timeBound, flags, time);
1091  }
1092  p.translate(summaryBound.x(), summaryBound.y());
1093  textDoc.drawContents(&p, clipBox);
1094  p.restore();
1095  boxOverflow = textDoc.pageCount() > 1;
1096  }
1097  if (summaryBound.bottom() < dayBox.bottom()) {
1098  QPen oldPen(p.pen());
1099  p.setPen(QPen());
1100  p.drawLine(dayBox.x(), summaryBound.bottom(),
1101  dayBox.x() + dayBox.width(), summaryBound.bottom());
1102  p.setPen(oldPen);
1103  }
1104  textY += summaryBound.height();
1105 
1106  // show that we have overflowed the box
1107  if (boxOverflow) {
1108  QPolygon poly(3);
1109  int x = dayBox.x() + dayBox.width();
1110  int y = dayBox.y() + dayBox.height();
1111  poly.setPoint(0, x - 10, y);
1112  poly.setPoint(1, x, y - 10);
1113  poly.setPoint(2, x, y);
1114  QBrush oldBrush(p.brush());
1115  p.setBrush(QBrush(Qt::black));
1116  p.drawPolygon(poly);
1117  p.setBrush(oldBrush);
1118  textY = dayBox.height();
1119  }
1120 }
1121 
1122 void CalPrintBase::drawNoteLines(QPainter &p, const QRect &box, int startY) const
1123 {
1124  int lineHeight = int(p.fontMetrics().lineSpacing() * 1.5);
1125  int linePos = box.y();
1126  int startPos = startY;
1127  // adjust line to start at multiple from top of box for alignment
1128  while (linePos < startPos) {
1129  linePos += lineHeight;
1130  }
1131  QPen oldPen(p.pen());
1132  p.setPen(Qt::DotLine);
1133  while (linePos < box.bottom()) {
1134  p.drawLine(box.left() + padding(), linePos,
1135  box.right() - padding(), linePos);
1136  linePos += lineHeight;
1137  }
1138  p.setPen(oldPen);
1139 }
1140 
1141 void CalPrintBase::drawDayBox(QPainter &p,
1142  const QRect &box,
1143  const QDate &date,
1144  const QTime &startTime, const QTime &endTime,
1145  bool fullDate) const
1146 {
1147  QString dayNumStr;
1148  const KLocale *local = KGlobal::locale();
1149 
1150  QTime myStartTime, myEndTime;
1151  if (startTime.isValid()) {
1152  myStartTime = startTime;
1153  } else {
1154  myStartTime = QTime(0, 0, 0);
1155  }
1156  if (endTime.isValid()) {
1157  myEndTime = endTime;
1158  } else {
1159  myEndTime = QTime(23, 59, 59);
1160  }
1161 
1162  if (fullDate && calendarSystem()) {
1163  dayNumStr = i18nc("weekday, shortmonthname daynumber",
1164  "%1, %2 <numid>%3</numid>",
1165  calendarSystem()->weekDayName(date),
1166  calendarSystem()->monthName(date, KCalendarSystem::ShortName),
1167  date.day());
1168  } else {
1169  dayNumStr = QString::number(date.day());
1170  }
1171 
1172  QRect subHeaderBox(box);
1173  subHeaderBox.setHeight(subHeaderHeight());
1174  drawShadedBox(p, boxBorderWidth(), p.background(), box);
1175  drawShadedBox(p, 0, QColor(232, 232, 232), subHeaderBox);
1176  drawBox(p, boxBorderWidth(), box);
1177  QString hstring(holidayString(date));
1178  const QFont oldFont(p.font());
1179 
1180  QRect headerTextBox(subHeaderBox);
1181  headerTextBox.setLeft(subHeaderBox.left() + 5);
1182  headerTextBox.setRight(subHeaderBox.right() - 5);
1183  if (!hstring.isEmpty()) {
1184  //TODO: option for this font
1185  p.setFont(QFont("sans-serif", 8, QFont::Bold, true));
1186  p.drawText(headerTextBox, Qt::AlignLeft | Qt::AlignVCenter, hstring);
1187  }
1188  //TODO: option for this font
1189  p.setFont(QFont("sans-serif", 10, QFont::Bold));
1190  p.drawText(headerTextBox, Qt::AlignRight | Qt::AlignVCenter, dayNumStr);
1191 
1192  const KCalCore::Event::List eventList =
1193  printCalendar()->events(date, KSystemTimeZones::local(),
1194  KCalCore::EventSortStartDate,
1195  KCalCore::SortDirectionAscending);
1196 
1197  QString timeText;
1198  //TODO: option for this font
1199  p.setFont(QFont("sans-serif", 7));
1200 
1201  const bool printConf = typeOptions().testFlag(
1202  CalPrintBase::TypeConfidential); //TODO should be false by default
1203  const bool printPrivate = typeOptions().testFlag(
1204  CalPrintBase::TypePrivate); //TODO should be false by default
1205  const bool printRecurDaily = rangeOptions().testFlag(
1206  CalPrintBase::RangeRecurDaily); //TODO should be false by default?
1207  const bool printRecurWeekly = rangeOptions().testFlag(
1208  CalPrintBase::RangeRecurWeekly); //TODO should be false by defualt?
1209 
1210  int textY = subHeaderHeight(); // gives the relative y-coord of the next printed entry
1211  unsigned int visibleEventsCounter = 0;
1212  Q_FOREACH (const KCalCore::Event::Ptr &currEvent, eventList) {
1213  Q_ASSERT(currEvent);
1214  if (!currEvent->allDay()) {
1215  if (currEvent->dtEnd().toLocalZone().time() <= myStartTime ||
1216  currEvent->dtStart().toLocalZone().time() > myEndTime) {
1217  continue;
1218  }
1219  }
1220  if ((!printRecurDaily && currEvent->recurrenceType() == KCalCore::Recurrence::rDaily) ||
1221  (!printRecurWeekly && currEvent->recurrenceType() == KCalCore::Recurrence::rWeekly)) {
1222  continue;
1223  }
1224  if ((!printConf && currEvent->secrecy() == KCalCore::Incidence::SecrecyConfidential) ||
1225  (!printPrivate && currEvent->secrecy() == KCalCore::Incidence::SecrecyPrivate)) {
1226  continue;
1227  }
1228  if (currEvent->allDay() || currEvent->isMultiDay()) {
1229  timeText.clear();
1230  } else {
1231  timeText = local->formatTime(currEvent->dtStart().toLocalZone().time()) + ' ';
1232  }
1233  p.save();
1234  setColorsByIncidenceCategory(p, currEvent);
1235  QString summaryStr = currEvent->summary();
1236  if (!currEvent->location().isEmpty()) {
1237  summaryStr = i18nc("summary, location",
1238  "%1, %2", summaryStr, currEvent->location());
1239  }
1240  drawDayIncidence(p, box, timeText,
1241  summaryStr, currEvent->description(),
1242  textY, currEvent->descriptionIsRich());
1243  p.restore();
1244  visibleEventsCounter++;
1245 
1246  if (textY >= box.height()) {
1247  const QChar downArrow(0x21e3);
1248 
1249  const unsigned int invisibleIncidences =
1250  (eventList.count() - visibleEventsCounter) + printCalendar()->todos(date).count();
1251  if (invisibleIncidences > 0) {
1252  const QString warningMsg =
1253  QString("%1 (%2)").arg(downArrow).arg(invisibleIncidences);
1254 
1255  QFontMetrics fm(p.font());
1256  QRect msgRect = fm.boundingRect(warningMsg);
1257  msgRect.setRect(box.right() - msgRect.width() - 2,
1258  box.bottom() - msgRect.height() - 2,
1259  msgRect.width(), msgRect.height());
1260 
1261  p.save();
1262  p.setPen(Qt::red); //krazy:exclude=qenums we don't allow custom print colors
1263  p.drawText(msgRect, Qt::AlignLeft, warningMsg);
1264  p.restore();
1265  }
1266  break;
1267  }
1268  }
1269 
1270  if (textY < box.height()) {
1271  KCalCore::Todo::List todoList = printCalendar()->todos(date);
1272  Q_FOREACH (const KCalCore::Todo::Ptr &todo, todoList) {
1273  if (!todo->allDay()) {
1274  if ((todo->hasDueDate() && todo->dtDue().toLocalZone().time() <= myStartTime) ||
1275  (todo->hasStartDate() && todo->dtStart().toLocalZone().time() > myEndTime)) {
1276  continue;
1277  }
1278  }
1279  if ((!printRecurDaily && todo->recurrenceType() == KCalCore::Recurrence::rDaily) ||
1280  (!printRecurWeekly && todo->recurrenceType() == KCalCore::Recurrence::rWeekly)) {
1281  continue;
1282  }
1283  if ((!printConf && todo->secrecy() == KCalCore::Incidence::SecrecyConfidential) ||
1284  (!printPrivate && todo->secrecy() == KCalCore::Incidence::SecrecyPrivate)) {
1285  continue;
1286  }
1287  if (todo->hasStartDate() && !todo->allDay()) {
1288  timeText =
1289  KGlobal::locale()->formatTime(todo->dtStart().toLocalZone().time()) + ' ';
1290  } else {
1291  timeText.clear();
1292  }
1293  p.save();
1294  setColorsByIncidenceCategory(p, todo);
1295  QString summaryStr = todo->summary();
1296  if (!todo->location().isEmpty()) {
1297  summaryStr = i18nc("summary, location",
1298  "%1, %2", summaryStr, todo->location());
1299  }
1300 
1301  QString str;
1302  if (todo->hasDueDate()) {
1303  if (!todo->allDay()) {
1304  str = i18nc("to-do summary (Due: datetime)", "%1 (Due: %2)",
1305  summaryStr,
1306  KGlobal::locale()->formatDateTime(todo->dtDue().toLocalZone()));
1307  } else {
1308  str = i18nc("to-do summary (Due: date)", "%1 (Due: %2)",
1309  summaryStr,
1310  KGlobal::locale()->formatDate(
1311  todo->dtDue().toLocalZone().date(), KLocale::ShortDate));
1312  }
1313  } else {
1314  str = summaryStr;
1315  }
1316  drawDayIncidence(p, box, timeText,
1317  i18n("To-do: %1", str), todo->description(),
1318  textY, todo->descriptionIsRich());
1319  p.restore();
1320  }
1321  }
1322  if (extraOptions().testFlag(CalPrintBase::ExtraNoteLines)) {//TODO should be false by default
1323  drawNoteLines(p, box, box.y() + textY);
1324  }
1325 
1326  p.setFont(oldFont);
1327 }
1328 
1329 // Utility Functions that could be moved into CalendarSupport or somesuch
1330 int CalPrintBase::weekdayColumn(const int weekday) const
1331 {
1332  int w = weekday + 7 - KGlobal::locale()->weekStartDay();
1333  return w % 7;
1334 }
1335 
1336 QString CalPrintBase::cleanString(const QString &str) const
1337 {
1338  QString ret = str;
1339  return ret.replace('\n', ' ');
1340 }
1341 
1342 QString CalPrintBase::toPlainText(const QString &htmlText) const
1343 {
1344  return QTextDocumentFragment::fromHtml(htmlText).toPlainText();
1345 }
1346 
1347 QColor CalPrintBase::getTextColor(const QColor &c) const
1348 {
1349  double luminance = (c.red() * 0.299) + (c.green() * 0.587) + (c.blue() * 0.114);
1350  return (luminance > 128.0) ? QColor(0, 0, 0) : QColor(255, 255, 255);
1351 }
1352 
1353 QColor CalPrintBase::categoryColor(const QStringList &categories) const
1354 {
1355  if (categories.isEmpty()) {
1356  return CalendarSupport::KCalPrefs::instance()->unsetCategoryColor();
1357  }
1358  // FIXME: Correctly treat events with multiple categories
1359  const QString cat = categories.first();
1360  QColor bgColor;
1361  if (cat.isEmpty()) {
1362  bgColor = CalendarSupport::KCalPrefs::instance()->unsetCategoryColor();
1363  } else {
1364  bgColor = CalendarSupport::KCalPrefs::instance()->categoryColor(cat);
1365  }
1366  return bgColor;
1367 }
1368 
1369 QColor CalPrintBase::categoryBgColor(const KCalCore::Incidence::Ptr &incidence) const
1370 {
1371  if (incidence) {
1372  QColor backColor = categoryColor(incidence->categories());
1373  if (incidence->type() == KCalCore::Incidence::TypeTodo) {
1374  if ((incidence.staticCast<KCalCore::Todo>())->isOverdue()) {
1375  //TODO make this available from CalendarSupport::KCalPrefs
1376  backColor = QColor(255, 100, 100); //was KOPrefs::instance()->todoOverdueColor();
1377  }
1378  }
1379  return backColor;
1380  } else {
1381  return QColor();
1382  }
1383 }
1384 
1385 void CalPrintBase::setColorsByIncidenceCategory(QPainter &p,
1386  const KCalCore::Incidence::Ptr &incidence) const
1387 {
1388  QColor bgColor = categoryBgColor(incidence);
1389  if (bgColor.isValid()) {
1390  p.setBrush(bgColor);
1391  }
1392  QColor tColor(getTextColor(bgColor));
1393  if (tColor.isValid()) {
1394  p.setPen(tColor);
1395  }
1396 }
1397 
1398 QString CalPrintBase::holidayString(const QDate &date) const
1399 {
1400  QStringList lst = CalendarSupport::holiday(date);
1401  return lst.join(i18nc("@item:intext delimiter for joining holiday names", ","));
1402 }
1403 
1404 KCalCore::Event::Ptr CalPrintBase::holidayEvent(const QDate &date) const
1405 {
1406  QString hstring(holidayString(date));
1407  if (hstring.isEmpty()) {
1408  return KCalCore::Event::Ptr();
1409  }
1410 
1411  KCalCore::Event::Ptr holiday(new KCalCore::Event);
1412  holiday->setSummary(hstring);
1413  holiday->setCategories(i18n("Holiday"));
1414 
1415  KDateTime kdt(date, QTime(), KSystemTimeZones::local());
1416  holiday->setDtStart(kdt);
1417  holiday->setDtEnd(kdt);
1418  holiday->setAllDay(true);
1419 
1420  return holiday;
1421 }
PimPrint::Calendar::CalPrintBase::CalPrintBase
CalPrintBase(QPrinter *printer)
Constructor.
Definition: calprintbase.cpp:119
QDate::daysTo
int daysTo(const QDate &d) const
PimPrint::Calendar::CellItem
Definition: cellitem.h:37
QTextDocument::drawContents
void drawContents(QPainter *p, const QRectF &rect)
QRect::setBottom
void setBottom(int y)
QTime::minute
int minute() const
QTextDocument::pageCount
int pageCount() const
PimPrint::Calendar::CalPrintBase::setPrintStyle
void setPrintStyle(const Style style)
Sets the printing Style.
Definition: calprintbase.cpp:193
QTextDocument::setPageSize
void setPageSize(const QSizeF &size)
PimPrint::Calendar::CalPrintBase::setExtraOptions
void setExtraOptions(ExtraOptions flags)
Sets extra options for printing.
Definition: calprintbase.cpp:361
QString::toUpper
QString toUpper() const
QTextCursor
sSubHeaderHeight
static int sSubHeaderHeight
Definition: calprintbase.cpp:48
PimPrint::Calendar::CalPrintBase::drawBox
void drawBox(QPainter &p, const int linewidth, const QRect &box) const
Draws a box with given width at the given coordinates.
Definition: calprintbase.cpp:371
QPainter::background
const QBrush & background() const
PimPrint::Calendar::CalPrintBase::printStyle
Style printStyle() const
Returns the current printing Style.
Definition: calprintbase.cpp:198
QListIterator::next
const T & next()
PimPrint::Calendar::CalPrintBase::setPadding
void setPadding(const int padding)
Sets the padding margin.
Definition: calprintbase.cpp:301
PimPrint::Calendar::CalPrintBase::thePrinter
QPrinter * thePrinter() const
Returns a pointer to the currently set QPrinter.
Definition: calprintbase.cpp:168
QRect::right
int right() const
QDate::daysInMonth
int daysInMonth() const
PimPrint::Calendar::CalPrintBase::calendarSystem
KCalendarSystem * calendarSystem() const
Returns a pointer to the currently set calendar system.
Definition: calprintbase.cpp:188
PimPrint::Calendar::CalPrintBase::drawAgendaDayBox
void drawAgendaDayBox(QPainter &p, const QRect &box, const QDate &date, const KCalCore::Event::List &eventList, const QTime &startTime, const QTime &endTime, const QList< QDate > &workDays) const
Draws the agenda box.
Definition: calprintbase.cpp:724
QPrinter
PimPrint::Calendar::CalPrintBase::RangeTimeExpand
Definition: calprintbase.h:296
QChar
QPainter::font
const QFont & font() const
QFont
PimPrint::Calendar::PrintCellItem::end
KDateTime end() const
Definition: cellitem.h:112
PimPrint::Calendar::CalPrintBase::typeOptions
TypeOptions typeOptions() const
Returns the current type option flags.
Definition: calprintbase.cpp:346
PimPrint::Calendar::CalPrintBase::extraOptions
ExtraOptions extraOptions() const
Returns the current extra option flags.
Definition: calprintbase.cpp:366
PimPrint::Calendar::CalPrintBase::itemBoxBorderWidth
int itemBoxBorderWidth() const
Returns the width of item box borders.
QTime::isValid
bool isValid() const
QPainter::save
void save()
PimPrint::Calendar::CalPrintBase::setHeaderHeight
void setHeaderHeight(const int height)
Sets the height of the page header.
Definition: calprintbase.cpp:255
QPainter::drawPolygon
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
PimPrint::Calendar::CalPrintBase::pageWidth
int pageWidth() const
Returns the current printed page width.
QRect::height
int height() const
PimPrint::Calendar::CalPrintBase::drawTimeTable
void drawTimeTable(QPainter &p, const QRect &box, const QDate &startDate, const QDate &endDate, const QTime &startTime, const QTime &endTime, bool expandAll=false) const
Draws the timetable view of the given time range from startDate to endDate.
Definition: calprintbase.cpp:655
QBrush
sPortraitPageHeight
static int sPortraitPageHeight
Definition: calprintbase.cpp:43
QRect::x
int x() const
QRect::y
int y() const
PimPrint::Calendar::CalPrintBase::RangeRecurWeekly
Definition: calprintbase.h:299
QFontMetrics
QStringList::join
QString join(const QString &separator) const
QPainter::rotate
void rotate(qreal angle)
QPainter::drawLine
void drawLine(const QLineF &line)
QDate::month
int month() const
PimPrint::Calendar::CalPrintBase::drawVerticalBox
void drawVerticalBox(QPainter &p, const int linewidth, const QRect &box, const QString &str, int flags=-1) const
Draws an event box with vertical text.
Definition: calprintbase.cpp:425
QTime
PimPrint::Calendar::CalPrintBase::setPageWidth
void setPageWidth(const int width) const
Sets the printed page width.
Definition: calprintbase.cpp:219
PimPrint::Calendar::CalPrintBase::weekdayColumn
int weekdayColumn(int weekday) const
Determines the column of the given weekday (1=Monday, 7=Sunday), taking the start of the week setting...
Definition: calprintbase.cpp:1330
QPolygon
PimPrint::Calendar::CellItem::subCells
int subCells() const
Definition: cellitem.h:54
PimPrint::Calendar::CalPrintBase::timeLineWidth
int timeLineWidth() const
Returns the width of timelines.
QObject::event
virtual bool event(QEvent *e)
QString::clear
void clear()
PimPrint::Calendar::CalPrintBase::rangeOptions
RangeOptions rangeOptions() const
Returns the current time-range option flags.
Definition: calprintbase.cpp:356
QDate::dayOfWeek
int dayOfWeek() const
PimPrint::Calendar::CalPrintBase::setSubHeaderHeight
void setSubHeaderHeight(const int height)
Sets the height of the page sub-header.
Definition: calprintbase.cpp:271
QPainter::drawRect
void drawRect(const QRectF &rectangle)
PimPrint::Calendar::CalPrintBase::setCalendarSystem
void setCalendarSystem(KCalendarSystem *calSystem)
Sets the calendar system to use when printing.
Definition: calprintbase.cpp:183
QAbstractTextDocumentLayout::documentSize
virtual QSizeF documentSize() const =0
QRect
QFontMetrics::boundingRect
QRect boundingRect(QChar ch) const
QPainter::setFont
void setFont(const QFont &font)
QString::number
QString number(int n, int base)
PimPrint::Calendar::CalPrintBase::InfoTimeRange
Definition: calprintbase.h:281
PimPrint::Calendar::CalPrintBase::drawItemString
void drawItemString(QPainter &p, const QRect &box, const QString &str, int flags=-1) const
Draws the given string (incidence summary) in the given rectangle.
Definition: calprintbase.cpp:395
QList::append
void append(const T &value)
PimPrint::Calendar::CalPrintBase::TypePrivate
Definition: calprintbase.h:291
QPainter::boundingRect
QRectF boundingRect(const QRectF &rectangle, int flags, const QString &text)
PimPrint::Calendar::CalPrintBase::margins
int margins() const
Returns the size of the page margins.
QRect::top
int top() const
PimPrint::Calendar::CalPrintBase::boxBorderWidth
int boxBorderWidth() const
Returns the width of box borders.
PimPrint::Calendar::CalPrintBase::InfoDescription
Definition: calprintbase.h:274
QColor::red
int red() const
QPainter::setPen
void setPen(const QColor &color)
PimPrint::Calendar::PrintCellItem
Definition: cellitem.h:88
QRect::setTop
void setTop(int y)
QRect::left
int left() const
PimPrint::Calendar::CalPrintBase::None
Definition: calprintbase.h:122
sLandscapeFooterHeight
static int sLandscapeFooterHeight
Definition: calprintbase.cpp:51
QList::isEmpty
bool isEmpty() const
QPainter
QRect::setWidth
void setWidth(int width)
QString::isEmpty
bool isEmpty() const
PimPrint::Calendar::CalPrintBase::setFooterHeight
void setFooterHeight(const int height)
Sets the height of the page footer.
Definition: calprintbase.cpp:281
QDate::day
int day() const
PimPrint::Calendar::CalPrintBase::drawShadedBox
void drawShadedBox(QPainter &p, const int linewidth, const QBrush &brush, const QRect &box) const
Draws a shaded box with given width at the given coordinates.
Definition: calprintbase.cpp:386
PimPrint::Calendar::CalPrintBase::infoOptions
InfoOptions infoOptions() const
Returns the current information option flags.
Definition: calprintbase.cpp:336
QDate::isValid
bool isValid() const
PimPrint::Calendar::CalPrintBase::drawFooter
int drawFooter(QPainter &p, const QRect &box) const
Draws a page footer containing the printing date and possibly other things, like a page number...
Definition: calprintbase.cpp:568
QTime::addSecs
QTime addSecs(int s) const
QTextDocument::documentLayout
QAbstractTextDocumentLayout * documentLayout() const
QPainter::setBrush
void setBrush(const QBrush &brush)
PimPrint::Calendar::CalPrintBase
Definition: calprintbase.h:67
PimPrint::Calendar::CalPrintBase::printCalendar
KCalCore::Calendar::Ptr printCalendar() const
Returns a pointer to the currently set print calendar.
Definition: calprintbase.cpp:178
QPainter::drawText
void drawText(const QPointF &position, const QString &text)
PimPrint::Calendar::CalPrintBase::ExtraNoteLines
Definition: calprintbase.h:305
PimPrint::Calendar::CalPrintBase::drawTimeLine
void drawTimeLine(QPainter &p, const QTime &startTime, const QTime &endTime, const QRect &box) const
Draws a (vertical) time scale from time startTime to endTime inside the given area of the painter...
Definition: calprintbase.cpp:583
sPortraitFooterHeight
static int sPortraitFooterHeight
Definition: calprintbase.cpp:50
PimPrint::Calendar::CalPrintBase::padding
int padding() const
Returns the current padding margin.
QDate
QDate::year
int year() const
QList::first
T & first()
QString
PimPrint::Calendar::CalPrintBase::setUseLandscape
void setUseLandscape(const bool landscape)
Sets the printed page orientation to landscape.
Definition: calprintbase.cpp:235
QList
PimPrint::Calendar::CalPrintBase::ExtraSingleLine
Definition: calprintbase.h:304
QColor
QRect::moveTop
void moveTop(int y)
QStringList
sPaddingSize
static int sPaddingSize
Definition: calprintbase.cpp:54
QTime::hour
int hour() const
QColor::green
int green() const
calprintbase.h
QSize
PimPrint::Calendar::PrintCellItem::start
KDateTime start() const
Definition: cellitem.h:107
QPainter::brush
const QBrush & brush() const
PimPrint::Calendar::CalPrintBase::setRangeOptions
void setRangeOptions(RangeOptions flags)
Sets time-range options for printing.
Definition: calprintbase.cpp:351
PimPrint::Calendar::CalPrintBase::headerHeight
int headerHeight() const
Returns the current height of the page header.
sBoxBorderWidth
static int sBoxBorderWidth
Definition: calprintbase.cpp:56
QList::contains
bool contains(const T &value) const
sLandscapeHeaderHeight
static int sLandscapeHeaderHeight
Definition: calprintbase.cpp:47
sTimeLineWidth
static int sTimeLineWidth
Definition: calprintbase.cpp:58
PimPrint::Calendar::CalPrintBase::setPrintCalendar
void setPrintCalendar(const KCalCore::Calendar::Ptr &calendar)
Sets the calendar containing the data to print.
Definition: calprintbase.cpp:173
PimPrint::Calendar::CellItem::subCell
int subCell() const
Definition: cellitem.h:64
QPainter::restore
void restore()
PimPrint::Calendar::CalPrintBase::setInfoOptions
void setInfoOptions(InfoOptions flags)
Sets information options for printing.
Definition: calprintbase.cpp:331
PimPrint::Calendar::CalPrintBase::drawHeader
int drawHeader(QPainter &p, const QRect &box, const QString &title, const QDate &leftMonth=QDate(), const QDate &rightMonth=QDate(), const bool expand=false, const QColor &backColor=QColor()) const
Draws the gray header bar of the printout to the QPainter.
Definition: calprintbase.cpp:497
PimPrint::Calendar::CalPrintBase::footerHeight
int footerHeight() const
Returns the current height of the page footer.
QString::replace
QString & replace(int position, int n, QChar after)
QRect::setRight
void setRight(int x)
QColor::blue
int blue() const
QDateTime::currentDateTime
QDateTime currentDateTime()
PimPrint::Calendar::CalPrintBase::drawDayBox
void drawDayBox(QPainter &p, const QRect &box, const QDate &date, const QTime &startTime, const QTime &endTime, bool fullDate=false) const
Draws the box containing a list of all events and to-dos of the given day.
Definition: calprintbase.cpp:1141
QRect::width
int width() const
sLandscapePageHeight
static int sLandscapePageHeight
Definition: calprintbase.cpp:44
sMarginSize
static int sMarginSize
Definition: calprintbase.cpp:53
PimPrint::Calendar::CalPrintBase::drawDaysOfWeek
void drawDaysOfWeek(QPainter &p, const QRect &box, const QDate &fromDate, const QDate &toDate) const
Draws a horizontal bar with the weekday names of the given date range in the given area of the painte...
Definition: calprintbase.cpp:926
QPen::width
int width() const
PimPrint::Calendar::CalPrintBase::useLandscape
bool useLandscape() const
Returns if the current printed page orientation is landscape.
PimPrint::Calendar::CalPrintBase::drawSubHeader
void drawSubHeader(QPainter &p, const QRect &box, const QString &str) const
Draws a subheader with a shaded background and the specified string.
Definition: calprintbase.cpp:558
PimPrint::Calendar::CalPrintBase::RangeRecurDaily
Definition: calprintbase.h:298
QTextDocument
QRect::setRect
void setRect(int x, int y, int width, int height)
QString::setNum
QString & setNum(short n, int base)
QPainter::fontMetrics
QFontMetrics fontMetrics() const
QRect::setHeight
void setHeight(int height)
PimPrint::Calendar::CalPrintBase::setTypeOptions
void setTypeOptions(TypeOptions flags)
Sets type options for printing.
Definition: calprintbase.cpp:341
QTextDocumentFragment::fromHtml
QTextDocumentFragment fromHtml(const QString &text)
QTextDocumentFragment::toPlainText
QString toPlainText() const
QRect::adjust
void adjust(int dx1, int dy1, int dx2, int dy2)
PimPrint::Calendar::CalPrintBase::subHeaderHeight
int subHeaderHeight() const
Returns the current height of the page sub-header.
Definition: calprintbase.cpp:276
PimPrint::Calendar::CalPrintBase::setPageHeight
void setPageHeight(const int height) const
Sets the printed page height.
Definition: calprintbase.cpp:203
QRect::bottom
int bottom() const
QPainter::translate
void translate(const QPointF &offset)
PimPrint::Calendar::CalPrintBase::pageHeight
int pageHeight() const
Returns the current printed page height.
QPen
PimPrint::Calendar::CalPrintBase::toPlainText
QString toPlainText(const QString &htmlText) const
Converts possible rich text to plain text.
Definition: calprintbase.cpp:1342
QListIterator
PimPrint::Calendar::CalPrintBase::cleanString
QString cleanString(const QString &str) const
Cleans a string of newlines and other characters that shouldn't be printed.
Definition: calprintbase.cpp:1336
sPortraitHeaderHeight
static int sPortraitHeaderHeight
Definition: calprintbase.cpp:46
QDate::addDays
QDate addDays(int ndays) const
PimPrint::Calendar::CalPrintBase::~CalPrintBase
~CalPrintBase()
Destructor.
Definition: calprintbase.cpp:125
QList::constEnd
const_iterator constEnd() const
QList::constBegin
const_iterator constBegin() const
QPrinter::setColorMode
void setColorMode(ColorMode newColorMode)
PimPrint::Calendar::CellItem::placeItem
static QList< CellItem * > placeItem(QList< CellItem * > cells, CellItem *placeItem)
Place item placeItem into stripe containing items cells in a way that items don't overlap...
Definition: cellitem.cpp:36
PimPrint::Calendar::CalPrintBase::Style
Style
Definition: calprintbase.h:121
QSizeF::height
qreal height() const
PimPrint::Calendar::PrintCellItem::event
KCalCore::Event::Ptr event() const
Definition: cellitem.h:97
QBrush::setColor
void setColor(const QColor &color)
QPainter::pen
const QPen & pen() const
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QRect::setLeft
void setLeft(int x)
sItemBoxBorderWidth
static int sItemBoxBorderWidth
Definition: calprintbase.cpp:57
QTime::secsTo
int secsTo(const QTime &t) const
PimPrint::Calendar::CalPrintBase::drawItemBox
void drawItemBox(QPainter &p, int linewidth, const QRect &box, const KCalCore::Incidence::Ptr &incidence, const QString &str, int flags=-1) const
Draws the box for the specified item with the given string.
Definition: calprintbase.cpp:404
QFontMetrics::lineSpacing
int lineSpacing() const
PimPrint::Calendar::CalPrintBase::setUseColor
void setUseColor(const bool useColor)
Sets if a color print is desired.
Definition: calprintbase.cpp:245
QColor::isValid
bool isValid() const
PimPrint::Calendar::CalPrintBase::TypeConfidential
Definition: calprintbase.h:290
PimPrint::Calendar::CalPrintBase::setThePrinter
void setThePrinter(QPrinter *printer)
Sets the QPrinter.
Definition: calprintbase.cpp:163
PimPrint::Calendar::CalPrintBase::useColor
bool useColor() const
Returns if a color printing is currently set.
PimPrint::Calendar::CalPrintBase::drawAgendaItem
void drawAgendaItem(PrintCellItem *item, QPainter &p, const KDateTime &startPrintDate, const KDateTime &endPrintDate, float minlen, const QRect &box) const
Definition: calprintbase.cpp:840
QListIterator::hasNext
bool hasNext() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:32:09 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

PIMPrint Library

Skip menu "PIMPrint Library"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal