File indexing completed on 2024-06-23 04:42:37
0001 // SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com> 0002 // SPDX-License-Identifier: LGPL-2.1-or-later 0003 0004 #pragma once 0005 0006 #include <Akonadi/CalendarUtils> 0007 #include <Akonadi/ETMCalendar> 0008 #include <Akonadi/IncidenceTreeModel> 0009 #include <Akonadi/TodoModel> 0010 #include <KConfigWatcher> 0011 #include <KFormat> 0012 #include <KSharedConfig> 0013 #include <QObject> 0014 #include <QSortFilterProxyModel> 0015 #include <QTimer> 0016 0017 class Filter; 0018 0019 class TodoSortFilterProxyModel : public QSortFilterProxyModel 0020 { 0021 Q_OBJECT 0022 Q_PROPERTY(Akonadi::IncidenceChanger *incidenceChanger READ incidenceChanger WRITE setIncidenceChanger NOTIFY incidenceChangerChanged) 0023 Q_PROPERTY(Akonadi::ETMCalendar::Ptr calendar READ calendar WRITE setCalendar NOTIFY calendarChanged) 0024 Q_PROPERTY(Filter *filterObject READ filterObject WRITE setFilterObject NOTIFY filterObjectChanged) 0025 Q_PROPERTY(int showCompleted READ showCompleted WRITE setShowCompleted NOTIFY showCompletedChanged) 0026 Q_PROPERTY(int sortBy READ sortBy WRITE setSortBy NOTIFY sortByChanged) 0027 Q_PROPERTY(bool sortAscending READ sortAscending WRITE setSortAscending NOTIFY sortAscendingChanged) 0028 Q_PROPERTY(bool showCompletedSubtodosInIncomplete READ showCompletedSubtodosInIncomplete WRITE setShowCompletedSubtodosInIncomplete NOTIFY 0029 showCompletedSubtodosInIncompleteChanged) 0030 0031 public: 0032 enum Roles { 0033 StartTimeRole = Akonadi::TodoModel::CalendarRole + 1, 0034 EndTimeRole, 0035 DisplayDueDateRole, 0036 LocationRole, 0037 AllDayRole, 0038 CompletedRole, 0039 PriorityRole, 0040 ColorRole, 0041 CollectionIdRole, 0042 DurationStringRole, 0043 RecursRole, 0044 IsOverdueRole, 0045 IncidenceIdRole, 0046 IncidenceTypeRole, 0047 IncidenceTypeStrRole, 0048 IncidenceTypeIconRole, 0049 IncidencePtrRole, 0050 TagsRole, 0051 ItemRole, 0052 CategoriesRole, 0053 CategoriesDisplayRole, 0054 TreeDepthRole, 0055 TopMostParentSummaryRole, // These three here are used to help us conserve the proper sections 0056 TopMostParentDueDateRole, // in the Kirigami TreeListView, which otherwise will create new 0057 TopMostParentPriorityRole, // sections for subtasks 0058 }; 0059 Q_ENUM(Roles) 0060 0061 enum BaseTodoModelColumns { 0062 SummaryColumn = Akonadi::TodoModel::SummaryColumn, 0063 PriorityColumn = Akonadi::TodoModel::PriorityColumn, 0064 PercentColumn = Akonadi::TodoModel::PercentColumn, 0065 StartDateColumn = Akonadi::TodoModel::StartDateColumn, 0066 DueDateColumn = Akonadi::TodoModel::DueDateColumn, 0067 CategoriesColumn = Akonadi::TodoModel::CategoriesColumn, 0068 DescriptionColumn = Akonadi::TodoModel::DescriptionColumn, 0069 CalendarColumn = Akonadi::TodoModel::CalendarColumn, 0070 }; 0071 Q_ENUM(BaseTodoModelColumns) 0072 0073 enum ShowComplete { 0074 ShowAll = 0, 0075 ShowCompleteOnly, 0076 ShowIncompleteOnly, 0077 }; 0078 Q_ENUM(ShowComplete) 0079 0080 enum DueDateDisplayFormat { 0081 DisplayDateOnly, 0082 DisplayDateTimeAndIfOverdue, 0083 }; 0084 Q_ENUM(DueDateDisplayFormat) 0085 0086 explicit TodoSortFilterProxyModel(QObject *parent = nullptr); 0087 ~TodoSortFilterProxyModel() = default; 0088 0089 int columnCount(const QModelIndex &parent) const override; 0090 QHash<int, QByteArray> roleNames() const override; 0091 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 0092 bool filterAcceptsRow(int row, const QModelIndex &sourceParent) const override; 0093 0094 bool filterAcceptsRowCheck(int row, const QModelIndex &sourceParent) const; 0095 bool hasAcceptedChildren(int row, const QModelIndex &sourceParent) const; 0096 0097 Akonadi::ETMCalendar::Ptr calendar() const; 0098 Akonadi::IncidenceChanger *incidenceChanger() const; 0099 int showCompleted() const; 0100 Filter *filterObject() const; 0101 int sortBy() const; 0102 bool sortAscending() const; 0103 bool showCompletedSubtodosInIncomplete() const; 0104 0105 Q_SIGNALS: 0106 void calendarChanged(); 0107 void filterObjectAboutToChange(); 0108 void filterObjectChanged(); 0109 void showCompletedChanged(); 0110 void sortByChanged(); 0111 void sortAscendingChanged(); 0112 void showCompletedSubtodosInIncompleteChanged(); 0113 void incidenceChangerChanged(); 0114 0115 public Q_SLOTS: 0116 void setCalendar(Akonadi::ETMCalendar::Ptr &calendar); 0117 void setIncidenceChanger(Akonadi::IncidenceChanger *changer); 0118 void setFilterObject(Filter *filterObject); 0119 void setShowCompleted(const int showCompleted); 0120 void setSortBy(const int sortBy); 0121 void setSortAscending(const bool sortAscending); 0122 void setShowCompletedSubtodosInIncomplete(const bool showCompletedSubtodosInIncomplete); 0123 0124 void sortTodoModel(); 0125 void filterTodoName(const QString &name, const int showCompleted = ShowAll); 0126 0127 protected: 0128 bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; 0129 0130 private Q_SLOTS: 0131 void setColorCache(const QHash<QString, QColor> colorCache); 0132 0133 void loadColors(); 0134 void updateDateLabels(); 0135 void emitDateDataChanged(const QModelIndex &idx); 0136 0137 private: 0138 QHash<QString, QColor> colorCache() const; 0139 QString todoDueDateDisplayString(const KCalendarCore::Todo::Ptr todo, const DueDateDisplayFormat format) const; 0140 0141 int compareStartDates(const QModelIndex &left, const QModelIndex &right) const; 0142 int compareDueDates(const QModelIndex &left, const QModelIndex &right) const; 0143 int compareCompletedDates(const QModelIndex &left, const QModelIndex &right) const; 0144 int comparePriorities(const QModelIndex &left, const QModelIndex &right) const; 0145 int compareCompletion(const QModelIndex &left, const QModelIndex &right) const; 0146 0147 Akonadi::ETMCalendar::Ptr m_calendar; 0148 QScopedPointer<Akonadi::IncidenceTreeModel> m_todoTreeModel; 0149 QScopedPointer<Akonadi::TodoModel> m_baseTodoModel; 0150 Akonadi::IncidenceChanger *m_lastSetChanger = nullptr; 0151 QHash<QString, QColor> m_colors; 0152 KConfigWatcher::Ptr m_colorWatcher; 0153 int m_showCompleted = ShowComplete::ShowAll; 0154 int m_showCompletedStore; // For when searches happen 0155 Filter *m_filterObject = nullptr; 0156 int m_sortColumn = DueDateColumn; 0157 bool m_sortAscending = false; 0158 bool m_showCompletedSubtodosInIncomplete = true; 0159 KFormat m_format; 0160 QTimer m_dateRefreshTimer; 0161 int m_dateRefreshTimerInterval = 60000; // msecs 0162 QDate m_lastDateRefreshDate = QDate::currentDate(); 0163 };