MauiKit Calendar

infinitecalendarviewmodel.cpp
1// SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com>
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#include "incidenceoccurrencemodel.h"
5#include <Akonadi/EntityTreeModel>
6#include <QMetaEnum>
7#include <cmath>
8#include <models/infinitecalendarviewmodel.h>
9
10InfiniteCalendarViewModel::InfiniteCalendarViewModel(QObject *parent)
11 : QAbstractListModel(parent)
12{
13 setup();
14}
15
16void InfiniteCalendarViewModel::setup()
17{
18 const QDate today = QDate::currentDate();
19 QTime time;
20
21 if (!m_hourlyViewLocalisedHourLabels.length()) {
22 m_hourlyViewLocalisedHourLabels.clear();
23 for (int i = 1; i < 24; i++) {
24 time.setHMS(i, 0, 0);
25 m_hourlyViewLocalisedHourLabels.append(QLocale::system().toString(time, QLocale::NarrowFormat));
26 }
27 }
28
29 switch (m_scale) {
30 case DayScale: {
31 QDate firstDay = today;
32 firstDay = firstDay.addDays(m_datesToAdd / 2);
33
34 addDayDates(true, firstDay);
35 break;
36 }
37 case ThreeDayScale: {
38 QDate firstDay = today;
39 firstDay = firstDay.addDays((-m_datesToAdd * 3) / 2);
40
41 addDayDates(true, firstDay, 3);
42 break;
43 }
44 case WeekScale: {
45 QDate firstDay = today.addDays(-today.dayOfWeek() + m_locale.firstDayOfWeek());
46 // We create dates before and after where our view will start from (which is today)
47 firstDay = firstDay.addDays((-m_datesToAdd * 7) / 2);
48
49 addWeekDates(true, firstDay);
50 break;
51 }
52 case MonthScale: {
53 QDate firstDay(today.year(), today.month(), 1);
54 firstDay = firstDay.addMonths(-m_datesToAdd / 2);
55
56 addMonthDates(true, firstDay);
57 break;
58 }
59 case YearScale: {
60 QDate firstDay(today.year(), today.month(), 1);
61 firstDay = firstDay.addYears(-m_datesToAdd / 2);
62
63 addYearDates(true, firstDay);
64 break;
65 }
66 case DecadeScale: {
67 const int firstYear = ((floor(today.year() / 10)) * 10) - 1; // E.g. For 2020 have view start at 2019...
68 QDate firstDay(firstYear, today.month(), 1);
69 firstDay = firstDay.addYears(((-m_datesToAdd * 12) / 2) + 10); // 3 * 4 grid so 12 years, end at 2030, and align for mid index to be current decade
70
71 addDecadeDates(true, firstDay);
72 break;
73 }
74 }
75}
76
77QVariant InfiniteCalendarViewModel::data(const QModelIndex &idx, int role) const
78{
79 if (!hasIndex(idx.row(), idx.column())) {
80 return {};
81 }
82
83 const QDate startDate = m_startDates[idx.row()];
84
85 if (m_scale == MonthScale && role != StartDateRole) {
86 const QDate firstDay = m_firstDayOfMonthDates[idx.row()];
87
88 switch (role) {
89 case FirstDayOfMonthRole:
90 return firstDay.startOfDay();
91 case SelectedMonthRole:
92 return firstDay.month();
93 case SelectedYearRole:
94 return firstDay.year();
95 default:
96 qWarning() << "Unknown role for startdate:" << QMetaEnum::fromType<Roles>().valueToKey(role);
97 return {};
98 }
99 }
100
101 switch (role) {
102 case StartDateRole:
103 return startDate.startOfDay();
104 case SelectedMonthRole:
105 return startDate.month();
106 case SelectedYearRole:
107 return startDate.year();
108 default:
109 qWarning() << "Unknown role for startdate:" << QMetaEnum::fromType<Roles>().valueToKey(role);
110 return {};
111 }
112}
113
114int InfiniteCalendarViewModel::rowCount(const QModelIndex &parent) const
115{
116 Q_UNUSED(parent)
117 return m_startDates.length();
118}
119
120QHash<int, QByteArray> InfiniteCalendarViewModel::roleNames() const
121{
122 return {
123 {StartDateRole, QByteArrayLiteral("startDate")},
124 {FirstDayOfMonthRole, QByteArrayLiteral("firstDay")},
125 {SelectedMonthRole, QByteArrayLiteral("selectedMonth")},
126 {SelectedYearRole, QByteArrayLiteral("selectedYear")},
127 };
128}
129
130void InfiniteCalendarViewModel::addDates(bool atEnd, const QDate startFrom)
131{
132 switch (m_scale) {
133 case DayScale:
134 addDayDates(atEnd, startFrom);
135 break;
136 case ThreeDayScale:
137 addDayDates(atEnd, startFrom, 3);
138 break;
139 case WeekScale:
140 addWeekDates(atEnd, startFrom);
141 break;
142 case MonthScale:
143 addMonthDates(atEnd, startFrom);
144 break;
145 case YearScale:
146 addYearDates(atEnd, startFrom);
147 break;
148 case DecadeScale:
149 addDecadeDates(atEnd, startFrom);
150 break;
151 }
152}
153
154void InfiniteCalendarViewModel::addDayDates(bool atEnd, const QDate &startFrom, int amount)
155{
156 const int newRow = atEnd ? rowCount() : 0;
157
158 beginInsertRows(QModelIndex(), newRow, newRow + m_datesToAdd - 1);
159
160 for (int i = 0; i < m_datesToAdd; i++) {
161 QDate startDate = startFrom.isValid() && i == 0 ? startFrom : atEnd ? m_startDates[rowCount() - 1].addDays(amount) : m_startDates[0].addDays(-amount);
162
163 if (atEnd) {
164 m_startDates.append(startDate);
165 } else {
166 m_startDates.insert(0, startDate);
167 }
168 }
169
171}
172
173void InfiniteCalendarViewModel::addWeekDates(bool atEnd, const QDate &startFrom)
174{
175 const int newRow = atEnd ? rowCount() : 0;
176
177 beginInsertRows(QModelIndex(), newRow, newRow + m_datesToAdd - 1);
178
179 for (int i = 0; i < m_datesToAdd; i++) {
180 QDate startDate = startFrom.isValid() && i == 0 ? startFrom : atEnd ? m_startDates[rowCount() - 1].addDays(7) : m_startDates[0].addDays(-7);
181
182 if (startDate.dayOfWeek() != m_locale.firstDayOfWeek()) {
183 startDate = startDate.addDays(-startDate.dayOfWeek() + m_locale.firstDayOfWeek());
184 }
185
186 if (atEnd) {
187 m_startDates.append(startDate);
188 } else {
189 m_startDates.insert(0, startDate);
190 }
191 }
192
194}
195
196void InfiniteCalendarViewModel::addMonthDates(bool atEnd, const QDate &startFrom)
197{
198 const int newRow = atEnd ? rowCount() : 0;
199
200 beginInsertRows(QModelIndex(), newRow, newRow + m_datesToAdd - 1);
201
202 for (int i = 0; i < m_datesToAdd; i++) {
203 const QDate firstDay = startFrom.isValid() && i == 0 ? startFrom
204 : atEnd ? m_firstDayOfMonthDates[rowCount() - 1].addMonths(1)
205 : m_firstDayOfMonthDates[0].addMonths(-1);
206 QDate startDate = firstDay;
207
208 startDate = startDate.addDays(-startDate.dayOfWeek() + m_locale.firstDayOfWeek());
209 if (startDate >= firstDay) {
210 startDate = startDate.addDays(-7);
211 }
212
213 if (atEnd) {
214 m_firstDayOfMonthDates.append(firstDay);
215 m_startDates.append(startDate);
216 } else {
217 m_firstDayOfMonthDates.insert(0, firstDay);
218 m_startDates.insert(0, startDate);
219 }
220 }
221
223}
224
225void InfiniteCalendarViewModel::addYearDates(bool atEnd, const QDate &startFrom)
226{
227 const int newRow = atEnd ? rowCount() : 0;
228
229 beginInsertRows(QModelIndex(), newRow, newRow + m_datesToAdd - 1);
230
231 for (int i = 0; i < m_datesToAdd; i++) {
232 QDate startDate = startFrom.isValid() && i == 0 ? startFrom : atEnd ? m_startDates[rowCount() - 1].addYears(1) : m_startDates[0].addYears(-1);
233
234 if (atEnd) {
235 m_startDates.append(startDate);
236 } else {
237 m_startDates.insert(0, startDate);
238 }
239 }
240
242}
243
244void InfiniteCalendarViewModel::addDecadeDates(bool atEnd, const QDate &startFrom)
245{
246 const int newRow = atEnd ? rowCount() : 0;
247
248 beginInsertRows(QModelIndex(), newRow, newRow + m_datesToAdd - 1);
249
250 for (int i = 0; i < m_datesToAdd; i++) {
251 QDate startDate = startFrom.isValid() && i == 0 ? startFrom : atEnd ? m_startDates[rowCount() - 1].addYears(10) : m_startDates[0].addYears(-10);
252
253 if (atEnd) {
254 m_startDates.append(startDate);
255 } else {
256 m_startDates.insert(0, startDate);
257 }
258 }
259
261}
262
263int InfiniteCalendarViewModel::datesToAdd() const
264{
265 return m_datesToAdd;
266}
267
268void InfiniteCalendarViewModel::setDatesToAdd(int datesToAdd)
269{
270 m_datesToAdd = datesToAdd;
271 Q_EMIT datesToAddChanged();
272}
273
274int InfiniteCalendarViewModel::scale() const
275{
276 return m_scale;
277}
278
279void InfiniteCalendarViewModel::setScale(int scale)
280{
282
283 m_startDates.clear();
284 m_firstDayOfMonthDates.clear();
285
286 m_scale = scale;
287 setup();
288 Q_EMIT scaleChanged();
289
291}
292
293#include "infinitecalendarviewmodel.moc"
294#include "moc_infinitecalendarviewmodel.cpp"
295
char * toString(const EngineQuery &query)
void beginInsertRows(const QModelIndex &parent, int first, int last)
bool hasIndex(int row, int column, const QModelIndex &parent) const const
QDate addDays(qint64 ndays) const const
QDate addMonths(int nmonths) const const
QDate addYears(int nyears) const const
QDate currentDate()
int dayOfWeek() const const
bool isValid(int year, int month, int day)
int month() const const
QDateTime startOfDay() const const
int year() const const
void append(QList< T > &&value)
void clear()
qsizetype length() const const
Qt::DayOfWeek firstDayOfWeek() const const
QLocale system()
QMetaEnum fromType()
const char * valueToKey(int value) const const
int column() const const
int row() const const
Q_EMITQ_EMIT
QObject * parent() const const
QTestData & newRow(const char *dataTag)
bool setHMS(int h, int m, int s, int ms)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:08:19 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.