/* * This file is part of the Flowee project * Copyright (C) 2025 Tom Zander * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick import QtQuick.Controls.Basic as QQC2 import "../Flowee" as Flowee Item { id: root // please only set it ever to be the first of the month! required property date month // the date before which all items have lower visibility property date oldCutoff: new Date(1978, 0, 1) // when the user clicks on a date. property int selected: 0 // an array of ints. property var highlights: [] property string monthFormat: "MMM yy" width: implicitWidth height: implicitHeight implicitWidth: 88 implicitHeight: days.y + 6 * 13 onVisibleChanged: if (visible) selected = 0; QQC2.Label { id: monthLabel anchors.horizontalCenter: parent.horizontalCenter text: Qt.locale().toString(root.month, root.monthFormat) font.pixelSize: 9 color: palette.dark } Rectangle { // sundays anchors.top: days.top anchors.topMargin: root.month.getDay() === 0 ? 0 : 10 anchors.bottom: days.bottom width: 10 color: palette.highlight opacity: 0.2 radius: 3 } Rectangle { // saturdays anchors.top: days.top anchors.bottom: days.bottom anchors.bottomMargin: { var last = new Date(root.month.getFullYear(), root.month.getMonth() + 1, 0).getDay(); return last === 6 ? 0 : 13; } anchors.right: days.right width: 10 color: palette.highlight opacity: 0.27 radius: 3 } Flow { id: days anchors.top: monthLabel.bottom width: parent.width spacing: 3 property int lowBrightnessDay: { if (isNaN(root.oldCutoff)) return -1; let cutOff = root.oldCutoff; let current = root.month; // remember, this one is always the first of the month let copy = new Date(cutOff.getFullYear(), cutOff.getMonth(), 1); if (current < copy) // the entire month is before cutoff. return 40; if (current.getFullYear() !== cutOff.getFullYear() || current.getMonth() !== cutOff.getMonth()) return -1; return cutOff.getDate() - 1; } Repeater { model: root.month.getDay() Item { width: 10; height: 10 } } Repeater { model: { // a dirty JavaScript hack. Day zero is actually the last day in the previous month. var hack = new Date(root.month.getFullYear(), root.month.getMonth() + 1, 0) return hack.getDate(); } Item { width: 10 height: theLabel.contentHeight property bool highlighted: root.highlights.includes(modelData + 1) Rectangle { color: parent.highlighted ? mainWindow.floweeGreen : "#00000000" width: parent.width height: width anchors.centerIn: parent radius: 6 } QQC2.Label { id: theLabel text: (modelData + 1) width: parent.width horizontalAlignment: Text.AlignHCenter font.pixelSize: 7 color: parent.highlighted ? "black" : palette.dark opacity: modelData < days.lowBrightnessDay ? 0.3 : 1 } MouseArea { anchors.fill: parent enabled: modelData >= days.lowBrightnessDay onClicked: root.selected = modelData + 1; } } } } }