Skip to content

Instantly share code, notes, and snippets.

@alex-spataru
Created October 16, 2023 07:22
Show Gist options
  • Save alex-spataru/fdd07a467c017722e33f5ff7d8acc9ed to your computer and use it in GitHub Desktop.
Save alex-spataru/fdd07a467c017722e33f5ff7d8acc9ed to your computer and use it in GitHub Desktop.
Classical Qt Quick Controls 1.0 Calendar widget for Qt 6
/*
* Copyright (c) 2023 Alex Spataru <https://github.com/alex-spataru>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
Item {
id: root
//
// Custom properties
//
property date selectedDate: new Date()
property string monthName: Qt.formatDate(selectedDate, "MMMM yyyy")
property int firstDay: new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1).getDay()
property int daysInMonth: new Date(selectedDate.getFullYear(), selectedDate.getMonth() + 1, 0).getDate()
//
// Update custom properties when the selected date is changed
//
onSelectedDateChanged: {
root.monthName = Qt.formatDate(selectedDate, "MMMM yyyy")
root.firstDay = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1).getDay()
root.daysInMonth = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + 1, 0).getDate()
}
//
// Widget elements
//
ColumnLayout {
spacing: -1
anchors.fill: parent
//
// Month/Year display & navigator
//
Rectangle {
height: 48
color: "#F9F9F9"
Layout.fillWidth: true
border {
width: 1
color: "#A9A9A9"
}
Button {
icon.width: 24
icon.height: 24
background: Item {}
icon.source: "qrc:/icons/chevron-left.svg" // replace with your actual chevron left icon
anchors {
leftMargin: 8
left: parent.left
verticalCenter: parent.verticalCenter
}
onClicked: {
if (selectedDate.getMonth() === 0)
selectedDate = new Date(selectedDate.getFullYear() - 1, 11, selectedDate.getDate());
else
selectedDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth() - 1, selectedDate.getDate());
}
}
Label {
font.pixelSize: 18
text: root.monthName
anchors.centerIn: parent
}
Button {
icon.width: 24
icon.height: 24
background: Item {}
icon.source: "qrc:/icons/chevron-right.svg" // replace with your actual chevron right icon
anchors {
rightMargin: 8
right: parent.right
verticalCenter: parent.verticalCenter
}
onClicked: {
if (selectedDate.getMonth() === 11)
selectedDate = new Date(selectedDate.getFullYear() + 1, 0, selectedDate.getDate());
else
selectedDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + 1, selectedDate.getDate());
}
}
}
//
// Row with day names
//
Rectangle {
height: 40
color: "#FCFCFC"
Layout.fillWidth: true
border {
width: 1
color: "#A9A9A9"
}
RowLayout {
spacing: -1
anchors.fill: parent
Repeater {
id: daysOfWeek
property var days: [
qsTr("Sun"),
qsTr("Mon"),
qsTr("Tue"),
qsTr("Wed"),
qsTr("Thu"),
qsTr("Fri"),
qsTr("Sat")
]
model: 7
delegate: Item {
Layout.fillWidth: true
Layout.fillHeight: true
Label {
anchors.centerIn: parent
text: daysOfWeek.days[index]
horizontalAlignment: Qt.AlignHCenter
}
}
}
}
}
//
// Grid with day numbers
//
Rectangle {
color: "#FFFFFF"
Layout.fillWidth: true
Layout.fillHeight: true
border {
width: 1
color: "#DDDDDD"
}
GridLayout {
columns: 7
rowSpacing: -1
columnSpacing: -1
anchors.fill: parent
Repeater {
model: 42
delegate: Rectangle {
id: cell
Layout.fillWidth: true
Layout.fillHeight: true
property int daysInPrevMonth: new Date(root.selectedDate.getFullYear(), root.selectedDate.getMonth(), 0).getDate()
property int relativeDay: index + 1 - root.firstDay
property int day: relativeDay <= 0 ? daysInPrevMonth + relativeDay : (relativeDay > root.daysInMonth ? relativeDay - root.daysInMonth : relativeDay)
property bool dayInMonth: relativeDay > 0 && relativeDay <= root.daysInMonth
color: root.selectedDate.getDate() === relativeDay && dayInMonth ? "#1B77D7" : "transparent"
border {
width: 1
color: root.selectedDate.getDate() === relativeDay && dayInMonth ? "#1B77D7" : "#DDDDDD"
}
Label {
text: day
anchors.centerIn: parent
opacity: dayInMonth ? 1 : 0.5
horizontalAlignment: Qt.AlignHCenter
color: root.selectedDate.getDate() === relativeDay && dayInMonth ? "#FFFFFF" : "#000000"
}
MouseArea {
enabled: dayInMonth
anchors.fill: parent
onClicked: root.selectedDate.setDate(day)
}
}
}
}
}
}
//
// Widget border
//
Rectangle {
color: "transparent"
anchors.fill: parent
border {
width: 1
color: "#A9A9A9"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment