Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickmonthmodel.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6
7#include <QtCore/private/qabstractitemmodel_p.h>
8#include <QtCore/qloggingcategory.h>
9#include <QtCore/qtimezone.h>
10
11namespace {
12 static const int daysInAWeek = 7;
13 static const int weeksOnACalendarMonth = 6;
14 static const int daysOnACalendarMonth = daysInAWeek * weeksOnACalendarMonth;
15}
16
18
19Q_STATIC_LOGGING_CATEGORY(lcMonthModel, "qt.quick.controls.monthmodel")
20
22{
23 Q_DECLARE_PUBLIC(QQuickMonthModel)
24
25public:
32
33 bool populate(int month, int year, const QLocale &locale, bool force = false);
34
35 int month;
36 int year;
41};
42
43bool QQuickMonthModelPrivate::populate(int m, int y, const QLocale &l, bool force)
44{
45 Q_Q(QQuickMonthModel);
46 if (!force && m == month && y == year && l.firstDayOfWeek() == locale.firstDayOfWeek())
47 return false;
48
49 // The actual first (1st) day of the month.
50 const QDate firstDayOfMonthDate = QDate(y, m, 1);
51 // QDate is converted to local time when converted to a JavaScript Date,
52 // so if we stored our dates as QDates, it's possible that the date provided
53 // to delegates will be wrong in certain timezones:
54 // e.g. 00:00 UTC converted to UTC-8 is 16:00 the day before.
55 // To account for this, we store our dates as local QDateTimes.
56 const QDateTime firstDayOfMonthDateTime = firstDayOfMonthDate.startOfDay();
57 int difference = ((firstDayOfMonthDate.dayOfWeek() - l.firstDayOfWeek()) + 7) % 7;
58 // The first day to display should never be the 1st of the month, as we want some days from
59 // the previous month to be visible.
60 if (difference == 0)
61 difference += 7;
62 const QDateTime firstDateToDisplay = firstDayOfMonthDateTime.addDays(-difference);
63
64 today = QDate::currentDate();
65 for (int i = 0; i < daysOnACalendarMonth; ++i)
66 dates[i] = firstDateToDisplay.addDays(i);
67
68 q->setTitle(l.standaloneMonthName(m) + QStringLiteral(" ") + QString::number(y));
69
70 qCDebug(lcMonthModel) << "populated model for month" << m << "year" << y << "locale" << locale
71 << "firstDayOfMonthDateTime" << firstDayOfMonthDateTime;
72
73 return true;
74}
75
76QQuickMonthModel::QQuickMonthModel(QObject *parent) :
77 QAbstractListModel(*(new QQuickMonthModelPrivate), parent)
78{
79 Q_D(QQuickMonthModel);
80 d->populate(d->month, d->year, d->locale, true);
81}
82
84{
85 Q_D(const QQuickMonthModel);
86 return d->month;
87}
88
89void QQuickMonthModel::setMonth(int month)
90{
91 Q_D(QQuickMonthModel);
92 if (d->month != month) {
93 if (d->populate(month, d->year, d->locale))
94 emit dataChanged(index(0, 0), index(daysOnACalendarMonth - 1, 0));
95 d->month = month;
96 emit monthChanged();
97 }
98}
99
101{
102 Q_D(const QQuickMonthModel);
103 return d->year;
104}
105
107{
108 Q_D(QQuickMonthModel);
109 if (d->year != year) {
110 if (d->populate(d->month, year, d->locale))
111 emit dataChanged(index(0, 0), index(daysOnACalendarMonth - 1, 0));
112 d->year = year;
113 emit yearChanged();
114 }
115}
116
118{
119 Q_D(const QQuickMonthModel);
120 return d->locale;
121}
122
123void QQuickMonthModel::setLocale(const QLocale &locale)
124{
125 Q_D(QQuickMonthModel);
126 if (d->locale != locale) {
127 if (d->populate(d->month, d->year, locale))
128 emit dataChanged(index(0, 0), index(daysOnACalendarMonth - 1, 0));
129 d->locale = locale;
130 emit localeChanged();
131 }
132}
133
135{
136 Q_D(const QQuickMonthModel);
137 return d->title;
138}
139
140void QQuickMonthModel::setTitle(const QString &title)
141{
142 Q_D(QQuickMonthModel);
143 if (d->title != title) {
144 d->title = title;
145 emit titleChanged();
146 }
147}
148
149QDateTime QQuickMonthModel::dateAt(int index) const
150{
151 Q_D(const QQuickMonthModel);
152 return d->dates.value(index);
153}
154
155int QQuickMonthModel::indexOf(QDateTime date) const
156{
157 Q_D(const QQuickMonthModel);
158 if (date < d->dates.first() || date > d->dates.last())
159 return -1;
160 return qMax(qint64(0), d->dates.first().daysTo(date));
161}
162
163QVariant QQuickMonthModel::data(const QModelIndex &index, int role) const
164{
165 Q_D(const QQuickMonthModel);
166 if (index.isValid() && index.row() < daysOnACalendarMonth) {
167 const QDateTime dateTime = d->dates.at(index.row());
168 // As mentioned in populate, we store dates whose time is adjusted
169 // by the timezone offset, so we need to convert back to local time
170 // to get the correct date if the conversion to JavaScript's Date
171 // isn't being done for us.
172 const QDate date = d->dates.at(index.row()).toLocalTime().date();
173 switch (role) {
174 case DateRole:
175 return dateTime;
176 case DayRole:
177 return date.day();
178 case TodayRole:
179 return date == d->today;
180 case WeekNumberRole:
181 return date.weekNumber();
182 case MonthRole:
183 return date.month() - 1;
184 case YearRole:
185 return date.year();
186 default:
187 break;
188 }
189 }
190 return QVariant();
191}
192
193int QQuickMonthModel::rowCount(const QModelIndex &parent) const
194{
195 if (parent.isValid())
196 return 0;
197 return daysOnACalendarMonth;
198}
199
201{
202 QHash<int, QByteArray> roles;
203 roles[DateRole] = QByteArrayLiteral("date");
204 roles[DayRole] = QByteArrayLiteral("day");
205 roles[TodayRole] = QByteArrayLiteral("today");
206 roles[WeekNumberRole] = QByteArrayLiteral("weekNumber");
207 roles[MonthRole] = QByteArrayLiteral("month");
208 roles[YearRole] = QByteArrayLiteral("year");
209 return roles;
210}
211
212QT_END_NAMESPACE
213
214#include "moc_qquickmonthmodel_p.cpp"
QVector< QDateTime > dates
QVariant data(const QModelIndex &index, int role) const override
Returns the data stored under the given role for the item referred to by the index.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows under the given parent.
QHash< int, QByteArray > roleNames() const override
void setMonth(int month)
QString title() const
void setYear(int year)
void setLocale(const QLocale &locale)
Q_INVOKABLE int indexOf(QDateTime date) const
void setTitle(const QString &title)
QLocale locale() const
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")