File indexing completed on 2024-06-23 04:42:35
0001 // SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com> 0002 // SPDX-License-Identifier: LGPL-2.1-or-later 0003 0004 #include "incidenceoccurrencemodel.h" 0005 #include <Akonadi/EntityTreeModel> 0006 #include <QMetaEnum> 0007 #include <cmath> 0008 #include <models/infinitecalendarviewmodel.h> 0009 0010 InfiniteCalendarViewModel::InfiniteCalendarViewModel(QObject *parent) 0011 : QAbstractListModel(parent) 0012 { 0013 setup(); 0014 } 0015 0016 void InfiniteCalendarViewModel::setup() 0017 { 0018 const QDate today = QDate::currentDate(); 0019 QTime time; 0020 0021 if (!m_hourlyViewLocalisedHourLabels.length()) { 0022 m_hourlyViewLocalisedHourLabels.clear(); 0023 for (int i = 1; i < 24; i++) { 0024 time.setHMS(i, 0, 0); 0025 m_hourlyViewLocalisedHourLabels.append(QLocale::system().toString(time, QLocale::NarrowFormat)); 0026 } 0027 } 0028 0029 switch (m_scale) { 0030 case DayScale: { 0031 QDate firstDay = today; 0032 firstDay = firstDay.addDays(m_datesToAdd / 2); 0033 0034 addDayDates(true, firstDay); 0035 break; 0036 } 0037 case ThreeDayScale: { 0038 QDate firstDay = today; 0039 firstDay = firstDay.addDays((-m_datesToAdd * 3) / 2); 0040 0041 addDayDates(true, firstDay, 3); 0042 break; 0043 } 0044 case WeekScale: { 0045 QDate firstDay = today.addDays(-today.dayOfWeek() + m_locale.firstDayOfWeek()); 0046 // We create dates before and after where our view will start from (which is today) 0047 firstDay = firstDay.addDays((-m_datesToAdd * 7) / 2); 0048 0049 addWeekDates(true, firstDay); 0050 break; 0051 } 0052 case MonthScale: { 0053 QDate firstDay(today.year(), today.month(), 1); 0054 firstDay = firstDay.addMonths(-m_datesToAdd / 2); 0055 0056 addMonthDates(true, firstDay); 0057 break; 0058 } 0059 case YearScale: { 0060 QDate firstDay(today.year(), today.month(), 1); 0061 firstDay = firstDay.addYears(-m_datesToAdd / 2); 0062 0063 addYearDates(true, firstDay); 0064 break; 0065 } 0066 case DecadeScale: { 0067 const int firstYear = ((floor(today.year() / 10)) * 10) - 1; // E.g. For 2020 have view start at 2019... 0068 QDate firstDay(firstYear, today.month(), 1); 0069 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 0070 0071 addDecadeDates(true, firstDay); 0072 break; 0073 } 0074 } 0075 } 0076 0077 QVariant InfiniteCalendarViewModel::data(const QModelIndex &idx, int role) const 0078 { 0079 if (!hasIndex(idx.row(), idx.column())) { 0080 return {}; 0081 } 0082 0083 const QDate startDate = m_startDates[idx.row()]; 0084 0085 if (m_scale == MonthScale && role != StartDateRole) { 0086 const QDate firstDay = m_firstDayOfMonthDates[idx.row()]; 0087 0088 switch (role) { 0089 case FirstDayOfMonthRole: 0090 return firstDay.startOfDay(); 0091 case SelectedMonthRole: 0092 return firstDay.month(); 0093 case SelectedYearRole: 0094 return firstDay.year(); 0095 default: 0096 qWarning() << "Unknown role for startdate:" << QMetaEnum::fromType<Roles>().valueToKey(role); 0097 return {}; 0098 } 0099 } 0100 0101 switch (role) { 0102 case StartDateRole: 0103 return startDate.startOfDay(); 0104 case SelectedMonthRole: 0105 return startDate.month(); 0106 case SelectedYearRole: 0107 return startDate.year(); 0108 default: 0109 qWarning() << "Unknown role for startdate:" << QMetaEnum::fromType<Roles>().valueToKey(role); 0110 return {}; 0111 } 0112 } 0113 0114 int InfiniteCalendarViewModel::rowCount(const QModelIndex &parent) const 0115 { 0116 Q_UNUSED(parent) 0117 return m_startDates.length(); 0118 } 0119 0120 QHash<int, QByteArray> InfiniteCalendarViewModel::roleNames() const 0121 { 0122 return { 0123 {StartDateRole, QByteArrayLiteral("startDate")}, 0124 {FirstDayOfMonthRole, QByteArrayLiteral("firstDay")}, 0125 {SelectedMonthRole, QByteArrayLiteral("selectedMonth")}, 0126 {SelectedYearRole, QByteArrayLiteral("selectedYear")}, 0127 }; 0128 } 0129 0130 void InfiniteCalendarViewModel::addDates(bool atEnd, const QDate startFrom) 0131 { 0132 switch (m_scale) { 0133 case DayScale: 0134 addDayDates(atEnd, startFrom); 0135 break; 0136 case ThreeDayScale: 0137 addDayDates(atEnd, startFrom, 3); 0138 break; 0139 case WeekScale: 0140 addWeekDates(atEnd, startFrom); 0141 break; 0142 case MonthScale: 0143 addMonthDates(atEnd, startFrom); 0144 break; 0145 case YearScale: 0146 addYearDates(atEnd, startFrom); 0147 break; 0148 case DecadeScale: 0149 addDecadeDates(atEnd, startFrom); 0150 break; 0151 } 0152 } 0153 0154 void InfiniteCalendarViewModel::addDayDates(bool atEnd, const QDate &startFrom, int amount) 0155 { 0156 const int newRow = atEnd ? rowCount() : 0; 0157 0158 beginInsertRows(QModelIndex(), newRow, newRow + m_datesToAdd - 1); 0159 0160 for (int i = 0; i < m_datesToAdd; i++) { 0161 QDate startDate = startFrom.isValid() && i == 0 ? startFrom : atEnd ? m_startDates[rowCount() - 1].addDays(amount) : m_startDates[0].addDays(-amount); 0162 0163 if (atEnd) { 0164 m_startDates.append(startDate); 0165 } else { 0166 m_startDates.insert(0, startDate); 0167 } 0168 } 0169 0170 endInsertRows(); 0171 } 0172 0173 void InfiniteCalendarViewModel::addWeekDates(bool atEnd, const QDate &startFrom) 0174 { 0175 const int newRow = atEnd ? rowCount() : 0; 0176 0177 beginInsertRows(QModelIndex(), newRow, newRow + m_datesToAdd - 1); 0178 0179 for (int i = 0; i < m_datesToAdd; i++) { 0180 QDate startDate = startFrom.isValid() && i == 0 ? startFrom : atEnd ? m_startDates[rowCount() - 1].addDays(7) : m_startDates[0].addDays(-7); 0181 0182 if (startDate.dayOfWeek() != m_locale.firstDayOfWeek()) { 0183 startDate = startDate.addDays(-startDate.dayOfWeek() + m_locale.firstDayOfWeek()); 0184 } 0185 0186 if (atEnd) { 0187 m_startDates.append(startDate); 0188 } else { 0189 m_startDates.insert(0, startDate); 0190 } 0191 } 0192 0193 endInsertRows(); 0194 } 0195 0196 void InfiniteCalendarViewModel::addMonthDates(bool atEnd, const QDate &startFrom) 0197 { 0198 const int newRow = atEnd ? rowCount() : 0; 0199 0200 beginInsertRows(QModelIndex(), newRow, newRow + m_datesToAdd - 1); 0201 0202 for (int i = 0; i < m_datesToAdd; i++) { 0203 const QDate firstDay = startFrom.isValid() && i == 0 ? startFrom 0204 : atEnd ? m_firstDayOfMonthDates[rowCount() - 1].addMonths(1) 0205 : m_firstDayOfMonthDates[0].addMonths(-1); 0206 QDate startDate = firstDay; 0207 0208 startDate = startDate.addDays(-startDate.dayOfWeek() + m_locale.firstDayOfWeek()); 0209 if (startDate >= firstDay) { 0210 startDate = startDate.addDays(-7); 0211 } 0212 0213 if (atEnd) { 0214 m_firstDayOfMonthDates.append(firstDay); 0215 m_startDates.append(startDate); 0216 } else { 0217 m_firstDayOfMonthDates.insert(0, firstDay); 0218 m_startDates.insert(0, startDate); 0219 } 0220 } 0221 0222 endInsertRows(); 0223 } 0224 0225 void InfiniteCalendarViewModel::addYearDates(bool atEnd, const QDate &startFrom) 0226 { 0227 const int newRow = atEnd ? rowCount() : 0; 0228 0229 beginInsertRows(QModelIndex(), newRow, newRow + m_datesToAdd - 1); 0230 0231 for (int i = 0; i < m_datesToAdd; i++) { 0232 QDate startDate = startFrom.isValid() && i == 0 ? startFrom : atEnd ? m_startDates[rowCount() - 1].addYears(1) : m_startDates[0].addYears(-1); 0233 0234 if (atEnd) { 0235 m_startDates.append(startDate); 0236 } else { 0237 m_startDates.insert(0, startDate); 0238 } 0239 } 0240 0241 endInsertRows(); 0242 } 0243 0244 void InfiniteCalendarViewModel::addDecadeDates(bool atEnd, const QDate &startFrom) 0245 { 0246 const int newRow = atEnd ? rowCount() : 0; 0247 0248 beginInsertRows(QModelIndex(), newRow, newRow + m_datesToAdd - 1); 0249 0250 for (int i = 0; i < m_datesToAdd; i++) { 0251 QDate startDate = startFrom.isValid() && i == 0 ? startFrom : atEnd ? m_startDates[rowCount() - 1].addYears(10) : m_startDates[0].addYears(-10); 0252 0253 if (atEnd) { 0254 m_startDates.append(startDate); 0255 } else { 0256 m_startDates.insert(0, startDate); 0257 } 0258 } 0259 0260 endInsertRows(); 0261 } 0262 0263 int InfiniteCalendarViewModel::datesToAdd() const 0264 { 0265 return m_datesToAdd; 0266 } 0267 0268 void InfiniteCalendarViewModel::setDatesToAdd(int datesToAdd) 0269 { 0270 m_datesToAdd = datesToAdd; 0271 Q_EMIT datesToAddChanged(); 0272 } 0273 0274 int InfiniteCalendarViewModel::scale() const 0275 { 0276 return m_scale; 0277 } 0278 0279 void InfiniteCalendarViewModel::setScale(int scale) 0280 { 0281 beginResetModel(); 0282 0283 m_startDates.clear(); 0284 m_firstDayOfMonthDates.clear(); 0285 0286 m_scale = scale; 0287 setup(); 0288 Q_EMIT scaleChanged(); 0289 0290 endResetModel(); 0291 } 0292 0293 #include "infinitecalendarviewmodel.moc" 0294 #include "moc_infinitecalendarviewmodel.cpp" 0295