aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates/qquickmonthgrid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates/qquickmonthgrid.cpp')
-rw-r--r--src/quicktemplates/qquickmonthgrid.cpp391
1 files changed, 391 insertions, 0 deletions
diff --git a/src/quicktemplates/qquickmonthgrid.cpp b/src/quicktemplates/qquickmonthgrid.cpp
new file mode 100644
index 0000000000..957c9b8f93
--- /dev/null
+++ b/src/quicktemplates/qquickmonthgrid.cpp
@@ -0,0 +1,391 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include "qquickmonthgrid_p.h"
+#include "qquickmonthmodel_p.h"
+
+#include <QtGui/qstylehints.h>
+#include <QtGui/qguiapplication.h>
+#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
+#include <QtQml/qqmlinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype MonthGrid
+ \inherits Control
+//! \instantiates QQuickMonthGrid
+ \inqmlmodule QtQuick.Controls
+ \brief A grid of days for a calendar month.
+
+ MonthGrid presents a calendar month in a grid. The contents are
+ calculated for a given \l month and \l year, using the specified
+ \l {Control::locale}{locale}.
+
+ \image qtquickcontrols-monthgrid.png
+ \snippet qtquickcontrols-monthgrid.qml 1
+
+ MonthGrid can be used as a standalone control, but it is most often
+ used in conjunction with DayOfWeekRow and WeekNumberColumn. Regardless
+ of the use case, positioning of the grid is left to the user.
+
+ \image qtquickcontrols-monthgrid-layout.png
+ \snippet qtquickcontrols-monthgrid-layout.qml 1
+
+ The visual appearance of MonthGrid can be changed by
+ implementing a \l {delegate}{custom delegate}.
+
+ When viewing any given month, MonthGrid shows days from the previous and
+ next month. This means it always shows six rows, even when first or last
+ row is entirely within an adjacent month.
+
+ \section1 Localizing days
+
+ To localize days, use \l {Locale::toString()}{Locale.toString()}.
+ For example, to display day numbers in an Arabic locale:
+
+ \snippet qtquickcontrols-monthgrid-localization.qml 1
+
+ \sa DayOfWeekRow, WeekNumberColumn, CalendarModel
+*/
+
+/*!
+ \qmlsignal QtQuick.Controls::MonthGrid::pressed(date date)
+
+ This signal is emitted when \a date is pressed.
+*/
+
+/*!
+ \qmlsignal QtQuick.Controls::MonthGrid::released(date date)
+
+ This signal is emitted when \a date is released.
+*/
+
+/*!
+ \qmlsignal QtQuick.Controls::MonthGrid::clicked(date date)
+
+ This signal is emitted when \a date is clicked.
+*/
+
+/*!
+ \qmlsignal QtQuick.Controls::MonthGrid::pressAndHold(date date)
+
+ This signal is emitted when \a date is pressed and held down.
+*/
+
+class QQuickMonthGridPrivate : public QQuickControlPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickMonthGrid)
+
+public:
+ QQuickMonthGridPrivate() : pressTimer(0), pressedItem(nullptr), model(nullptr), delegate(nullptr) { }
+
+ void resizeItems();
+
+ QQuickItem *cellAt(const QPointF &pos) const;
+ QDate dateOf(QQuickItem *cell) const;
+
+ void updatePress(const QPointF &pos);
+ void clearPress(bool clicked);
+
+ bool handlePress(const QPointF &point, ulong timestamp) override;
+ bool handleMove(const QPointF &point, ulong timestamp) override;
+ bool handleRelease(const QPointF &point, ulong timestamp) override;
+ void handleUngrab() override;
+
+ QString title;
+ QVariant source;
+ QDate pressedDate;
+ int pressTimer;
+ QQuickItem *pressedItem;
+ QQuickMonthModel *model;
+ QQmlComponent *delegate;
+};
+
+void QQuickMonthGridPrivate::resizeItems()
+{
+ if (!contentItem)
+ return;
+
+ QSizeF itemSize;
+ itemSize.setWidth((contentItem->width() - 6 * spacing) / 7);
+ itemSize.setHeight((contentItem->height() - 5 * spacing) / 6);
+
+ const auto childItems = contentItem->childItems();
+ for (QQuickItem *item : childItems) {
+ if (!QQuickItemPrivate::get(item)->isTransparentForPositioner())
+ item->setSize(itemSize);
+ }
+}
+
+QQuickItem *QQuickMonthGridPrivate::cellAt(const QPointF &pos) const
+{
+ Q_Q(const QQuickMonthGrid);
+ if (contentItem) {
+ QPointF mapped = q->mapToItem(contentItem, pos);
+ return contentItem->childAt(mapped.x(), mapped.y());
+ }
+ return nullptr;
+}
+
+QDate QQuickMonthGridPrivate::dateOf(QQuickItem *cell) const
+{
+ if (contentItem)
+ return model->dateAt(contentItem->childItems().indexOf(cell));
+ return QDate();
+}
+
+void QQuickMonthGridPrivate::updatePress(const QPointF &pos)
+{
+ Q_Q(QQuickMonthGrid);
+ clearPress(false);
+ pressedItem = cellAt(pos);
+ pressedDate = dateOf(pressedItem);
+ if (pressedDate.isValid())
+ emit q->pressed(pressedDate);
+}
+
+void QQuickMonthGridPrivate::clearPress(bool clicked)
+{
+ Q_Q(QQuickMonthGrid);
+ if (pressedDate.isValid()) {
+ emit q->released(pressedDate);
+ if (clicked)
+ emit q->clicked(pressedDate);
+ }
+ pressedDate = QDate();
+ pressedItem = nullptr;
+}
+
+bool QQuickMonthGridPrivate::handlePress(const QPointF &point, ulong timestamp)
+{
+ Q_Q(QQuickMonthGrid);
+ QQuickControlPrivate::handlePress(point, timestamp);
+ updatePress(point);
+ if (pressedDate.isValid())
+ pressTimer = q->startTimer(qGuiApp->styleHints()->mousePressAndHoldInterval());
+ return true;
+}
+
+bool QQuickMonthGridPrivate::handleMove(const QPointF &point, ulong timestamp)
+{
+ QQuickControlPrivate::handleMove(point, timestamp);
+ updatePress(point);
+ return true;
+}
+
+bool QQuickMonthGridPrivate::handleRelease(const QPointF &point, ulong timestamp)
+{
+ QQuickControlPrivate::handleRelease(point, timestamp);
+ clearPress(true);
+ return true;
+}
+
+void QQuickMonthGridPrivate::handleUngrab()
+{
+ QQuickControlPrivate::handleUngrab();
+ clearPress(false);
+}
+
+QQuickMonthGrid::QQuickMonthGrid(QQuickItem *parent) :
+ QQuickControl(*(new QQuickMonthGridPrivate), parent)
+{
+ Q_D(QQuickMonthGrid);
+ setFlag(ItemIsFocusScope);
+ setActiveFocusOnTab(true);
+ setAcceptedMouseButtons(Qt::LeftButton);
+#if QT_CONFIG(cursor)
+ setCursor(Qt::ArrowCursor);
+#endif
+
+ d->model = new QQuickMonthModel(this);
+ d->source = QVariant::fromValue(d->model);
+ connect(d->model, &QQuickMonthModel::monthChanged, this, &QQuickMonthGrid::monthChanged);
+ connect(d->model, &QQuickMonthModel::yearChanged, this, &QQuickMonthGrid::yearChanged);
+ connect(d->model, &QQuickMonthModel::titleChanged, this, &QQuickMonthGrid::titleChanged);
+}
+
+/*!
+ \qmlproperty int QtQuick.Controls::MonthGrid::month
+
+ This property holds the number of the month. The default value is the
+ current month.
+
+ \include zero-based-months.qdocinc
+
+ \sa Calendar
+*/
+int QQuickMonthGrid::month() const
+{
+ Q_D(const QQuickMonthGrid);
+ return d->model->month() - 1;
+}
+
+void QQuickMonthGrid::setMonth(int month)
+{
+ Q_D(QQuickMonthGrid);
+ if (month < 0 || month > 11) {
+ qmlWarning(this) << "month " << month << " is out of range [0...11]";
+ return;
+ }
+ d->model->setMonth(month + 1);
+}
+
+/*!
+ \qmlproperty int QtQuick.Controls::MonthGrid::year
+
+ This property holds the number of the year.
+
+ The value must be in the range from \c -271820 to \c 275759. The default
+ value is the current year.
+*/
+int QQuickMonthGrid::year() const
+{
+ Q_D(const QQuickMonthGrid);
+ return d->model->year();
+}
+
+void QQuickMonthGrid::setYear(int year)
+{
+ Q_D(QQuickMonthGrid);
+ if (year < -271820 || year > 275759) {
+ qmlWarning(this) << "year " << year << " is out of range [-271820...275759]";
+ return;
+ }
+ d->model->setYear(year);
+}
+
+/*!
+ \internal
+ \qmlproperty model QtQuick.Controls::MonthGrid::source
+
+ This property holds the source model that is used as a data model
+ for the internal content column.
+*/
+QVariant QQuickMonthGrid::source() const
+{
+ Q_D(const QQuickMonthGrid);
+ return d->source;
+}
+
+void QQuickMonthGrid::setSource(const QVariant &source)
+{
+ Q_D(QQuickMonthGrid);
+ if (d->source != source) {
+ d->source = source;
+ emit sourceChanged();
+ }
+}
+
+/*!
+ \qmlproperty string QtQuick.Controls::MonthGrid::title
+
+ This property holds a title for the calendar.
+
+ This property is provided for convenience. MonthGrid itself does
+ not visualize the title. The default value consists of the month name,
+ formatted using \l {Control::locale}{locale}, and the year number.
+*/
+QString QQuickMonthGrid::title() const
+{
+ Q_D(const QQuickMonthGrid);
+ if (d->title.isNull())
+ return d->model->title();
+ return d->title;
+}
+
+void QQuickMonthGrid::setTitle(const QString &title)
+{
+ Q_D(QQuickMonthGrid);
+ if (d->title != title) {
+ d->title = title;
+ emit titleChanged();
+ }
+}
+
+/*!
+ \qmlproperty Component QtQuick.Controls::MonthGrid::delegate
+
+ This property holds the item delegate that visualizes each day.
+
+ In addition to the \c index property, a list of model data roles
+ are available in the context of each delegate:
+ \table
+ \row \li \b model.date : date \li The date of the cell
+ \row \li \b model.day : int \li The number of the day
+ \row \li \b model.today : bool \li Whether the delegate represents today
+ \row \li \b model.weekNumber : int \li The week number
+ \row \li \b model.month : int \li The number of the month
+ \row \li \b model.year : int \li The number of the year
+ \endtable
+
+ The following snippet presents the default implementation of the item
+ delegate. It can be used as a starting point for implementing custom
+ delegates.
+
+ \snippet basic/MonthGrid.qml delegate
+*/
+QQmlComponent *QQuickMonthGrid::delegate() const
+{
+ Q_D(const QQuickMonthGrid);
+ return d->delegate;
+}
+
+void QQuickMonthGrid::setDelegate(QQmlComponent *delegate)
+{
+ Q_D(QQuickMonthGrid);
+ if (d->delegate != delegate) {
+ d->delegate = delegate;
+ emit delegateChanged();
+ }
+}
+
+void QQuickMonthGrid::componentComplete()
+{
+ Q_D(QQuickMonthGrid);
+ QQuickControl::componentComplete();
+ d->resizeItems();
+}
+
+void QQuickMonthGrid::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickMonthGrid);
+ QQuickControl::geometryChange(newGeometry, oldGeometry);
+ if (isComponentComplete())
+ d->resizeItems();
+}
+
+void QQuickMonthGrid::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
+{
+ Q_D(QQuickMonthGrid);
+ QQuickControl::localeChange(newLocale, oldLocale);
+ d->model->setLocale(newLocale);
+}
+
+void QQuickMonthGrid::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
+{
+ Q_D(QQuickMonthGrid);
+ QQuickControl::paddingChange(newPadding, oldPadding);
+ if (isComponentComplete())
+ d->resizeItems();
+}
+
+void QQuickMonthGrid::updatePolish()
+{
+ Q_D(QQuickMonthGrid);
+ QQuickControl::updatePolish();
+ d->resizeItems();
+}
+
+void QQuickMonthGrid::timerEvent(QTimerEvent *event)
+{
+ Q_D(QQuickMonthGrid);
+ if (event->timerId() == d->pressTimer) {
+ if (d->pressedDate.isValid())
+ emit pressAndHold(d->pressedDate);
+ killTimer(d->pressTimer);
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickmonthgrid_p.cpp"