// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
    \example richtext/calendar
    \title Calendar Example
    \ingroup examples-richtext
    \brief The Calendar example shows how to create rich text content
    and display it using a rich text editor.

    \brief The Calendar example shows how to create rich text content and display it using
    a rich text editor.

    \image calendar-example.png

    Specifically, the example demonstrates the following:

    \list
      \li Use of a text editor with a text document
      \li Insertion of tables and frames into a document
      \li Navigation within a table
      \li Insert text in different styles
    \endlist

    The rich text editor used to display the document is used within a main window
    application.

    \section1 MainWindow Class Definition

    The \c MainWindow class provides a text editor widget and some controls to
    allow the user to change the month and year shown. The font size used for the
    text can also be adjusted.

    \snippet richtext/calendar/mainwindow.h 0

    The private \c insertCalendar() function performs most of the work, relying on
    the \c fontSize and \c selectedDate variables to write useful information to
    the \c editor.

    \section1 MainWindow Class Implementation

    The \c MainWindow constructor sets up the user interface and initializes
    variables used to generate a calendar for each month.

    \snippet richtext/calendar/mainwindow.cpp 0

    We begin by setting default values for the selected date that will be highlighted
    in the calendar and the font size to be used. Since we are using a QMainWindow
    for the user interface, we construct a widget for use as the central widget.

    The user interface will include a line of controls above the generated calendar;
    we construct a label and a combobox to allow the month to be selected, and a
    spin box for the year. These widgets are configured to provide a reasonable range
    of values for the user to try:

    \snippet richtext/calendar/mainwindow.cpp 1

    We use the \c selectedDate object to obtain the current month and year, and we
    set these in the combobox and spin box:

    The font size is displayed in a spin box which we restrict to a sensible range
    of values:

    \snippet richtext/calendar/mainwindow.cpp 2

    We construct an editor and use the \c insertCalendar() function to create
    a calendar for it. Each calendar is displayed in the same text editor; in
    this example we use a QTextBrowser since we do not allow the calendar to be
    edited.

    The controls used to set the month, year, and font size will not have any
    effect on the appearance of the calendar unless we make some signal-slot
    connections:

    \snippet richtext/calendar/mainwindow.cpp 3

    The signals are connected to some simple slots in the \c MainWindow class
    which we will describe later.

    We create layouts to manage the widgets we constructed:

    \snippet richtext/calendar/mainwindow.cpp 4

    Finally, the central widget is set for the window.

    Each calendar is created for the editor by the \c insertCalendar() function
    which uses the date and font size, defined by the private \a selectedDate
    and \c fontSize variables, to produce a suitable plan for the specified
    month and year.

    \snippet richtext/calendar/mainwindow.cpp 5

    We begin by clearing the editor's rich text document, and obtain a text
    cursor from the editor that we will use to add content. We also create a
    QDate object based on the currently selected date.

    The calendar is made up of a table with a gray background color that contains
    seven columns: one for each day of the week. It is placed in the center of the
    page with equal space to the left and right of it. All of these properties are
    set in a QTextTableFormat object:

    \snippet richtext/calendar/mainwindow.cpp 6

    Each cell in the table will be padded and spaced to make the text easier to
    read.

    We want the columns to have equal widths, so we provide a list containing
    percentage widths for each of them and set the constraints in the
    QTextTableFormat:

    \snippet richtext/calendar/mainwindow.cpp 7

    The constraints used for the column widths are only useful if the table has
    an appropriate number of columns. With the format for the table defined, we
    construct a new table with one row and seven columns at the current cursor
    position:

    \snippet richtext/calendar/mainwindow.cpp 8

    We only need one row to start with; more can be added as we need them. Using
    this approach means that we do not need to perform any date calculations
    until we add cells to the table.

    When inserting objects into a document with the cursor's insertion functions,
    the cursor is automatically moved inside the newly inserted object. This means
    that we can immediately start modifying the table from within:

    \snippet richtext/calendar/mainwindow.cpp 9

    Since the table has an outer frame, we obtain the frame and its format so that
    we can customize it. After making the changes we want, we set the frame's format
    using the modified format object. We have given the table an outer border one
    pixel wide.

    \snippet richtext/calendar/mainwindow.cpp 10

    In a similar way, we obtain the cursor's current character format and
    create customized formats based on it.

    We do not set the format on the cursor because this would change the default
    character format; instead, we use the customized formats explicitly when we
    insert text. The following loop inserts the days of the week into the table
    as bold text:

    \snippet richtext/calendar/mainwindow.cpp 11

    For each day of the week, we obtain an existing table cell in the first row
    (row 0) using the table's \l{QTextTable::cellAt()}{cellAt()} function. Since
    we start counting the days of the week at day 1 (Monday), we subtract 1 from
    \c weekDay to ensure that we obtain the cell for the correct column of the
    table.

    Before text can be inserted into a cell, we must obtain a cursor with the
    correct position in the document. The cell provides a function for this
    purpose, and we use this cursor to insert text using the \c boldFormat
    character format that we created earlier:

    \snippet richtext/calendar/mainwindow.cpp 12

    Inserting text into document objects usually follows the same pattern.
    Each object can provide a new cursor that corresponds to the first valid
    position within itself, and this can be used to insert new content. We
    continue to use this pattern as we insert the days of the month into the
    table.

    Since every month has more than seven days, we insert a single row to begin
    and add days until we reach the end of the month. If the current date is
    encountered, it is inserted with a special format (created earlier) that
    makes it stand out:

    \snippet richtext/calendar/mainwindow.cpp 13

    We add a new row to the table at the end of each week only if the next week
    falls within the currently selected month.

    For each calendar that we create, we change the window title to reflect the
    currently selected month and year:

    \snippet richtext/calendar/mainwindow.cpp 14

    The \c insertCalendar() function relies on up-to-date values for the month,
    year, and font size. These are set in the following slots:

    \snippet richtext/calendar/mainwindow.cpp 15

    The \c setFontSize() function simply changes the private \c fontSize variable
    before updating the calendar.

    \snippet richtext/calendar/mainwindow.cpp 16

    The \c setMonth slot is called when the QComboBox used to select the month is
    updated. The value supplied is the currently selected row in the combobox.
    We add 1 to this value to obtain a valid month number, and create a new QDate
    based on the existing one. The calendar is then updated to use this new date.

    \snippet richtext/calendar/mainwindow.cpp 17

    The \c setYear() slot is called when the QDateTimeEdit used to select the
    year is updated. The value supplied is a QDate object; this makes
    the construction of a new value for \c selectedDate simple. We update the
    calendar afterwards to use this new date.
*/
