1 /* 2 SPDX-FileCopyrightText: 1998 Preston Brown <pbrown@kde.org> 3 SPDX-FileCopyrightText: 2003 Reinhold Kainhofer <reinhold@kainhofer.com> 4 SPDX-FileCopyrightText: 2008 Ron Goodheart <rong.dev@gmail.com> 5 SPDX-FileCopyrightText: 2012-2013 Allen Winter <winter@kde.org> 6 7 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 8 */ 9 10 #pragma once 11 12 #include "calendarsupport_export.h" 13 #include "printplugin.h" 14 15 #include <Akonadi/Calendar/ETMCalendar> 16 17 #include <KCalendarCore/Event> 18 #include <KCalendarCore/Journal> 19 #include <KCalendarCore/Todo> 20 21 #include <QDateTime> 22 #include <QPainter> 23 24 class PrintCellItem; 25 class QWidget; 26 27 #define PORTRAIT_HEADER_HEIGHT 80 // header height, for portrait orientation 28 #define LANDSCAPE_HEADER_HEIGHT 54 // header height, for landscape orientation 29 #define SUBHEADER_HEIGHT 28 // subheader height, for all orientations 30 #define PORTRAIT_FOOTER_HEIGHT 16 // footer height, for portrait orientation 31 #define LANDSCAPE_FOOTER_HEIGHT 14 // footer height, for landscape orientation 32 #define MARGIN_SIZE 36 // margins, for all orientations 33 #define PADDING_SIZE 7 // padding between the various top-level boxes 34 #define BOX_BORDER_WIDTH 2 // width of the border of all top-level boxes 35 #define EVENT_BORDER_WIDTH 0 // with of the border of all incidence boxes 36 37 #define TIMELINE_WIDTH 50 // width of timeline (day and timetable) 38 39 namespace CalendarSupport 40 { 41 /** 42 Base class for Calendar printing classes. Each sub class represents one 43 calendar print format. 44 */ 45 class CalPrintPluginBase : public PrintPlugin 46 { 47 public: 48 enum DisplayFlags { Text = 0x0001, TimeBoxes = 0x0002 }; 49 50 public: 51 /** 52 Constructor 53 */ 54 CalPrintPluginBase(); 55 ~CalPrintPluginBase() override; 56 57 /** 58 Returns widget for configuring the print format. 59 */ 60 QWidget *createConfigWidget(QWidget *) override; 61 62 /** 63 Actually do the printing. 64 65 @param p QPainter the print result is painted to 66 @param width Width of printable area 67 @param height Height of printable area 68 */ 69 70 virtual void print(QPainter &p, int width, int height) = 0; 71 /** 72 Start printing. 73 */ 74 void doPrint(QPrinter *printer) override; 75 76 void doLoadConfig() override; 77 78 void doSaveConfig() override; 79 80 /** HELPER FUNCTIONS */ 81 public: 82 bool useColors() const; 83 void setUseColors(bool useColors); 84 85 bool printFooter() const; 86 void setPrintFooter(bool printFooter); 87 88 /** 89 Determines the column of the given weekday ( 1=Monday, 7=Sunday ), taking the 90 start of the week setting into account as given in kcontrol. 91 @param weekday Index of the weekday 92 */ 93 static int weekdayColumn(int weekday); 94 95 QPageLayout::Orientation orientation() const; 96 97 /** Returns the height of the page header. If the height was explicitly 98 set using setHeaderHeight, that value is returned, otherwise a 99 default value based on the printer orientation. 100 @return height of the page header of the printout 101 */ 102 int headerHeight() const; 103 void setHeaderHeight(const int height); 104 105 int subHeaderHeight() const; 106 void setSubHeaderHeight(const int height); 107 /** Returns the height of the page footer. If the height was explicitly 108 set using setFooterHeight, that value is returned, otherwise a 109 default value based on the printer orientation. 110 @return height of the page footer of the printout 111 */ 112 int footerHeight() const; 113 void setFooterHeight(const int height); 114 115 int margin() const; 116 void setMargin(const int margin); 117 118 int padding() const; 119 void setPadding(const int margin); 120 121 int borderWidth() const; 122 void setBorderWidth(const int border); 123 124 /***************************************************************** 125 ** PRINTING HELPER FUNCTIONS ** 126 *****************************************************************/ 127 public: 128 /** 129 Draw a box with given width at the given coordinates. 130 @param p The printer to be used 131 @param linewidth The border width of the box 132 @param rect The rectangle of the box 133 */ 134 static void drawBox(QPainter &p, int linewidth, QRect rect); 135 /** 136 Draw a shaded box with given width at the given coordinates. 137 @param p The printer to be used 138 @param linewidth The border width of the box 139 @param brush The brush to fill the box 140 @param rect The rectangle of the box 141 */ 142 static void drawShadedBox(QPainter &p, int linewidth, const QBrush &brush, QRect rect); 143 144 /** 145 Print the given string (event summary) in the given rectangle. Margins 146 and justification (centered or not) are automatically adjusted. 147 @param p QPainter of the printout 148 @param box Coordinates of the surrounding event box 149 @param str The text to be printed in the box 150 */ 151 void printEventString(QPainter &p, QRect box, const QString &str, int flags = -1); 152 153 /** 154 Print the box for the given event with the given string. 155 @param p QPainter of the printout 156 @param linewidth is the width of the line used to draw the box, ignored if less than 1. 157 @param box Coordinates of the event's box 158 @param incidence The incidence (if available), from which the category 159 color will be deduced, if applicable. 160 @param str The string to print inside the box 161 @param flags is a bitwise OR of Qt::AlignmentFlags and Qt::TextFlags values. 162 */ 163 void showEventBox(QPainter &p, int linewidth, QRect box, const KCalendarCore::Incidence::Ptr &incidence, const QString &str, int flags = -1); 164 165 /** 166 Draw a subheader box with a shaded background and the given string 167 @param p QPainter of the printout 168 @param str Text to be printed inside the box 169 @param box Coordinates of the box 170 */ 171 void drawSubHeaderBox(QPainter &p, const QString &str, QRect box); 172 173 /** 174 Draw an event box with vertical text. 175 @param p QPainter of the printout 176 @param linewidth is the width of the line used to draw the box, ignored if less than 1. 177 @param box Coordinates of the box 178 @param str ext to be printed inside the box 179 @param flags is a bitwise OR of Qt::AlignmentFlags and Qt::TextFlags values. 180 */ 181 void drawVerticalBox(QPainter &p, int linewidth, QRect box, const QString &str, int flags = -1); 182 183 /** 184 Draw a component box with a heading (printed in bold). 185 @param p QPainter of the printout 186 @param box Coordinates of the box 187 @param caption Caption string to be printed inside the box 188 @param contents Normal text contents of the box. If contents.isNull(), 189 then no text will be printed, only the caption. 190 @param sameLine Whether the contents should start on the same line as 191 the caption (the space below the caption text will be 192 used as indentation in the subsequent lines) or on the 193 next line (no indentation of the contents) 194 @param expand Whether to expand the box vertically to fit the 195 whole text in it. 196 @param rickContents Whether contents contains rich text. 197 @return The bottom of the printed box. If expand==true, the bottom of 198 the drawn box is returned, if expand==false, the vertical 199 end of the printed contents inside the box is returned. 200 If you want to print some custom graphics or text below 201 the contents, use the return value as the top-value of your 202 custom contents in that case. 203 */ 204 int drawBoxWithCaption(QPainter &p, 205 QRect box, 206 const QString &caption, 207 const QString &contents, 208 bool sameLine, 209 bool expand, 210 const QFont &captionFont, 211 const QFont &textFont, 212 bool richContents = false); 213 214 /** 215 Draw the gray header bar of the printout to the QPainter. 216 It prints the given text and optionally one or two small 217 month views, as specified by the two QDate. The printed 218 text can also contain a line feed. 219 If month2 is invalid, only the month that contains month1 220 is printed. 221 E.g. the filofax week view draws just the current month, 222 while the month view draws the previous and the next month. 223 @param p QPainter of the printout 224 @param title The string printed as the title of the page 225 (e.g. the date, date range or todo list title) 226 @param month1 Date specifying the month for the left one of 227 the small month views in the title bar. If left 228 empty, only month2 will be printed (or none, 229 it that is invalid as well). 230 @param month2 Date specifying the month for the right one of 231 the small month views in the title bar. If left 232 empty, only month1 will be printed (or none, 233 it that is invalid as well). 234 @param box coordinates of the title bar 235 @param expand Whether to expand the box vertically to fit the 236 whole title in it. 237 @param backColor background color for the header box. 238 @return The bottom of the printed box. If expand==false, this 239 is box.bottom, otherwise it is larger than box.bottom 240 and matches the y-coordinate of the surrounding rectangle. 241 */ 242 int drawHeader(QPainter &p, const QString &title, QDate month1, QDate month2, QRect box, bool expand = false, QColor backColor = QColor()); 243 244 /** 245 Draw a page footer containing the printing date and possibly 246 other things, like a page number. 247 @param p QPainter of the printout 248 @param box coordinates of the footer 249 @return The bottom of the printed box. 250 */ 251 int drawFooter(QPainter &p, QRect box); 252 253 /** 254 Draw a small calendar with the days of a month into the given area. 255 Used for example in the title bar of the sheet. 256 @param p QPainter of the printout 257 @param qd Arbitrary Date within the month to be printed. 258 @param box coordinates of the small calendar 259 */ 260 void drawSmallMonth(QPainter &p, QDate qd, QRect box); 261 262 /** 263 Draw a horizontal bar with the weekday names of the given date range 264 in the given area of the painter. 265 This is used for the weekday-bar on top of the timetable view and the month view. 266 @param p QPainter of the printout 267 @param fromDate First date of the printed dates 268 @param toDate Last date of the printed dates 269 @param box coordinates of the box for the days of the week 270 */ 271 void drawDaysOfWeek(QPainter &p, QDate fromDate, QDate toDate, QRect box); 272 273 /** 274 Draw a single weekday name in a box inside the given area of the painter. 275 This is called in a loop by drawDaysOfWeek. 276 @param p QPainter of the printout 277 @param qd Date of the printed day 278 @param box coordinates of the weekbox 279 */ 280 void drawDaysOfWeekBox(QPainter &p, QDate qd, QRect box); 281 282 /** 283 Draw a (vertical) time scale from time fromTime to toTime inside the 284 given area of the painter. Every hour will have a one-pixel line over 285 the whole width, every half-hour the line will only span the left half 286 of the width. This is used in the day and timetable print styles 287 @param p QPainter of the printout 288 @param fromTime Start time of the time range to display 289 @param toTime End time of the time range to display 290 @param box coordinates of the timeline 291 */ 292 void drawTimeLine(QPainter &p, QTime fromTime, QTime toTime, QRect box); 293 294 /** 295 Draw the agenda box for the day print style (the box showing all events of that day). 296 Also draws a grid with half-hour spacing of the grid lines. 297 Does NOT draw allday events. Use drawAllDayBox for allday events. 298 299 Obeys configuration options #mExcludeConfidential, #excludePrivate. 300 @param p QPainter of the printout 301 @param eventList The list of the events that are supposed to be printed 302 inside this box 303 @param qd The date of the currently printed day 304 @param expandable If true, the start and end times are adjusted to include 305 the whole range of all events of that day, not just of the given time range. 306 The height of the box will not be affected by this (but the height 307 of one hour will be scaled down so that the whole range fits into 308 the box. fromTime and toTime receive the actual time range printed 309 by this function). 310 @param fromTime Start of the time range to be printed. Might be adjusted 311 to include all events if expandable==true 312 @param toTime End of the time range to be printed. Might be adjusted 313 to include all events if expandable==true 314 @param box coordinates of the agenda day box. 315 @param includeDescription Whether to print the event description as well. 316 @param includeCategories Whether to print the event categories (tags) as well. 317 @param excludeTime Whether the time is printed in the detail area. 318 @param workDays List of workDays 319 */ 320 void drawAgendaDayBox(QPainter &p, 321 const KCalendarCore::Event::List &eventList, 322 QDate qd, 323 bool expandable, 324 QTime fromTime, 325 QTime toTime, 326 QRect box, 327 bool includeDescription, 328 bool includeCategories, 329 bool excludeTime, 330 const QList<QDate> &workDays); 331 332 void drawAgendaItem(PrintCellItem *item, 333 QPainter &p, 334 const QDateTime &startPrintDate, 335 const QDateTime &endPrintDate, 336 float minlen, 337 QRect box, 338 bool includeDescription, 339 bool includeCategories, 340 bool excludeTime); 341 342 /** 343 Draw the box containing a list of all events of the given day (with their times, 344 of course). Used in the Filofax and the month print style. 345 346 Obeys configuration options #mExcludeConfidential, #mExcludePrivate, #mShowNoteLines, #mUseColors. 347 @param p QPainter of the printout 348 @param qd The date of the currently printed day. All events of the calendar 349 that appear on that day will be printed. 350 @param fromTime Start time of the time range to display 351 @param toTime End time of the time range to display 352 @param box coordinates of the day box. 353 @param fullDate Whether the title bar of the box should contain the full 354 date string or just a short. 355 @param printRecurDaily Whether daily recurring incidences should be printed. 356 @param printRecurWeekly Whether weekly recurring incidences should be printed. 357 @param singleLineLimit Whether Incidence text wraps or truncates. 358 @param includeDescription Whether to print the event description as well. 359 @param includeCategories Whether to print the event categories (tags) as well. 360 */ 361 void drawDayBox(QPainter &p, 362 QDate qd, 363 QTime fromTime, 364 QTime toTime, 365 QRect box, 366 bool fullDate = false, 367 bool printRecurDaily = true, 368 bool printRecurWeekly = true, 369 bool singleLineLimit = true, 370 bool includeDescription = false, 371 bool includeCategories = false); 372 373 /** 374 Draw the month table of the month containing the date qd. Each day gets one 375 box (using drawDayBox) that contains a list of all events on that day. They are arranged 376 in a matrix, with the first column being the first day of the 377 week (so it might display some days of the previous and the next month). 378 Above the matrix there is a bar showing the weekdays (drawn using drawDaysOfWeek). 379 380 Obeys configuration options #mExcludeConfidential, #mExcludePrivate, #mShowNoteLines, #mUseColors. 381 @param p QPainter of the printout 382 @param qd Arbitrary date within the month to be printed. 383 @param fromTime Start time of the displayed time range 384 @param toTime End time of the displayed time range 385 @param weeknumbers Whether the week numbers are printed left of each row of the matrix 386 @param recurDaily Whether daily recurring incidences should be printed. 387 @param recurWeekly Whether weekly recurring incidences should be printed. 388 @param singleLineLimit Whether Incidence text wraps or truncates. 389 @param includeDescription Whether descriptions are printed. 390 @param includeCategories Whether to print the event categories (tags) as well. 391 @param box coordinates of the month. 392 */ 393 void drawMonthTable(QPainter &p, 394 QDate qd, 395 QTime fromTime, 396 QTime toTime, 397 bool weeknumbers, 398 bool recurDaily, 399 bool recurWeekly, 400 bool singleLineLimit, 401 bool includeDescription, 402 bool includeCategories, 403 QRect box); 404 405 /** 406 Draw a vertical representation of the month containing the date dt. Each 407 day gets one line. 408 409 Obeys configuration options #mExcludeConfidential, #excludePrivate. 410 @param p QPainter of the printout 411 @param dt Arbitrary date within the month to be printed 412 @param box coordinates of the box reserved for the month 413 @param maxdays Days to print. If a value of -1 is given, the number of days 414 is deduced from the month. If maxdays is larger than the 415 number of days in the month, the remaining boxes are 416 shaded to indicate they are not days of the month. 417 @param subDailyFlags Bitfield consisting of DisplayFlags flags to determine 418 how events that do not cross midnight should be printed. 419 @param holidaysFlags Bitfield consisting of DisplayFlags flags to determine 420 how holidays should be printed. 421 */ 422 void drawMonth(QPainter &p, 423 QDate dt, 424 QRect box, 425 int maxdays = -1, 426 int subDailyFlags = TimeBoxes, 427 int holidaysFlags = Text); 428 429 /** 430 Internal class representing the start of a todo. 431 */ 432 class TodoParentStart; 433 434 /** 435 Draws single to-do and its (indented) sub-to-dos, optionally connects them 436 by a tree-like line, and optionally shows due date, summary, description 437 and priority. 438 @param count The number of the currently printed to-do (count will be 439 incremented for each to-do drawn) 440 @param todo The to-do to be printed. It's sub-to-dos are recursively drawn, 441 so drawTodo should only be called on the to-dos of the highest level. 442 @param p QPainter of the printout 443 @param sortField Specifies on which attribute of the todo you want to sort. 444 @param sortDir Specifies if you want to sort ascending or descending. 445 @param connectSubTodos Whether sub-to-dos shall be connected with 446 their parent by a line (tree-like). 447 @param strikeoutCompleted Whether completed to-dos should be printed with 448 strike-out summaries. 449 @param desc Whether to print the whole description of the to-do 450 (the summary is always printed). 451 @param posPriority x-coordinate where the priority is supposed to be 452 printed. If negative, no priority will be printed. 453 @param posSummary x-coordinate where the summary of the to-do is supposed 454 to be printed. 455 @param posCategories x-coordinate where the categories (tags) should be 456 printed. If negative, no categories will be printed. 457 @param posStartDt x-coordinate where the due date is supposed to the be 458 printed. If negative, no start date will be printed. 459 @param posDueDt x-coordinate where the due date is supposed to the be 460 printed. If negative, no due date will be printed. 461 @param posPercentComplete x-coordinate where the percentage complete is 462 supposed to be printed. If negative, percentage complete will not be printed. 463 @param level Level of the current to-do in the to-do hierarchy (0 means 464 highest level of printed to-dos, 1 are their sub-to-dos, etc.) 465 @param x x-coordinate of the upper left coordinate of the first to-do. 466 @param y y-coordinate of the upper left coordinate of the first to-do. 467 @param width width of the whole to-do list. 468 @param pageHeight Total height allowed for the to-do list on a page. 469 If an to-do would be below that line, a new page is started. 470 @param todoList Contains a list of sub-todos for the specified @p todo . 471 @param r Internal (used when printing sub-to-dos to give information 472 about its parent) 473 */ 474 void drawTodo(int &count, 475 const KCalendarCore::Todo::Ptr &todo, 476 QPainter &p, 477 KCalendarCore::TodoSortField sortField, 478 KCalendarCore::SortDirection sortDir, 479 bool connectSubTodos, 480 bool strikeoutCompleted, 481 bool desc, 482 int posPriority, 483 int posSummary, 484 int posCategories, 485 int posStartDt, 486 int posDueDt, 487 int posPercentComplete, 488 int level, 489 int x, 490 int &y, 491 int width, 492 int pageHeight, 493 const KCalendarCore::Todo::List &todoList, 494 TodoParentStart *r); 495 496 /** 497 Draws text lines splitting on page boundaries. 498 @param p QPainter of the printout 499 @param x x-coordinate of the upper left coordinate of the first item 500 @param y y-coordinate of the upper left coordinate of the first item 501 @param width width of the whole list 502 @param pageHeight size of the page. A new page is started when the 503 text reaches the end of the page. 504 */ 505 void drawTextLines(QPainter &p, const QString &entry, int x, int &y, int width, int pageHeight, bool richTextEntry); 506 507 void drawSplitHeaderRight(QPainter &p, QDate fd, QDate td, QDate cd, int width, int height); 508 509 /** 510 Draws dotted lines for notes in a box. 511 @param p QPainter of the printout 512 @param box coordinates of the box where the lines will be placed 513 @param startY starting y-coordinate for the first line 514 */ 515 void drawNoteLines(QPainter &p, QRect box, int startY); 516 517 protected: 518 QTime dayStart() const; 519 QColor categoryBgColor(const KCalendarCore::Incidence::Ptr &incidence) const; 520 521 void drawIncidence(QPainter &p, 522 QRect dayBox, 523 const QString &time, 524 const QString &summary, 525 const QString &description, 526 int &textY, 527 bool singleLineLimit, 528 bool includeDescription, 529 bool richDescription); 530 531 QString toPlainText(const QString &htmlText); 532 533 void drawTodoLines(QPainter &p, 534 const QString &entry, 535 int x, 536 int &y, 537 int width, 538 int pageHeight, 539 bool richTextEntry, 540 QList<TodoParentStart *> &startPoints, 541 bool connectSubTodos); 542 543 KCalendarCore::Event::Ptr holidayEvent(QDate date) const; 544 545 protected: 546 bool mUseColors; /**< Whether or not to use event category colors to draw the events. */ 547 bool mPrintFooter; /**< Whether or not to print a footer at the bottoms of pages. */ 548 bool mShowNoteLines; /**< Whether or not to print horizontal lines in note areas. */ 549 bool mExcludeConfidential; /**< Whether or not to print incidences with secrecy "confidential". */ 550 bool mExcludePrivate; /**< Whether or not to print incidences with secrecy "private". */ 551 int mHeaderHeight; 552 int mSubHeaderHeight; 553 int mFooterHeight; 554 int mMargin; 555 int mPadding; 556 int mBorder; 557 558 static const QColor sHolidayBackground; 559 560 private: 561 QColor categoryColor(const QStringList &categories) const; 562 563 /** 564 * Sets the QPainter's brush and pen color according to the Incidence's category. 565 */ 566 void setColorsByIncidenceCategory(QPainter &p, const KCalendarCore::Incidence::Ptr &incidence) const; 567 568 QString holidayString(QDate date) const; 569 570 /** 571 * Returns a nice QColor for text, give the input color &c. 572 */ 573 QColor getTextColor(const QColor &c) const; 574 }; 575 } 576 577