Files
Flora/qml/panels/MonthCalendar.qml
T
grendervill fdf59f5b39 SQLite-база хранилища: свойства, ~sql-блоки, настройки хранилища
- Frontmatter: шапка --- ключ: значение (источник правды свойств)
- VaultSettings: .flora/settings.json (журнал, sqlEnabled, sqlMaxRows)
- Database: files/tags/file_tags/links/properties, только SELECT/WITH
  на read-only соединении (mode=ro + query_only + зонд), лимит строк
- MdParser: ~sql-блоки таблицей (parseBlocks + Renderer), шапка скрыта в просмотре
- Окно: per-window Database/VaultSettings, sync при сохранении, дебаунс reindex
- QML: VaultSettingsDialog, FilePropertiesDialog, меню, автообновление ~sql
- FileStore.journalDir, DocumentManager.reloadDocument
- Тест flora_db_test (23/23 зелёных)
2026-09-07 16:30:06 +03:00

231 lines
9.2 KiB
QML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Flora
Item {
id: cal
signal daySelected(string dateStr)
property date currentMonth: new Date()
readonly property int year: currentMonth.getFullYear()
readonly property int month: currentMonth.getMonth()
function fmtDate(d) {
function pad(n) { return n < 10 ? "0" + n : "" + n }
return d.getFullYear() + "-" + pad(d.getMonth() + 1) + "-" + pad(d.getDate())
}
function gridModel() {
const first = new Date(year, month, 1)
const dowSun0 = first.getDay()
const startDow = (dowSun0 + 6) % 7
const daysInMonth = new Date(year, month + 1, 0).getDate()
const list = []
for (let i = 0; i < startDow; ++i) list.push(0)
for (let d = 1; d <= daysInMonth; ++d) list.push(d)
while (list.length % 7 !== 0) list.push(0)
while (list.length < 42) list.push(0)
return list
}
ColumnLayout {
anchors.fill: parent
spacing: 4
RowLayout {
Layout.fillWidth: true
spacing: 4
// Кнопка Назад — круглая, без прозрачности
ToolButton {
text: "‹"
font.pixelSize: 16
font.bold: true
implicitWidth: 28
implicitHeight: 28
Layout.preferredWidth: 28
Layout.preferredHeight: 28
Layout.alignment: Qt.AlignVCenter
background: Rectangle {
color: parent.pressed ? Theme.surfaceSelected : (parent.hovered ? Theme.surfaceHover : Theme.surface)
border.color: parent.pressed ? Theme.accent : (parent.hovered ? Theme.borderStrong : Theme.border)
radius: 14
}
contentItem: Label {
text: parent.text
font: parent.font
color: Theme.text
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: cal.currentMonth = new Date(year, month - 1, 1)
}
// Поле месяца и года — шире, чтобы всегда влезало, год не пропадает
// Разделяем на два Label: месяц (эластичный, с elide) и год (фикс)
Label {
Layout.fillWidth: true
Layout.minimumWidth: 70
Layout.preferredWidth: 110
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
font.bold: true
color: Theme.text
font.pixelSize: 11
elide: Text.ElideRight
maximumLineCount: 1
wrapMode: Text.NoWrap
text: Qt.locale().monthName(month, Locale.LongFormat)
}
Label {
Layout.preferredWidth: 42
Layout.minimumWidth: 38
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
font.bold: true
color: Theme.text
font.pixelSize: 11
text: year
}
ToolButton {
text: "›"
font.pixelSize: 16
font.bold: true
implicitWidth: 28
implicitHeight: 28
Layout.preferredWidth: 28
Layout.preferredHeight: 28
Layout.alignment: Qt.AlignVCenter
background: Rectangle {
color: parent.pressed ? Theme.surfaceSelected : (parent.hovered ? Theme.surfaceHover : Theme.surface)
border.color: parent.pressed ? Theme.accent : (parent.hovered ? Theme.borderStrong : Theme.border)
radius: 14
}
contentItem: Label {
text: parent.text
font: parent.font
color: Theme.text
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: cal.currentMonth = new Date(year, month + 1, 1)
}
ToolButton {
text: "\u2302"
font.pixelSize: 12
implicitWidth: 28
implicitHeight: 28
Layout.preferredWidth: 28
Layout.preferredHeight: 28
Layout.alignment: Qt.AlignVCenter
background: Rectangle {
color: parent.pressed ? Theme.surfaceSelected : (parent.hovered ? Theme.surfaceHover : Theme.surface)
border.color: parent.pressed ? Theme.accent : (parent.hovered ? Theme.borderStrong : Theme.border)
radius: 14
}
contentItem: Label {
text: parent.text
font: parent.font
color: Theme.text
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
ToolTip.text: qsTr("Сегодня")
ToolTip.visible: hovered
onClicked: cal.currentMonth = new Date()
}
}
RowLayout {
Layout.fillWidth: true
Repeater {
model: ["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"]
Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 10
font.bold: true
color: Theme.textMuted
text: modelData
}
}
}
Grid {
Layout.fillWidth: true
Layout.fillHeight: true
columns: 7
rowSpacing: 2
columnSpacing: 2
Repeater {
model: cal.gridModel()
delegate: Rectangle {
required property int modelData
width: (cal.width - 12) / 7
height: (cal.height - 50) / 6
radius: 6
border.width: isToday ? 1 : 0
border.color: Theme.accent
color: {
if (modelData <= 0) return "transparent"
if (isToday) return Theme.calendarToday
if (isSelected) return Theme.accentMuted
if (hasNote) return Theme.isDark ? "#252a33" : "#f8f9fb"
return Theme.surface
}
readonly property var now: { const t = new Date(); return { day: t.getDate(), month: t.getMonth(), year: t.getFullYear() } }
readonly property bool isToday: modelData > 0 && now.day === modelData && now.month === cal.month && now.year === cal.year
readonly property string ds: modelData > 0 ? Qt.formatDate(new Date(cal.year, cal.month, modelData), "yyyy-MM-dd") : ""
readonly property bool hasNote: {
const _ = cal.currentMonth
if (modelData <= 0 || !fileStore.ready) return false
return fileStore.fileExists(fileStore.vault + "/" + fileStore.journalDir + "/" + ds + ".md")
}
readonly property bool isSelected: false // можно подсветить выбранный день
Label {
id: dayLabel
anchors.centerIn: parent
anchors.verticalCenterOffset: hasNote ? -3 : 0
visible: modelData > 0
text: modelData
font.pixelSize: 11
font.bold: isToday
color: modelData > 0 ? (isToday ? Theme.accentText : Theme.text) : "transparent"
}
Rectangle {
visible: modelData > 0 && parent.hasNote
width: 5; height: 5; radius: 2.5
color: Theme.calendarDot
anchors.top: dayLabel.bottom
anchors.topMargin: 2
anchors.horizontalCenter: parent.horizontalCenter
}
MouseArea {
anchors.fill: parent
enabled: modelData > 0
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const d = new Date(cal.year, cal.month, modelData)
cal.daySelected(fmtDate(d))
}
}
}
}
}
// подпись
Label {
Layout.fillWidth: true
text: qsTr("Клик — заметка дня")
color: Theme.textFaint
font.pixelSize: 9
horizontalAlignment: Text.AlignHCenter
}
}
}