File indexing completed on 2024-05-12 17:08:52

0001 /*
0002     SPDX-FileCopyrightText: 2013 Mark Gaiser <markg85@gmail.com>
0003     SPDX-FileCopyrightText: 2016 Martin Klapetek <mklapetek@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #pragma once
0009 
0010 #include <QDate>
0011 #include <QJsonArray>
0012 #include <QObject>
0013 
0014 #include "daydata.h"
0015 #include "daysmodel.h"
0016 
0017 class QAbstractItemModel;
0018 class CalendarPrivate;
0019 
0020 class Calendar : public QObject
0021 {
0022     Q_OBJECT
0023     /* The conversion between QDate and JS Date is broken. The specification says that a date
0024      * is represented by the start of the UTC day, but for negative to UTC timezones this results
0025      * in wrong dates: Jan 2 in C++ -> Jan 2 (00:00) UTC -> Jan 1 (23:00) UTC-1 in JS.
0026      * So use QDateTime for interfacing to always carry a timezone around.
0027      * https://bugreports.qt.io/browse/QTBUG-29328 */
0028 
0029     /**
0030      * This property is used to determine which data from which month to show, it ensures
0031      * the day passed in the QDate is visible
0032      */
0033     Q_PROPERTY(QDateTime displayedDate READ displayedDate WRITE setDisplayedDate NOTIFY displayedDateChanged)
0034 
0035     /**
0036      * This property is used to determine which data from which month to show, it ensures
0037      * the day passed in the QDate is visible
0038      */
0039     Q_PROPERTY(QDateTime today READ today WRITE setToday NOTIFY todayChanged)
0040 
0041     /**
0042      * This determines which kind of data types should be contained in
0043      * selectedDayModel and upcomingEventsModel. By default all types are included.
0044      * NOTE: Only the Event type is fully implemented.
0045      * TODO: Fully implement the other data types throughout this code.
0046      */
0047     Q_PROPERTY(int types READ types WRITE setTypes NOTIFY typesChanged)
0048 
0049     /**
0050      * This model contains the week numbers for the given date grid.
0051      */
0052     Q_PROPERTY(QJsonArray weeksModel READ weeksModel NOTIFY weeksModelChanged)
0053 
0054     /**
0055      * The number of days a week contains.
0056      * TODO: perhaps this one can just be removed. A week is 7 days by definition.
0057      * However, i don't know if that's also the case in other more exotic calendars.
0058      */
0059     Q_PROPERTY(int days READ days WRITE setDays NOTIFY daysChanged)
0060 
0061     /**
0062      * The number of weeks that the model property should contain.
0063      */
0064     Q_PROPERTY(int weeks READ weeks WRITE setWeeks NOTIFY weeksChanged)
0065 
0066     /**
0067      * The start day of a week. By default this follows current Locale. It can be
0068      * changed. One then needs to use the numbers in the Qt DayOfWeek enum:
0069      *
0070      *    Monday = 1
0071      *    Tuesday = 2
0072      *    Wednesday = 3
0073      *    Thursday = 4
0074      *    Friday = 5
0075      *    Saturday = 6
0076      *    Sunday = 7
0077      *
0078      * This value doesn't do anything to other data structures, but helps you
0079      * visualizing the data.
0080      *
0081      * WARNING: QML has different enum values for week days - Sunday is 0, this function
0082      *          automatically converts that on READ and WRITE and it's stored as QDate format
0083      *          (ie. the one above). So firstDayOfWeek() call from QML would return 0 for Sunday
0084      *          while internally it's 7 and vice-versa.
0085      */
0086     Q_PROPERTY(int firstDayOfWeek READ firstDayOfWeek WRITE setFirstDayOfWeek NOTIFY firstDayOfWeekChanged)
0087 
0088     /**
0089      * The full year in a numeric value. For example 2013, not 13.
0090      */
0091     Q_PROPERTY(int year READ year NOTIFY yearChanged)
0092 
0093     /**
0094      * If an error occurred, it will be set in this string as human readable text.
0095      */
0096     Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
0097 
0098     /**
0099      * This is the human readable long month name. So not "Feb" but "February".
0100      * TODO: this should either be done in QML using javascript or by making a
0101      *       function available because this is limiting. There are places
0102      *       where you would want the short month name.
0103      */
0104     Q_PROPERTY(QString monthName READ monthName NOTIFY monthNameChanged)
0105     Q_PROPERTY(int month READ month NOTIFY monthChanged)
0106 
0107     /**
0108      * This model contains the actual grid data of days. For example, if you had set:
0109      * - days = 7 (7 days in one week)
0110      * - weeks = 6 (6 weeks in one month view)
0111      * then this model will contain 42 entries (days * weeks). Each entry contains
0112      * metadata about the current day. The exact metadata can be found in "daysmodel.cpp"
0113      * where the exact names usable in QML are being set.
0114      */
0115     Q_PROPERTY(QAbstractItemModel *daysModel READ daysModel CONSTANT)
0116 
0117 public:
0118     enum Type {
0119         Holiday = 1,
0120         Event = 2,
0121         Todo = 4,
0122         Journal = 8,
0123     };
0124     Q_ENUM(Type)
0125     Q_DECLARE_FLAGS(Types, Type)
0126 
0127     enum DateMatchingPrecision {
0128         MatchYear,
0129         MatchYearAndMonth,
0130         MatchYearMonthAndDay,
0131     };
0132     Q_ENUM(DateMatchingPrecision)
0133 
0134     explicit Calendar(QObject *parent = nullptr);
0135     ~Calendar() override;
0136 
0137     // Displayed date
0138     QDateTime displayedDate() const;
0139     void setDisplayedDate(const QDate &dateTime);
0140     void setDisplayedDate(const QDateTime &dateTime);
0141 
0142     // The day that represents "today"
0143     QDateTime today() const;
0144     void setToday(const QDateTime &dateTime);
0145 
0146     // Types
0147     int types() const;
0148     void setTypes(int types);
0149 
0150     // Days
0151     int days();
0152     void setDays(int days);
0153 
0154     // Weeks
0155     int weeks() const;
0156     void setWeeks(int weeks);
0157 
0158     // Start day
0159     int firstDayOfWeek() const;
0160     void setFirstDayOfWeek(int day);
0161 
0162     // Error message
0163     QString errorMessage() const;
0164 
0165     // Month name
0166     QString monthName() const;
0167     int month() const;
0168     int year() const;
0169 
0170     // Models
0171     QAbstractItemModel *daysModel() const;
0172     QJsonArray weeksModel() const;
0173 
0174     // QML invokables
0175     Q_INVOKABLE void nextMonth();
0176     Q_INVOKABLE void previousMonth();
0177     Q_INVOKABLE void nextYear();
0178     Q_INVOKABLE void previousYear();
0179     Q_INVOKABLE void nextDecade();
0180     Q_INVOKABLE void previousDecade();
0181     Q_INVOKABLE QString dayName(int weekday) const;
0182     Q_INVOKABLE int currentWeek() const;
0183     Q_INVOKABLE void resetToToday();
0184     Q_INVOKABLE void goToMonth(int month);
0185     Q_INVOKABLE void goToYear(int year);
0186 
0187 Q_SIGNALS:
0188     void displayedDateChanged();
0189     void todayChanged();
0190     void typesChanged();
0191     void daysChanged();
0192     void weeksChanged();
0193     void firstDayOfWeekChanged();
0194     void errorMessageChanged();
0195     void monthNameChanged();
0196     void monthChanged();
0197     void yearChanged();
0198     void weeksModelChanged();
0199 
0200 public Q_SLOTS:
0201     void updateData();
0202 
0203 private:
0204     CalendarPrivate *const d;
0205 };