File indexing completed on 2025-03-09 04:53:44

0001 // Copyright (c) 2018 Michael Bohlender <michael.bohlender@kdemail.net>
0002 // Copyright (c) 2018 Christian Mollekopf <mollekopf@kolabsys.com>
0003 // Copyright (c) 2018 RĂ©mi Nicole <minijackson@riseup.net>
0004 // Copyright (c) 2021 Carl Schwan <carlschwan@kde.org>
0005 // Copyright (c) 2021 Claudio Cambra <claudio.cambra@gmail.com>
0006 // SPDX-License-Identifier: LGPL-2.0-or-later
0007 
0008 #pragma once
0009 
0010 #include <Akonadi/ETMCalendar>
0011 #include <QObject>
0012 
0013 #include <KConfigWatcher>
0014 #include <KFormat>
0015 #include <QAbstractItemModel>
0016 #include <QColor>
0017 #include <QDateTime>
0018 #include <QList>
0019 #include <QSharedPointer>
0020 #include <QTimer>
0021 
0022 class Filter;
0023 namespace KCalendarCore
0024 {
0025 class Incidence;
0026 }
0027 namespace Akonadi
0028 {
0029 class ETMCalendar;
0030 }
0031 
0032 using namespace KCalendarCore;
0033 
0034 /**
0035  * Loads all event occurrences within the given period and matching the given filter.
0036  *
0037  * Recurrences are expanded
0038  */
0039 class IncidenceOccurrenceModel : public QAbstractListModel
0040 {
0041     Q_OBJECT
0042     Q_PROPERTY(QDate start READ start WRITE setStart NOTIFY startChanged)
0043     Q_PROPERTY(int length READ length WRITE setLength NOTIFY lengthChanged)
0044     Q_PROPERTY(Filter *filter READ filter WRITE setFilter NOTIFY filterChanged)
0045     Q_PROPERTY(Akonadi::ETMCalendar::Ptr calendar READ calendar WRITE setCalendar NOTIFY calendarChanged)
0046     Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
0047     Q_PROPERTY(int resetThrottleInterval READ resetThrottleInterval WRITE setResetThrottleInterval NOTIFY resetThrottleIntervalChanged)
0048 
0049 public:
0050     enum Roles {
0051         Summary = Qt::UserRole + 1,
0052         Description,
0053         Location,
0054         StartTime,
0055         EndTime,
0056         Duration,
0057         DurationString,
0058         Recurs,
0059         HasReminders,
0060         Priority,
0061         Color,
0062         CollectionId,
0063         AllDay,
0064         TodoCompleted,
0065         IsOverdue,
0066         IsReadOnly,
0067         IncidenceId,
0068         IncidenceType,
0069         IncidenceTypeStr,
0070         IncidenceTypeIcon,
0071         IncidencePtr,
0072         IncidenceOccurrence,
0073         LastRole
0074     };
0075     Q_ENUM(Roles)
0076     explicit IncidenceOccurrenceModel(QObject *parent = nullptr);
0077     ~IncidenceOccurrenceModel() override = default;
0078 
0079     int rowCount(const QModelIndex &parent = {}) const override;
0080     QVariant data(const QModelIndex &index, int role) const override;
0081 
0082     Akonadi::ETMCalendar::Ptr calendar() const;
0083     QDate start() const;
0084     int length() const;
0085     Filter *filter() const;
0086     bool loading() const;
0087     int resetThrottleInterval() const;
0088 
0089     struct Occurrence {
0090         QDateTime start;
0091         QDateTime end;
0092         KCalendarCore::Incidence::Ptr incidence;
0093         QColor color;
0094         qint64 collectionId;
0095         bool allDay;
0096     };
0097 
0098 Q_SIGNALS:
0099     void startChanged();
0100     void lengthChanged();
0101     void filterChanged();
0102     void calendarChanged();
0103     void loadingChanged();
0104     void resetThrottleIntervalChanged();
0105 
0106 public Q_SLOTS:
0107     void setStart(const QDate &start);
0108     void setLength(int length);
0109     void setFilter(Filter *filter);
0110     void setCalendar(Akonadi::ETMCalendar::Ptr calendar);
0111     void setResetThrottleInterval(const int resetThrottleInterval);
0112 
0113 private Q_SLOTS:
0114     void loadColors();
0115     void scheduleReset();
0116     void resetFromSource();
0117     void setLoading(const bool loading);
0118 
0119 private:
0120     static std::pair<QDateTime, QDateTime> incidenceOccurrenceStartEnd(const QDateTime &ocStart, const KCalendarCore::Incidence::Ptr &incidence);
0121     bool incidencePassesFilter(const KCalendarCore::Incidence::Ptr &incidence);
0122 
0123     QColor getColor(const KCalendarCore::Incidence::Ptr &incidence);
0124     qint64 getCollectionId(const KCalendarCore::Incidence::Ptr &incidence);
0125 
0126     QSharedPointer<QAbstractItemModel> mSourceModel;
0127     QDate mStart;
0128     QDate mEnd;
0129     int mLength{0};
0130     Akonadi::ETMCalendar::Ptr m_coreCalendar;
0131 
0132     QTimer m_resetThrottlingTimer;
0133     int m_resetThrottleInterval = 100;
0134 
0135     bool m_loading = false;
0136     QList<Occurrence> m_incidences; // We need incidences to be in a preditable order for the model
0137     QHash<Akonadi::Collection::Id, QColor> m_colors;
0138     KConfigWatcher::Ptr m_colorWatcher;
0139     Filter *mFilter = nullptr;
0140     KFormat m_format;
0141 };
0142 
0143 Q_DECLARE_METATYPE(IncidenceOccurrenceModel::Occurrence)