File indexing completed on 2025-01-05 04:47:43

0001 /*
0002   SPDX-FileCopyrightText: 1998 Preston Brown <pbrown@kde.org>
0003   SPDX-FileCopyrightText: 2003 Reinhold Kainhofer <reinhold@kainhofer.com>
0004   SPDX-FileCopyrightText: 2008 Ron Goodheart <rong.dev@gmail.com>
0005   SPDX-FileCopyrightText: 2012-2013 Allen Winter <winter@kde.org>
0006 
0007   SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0008 */
0009 
0010 #pragma once
0011 
0012 #include "calendarsupport_export.h"
0013 #include "printplugin.h"
0014 
0015 #include <KCalendarCore/Calendar>
0016 #include <KCalendarCore/Event>
0017 #include <KCalendarCore/Todo>
0018 
0019 #include <QDateTime>
0020 #include <QPainter>
0021 
0022 class PrintCellItem;
0023 class QWidget;
0024 
0025 #define PORTRAIT_HEADER_HEIGHT 80 // header height, for portrait orientation
0026 #define LANDSCAPE_HEADER_HEIGHT 54 // header height, for landscape orientation
0027 #define SUBHEADER_HEIGHT 28 // subheader height, for all orientations
0028 #define PORTRAIT_FOOTER_HEIGHT 16 // footer height, for portrait orientation
0029 #define LANDSCAPE_FOOTER_HEIGHT 14 // footer height, for landscape orientation
0030 #define MARGIN_SIZE 36 // margins, for all orientations
0031 #define PADDING_SIZE 7 // padding between the various top-level boxes
0032 #define BOX_BORDER_WIDTH 2 // width of the border of all top-level boxes
0033 #define EVENT_BORDER_WIDTH 0 // with of the border of all incidence boxes
0034 
0035 #define TIMELINE_WIDTH 50 // width of timeline (day and timetable)
0036 
0037 namespace CalendarSupport
0038 {
0039 /**
0040   Base class for Calendar printing classes. Each sub class represents one
0041   calendar print format.
0042 */
0043 class CalPrintPluginBase : public PrintPlugin
0044 {
0045 public:
0046     enum DisplayFlags { Text = 0x0001, TimeBoxes = 0x0002 };
0047 
0048 public:
0049     /**
0050       Constructor
0051     */
0052     CalPrintPluginBase();
0053     ~CalPrintPluginBase() override;
0054 
0055     /**
0056       Returns widget for configuring the print format.
0057     */
0058     QWidget *createConfigWidget(QWidget *) override;
0059 
0060     /**
0061       Actually do the printing.
0062 
0063       @param p QPainter the print result is painted to
0064       @param width Width of printable area
0065       @param height Height of printable area
0066     */
0067 
0068     virtual void print(QPainter &p, int width, int height) = 0;
0069     /**
0070       Start printing.
0071     */
0072     void doPrint(QPrinter *printer) override;
0073 
0074     void doLoadConfig() override;
0075 
0076     void doSaveConfig() override;
0077 
0078     /** HELPER FUNCTIONS */
0079 public:
0080     bool useColors() const;
0081     void setUseColors(bool useColors);
0082 
0083     bool printFooter() const;
0084     void setPrintFooter(bool printFooter);
0085 
0086     /**
0087       Determines the column of the given weekday ( 1=Monday, 7=Sunday ), taking the
0088       start of the week setting into account as given in kcontrol.
0089       @param weekday Index of the weekday
0090     */
0091     static int weekdayColumn(int weekday);
0092 
0093     QPageLayout::Orientation orientation() const;
0094 
0095     /** Returns the height of the page header. If the height was explicitly
0096         set using setHeaderHeight, that value is returned, otherwise a
0097         default value based on the printer orientation.
0098         @return height of the page header of the printout
0099     */
0100     int headerHeight() const;
0101     void setHeaderHeight(const int height);
0102 
0103     int subHeaderHeight() const;
0104     void setSubHeaderHeight(const int height);
0105     /** Returns the height of the page footer. If the height was explicitly
0106         set using setFooterHeight, that value is returned, otherwise a
0107         default value based on the printer orientation.
0108         @return height of the page footer of the printout
0109     */
0110     int footerHeight() const;
0111     void setFooterHeight(const int height);
0112 
0113     int margin() const;
0114     void setMargin(const int margin);
0115 
0116     int padding() const;
0117     void setPadding(const int margin);
0118 
0119     int borderWidth() const;
0120     void setBorderWidth(const int border);
0121 
0122     /*****************************************************************
0123      **               PRINTING HELPER FUNCTIONS                     **
0124      *****************************************************************/
0125 public:
0126     /**
0127       Draw a box with given width at the given coordinates.
0128       @param p The printer to be used
0129       @param linewidth The border width of the box
0130       @param rect The rectangle of the box
0131     */
0132     static void drawBox(QPainter &p, int linewidth, QRect rect);
0133     /**
0134       Draw a shaded box with given width at the given coordinates.
0135       @param p The printer to be used
0136       @param linewidth The border width of the box
0137       @param brush The brush to fill the box
0138       @param rect The rectangle of the box
0139     */
0140     static void drawShadedBox(QPainter &p, int linewidth, const QBrush &brush, QRect rect);
0141 
0142     /**
0143       Print the given string (event summary) in the given rectangle. Margins
0144       and justification (centered or not) are automatically adjusted.
0145       @param p QPainter of the printout
0146       @param box Coordinates of the surrounding event box
0147       @param str The text to be printed in the box
0148     */
0149     void printEventString(QPainter &p, QRect box, const QString &str, int flags = -1);
0150 
0151     /**
0152       Print the box for the given event with the given string.
0153       @param p QPainter of the printout
0154       @param linewidth is the width of the line used to draw the box, ignored if less than 1.
0155       @param box Coordinates of the event's box
0156       @param incidence The incidence (if available), from which the category
0157                        color will be deduced, if applicable.
0158       @param str The string to print inside the box
0159       @param flags is a bitwise OR of Qt::AlignmentFlags and Qt::TextFlags values.
0160     */
0161     void showEventBox(QPainter &p, int linewidth, QRect box, const KCalendarCore::Incidence::Ptr &incidence, const QString &str, int flags = -1);
0162 
0163     /**
0164       Draw a subheader box with a shaded background and the given string
0165       @param p QPainter of the printout
0166       @param str Text to be printed inside the box
0167       @param box Coordinates of the box
0168     */
0169     void drawSubHeaderBox(QPainter &p, const QString &str, QRect box);
0170 
0171     /**
0172       Draw an event box with vertical text.
0173       @param p QPainter of the printout
0174       @param linewidth is the width of the line used to draw the box, ignored if less than 1.
0175       @param box Coordinates of the box
0176       @param str ext to be printed inside the box
0177       @param flags is a bitwise OR of Qt::AlignmentFlags and Qt::TextFlags values.
0178     */
0179     void drawVerticalBox(QPainter &p, int linewidth, QRect box, const QString &str, int flags = -1);
0180 
0181     /**
0182       Draw a component box with a heading (printed in bold).
0183       @param p QPainter of the printout
0184       @param box Coordinates of the box
0185       @param caption Caption string to be printed inside the box
0186       @param contents Normal text contents of the box. If contents.isNull(),
0187                       then no text will be printed, only the caption.
0188       @param sameLine Whether the contents should start on the same line as
0189                       the caption (the space below the caption text will be
0190                       used as indentation in the subsequent lines) or on the
0191                       next line (no indentation of the contents)
0192       @param expand Whether to expand the box vertically to fit the
0193                     whole text in it.
0194       @param rickContents Whether contents contains rich text.
0195       @return The bottom of the printed box. If expand==true, the bottom of
0196               the drawn box is returned, if expand==false, the vertical
0197               end of the printed contents inside the box is returned.
0198               If you want to print some custom graphics or text below
0199               the contents, use the return value as the top-value of your
0200               custom contents in that case.
0201     */
0202     int drawBoxWithCaption(QPainter &p,
0203                            QRect box,
0204                            const QString &caption,
0205                            const QString &contents,
0206                            bool sameLine,
0207                            bool expand,
0208                            const QFont &captionFont,
0209                            const QFont &textFont,
0210                            bool richContents = false);
0211 
0212     /**
0213       Draw the gray header bar of the printout to the QPainter.
0214       It prints the given text and optionally one or two small
0215       month views, as specified by the two QDate. The printed
0216       text can also contain a line feed.
0217       If month2 is invalid, only the month that contains month1
0218       is printed.
0219       E.g. the filofax week view draws just the current month,
0220       while the month view draws the previous and the next month.
0221       @param p QPainter of the printout
0222       @param title The string printed as the title of the page
0223                    (e.g. the date, date range or todo list title)
0224       @param month1 Date specifying the month for the left one of
0225                     the small month views in the title bar. If left
0226                     empty, only month2 will be printed (or none,
0227                     it that is invalid as well).
0228       @param month2 Date specifying the month for the right one of
0229                     the small month views in the title bar. If left
0230                     empty, only month1 will be printed (or none,
0231                     it that is invalid as well).
0232       @param box coordinates of the title bar
0233       @param expand Whether to expand the box vertically to fit the
0234                     whole title in it.
0235       @param backColor background color for the header box.
0236       @return The bottom of the printed box. If expand==false, this
0237               is box.bottom, otherwise it is larger than box.bottom
0238               and matches the y-coordinate of the surrounding rectangle.
0239     */
0240     int drawHeader(QPainter &p, const QString &title, QDate month1, QDate month2, QRect box, bool expand = false, QColor backColor = QColor());
0241 
0242     /**
0243       Draw a page footer containing the printing date and possibly
0244       other things, like a page number.
0245       @param p QPainter of the printout
0246       @param box coordinates of the footer
0247       @return The bottom of the printed box.
0248     */
0249     int drawFooter(QPainter &p, QRect box);
0250 
0251     /**
0252       Draw a small calendar with the days of a month into the given area.
0253       Used for example in the title bar of the sheet.
0254       @param p QPainter of the printout
0255       @param qd Arbitrary Date within the month to be printed.
0256       @param box coordinates of the small calendar
0257     */
0258     void drawSmallMonth(QPainter &p, QDate qd, QRect box);
0259 
0260     /**
0261       Draw a horizontal bar with the weekday names of the given date range
0262       in the given area of the painter.
0263       This is used for the weekday-bar on top of the timetable view and the month view.
0264       @param p QPainter of the printout
0265       @param fromDate First date of the printed dates
0266       @param toDate Last date of the printed dates
0267       @param box coordinates of the box for the days of the week
0268     */
0269     void drawDaysOfWeek(QPainter &p, QDate fromDate, QDate toDate, QRect box);
0270 
0271     /**
0272       Draw a single weekday name in a box inside the given area of the painter.
0273       This is called in a loop by drawDaysOfWeek.
0274       @param p QPainter of the printout
0275       @param qd Date of the printed day
0276       @param box coordinates of the weekbox
0277     */
0278     void drawDaysOfWeekBox(QPainter &p, QDate qd, QRect box);
0279 
0280     /**
0281       Draw a (vertical) time scale from time fromTime to toTime inside the
0282       given area of the painter. Every hour will have a one-pixel line over
0283       the whole width, every half-hour the line will only span the left half
0284       of the width. This is used in the day and timetable print styles
0285       @param p QPainter of the printout
0286       @param fromTime Start time of the time range to display
0287       @param toTime End time of the time range to display
0288       @param box coordinates of the timeline
0289     */
0290     void drawTimeLine(QPainter &p, QTime fromTime, QTime toTime, QRect box);
0291 
0292     /**
0293       Draw the agenda box for the day print style (the box showing all events of that day).
0294       Also draws a grid with half-hour spacing of the grid lines.
0295       Does NOT draw allday events.  Use drawAllDayBox for allday events.
0296 
0297       Obeys configuration options #mExcludeConfidential, #excludePrivate.
0298       @param p QPainter of the printout
0299       @param eventList The list of the events that are supposed to be printed
0300              inside this box
0301       @param qd The date of the currently printed day
0302       @param expandable If true, the start and end times are adjusted to include
0303              the whole range of all events of that day, not just of the given time range.
0304              The height of the box will not be affected by this (but the height
0305              of one hour will be scaled down so that the whole range fits into
0306              the box. fromTime and toTime receive the actual time range printed
0307              by this function).
0308       @param fromTime Start of the time range to be printed. Might be adjusted
0309                       to include all events if expandable==true
0310       @param toTime End of the time range to be printed. Might be adjusted
0311                    to include all events if expandable==true
0312       @param box coordinates of the agenda day box.
0313       @param includeDescription Whether to print the event description as well.
0314       @param includeCategories Whether to print the event categories (tags) as well.
0315       @param excludeTime Whether the time is printed in the detail area.
0316       @param workDays List of workDays
0317     */
0318     void drawAgendaDayBox(QPainter &p,
0319                           const KCalendarCore::Event::List &eventList,
0320                           QDate qd,
0321                           bool expandable,
0322                           QTime fromTime,
0323                           QTime toTime,
0324                           QRect box,
0325                           bool includeDescription,
0326                           bool includeCategories,
0327                           bool excludeTime,
0328                           const QList<QDate> &workDays);
0329 
0330     void drawAgendaItem(PrintCellItem *item,
0331                         QPainter &p,
0332                         const QDateTime &startPrintDate,
0333                         const QDateTime &endPrintDate,
0334                         float minlen,
0335                         QRect box,
0336                         bool includeDescription,
0337                         bool includeCategories,
0338                         bool excludeTime);
0339 
0340     /**
0341       Draw the box containing a list of all events of the given day (with their times,
0342       of course). Used in the Filofax and the month print style.
0343 
0344       Obeys configuration options #mExcludeConfidential, #mExcludePrivate, #mShowNoteLines, #mUseColors.
0345       @param p QPainter of the printout
0346       @param qd The date of the currently printed day. All events of the calendar
0347                 that appear on that day will be printed.
0348       @param fromTime Start time of the time range to display
0349       @param toTime End time of the time range to display
0350       @param box coordinates of the day box.
0351       @param fullDate Whether the title bar of the box should contain the full
0352                       date string or just a short.
0353       @param printRecurDaily Whether daily recurring incidences should be printed.
0354       @param printRecurWeekly Whether weekly recurring incidences should be printed.
0355       @param singleLineLimit Whether Incidence text wraps or truncates.
0356       @param includeDescription Whether to print the event description as well.
0357       @param includeCategories Whether to print the event categories (tags) as well.
0358     */
0359     void drawDayBox(QPainter &p,
0360                     QDate qd,
0361                     QTime fromTime,
0362                     QTime toTime,
0363                     QRect box,
0364                     bool fullDate = false,
0365                     bool printRecurDaily = true,
0366                     bool printRecurWeekly = true,
0367                     bool singleLineLimit = true,
0368                     bool includeDescription = false,
0369                     bool includeCategories = false);
0370 
0371     /**
0372       Draw the month table of the month containing the date qd. Each day gets one
0373       box (using drawDayBox) that contains a list of all events on that day. They are arranged
0374       in a matrix, with the first column being the first day of the
0375       week (so it might display some days of the previous and the next month).
0376       Above the matrix there is a bar showing the weekdays (drawn using drawDaysOfWeek).
0377 
0378       Obeys configuration options #mExcludeConfidential, #mExcludePrivate, #mShowNoteLines, #mUseColors.
0379       @param p QPainter of the printout
0380       @param qd Arbitrary date within the month to be printed.
0381       @param fromTime Start time of the displayed time range
0382       @param toTime End time of the displayed time range
0383       @param weeknumbers Whether the week numbers are printed left of each row of the matrix
0384       @param recurDaily Whether daily recurring incidences should be printed.
0385       @param recurWeekly Whether weekly recurring incidences should be printed.
0386       @param singleLineLimit Whether Incidence text wraps or truncates.
0387       @param includeDescription Whether descriptions are printed.
0388       @param includeCategories Whether to print the event categories (tags) as well.
0389       @param box coordinates of the month.
0390     */
0391     void drawMonthTable(QPainter &p,
0392                         QDate qd,
0393                         QTime fromTime,
0394                         QTime toTime,
0395                         bool weeknumbers,
0396                         bool recurDaily,
0397                         bool recurWeekly,
0398                         bool singleLineLimit,
0399                         bool includeDescription,
0400                         bool includeCategories,
0401                         QRect box);
0402 
0403     /**
0404       Draw a vertical representation of the month containing the date dt. Each
0405       day gets one line.
0406 
0407       Obeys configuration options #mExcludeConfidential, #excludePrivate.
0408       @param p QPainter of the printout
0409       @param dt Arbitrary date within the month to be printed
0410       @param box coordinates of the box reserved for the month
0411       @param maxdays Days to print. If a value of -1 is given, the number of days
0412                      is deduced from the month. If maxdays is larger than the
0413                      number of days in the month, the remaining boxes are
0414                      shaded to indicate they are not days of the month.
0415       @param subDailyFlags Bitfield consisting of DisplayFlags flags to determine
0416                            how events that do not cross midnight should be printed.
0417       @param holidaysFlags Bitfield consisting of DisplayFlags flags to determine
0418                            how holidays should be printed.
0419     */
0420     void drawMonth(QPainter &p, QDate dt, QRect box, int maxdays = -1, int subDailyFlags = TimeBoxes, int holidaysFlags = Text);
0421 
0422     /**
0423       Internal class representing the start of a todo.
0424     */
0425     class TodoParentStart;
0426 
0427     /**
0428       Draws single to-do and its (indented) sub-to-dos, optionally connects them
0429       by a tree-like line, and optionally shows due date, summary, description
0430       and priority.
0431       @param count The number of the currently printed to-do (count will be
0432       incremented for each to-do drawn)
0433       @param todo The to-do to be printed. It's sub-to-dos are recursively drawn,
0434       so drawTodo should only be called on the to-dos of the highest level.
0435       @param p QPainter of the printout
0436       @param sortField Specifies on which attribute of the todo you want to sort.
0437       @param sortDir Specifies if you want to sort ascending or descending.
0438       @param connectSubTodos Whether sub-to-dos shall be connected with
0439       their parent by a line (tree-like).
0440       @param strikeoutCompleted Whether completed to-dos should be printed with
0441       strike-out summaries.
0442       @param desc Whether to print the whole description of the to-do
0443       (the summary is always printed).
0444       @param posPriority x-coordinate where the priority is supposed to be
0445       printed. If negative, no priority will be printed.
0446       @param posSummary x-coordinate where the summary of the to-do is supposed
0447       to be printed.
0448       @param posCategories x-coordinate where the categories (tags) should be
0449       printed. If negative, no categories will be printed.
0450       @param posStartDt x-coordinate where the due date is supposed to the be
0451       printed. If negative, no start date will be printed.
0452       @param posDueDt x-coordinate where the due date is supposed to the be
0453       printed. If negative, no due date will be printed.
0454       @param posPercentComplete x-coordinate where the percentage complete is
0455       supposed to be printed. If negative, percentage complete will not be printed.
0456       @param level Level of the current to-do in the to-do hierarchy (0 means
0457       highest level of printed to-dos, 1 are their sub-to-dos, etc.)
0458       @param x x-coordinate of the upper left coordinate of the first to-do.
0459       @param y y-coordinate of the upper left coordinate of the first to-do.
0460       @param width width of the whole to-do list.
0461       @param pageHeight Total height allowed for the to-do list on a page.
0462       If an to-do would be below that line, a new page is started.
0463       @param todoList Contains a list of sub-todos for the specified @p todo .
0464       @param r Internal (used when printing sub-to-dos to give information
0465       about its parent)
0466     */
0467     void drawTodo(int &count,
0468                   const KCalendarCore::Todo::Ptr &todo,
0469                   QPainter &p,
0470                   KCalendarCore::TodoSortField sortField,
0471                   KCalendarCore::SortDirection sortDir,
0472                   bool connectSubTodos,
0473                   bool strikeoutCompleted,
0474                   bool desc,
0475                   int posPriority,
0476                   int posSummary,
0477                   int posCategories,
0478                   int posStartDt,
0479                   int posDueDt,
0480                   int posPercentComplete,
0481                   int level,
0482                   int x,
0483                   int &y,
0484                   int width,
0485                   int pageHeight,
0486                   const KCalendarCore::Todo::List &todoList,
0487                   TodoParentStart *r);
0488 
0489     /**
0490       Draws text lines splitting on page boundaries.
0491       @param p QPainter of the printout
0492       @param x x-coordinate of the upper left coordinate of the first item
0493       @param y y-coordinate of the upper left coordinate of the first item
0494       @param width width of the whole list
0495       @param pageHeight size of the page. A new page is started when the
0496              text reaches the end of the page.
0497     */
0498     void drawTextLines(QPainter &p, const QString &entry, int x, int &y, int width, int pageHeight, bool richTextEntry);
0499 
0500     void drawSplitHeaderRight(QPainter &p, QDate fd, QDate td, QDate cd, int width, int height);
0501 
0502     /**
0503       Draws dotted lines for notes in a box.
0504       @param p QPainter of the printout
0505       @param box coordinates of the box where the lines will be placed
0506       @param startY starting y-coordinate for the first line
0507     */
0508     void drawNoteLines(QPainter &p, QRect box, int startY);
0509 
0510 protected:
0511     QTime dayStart() const;
0512     QColor categoryBgColor(const KCalendarCore::Incidence::Ptr &incidence) const;
0513 
0514     void drawIncidence(QPainter &p,
0515                        QRect dayBox,
0516                        const QString &time,
0517                        const QString &summary,
0518                        const QString &description,
0519                        int &textY,
0520                        bool singleLineLimit,
0521                        bool includeDescription,
0522                        bool richDescription);
0523 
0524     QString toPlainText(const QString &htmlText);
0525 
0526     void drawTodoLines(QPainter &p,
0527                        const QString &entry,
0528                        int x,
0529                        int &y,
0530                        int width,
0531                        int pageHeight,
0532                        bool richTextEntry,
0533                        QList<TodoParentStart *> &startPoints,
0534                        bool connectSubTodos);
0535 
0536     KCalendarCore::Event::Ptr holidayEvent(QDate date) const;
0537 
0538 protected:
0539     bool mUseColors; /**< Whether or not to use event category colors to draw the events. */
0540     bool mPrintFooter; /**< Whether or not to print a footer at the bottoms of pages. */
0541     bool mShowNoteLines; /**< Whether or not to print horizontal  lines in note areas. */
0542     bool mExcludeConfidential; /**< Whether or not to print incidences with secrecy "confidential". */
0543     bool mExcludePrivate; /**< Whether or not to print incidences with secrecy "private". */
0544     int mHeaderHeight;
0545     int mSubHeaderHeight;
0546     int mFooterHeight;
0547     int mMargin;
0548     int mPadding;
0549     int mBorder;
0550 
0551     static const QColor sHolidayBackground;
0552 
0553 private:
0554     QColor categoryColor(const QStringList &categories) const;
0555 
0556     /**
0557      * Sets the QPainter's brush and pen color according to the Incidence's category.
0558      */
0559     void setColorsByIncidenceCategory(QPainter &p, const KCalendarCore::Incidence::Ptr &incidence) const;
0560 
0561     QString holidayString(QDate date) const;
0562 
0563     /**
0564      * Returns a nice QColor for text, give the input color &c.
0565      */
0566     QColor getTextColor(const QColor &c) const;
0567 };
0568 }