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
qquickmonthgrid.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
6
7#include <QtGui/qstylehints.h>
8#include <QtGui/qguiapplication.h>
9#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
10#include <QtQml/qqmlinfo.h>
11
13
14/*!
15 \qmltype MonthGrid
16 \inherits Control
17//! \nativetype QQuickMonthGrid
18 \inqmlmodule QtQuick.Controls
19 \brief A grid of days for a calendar month.
20
21 MonthGrid presents a calendar month in a grid. The contents are
22 calculated for a given \l month and \l year, using the specified
23 \l {Control::locale}{locale}.
24
25 \image qtquickcontrols-monthgrid.webp
26 {Month grid displaying calendar days}
27 \snippet qtquickcontrols-monthgrid.qml 1
28
29 MonthGrid can be used as a standalone control, but it is most often
30 used in conjunction with DayOfWeekRow and WeekNumberColumn. Regardless
31 of the use case, positioning of the grid is left to the user.
32
33 \image qtquickcontrols-monthgrid-layout.webp
34 {Month grid in calendar layout}
35 \snippet qtquickcontrols-monthgrid-layout.qml 1
36
37 The visual appearance of MonthGrid can be changed by
38 implementing a \l {delegate}{custom delegate}.
39
40 When viewing any given month, MonthGrid shows days from the previous and
41 next month. This means it always shows six rows, even when first or last
42 row is entirely within an adjacent month.
43
44 \section1 Localizing days
45
46 To localize days, use \l {Locale::toString()}{Locale.toString()}.
47 For example, to display day numbers in an Arabic locale:
48
49 \snippet qtquickcontrols-monthgrid-localization.qml 1
50
51 \sa DayOfWeekRow, WeekNumberColumn, CalendarModel,
52 {Qt Quick Controls - Event Calendar}
53*/
54
55/*!
56 \qmlsignal QtQuick.Controls::MonthGrid::pressed(date date)
57
58 This signal is emitted when \a date is pressed.
59*/
60
61/*!
62 \qmlsignal QtQuick.Controls::MonthGrid::released(date date)
63
64 This signal is emitted when \a date is released.
65*/
66
67/*!
68 \qmlsignal QtQuick.Controls::MonthGrid::clicked(date date)
69
70 This signal is emitted when \a date is clicked.
71*/
72
73/*!
74 \qmlsignal QtQuick.Controls::MonthGrid::pressAndHold(date date)
75
76 This signal is emitted when \a date is pressed and held down.
77*/
78
80{
81 Q_DECLARE_PUBLIC(QQuickMonthGrid)
82
83public:
84 QQuickMonthGridPrivate() : pressTimer(0), pressedItem(nullptr), model(nullptr), delegate(nullptr) { }
85
87
88 QQuickItem *cellAt(const QPointF &pos) const;
89 QDateTime dateOf(QQuickItem *cell) const;
90
91 void updatePress(const QPointF &pos);
92 void clearPress(bool clicked);
93
94 bool handlePress(const QPointF &point, ulong timestamp) override;
95 bool handleMove(const QPointF &point, ulong timestamp) override;
96 bool handleRelease(const QPointF &point, ulong timestamp) override;
98
101
102 // Only the date matters, but we have to store it as QDateTime for compatibility
103 // with Date: QTBUG-72208. See QQuickMonthModelPrivate::populate for more info.
108 QQmlComponent *delegate;
109};
110
111void QQuickMonthGridPrivate::resizeItems()
112{
113 if (!contentItem)
114 return;
115
116 QSizeF itemSize;
117 itemSize.setWidth((contentItem->width() - 6 * spacing) / 7);
118 itemSize.setHeight((contentItem->height() - 5 * spacing) / 6);
119
120 const auto childItems = contentItem->childItems();
121 for (QQuickItem *item : childItems) {
122 if (!QQuickItemPrivate::get(item)->isTransparentForPositioner())
123 item->setSize(itemSize);
124 }
125}
126
127QQuickItem *QQuickMonthGridPrivate::cellAt(const QPointF &pos) const
128{
129 Q_Q(const QQuickMonthGrid);
130 if (contentItem) {
131 QPointF mapped = q->mapToItem(contentItem, pos);
132 return contentItem->childAt(mapped.x(), mapped.y());
133 }
134 return nullptr;
135}
136
138{
139 if (contentItem)
140 return model->dateAt(contentItem->childItems().indexOf(cell));
141 return {};
142}
143
144void QQuickMonthGridPrivate::updatePress(const QPointF &pos)
145{
146 Q_Q(QQuickMonthGrid);
147 clearPress(false);
148 pressedItem = cellAt(pos);
149 pressedDate = dateOf(pressedItem);
150 if (pressedDate.isValid())
151 emit q->pressed(pressedDate);
152}
153
155{
156 Q_Q(QQuickMonthGrid);
157 if (pressedDate.isValid()) {
158 emit q->released(pressedDate);
159 if (clicked)
160 emit q->clicked(pressedDate);
161 }
162 pressedDate = {};
163 pressedItem = nullptr;
164}
165
166bool QQuickMonthGridPrivate::handlePress(const QPointF &point, ulong timestamp)
167{
168 Q_Q(QQuickMonthGrid);
169 QQuickControlPrivate::handlePress(point, timestamp);
170 updatePress(point);
171 if (pressedDate.isValid())
172 pressTimer = q->startTimer(qGuiApp->styleHints()->mousePressAndHoldInterval());
173 return true;
174}
175
176bool QQuickMonthGridPrivate::handleMove(const QPointF &point, ulong timestamp)
177{
178 QQuickControlPrivate::handleMove(point, timestamp);
179 updatePress(point);
180 return true;
181}
182
183bool QQuickMonthGridPrivate::handleRelease(const QPointF &point, ulong timestamp)
184{
185 QQuickControlPrivate::handleRelease(point, timestamp);
186 clearPress(true);
187 return true;
188}
189
191{
192 QQuickControlPrivate::handleUngrab();
193 clearPress(false);
194}
195
196QQuickMonthGrid::QQuickMonthGrid(QQuickItem *parent) :
197 QQuickControl(*(new QQuickMonthGridPrivate), parent)
198{
199 Q_D(QQuickMonthGrid);
200 setFlag(ItemIsFocusScope);
201 setActiveFocusOnTab(true);
202 setAcceptedMouseButtons(Qt::LeftButton);
203#if QT_CONFIG(cursor)
204 setCursor(Qt::ArrowCursor);
205#endif
206
207 d->model = new QQuickMonthModel(this);
208 d->source = QVariant::fromValue(d->model);
209 connect(d->model, &QQuickMonthModel::monthChanged, this, &QQuickMonthGrid::monthChanged);
212}
213
214/*!
215 \qmlproperty int QtQuick.Controls::MonthGrid::month
216
217 This property holds the number of the month. The default value is the
218 current month.
219
220 \include zero-based-months.qdocinc
221
222 \sa Calendar
223*/
225{
226 Q_D(const QQuickMonthGrid);
227 return d->model->month() - 1;
228}
229
230void QQuickMonthGrid::setMonth(int month)
231{
232 Q_D(QQuickMonthGrid);
233 if (month < 0 || month > 11) {
234 qmlWarning(this) << "month " << month << " is out of range [0...11]";
235 return;
236 }
237 d->model->setMonth(month + 1);
238}
239
240/*!
241 \qmlproperty int QtQuick.Controls::MonthGrid::year
242
243 This property holds the number of the year.
244
245 The value must be in the range from \c -271820 to \c 275759. The default
246 value is the current year.
247*/
249{
250 Q_D(const QQuickMonthGrid);
251 return d->model->year();
252}
253
255{
256 Q_D(QQuickMonthGrid);
257 if (year < -271820 || year > 275759) {
258 qmlWarning(this) << "year " << year << " is out of range [-271820...275759]";
259 return;
260 }
261 d->model->setYear(year);
262}
263
264/*!
265 \internal
266 \qmlproperty model QtQuick.Controls::MonthGrid::source
267
268 This property holds the source model that is used as a data model
269 for the internal content column.
270*/
272{
273 Q_D(const QQuickMonthGrid);
274 return d->source;
275}
276
277void QQuickMonthGrid::setSource(const QVariant &source)
278{
279 Q_D(QQuickMonthGrid);
280 if (d->source != source) {
281 d->source = source;
282 emit sourceChanged();
283 }
284}
285
286/*!
287 \qmlproperty string QtQuick.Controls::MonthGrid::title
288
289 This property holds a title for the calendar.
290
291 This property is provided for convenience. MonthGrid itself does
292 not visualize the title. The default value consists of the month name,
293 formatted using \l {Control::locale}{locale}, and the year number.
294*/
296{
297 Q_D(const QQuickMonthGrid);
298 if (d->title.isNull())
299 return d->model->title();
300 return d->title;
301}
302
303void QQuickMonthGrid::setTitle(const QString &title)
304{
305 Q_D(QQuickMonthGrid);
306 if (d->title != title) {
307 d->title = title;
308 emit titleChanged();
309 }
310}
311
312/*!
313 \qmlproperty Component QtQuick.Controls::MonthGrid::delegate
314
315 This property holds the item delegate that visualizes each day.
316
317 In addition to the \c index property, a list of model data roles
318 are available in the context of each delegate:
319 \table
320 \row \li \b model.date : date \li The date of the cell
321 \row \li \b model.day : int \li The number of the day
322 \row \li \b model.today : bool \li Whether the delegate represents today
323 \row \li \b model.weekNumber : int \li The week number
324 \row \li \b model.month : int \li The number of the month
325 \row \li \b model.year : int \li The number of the year
326 \endtable
327
328 The following snippet presents the default implementation of the item
329 delegate. It can be used as a starting point for implementing custom
330 delegates.
331
332 \include delegate-ownership.qdocinc {no-ownership} {MonthGrid}
333
334 \snippet basic/MonthGrid.qml delegate
335*/
336QQmlComponent *QQuickMonthGrid::delegate() const
337{
338 Q_D(const QQuickMonthGrid);
339 return d->delegate;
340}
341
342void QQuickMonthGrid::setDelegate(QQmlComponent *delegate)
343{
344 Q_D(QQuickMonthGrid);
345 if (d->delegate != delegate) {
346 d->delegate = delegate;
347 emit delegateChanged();
348 }
349}
350
352{
353 Q_D(QQuickMonthGrid);
354 QQuickControl::componentComplete();
355 d->resizeItems();
356}
357
358void QQuickMonthGrid::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
359{
360 Q_D(QQuickMonthGrid);
361 QQuickControl::geometryChange(newGeometry, oldGeometry);
362 if (isComponentComplete())
363 d->resizeItems();
364}
365
366void QQuickMonthGrid::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
367{
368 Q_D(QQuickMonthGrid);
369 QQuickControl::localeChange(newLocale, oldLocale);
370 d->model->setLocale(newLocale);
371}
372
373void QQuickMonthGrid::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
374{
375 Q_D(QQuickMonthGrid);
376 QQuickControl::paddingChange(newPadding, oldPadding);
377 if (isComponentComplete())
378 d->resizeItems();
379}
380
382{
383 Q_D(QQuickMonthGrid);
384 QQuickControl::updatePolish();
385 d->resizeItems();
386}
387
388void QQuickMonthGrid::timerEvent(QTimerEvent *event)
389{
390 Q_D(QQuickMonthGrid);
391 if (event->timerId() == d->pressTimer) {
392 if (d->pressedDate.isValid())
393 emit pressAndHold(d->pressedDate);
394 killTimer(d->pressTimer);
395 }
396}
397
398QT_END_NAMESPACE
399
400#include "moc_qquickmonthgrid_p.cpp"
A grid of days for a calendar month.
bool handleRelease(const QPointF &point, ulong timestamp) override
bool handlePress(const QPointF &point, ulong timestamp) override
QQuickMonthModel * model
QQuickItem * cellAt(const QPointF &pos) const
QDateTime dateOf(QQuickItem *cell) const
bool handleMove(const QPointF &point, ulong timestamp) override
void clearPress(bool clicked)
void updatePress(const QPointF &pos)
void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override
void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
int month() const
\qmlproperty int QtQuick.Controls::MonthGrid::month
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
void setTitle(const QString &title)
void timerEvent(QTimerEvent *event) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
QQmlComponent * delegate() const
\qmlproperty Component QtQuick.Controls::MonthGrid::delegate
void setSource(const QVariant &source)
void setDelegate(QQmlComponent *delegate)
QString title() const
\qmlproperty string QtQuick.Controls::MonthGrid::title
void setMonth(int month)
void updatePolish() override
This function should perform any layout as required for this item.
QVariant source() const
void setYear(int year)
int year() const
\qmlproperty int QtQuick.Controls::MonthGrid::year
Combined button and popup list for selecting options.