aboutsummaryrefslogtreecommitdiffstats
path: root/examples/quickcontrols/eventcalendar
diff options
context:
space:
mode:
Diffstat (limited to 'examples/quickcontrols/eventcalendar')
-rw-r--r--examples/quickcontrols/eventcalendar/CMakeLists.txt53
-rw-r--r--examples/quickcontrols/eventcalendar/MonthGridDelegate.qml78
-rw-r--r--examples/quickcontrols/eventcalendar/doc/images/qtquickcalendar-eventcalendar.pngbin0 -> 76700 bytes
-rw-r--r--examples/quickcontrols/eventcalendar/doc/src/qtquickcontrols-eventcalendar.qdoc20
-rw-r--r--examples/quickcontrols/eventcalendar/event.h16
-rw-r--r--examples/quickcontrols/eventcalendar/eventcalendar.cpp29
-rw-r--r--examples/quickcontrols/eventcalendar/eventcalendar.pro25
-rw-r--r--examples/quickcontrols/eventcalendar/eventcalendar.qml113
-rw-r--r--examples/quickcontrols/eventcalendar/eventmodel.cpp88
-rw-r--r--examples/quickcontrols/eventcalendar/eventmodel.h56
-rw-r--r--examples/quickcontrols/eventcalendar/qmldir1
-rw-r--r--examples/quickcontrols/eventcalendar/qtquickcontrols2.conf2
-rw-r--r--examples/quickcontrols/eventcalendar/sqleventdatabase.cpp70
-rw-r--r--examples/quickcontrols/eventcalendar/sqleventdatabase.h28
14 files changed, 579 insertions, 0 deletions
diff --git a/examples/quickcontrols/eventcalendar/CMakeLists.txt b/examples/quickcontrols/eventcalendar/CMakeLists.txt
new file mode 100644
index 0000000000..43ed385a3e
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/CMakeLists.txt
@@ -0,0 +1,53 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(eventcalendar LANGUAGES CXX)
+
+set(CMAKE_AUTOMOC ON)
+
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Sql)
+
+qt_add_executable(eventcalendar
+ event.h
+ eventcalendar.cpp
+ eventmodel.cpp eventmodel.h
+ sqleventdatabase.cpp sqleventdatabase.h
+)
+
+set_target_properties(eventcalendar PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+)
+
+target_link_libraries(eventcalendar PUBLIC
+ Qt6::Core
+ Qt6::Gui
+ Qt6::Qml
+ Qt6::Sql
+)
+
+qt_add_qml_module(eventcalendar
+ URI App
+ QML_FILES
+ MonthGridDelegate.qml
+ eventcalendar.qml
+ RESOURCES
+ qtquickcontrols2.conf
+ NO_RESOURCE_TARGET_PATH
+)
+
+install(TARGETS eventcalendar
+ BUNDLE DESTINATION .
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+)
+
+qt_generate_deploy_qml_app_script(
+ TARGET eventcalendar
+ OUTPUT_SCRIPT deploy_script
+ MACOS_BUNDLE_POST_BUILD
+ NO_UNSUPPORTED_PLATFORM_ERROR
+ DEPLOY_USER_QML_MODULES_ON_UNSUPPORTED_PLATFORM
+)
+install(SCRIPT ${deploy_script})
diff --git a/examples/quickcontrols/eventcalendar/MonthGridDelegate.qml b/examples/quickcontrols/eventcalendar/MonthGridDelegate.qml
new file mode 100644
index 0000000000..c49dfda1ae
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/MonthGridDelegate.qml
@@ -0,0 +1,78 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import QtQuick.Controls.Material
+
+import App
+
+ColumnLayout {
+ id: root
+
+ required property EventDatabase eventDatabase
+
+ required property bool today
+ required property int year
+ required property int month
+ required property int day
+
+ required property int visibleMonth
+
+ Material.theme: today ? Material.Dark : undefined
+
+ Label {
+ id: dayText
+ horizontalAlignment: Text.AlignHCenter
+ topPadding: 4
+ opacity: month === root.visibleMonth ? 1 : 0
+ text: day
+
+ Layout.fillWidth: true
+
+ Rectangle {
+ width: height
+ height: Math.max(dayText.implicitWidth, dayText.implicitHeight)
+ radius: width / 2
+ color: Material.primary
+ anchors.centerIn: dayText
+ anchors.verticalCenterOffset: dayText.height - dayText.baselineOffset
+ z: -1
+ visible: root.today
+ }
+ }
+
+ ListView {
+ spacing: 1
+ clip: true
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.topMargin: 4
+
+ delegate: ItemDelegate {
+ id: itemDelegate
+ width: parent.width
+ text: name
+ font.pixelSize: Qt.application.font.pixelSize * 0.8
+ leftPadding: 4
+ rightPadding: 4
+ topPadding: 4
+ bottomPadding: 4
+
+ required property string name
+
+ Material.theme: Material.Dark
+
+ background: Rectangle {
+ color: itemDelegate.Material.primary
+ radius: 3
+ }
+ }
+ model: EventModel {
+ eventDatabase: root.eventDatabase
+ date: new Date(root.year, root.month, root.day)
+ }
+ }
+}
diff --git a/examples/quickcontrols/eventcalendar/doc/images/qtquickcalendar-eventcalendar.png b/examples/quickcontrols/eventcalendar/doc/images/qtquickcalendar-eventcalendar.png
new file mode 100644
index 0000000000..35d905be6d
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/doc/images/qtquickcalendar-eventcalendar.png
Binary files differ
diff --git a/examples/quickcontrols/eventcalendar/doc/src/qtquickcontrols-eventcalendar.qdoc b/examples/quickcontrols/eventcalendar/doc/src/qtquickcontrols-eventcalendar.qdoc
new file mode 100644
index 0000000000..450b1d37a8
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/doc/src/qtquickcontrols-eventcalendar.qdoc
@@ -0,0 +1,20 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \example eventcalendar
+ \keyword Qt Quick Controls - Event Calendar
+ \title Qt Quick Controls - Event Calendar
+ \ingroup qtquickcontrols-examples
+ \examplecategory {User Interface Components}
+ \brief A simple event calendar.
+
+ \image qtquickcalendar-eventcalendar.png
+
+ The Event Calendar example is a simple application that shows how to use
+ \l DayOfWeekRow, \l WeekNumberColumn, and \l MonthGrid to create a calendar.
+ It uses an in-memory SQL database to populate the calendar with events.
+ The example uses the \l {Material Style}{Material style}.
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/quickcontrols/eventcalendar/event.h b/examples/quickcontrols/eventcalendar/event.h
new file mode 100644
index 0000000000..b2cc6b45cf
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/event.h
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef EVENT_H
+#define EVENT_H
+
+#include <QAbstractListModel>
+#include <QDateTime>
+
+struct Event {
+ QString name;
+ QDateTime startDate;
+ QDateTime endDate;
+};
+
+#endif // EVENT_H
diff --git a/examples/quickcontrols/eventcalendar/eventcalendar.cpp b/examples/quickcontrols/eventcalendar/eventcalendar.cpp
new file mode 100644
index 0000000000..bc952a3f9a
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/eventcalendar.cpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QIcon>
+
+#include "sqleventdatabase.h"
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QIcon::setThemeName("eventcalendar");
+
+ QQmlApplicationEngine engine;
+ SqlEventDatabase eventDatabase;
+ engine.setInitialProperties({{ "eventDatabase", QVariant::fromValue(&eventDatabase) }});
+
+ const QUrl url(QStringLiteral("qrc:/eventcalendar.qml"));
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
+ &app, [url](QObject *obj, const QUrl &objUrl) {
+ if (!obj && url == objUrl)
+ QCoreApplication::exit(-1);
+ }, Qt::QueuedConnection);
+ engine.load(url);
+
+ return app.exec();
+}
diff --git a/examples/quickcontrols/eventcalendar/eventcalendar.pro b/examples/quickcontrols/eventcalendar/eventcalendar.pro
new file mode 100644
index 0000000000..742c5d09e8
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/eventcalendar.pro
@@ -0,0 +1,25 @@
+TEMPLATE = app
+TARGET = eventcalendar
+QT += sql qml
+
+CONFIG += qmltypes
+QML_IMPORT_NAME = App
+QML_IMPORT_MAJOR_VERSION = 1
+
+HEADERS += \
+ event.h \
+ eventmodel.h \
+ sqleventdatabase.h
+
+SOURCES += \
+ eventcalendar.cpp \
+ eventmodel.cpp \
+ sqleventdatabase.cpp
+
+RESOURCES += \
+ eventcalendar.qml \
+ MonthGridDelegate.qml \
+ qtquickcontrols2.conf
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quickcalendar/eventcalendar
+INSTALLS += target
diff --git a/examples/quickcontrols/eventcalendar/eventcalendar.qml b/examples/quickcontrols/eventcalendar/eventcalendar.qml
new file mode 100644
index 0000000000..65d85d8d4e
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/eventcalendar.qml
@@ -0,0 +1,113 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Controls.Material
+import QtQuick.Layouts
+
+import App
+
+ApplicationWindow {
+ id: window
+ width: 800
+ height: 600
+ title: qsTr("Event Calendar")
+ visible: true
+
+ required property EventDatabase eventDatabase
+
+ readonly property date currentDate: new Date()
+
+ header: ToolBar {
+ Label {
+ text: window.currentDate.toLocaleString(locale, "MMMM yyyy")
+ font.pixelSize: Qt.application.font.pixelSize * 1.25
+ anchors.centerIn: parent
+ }
+ }
+
+ GridLayout {
+ anchors.fill: parent
+ columns: 2
+
+ DayOfWeekRow {
+ id: dayOfWeekRow
+ locale: grid.locale
+ font.bold: false
+ delegate: Label {
+ text: model.shortName
+ font: dayOfWeekRow.font
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ Layout.column: 1
+ Layout.fillWidth: true
+ }
+
+ WeekNumberColumn {
+ month: grid.month
+ year: grid.year
+ locale: grid.locale
+ font.bold: false
+
+ Layout.fillHeight: true
+ }
+
+ MonthGrid {
+ id: grid
+ month: window.currentDate.getMonth()
+ year: window.currentDate.getFullYear()
+ spacing: 0
+
+ readonly property int gridLineThickness: 1
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ delegate: MonthGridDelegate {
+ id: gridDelegate
+ visibleMonth: grid.month
+ eventDatabase: window.eventDatabase
+ }
+
+ background: Item {
+ x: grid.leftPadding
+ y: grid.topPadding
+ width: grid.availableWidth
+ height: grid.availableHeight
+
+ // Vertical lines
+ Row {
+ spacing: (parent.width - (grid.gridLineThickness * rowRepeater.model)) / rowRepeater.model
+
+ Repeater {
+ id: rowRepeater
+ model: 7
+ delegate: Rectangle {
+ width: 1
+ height: grid.height
+ color: "#ccc"
+ }
+ }
+ }
+
+ // Horizontal lines
+ Column {
+ spacing: (parent.height - (grid.gridLineThickness * columnRepeater.model)) / columnRepeater.model
+
+ Repeater {
+ id: columnRepeater
+ model: 6
+ delegate: Rectangle {
+ width: grid.width
+ height: 1
+ color: "#ccc"
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/quickcontrols/eventcalendar/eventmodel.cpp b/examples/quickcontrols/eventcalendar/eventmodel.cpp
new file mode 100644
index 0000000000..0b225883ff
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/eventmodel.cpp
@@ -0,0 +1,88 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "eventmodel.h"
+
+#include "sqleventdatabase.h"
+
+EventModel::EventModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+}
+
+SqlEventDatabase *EventModel::eventDatabase()
+{
+ return m_eventDatabase;
+}
+
+void EventModel::setEventDatabase(SqlEventDatabase *eventDatabase)
+{
+ if (eventDatabase == m_eventDatabase)
+ return;
+
+ m_eventDatabase = eventDatabase;
+ repopulate();
+ emit eventDatabaseChanged();
+}
+
+QDate EventModel::date() const
+{
+ return m_date;
+}
+
+void EventModel::setDate(QDate date)
+{
+ if (date == m_date)
+ return;
+
+ m_date = date;
+ repopulate();
+ emit dateChanged();
+}
+
+int EventModel::rowCount(const QModelIndex &) const
+{
+ return m_events.size();
+}
+
+QVariant EventModel::data(const QModelIndex &index, int role) const
+{
+ if (!checkIndex(index, CheckIndexOption::IndexIsValid))
+ return QVariant();
+
+ switch (role) {
+ case NameRole: return m_events.at(index.row()).name;
+ case StartDateRole: return m_events.at(index.row()).startDate;
+ case EndDateRole: return m_events.at(index.row()).endDate;
+ default: return QVariant();
+ }
+}
+
+QHash<int, QByteArray> EventModel::roleNames() const
+{
+ static const QHash<int, QByteArray> roles {
+ { NameRole, "name" },
+ { StartDateRole, "startDate" },
+ { EndDateRole, "endDate" }
+ };
+ return roles;
+}
+
+bool EventModel::isValid() const
+{
+ return m_eventDatabase && !m_date.isNull();
+}
+
+void EventModel::repopulate()
+{
+ beginResetModel();
+
+ if (!m_eventDatabase || m_date.isNull()) {
+ m_events.clear();
+ return;
+ }
+
+ m_events = m_eventDatabase->eventsForDate(m_date);
+
+ endResetModel();
+}
diff --git a/examples/quickcontrols/eventcalendar/eventmodel.h b/examples/quickcontrols/eventcalendar/eventmodel.h
new file mode 100644
index 0000000000..62a30df33b
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/eventmodel.h
@@ -0,0 +1,56 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef CONTACTMODEL_H
+#define CONTACTMODEL_H
+
+#include <QAbstractListModel>
+#include <QDate>
+#include <QtQml>
+
+#include "event.h"
+
+class SqlEventDatabase;
+
+class EventModel : public QAbstractListModel
+{
+ Q_OBJECT
+ Q_PROPERTY(SqlEventDatabase *eventDatabase READ eventDatabase WRITE setEventDatabase NOTIFY eventDatabaseChanged)
+ Q_PROPERTY(QDate date READ date WRITE setDate NOTIFY dateChanged)
+ QML_ELEMENT
+ Q_MOC_INCLUDE("sqleventdatabase.h")
+
+public:
+ EventModel(QObject *parent = nullptr);
+
+ enum ContactRole {
+ NameRole = Qt::UserRole,
+ StartDateRole,
+ EndDateRole
+ };
+ Q_ENUM(ContactRole)
+
+ SqlEventDatabase *eventDatabase();
+ void setEventDatabase(SqlEventDatabase *eventDatabase);
+
+ QDate date() const;
+ void setDate(QDate date);
+
+ int rowCount(const QModelIndex & = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ QHash<int, QByteArray> roleNames() const;
+
+signals:
+ void eventDatabaseChanged();
+ void dateChanged();
+
+private:
+ bool isValid() const;
+ void repopulate();
+
+ SqlEventDatabase *m_eventDatabase = nullptr;
+ QDate m_date;
+ QVector<Event> m_events;
+};
+
+#endif // CONTACTMODEL_H
diff --git a/examples/quickcontrols/eventcalendar/qmldir b/examples/quickcontrols/eventcalendar/qmldir
new file mode 100644
index 0000000000..6b7f86bfac
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/qmldir
@@ -0,0 +1 @@
+module App
diff --git a/examples/quickcontrols/eventcalendar/qtquickcontrols2.conf b/examples/quickcontrols/eventcalendar/qtquickcontrols2.conf
new file mode 100644
index 0000000000..b6c7c87ea1
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/qtquickcontrols2.conf
@@ -0,0 +1,2 @@
+[Controls]
+Style=Material
diff --git a/examples/quickcontrols/eventcalendar/sqleventdatabase.cpp b/examples/quickcontrols/eventcalendar/sqleventdatabase.cpp
new file mode 100644
index 0000000000..3d845f3b3b
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/sqleventdatabase.cpp
@@ -0,0 +1,70 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "sqleventdatabase.h"
+
+#include <QDebug>
+#include <QFileInfo>
+#include <QSqlError>
+#include <QSqlQuery>
+
+SqlEventDatabase::SqlEventDatabase()
+{
+ createConnection();
+}
+
+QVector<Event> SqlEventDatabase::eventsForDate(QDate date)
+{
+ const QString queryStr = QString::fromLatin1("SELECT * FROM Event WHERE '%1' >= startDate AND '%1' <= endDate").arg(date.toString("yyyy-MM-dd"));
+ QSqlQuery query(queryStr);
+ if (!query.exec()) {
+ qWarning() << "SQL query failed";
+ return {};
+ }
+
+ QVector<Event> events;
+ while (query.next()) {
+ Event event;
+ event.name = query.value("name").toString();
+
+ QDateTime startDate;
+ startDate.setDate(query.value("startDate").toDate());
+ startDate.setTime(QTime(0, 0).addSecs(query.value("startTime").toInt()));
+ event.startDate = startDate;
+
+ QDateTime endDate;
+ endDate.setDate(query.value("endDate").toDate());
+ endDate.setTime(QTime(0, 0).addSecs(query.value("endTime").toInt()));
+ event.endDate = endDate;
+
+ events.append(event);
+ }
+ return events;
+}
+
+/*
+ Defines a helper function to open a connection to an
+ in-memory SQLITE database and to create a table.
+*/
+void SqlEventDatabase::createConnection()
+{
+ QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
+ db.setDatabaseName(":memory:");
+ if (!db.open()) {
+ qFatal("Cannot open database");
+ return;
+ }
+
+ QSqlQuery query;
+ const QString year = QDate::currentDate().toString("yyyy");
+ const QString month = QDate::currentDate().toString("MM");
+ // Keep the example up-to-date by making the events fall in the current year and month.
+ // We store the time as seconds because it's easier to query.
+ query.exec("create table Event (name TEXT, startDate DATE, startTime INT, endDate DATE, endTime INT)");
+ query.exec(QString::fromLatin1("insert into Event values('Grocery shopping', '%1-%2-01', 36000, '%1-%2-01', 39600)").arg(year, month));
+ query.exec(QString::fromLatin1("insert into Event values('Ice skating', '%1-%2-01', 57600, '%1-%2-01', 61200)").arg(year, month));
+ query.exec(QString::fromLatin1("insert into Event values('Doctor''s appointment', '%1-%2-15', 57600, '%1-%2-15', 63000)").arg(year, month));
+ query.exec(QString::fromLatin1("insert into Event values('Conference', '%1-%2-24', 32400, '%1-%2-28', 61200)").arg(year, month));
+
+ return;
+}
diff --git a/examples/quickcontrols/eventcalendar/sqleventdatabase.h b/examples/quickcontrols/eventcalendar/sqleventdatabase.h
new file mode 100644
index 0000000000..b867b7860d
--- /dev/null
+++ b/examples/quickcontrols/eventcalendar/sqleventdatabase.h
@@ -0,0 +1,28 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef SQLEVENTDATABASE_H
+#define SQLEVENTDATABASE_H
+
+#include <QObject>
+#include <QtQml>
+#include <QVector>
+
+#include "event.h"
+
+class SqlEventDatabase : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(EventDatabase)
+ QML_UNCREATABLE("EventDatabase should not be created in QML")
+
+public:
+ SqlEventDatabase();
+
+ QVector<Event> eventsForDate(QDate date);
+
+private:
+ static void createConnection();
+};
+
+#endif // SQLEVENTDATABASE_H