1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the Qt Labs Calendar module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qquickcalendarmodel_p.h"
38
39#include <QtCore/private/qabstractitemmodel_p.h>
40
41QT_BEGIN_NAMESPACE
42
43/*!
44 \qmltype CalendarModel
45 \inherits QAbstractListModel
46//! \instantiates QQuickCalendarModel
47 \inqmlmodule Qt.labs.calendar
48 \brief A calendar model.
49
50 CalendarModel provides a way of creating a range of MonthGrid
51 instances. It is typically used as a model for a ListView that uses
52 MonthGrid as a delegate.
53
54 \snippet qtlabscalendar-calendarmodel.qml 1
55
56 In addition to the \c index property, a list of model data roles
57 are available in the context of each delegate:
58 \table
59 \row \li \b model.month : int \li The number of the month
60 \row \li \b model.year : int \li The number of the year
61 \endtable
62
63 The Qt Labs Calendar module uses 0-based month numbers to be consistent
64 with the JavaScript Date type, that is used by the QML language. This
65 means that \c Date::getMonth() can be passed to the methods as is. When
66 dealing with month numbers directly, it is highly recommended to use the
67 following enumeration values to avoid confusion.
68
69 \value Calendar.January January (0)
70 \value Calendar.February February (1)
71 \value Calendar.March March (2)
72 \value Calendar.April April (3)
73 \value Calendar.May May (4)
74 \value Calendar.June June (5)
75 \value Calendar.July July (6)
76 \value Calendar.August August (7)
77 \value Calendar.September September (8)
78 \value Calendar.October October (9)
79 \value Calendar.November November (10)
80 \value Calendar.December December (11)
81
82 \labs
83
84 \sa MonthGrid, Calendar
85*/
86
87class QQuickCalendarModelPrivate : public QAbstractItemModelPrivate
88{
89 Q_DECLARE_PUBLIC(QQuickCalendarModel)
90
91public:
92 QQuickCalendarModelPrivate() : complete(false),
93 from(1,1,1), to(275759, 9, 25), count(0)
94 {
95 }
96
97 static int getCount(const QDate& from, const QDate &to);
98
99 void populate(const QDate &from, const QDate &to, bool force = false);
100
101 bool complete;
102 QDate from;
103 QDate to;
104 int count;
105};
106
107int QQuickCalendarModelPrivate::getCount(const QDate& from, const QDate &to)
108{
109 if (!from.isValid() || !to.isValid())
110 return 0;
111
112 QDate f(from.year(), from.month(), 1);
113 QDate t(to.year(), to.month(), to.daysInMonth());
114 int days = f.daysTo(t);
115 if (days < 0)
116 return 0;
117
118 QDate r = QDate(1, 1, 1).addDays(days);
119 int years = r.year() - 1;
120 int months = r.month() - 1;
121 return 12 * years + months + (r.day() / t.day());
122}
123
124void QQuickCalendarModelPrivate::populate(const QDate &f, const QDate &t, bool force)
125{
126 Q_Q(QQuickCalendarModel);
127 if (!force && f == from && t == to)
128 return;
129
130 int c = getCount(from, to);
131 if (c != count) {
132 q->beginResetModel();
133 count = c;
134 q->endResetModel();
135 emit q->countChanged();
136 } else {
137 emit q->dataChanged(topLeft: q->index(row: 0, column: 0), bottomRight: q->index(row: c - 1, column: 0));
138 }
139}
140
141QQuickCalendarModel::QQuickCalendarModel(QObject *parent) :
142 QAbstractListModel(*(new QQuickCalendarModelPrivate), parent)
143{
144}
145
146/*!
147 \qmlproperty date Qt.labs.calendar::CalendarModel::from
148
149 This property holds the start date.
150*/
151QDate QQuickCalendarModel::from() const
152{
153 Q_D(const QQuickCalendarModel);
154 return d->from;
155}
156
157void QQuickCalendarModel::setFrom(const QDate &from)
158{
159 Q_D(QQuickCalendarModel);
160 if (d->from != from) {
161 if (d->complete)
162 d->populate(f: from, t: d->to);
163 d->from = from;
164 emit fromChanged();
165 }
166}
167
168/*!
169 \qmlproperty date Qt.labs.calendar::CalendarModel::to
170
171 This property holds the end date.
172*/
173QDate QQuickCalendarModel::to() const
174{
175 Q_D(const QQuickCalendarModel);
176 return d->to;
177}
178
179void QQuickCalendarModel::setTo(const QDate &to)
180{
181 Q_D(QQuickCalendarModel);
182 if (d->to != to) {
183 if (d->complete)
184 d->populate(f: d->from, t: to);
185 d->to = to;
186 emit toChanged();
187 }
188}
189
190/*!
191 \qmlmethod int Qt.labs.calendar::CalendarModel::monthAt(int index)
192
193 Returns the month number at the specified model \a index.
194*/
195int QQuickCalendarModel::monthAt(int index) const
196{
197 Q_D(const QQuickCalendarModel);
198 return d->from.addMonths(months: index).month() - 1;
199}
200
201/*!
202 \qmlmethod int Qt.labs.calendar::CalendarModel::yearAt(int index)
203
204 Returns the year number at the specified model \a index.
205*/
206int QQuickCalendarModel::yearAt(int index) const
207{
208 Q_D(const QQuickCalendarModel);
209 return d->from.addMonths(months: index).year();
210}
211
212/*!
213 \qmlmethod int Qt.labs.calendar::CalendarModel::indexOf(Date date)
214
215 Returns the model index of the specified \a date.
216*/
217int QQuickCalendarModel::indexOf(const QDate &date) const
218{
219 Q_D(const QQuickCalendarModel);
220 return d->getCount(from: d->from, to: date) - 1;
221}
222
223/*!
224 \qmlmethod int Qt.labs.calendar::CalendarModel::indexOf(int year, int month)
225
226 Returns the model index of the specified \a year and \a month.
227*/
228int QQuickCalendarModel::indexOf(int year, int month) const
229{
230 return indexOf(date: QDate(year, month + 1, 1));
231}
232
233QVariant QQuickCalendarModel::data(const QModelIndex &index, int role) const
234{
235 Q_D(const QQuickCalendarModel);
236 if (index.isValid() && index.row() < d->count) {
237 switch (role) {
238 case MonthRole:
239 return monthAt(index: index.row());
240 case YearRole:
241 return yearAt(index: index.row());
242 default:
243 break;
244 }
245 }
246 return QVariant();
247}
248
249int QQuickCalendarModel::rowCount(const QModelIndex &parent) const
250{
251 Q_D(const QQuickCalendarModel);
252 if (!parent.isValid())
253 return d->count;
254 return 0;
255}
256
257QHash<int, QByteArray> QQuickCalendarModel::roleNames() const
258{
259 QHash<int, QByteArray> roles;
260 roles[MonthRole] = QByteArrayLiteral("month");
261 roles[YearRole] = QByteArrayLiteral("year");
262 return roles;
263}
264
265void QQuickCalendarModel::classBegin()
266{
267}
268
269void QQuickCalendarModel::componentComplete()
270{
271 Q_D(QQuickCalendarModel);
272 d->complete = true;
273 d->populate(f: d->from, t: d->to, force: true);
274}
275
276QT_END_NAMESPACE
277

source code of qtquickcontrols2/src/imports/calendar/qquickcalendarmodel.cpp