Share one calendar with day selection and a month picker
This commit is contained in:
1 parent
d59725f193
commit
3164e50b36
10 files changed
+773
-543
No files matched your search
@@ -0,0 +1,176 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import "CalendarModel.js" as CalendarModel
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property var calendar
|
||||
|
||||
readonly property var weeks: CalendarModel.monthGrid(calendar.viewYear, calendar.viewMonth,
|
||||
calendar.weekStart, calendar.todayKey, calendar.selectedKey)
|
||||
readonly property var weekdays: CalendarModel.weekdayOrder(calendar.weekStart)
|
||||
readonly property color foreground: calendar.foreground
|
||||
readonly property real headerHeight: Style.space(16)
|
||||
|
||||
width: grid.width
|
||||
height: grid.height
|
||||
|
||||
Column {
|
||||
id: grid
|
||||
spacing: Style.space(3)
|
||||
|
||||
Row {
|
||||
id: headerRow
|
||||
spacing: root.calendar.cellSpacing
|
||||
|
||||
Rectangle {
|
||||
visible: root.calendar.showWeekNumbers
|
||||
width: root.calendar.weekColumnWidth
|
||||
height: root.headerHeight
|
||||
radius: Style.cornerRadius
|
||||
color: weekHeaderMouse.containsMouse ? Style.hoverFillFor(root.foreground, Color.accent) : "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "W"
|
||||
color: weekHeaderMouse.containsMouse
|
||||
? Style.hoverStateColor(root.foreground, Color.accent)
|
||||
: Qt.darker(root.foreground, 1.9)
|
||||
font.family: root.calendar.fontFamily
|
||||
font.pixelSize: Style.font.caption
|
||||
font.letterSpacing: 1
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: weekHeaderMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.calendar.weekHeaderClicked()
|
||||
}
|
||||
|
||||
PanelToolTip {
|
||||
visible: weekHeaderMouse.containsMouse && root.calendar.weekHeaderTooltip !== ""
|
||||
text: root.calendar.weekHeaderTooltip
|
||||
fontFamily: root.calendar.fontFamily
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: root.calendar.showWeekNumbers
|
||||
width: root.calendar.gutterWidth
|
||||
height: root.headerHeight
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: root.weekdays
|
||||
|
||||
Text {
|
||||
required property var modelData
|
||||
width: root.calendar.cellWidth
|
||||
height: root.headerHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
textFormat: Text.PlainText
|
||||
text: root.calendar.weekdayLabel(modelData)
|
||||
color: root.calendar.mutedForeground
|
||||
font.family: root.calendar.fontFamily
|
||||
font.pixelSize: Style.font.caption
|
||||
font.letterSpacing: 1
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: root.weeks
|
||||
|
||||
Row {
|
||||
required property var modelData
|
||||
spacing: root.calendar.cellSpacing
|
||||
|
||||
Text {
|
||||
visible: root.calendar.showWeekNumbers
|
||||
width: root.calendar.weekColumnWidth
|
||||
height: root.calendar.cellHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
textFormat: Text.PlainText
|
||||
text: modelData.week
|
||||
color: Qt.darker(root.foreground, 1.9)
|
||||
font.family: root.calendar.fontFamily
|
||||
font.pixelSize: Style.font.caption
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: root.calendar.showWeekNumbers
|
||||
width: root.calendar.gutterWidth
|
||||
height: root.calendar.cellHeight
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: modelData.days
|
||||
|
||||
DayCell {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: root.calendar.showWeekNumbers
|
||||
x: root.calendar.weekColumnWidth + root.calendar.cellSpacing
|
||||
+ Math.round((root.calendar.gutterWidth - width) / 2)
|
||||
y: headerRow.height + grid.spacing
|
||||
width: Style.spacing.hairline
|
||||
height: grid.height - headerRow.height - grid.spacing
|
||||
color: root.foreground
|
||||
opacity: 0.1
|
||||
}
|
||||
|
||||
component DayCell: Rectangle {
|
||||
id: cell
|
||||
|
||||
required property var modelData
|
||||
|
||||
readonly property color todayFill: Style.selectedStateColor(root.foreground, Color.accent)
|
||||
readonly property color dayColor: {
|
||||
if (modelData.today) return Color.background
|
||||
if (!modelData.inMonth) return root.foreground
|
||||
return modelData.weekend ? Qt.darker(root.foreground, 1.45) : root.foreground
|
||||
}
|
||||
|
||||
width: root.calendar.cellWidth
|
||||
height: root.calendar.cellHeight
|
||||
radius: Style.cornerRadius
|
||||
color: {
|
||||
if (modelData.today) return todayFill
|
||||
if (dayMouse.containsMouse) return Style.hoverFillFor(root.foreground, Color.accent)
|
||||
if (modelData.selected) return Style.selectedFillFor(root.foreground, Color.accent)
|
||||
return "transparent"
|
||||
}
|
||||
border.width: modelData.selected && !modelData.today ? Math.max(1, Style.spacing.hairline) : 0
|
||||
border.color: Style.selectedBorderFor(root.foreground, Color.accent)
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
textFormat: Text.PlainText
|
||||
text: cell.modelData.day
|
||||
color: cell.dayColor
|
||||
opacity: cell.modelData.inMonth || cell.modelData.today ? 1 : 0.3
|
||||
font.family: root.calendar.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
font.bold: cell.modelData.today || cell.modelData.selected
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: dayMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.calendar.selectDay(cell.modelData.year, cell.modelData.month, cell.modelData.day)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
.pragma library
|
||||
|
||||
var MS_PER_DAY = 86400000
|
||||
|
||||
var WEEKDAY_NAMES = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]
|
||||
|
||||
function pad2(value) {
|
||||
var n = Number(value)
|
||||
return (n < 10 ? "0" : "") + n
|
||||
}
|
||||
|
||||
function dateKey(year, month, day) {
|
||||
return year + "-" + pad2(Number(month) + 1) + "-" + pad2(day)
|
||||
}
|
||||
|
||||
function keyForDate(date) {
|
||||
return dateKey(date.getFullYear(), date.getMonth(), date.getDate())
|
||||
}
|
||||
|
||||
function coerceWeekStart(value) {
|
||||
if (value === undefined || value === null) return null
|
||||
if (typeof value === "number")
|
||||
return isFinite(value) ? ((Math.round(value) % 7) + 7) % 7 : null
|
||||
|
||||
var text = String(value).replace(/^\s+|\s+$/g, "").toLowerCase()
|
||||
if (text === "") return null
|
||||
|
||||
for (var i = 0; i < WEEKDAY_NAMES.length; i++)
|
||||
if (WEEKDAY_NAMES[i] === text || WEEKDAY_NAMES[i].substr(0, 3) === text) return i
|
||||
|
||||
var parsed = parseInt(text, 10)
|
||||
return isFinite(parsed) ? ((parsed % 7) + 7) % 7 : null
|
||||
}
|
||||
|
||||
function normalizedWeekStart(value, fallback) {
|
||||
var configured = coerceWeekStart(value)
|
||||
if (configured !== null) return configured
|
||||
var fallbackStart = coerceWeekStart(fallback)
|
||||
return fallbackStart === null ? 1 : fallbackStart
|
||||
}
|
||||
|
||||
function weekStartSettingName(index) {
|
||||
return WEEKDAY_NAMES[normalizedWeekStart(index, 1)]
|
||||
}
|
||||
|
||||
function toggledWeekStart(index) {
|
||||
return normalizedWeekStart(index, 1) === 1 ? 0 : 1
|
||||
}
|
||||
|
||||
function weekdayOrder(weekStart) {
|
||||
var start = normalizedWeekStart(weekStart, 1)
|
||||
var order = []
|
||||
for (var i = 0; i < 7; i++) order.push((start + i) % 7)
|
||||
return order
|
||||
}
|
||||
|
||||
function isoWeek(year, month, day) {
|
||||
var date = new Date(Date.UTC(year, month, day))
|
||||
var weekday = date.getUTCDay() || 7
|
||||
date.setUTCDate(date.getUTCDate() + 4 - weekday)
|
||||
var yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1))
|
||||
return Math.ceil(((date.getTime() - yearStart.getTime()) / MS_PER_DAY + 1) / 7)
|
||||
}
|
||||
|
||||
function isoWeekLiteral(year, month, day) {
|
||||
return pad2(isoWeek(year, month, day))
|
||||
}
|
||||
|
||||
function dayOfYear(year, month, day) {
|
||||
return Math.round((Date.UTC(year, month, day) - Date.UTC(year, 0, 1)) / MS_PER_DAY) + 1
|
||||
}
|
||||
|
||||
function daysInYear(year) {
|
||||
return dayOfYear(year, 11, 31)
|
||||
}
|
||||
|
||||
function daysInMonth(year, month) {
|
||||
return new Date(year, Number(month) + 1, 0).getDate()
|
||||
}
|
||||
|
||||
function yearProgress(year, month, day) {
|
||||
var total = daysInYear(year)
|
||||
if (total <= 0) return 0
|
||||
return Math.max(0, Math.min(1, (dayOfYear(year, month, day) - 1) / total))
|
||||
}
|
||||
|
||||
function yearProgressPercent(year, month, day) {
|
||||
return Math.round(yearProgress(year, month, day) * 100)
|
||||
}
|
||||
|
||||
function stepMonth(year, month, delta) {
|
||||
var target = new Date(year, Number(month) + Number(delta), 1)
|
||||
return { year: target.getFullYear(), month: target.getMonth() }
|
||||
}
|
||||
|
||||
function stepDay(year, month, day, delta) {
|
||||
var target = new Date(year, month, Number(day) + Number(delta))
|
||||
return { year: target.getFullYear(), month: target.getMonth(), day: target.getDate() }
|
||||
}
|
||||
|
||||
function clampDay(year, month, day) {
|
||||
return Math.max(1, Math.min(Number(day), daysInMonth(year, month)))
|
||||
}
|
||||
|
||||
function daysBetween(fromYear, fromMonth, fromDay, toYear, toMonth, toDay) {
|
||||
return Math.round((Date.UTC(toYear, toMonth, toDay) - Date.UTC(fromYear, fromMonth, fromDay)) / MS_PER_DAY)
|
||||
}
|
||||
|
||||
function relativeDayLabel(offset) {
|
||||
if (offset === 0) return "Today"
|
||||
if (offset === 1) return "Tomorrow"
|
||||
if (offset === -1) return "Yesterday"
|
||||
if (offset > 0) return "In " + offset + " days"
|
||||
return (-offset) + " days ago"
|
||||
}
|
||||
|
||||
function monthGrid(year, month, weekStart, todayKey, selectedKey) {
|
||||
var start = normalizedWeekStart(weekStart, 1)
|
||||
var leading = (new Date(year, month, 1).getDay() - start + 7) % 7
|
||||
var cursor = new Date(year, month, 1 - leading)
|
||||
var today = String(todayKey || "")
|
||||
var selected = String(selectedKey || "")
|
||||
var weeks = []
|
||||
|
||||
for (var row = 0; row < 6; row++) {
|
||||
var days = []
|
||||
var thursday = null
|
||||
for (var column = 0; column < 7; column++) {
|
||||
var cellYear = cursor.getFullYear()
|
||||
var cellMonth = cursor.getMonth()
|
||||
var cellDay = cursor.getDate()
|
||||
var weekday = cursor.getDay()
|
||||
var key = dateKey(cellYear, cellMonth, cellDay)
|
||||
if (weekday === 4) thursday = { year: cellYear, month: cellMonth, day: cellDay }
|
||||
days.push({
|
||||
key: key,
|
||||
year: cellYear,
|
||||
month: cellMonth,
|
||||
day: cellDay,
|
||||
weekday: weekday,
|
||||
inMonth: cellMonth === month && cellYear === year,
|
||||
weekend: weekday === 0 || weekday === 6,
|
||||
today: key === today,
|
||||
selected: key === selected
|
||||
})
|
||||
cursor.setDate(cursor.getDate() + 1)
|
||||
}
|
||||
var anchor = thursday || days[0]
|
||||
weeks.push({
|
||||
week: isoWeek(anchor.year, anchor.month, anchor.day),
|
||||
days: days
|
||||
})
|
||||
}
|
||||
return weeks
|
||||
}
|
||||
|
||||
if (typeof module !== "undefined") {
|
||||
module.exports = {
|
||||
pad2: pad2,
|
||||
dateKey: dateKey,
|
||||
keyForDate: keyForDate,
|
||||
normalizedWeekStart: normalizedWeekStart,
|
||||
weekStartSettingName: weekStartSettingName,
|
||||
toggledWeekStart: toggledWeekStart,
|
||||
weekdayOrder: weekdayOrder,
|
||||
isoWeek: isoWeek,
|
||||
isoWeekLiteral: isoWeekLiteral,
|
||||
dayOfYear: dayOfYear,
|
||||
daysInYear: daysInYear,
|
||||
daysInMonth: daysInMonth,
|
||||
yearProgress: yearProgress,
|
||||
yearProgressPercent: yearProgressPercent,
|
||||
stepMonth: stepMonth,
|
||||
stepDay: stepDay,
|
||||
clampDay: clampDay,
|
||||
daysBetween: daysBetween,
|
||||
relativeDayLabel: relativeDayLabel,
|
||||
monthGrid: monthGrid
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property var calendar
|
||||
|
||||
readonly property int columns: 4
|
||||
readonly property int rows: 3
|
||||
readonly property real gap: calendar.cellSpacing * 2
|
||||
readonly property color foreground: calendar.foreground
|
||||
|
||||
Grid {
|
||||
anchors.fill: parent
|
||||
columns: root.columns
|
||||
spacing: root.gap
|
||||
|
||||
Repeater {
|
||||
model: 12
|
||||
|
||||
Rectangle {
|
||||
id: monthCell
|
||||
|
||||
required property int index
|
||||
|
||||
readonly property bool isCurrentMonth: root.calendar.today.getFullYear() === root.calendar.pickerYear
|
||||
&& root.calendar.today.getMonth() === index
|
||||
readonly property bool isViewedMonth: root.calendar.viewYear === root.calendar.pickerYear
|
||||
&& root.calendar.viewMonth === index
|
||||
readonly property bool isCursor: root.calendar.pickerMonth === index
|
||||
|
||||
width: (root.width - root.gap * (root.columns - 1)) / root.columns
|
||||
height: (root.height - root.gap * (root.rows - 1)) / root.rows
|
||||
radius: Style.cornerRadius
|
||||
color: {
|
||||
if (isCurrentMonth) return Style.selectedStateColor(root.foreground, Color.accent)
|
||||
if (isCursor) return Style.hoverFillFor(root.foreground, Color.accent)
|
||||
return "transparent"
|
||||
}
|
||||
border.width: isViewedMonth && !isCurrentMonth ? Math.max(1, Style.spacing.hairline) : 0
|
||||
border.color: Style.selectedBorderFor(root.foreground, Color.accent)
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
textFormat: Text.PlainText
|
||||
text: root.calendar.monthLabel(monthCell.index)
|
||||
color: monthCell.isCurrentMonth ? Color.background : root.foreground
|
||||
font.family: root.calendar.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
font.letterSpacing: 1
|
||||
font.bold: monthCell.isCurrentMonth || monthCell.isViewedMonth
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onContainsMouseChanged: if (containsMouse) root.calendar.pickerMonth = monthCell.index
|
||||
onClicked: root.calendar.choosePickerMonth(root.calendar.pickerYear, monthCell.index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import "CalendarModel.js" as CalendarModel
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
property date today: new Date()
|
||||
property int weekStart: CalendarModel.normalizedWeekStart(null, Qt.locale().firstDayOfWeek)
|
||||
property color foreground: Color.foreground
|
||||
property string fontFamily: Style.font.family
|
||||
property bool showWeekNumbers: false
|
||||
property bool navigationAtBottom: false
|
||||
property string weekHeaderTooltip: ""
|
||||
|
||||
property real cellWidth: Style.space(36)
|
||||
property real cellHeight: Style.space(28)
|
||||
property real cellSpacing: Style.space(2)
|
||||
property real weekColumnWidth: Style.space(32)
|
||||
property real gutterWidth: Style.space(14)
|
||||
|
||||
property int viewYear: today.getFullYear()
|
||||
property int viewMonth: today.getMonth()
|
||||
property int selectedYear: today.getFullYear()
|
||||
property int selectedMonth: today.getMonth()
|
||||
property int selectedDay: today.getDate()
|
||||
|
||||
property bool pickingMonth: false
|
||||
property int pickerYear: viewYear
|
||||
property int pickerMonth: viewMonth
|
||||
|
||||
readonly property string todayKey: CalendarModel.keyForDate(today)
|
||||
readonly property string selectedKey: CalendarModel.dateKey(selectedYear, selectedMonth, selectedDay)
|
||||
readonly property bool selectionIsToday: selectedKey === todayKey
|
||||
readonly property bool viewingCurrentMonth: viewYear === today.getFullYear() && viewMonth === today.getMonth()
|
||||
readonly property date viewDate: new Date(viewYear, viewMonth, 1)
|
||||
readonly property date selectedDate: new Date(selectedYear, selectedMonth, selectedDay)
|
||||
readonly property int selectedOffset: CalendarModel.daysBetween(
|
||||
today.getFullYear(), today.getMonth(), today.getDate(), selectedYear, selectedMonth, selectedDay)
|
||||
readonly property var labelLocale: Qt.locale("en_US")
|
||||
readonly property real gridWidth: body.width
|
||||
readonly property color mutedForeground: Qt.darker(foreground, 1.5)
|
||||
|
||||
signal weekHeaderClicked()
|
||||
|
||||
spacing: Style.space(8)
|
||||
|
||||
function weekdayLabel(weekday) {
|
||||
return String(labelLocale.dayName(weekday, Locale.ShortFormat)).toUpperCase()
|
||||
}
|
||||
|
||||
function monthLabel(month) {
|
||||
return String(labelLocale.monthName(month, Locale.ShortFormat)).toUpperCase()
|
||||
}
|
||||
|
||||
function selectDay(year, month, day) {
|
||||
selectedYear = year
|
||||
selectedMonth = month
|
||||
selectedDay = day
|
||||
viewYear = year
|
||||
viewMonth = month
|
||||
pickingMonth = false
|
||||
}
|
||||
|
||||
function goToToday() {
|
||||
selectDay(today.getFullYear(), today.getMonth(), today.getDate())
|
||||
}
|
||||
|
||||
function moveMonth(delta) {
|
||||
var next = CalendarModel.stepMonth(viewYear, viewMonth, delta)
|
||||
selectDay(next.year, next.month, CalendarModel.clampDay(next.year, next.month, selectedDay))
|
||||
}
|
||||
|
||||
function moveYear(delta) {
|
||||
if (pickingMonth) pickerYear += delta
|
||||
else moveMonth(delta * 12)
|
||||
}
|
||||
|
||||
function moveSelection(days) {
|
||||
var next = CalendarModel.stepDay(selectedYear, selectedMonth, selectedDay, days)
|
||||
selectDay(next.year, next.month, next.day)
|
||||
}
|
||||
|
||||
function movePickerCursor(months) {
|
||||
var next = CalendarModel.stepMonth(pickerYear, pickerMonth, months)
|
||||
pickerYear = next.year
|
||||
pickerMonth = next.month
|
||||
}
|
||||
|
||||
function handleMove(dx, dy) {
|
||||
if (pickingMonth) movePickerCursor(dx + dy * 4)
|
||||
else moveSelection(dx + dy * 7)
|
||||
}
|
||||
|
||||
function openPicker() {
|
||||
pickerYear = viewYear
|
||||
pickerMonth = viewMonth
|
||||
pickingMonth = true
|
||||
}
|
||||
|
||||
function togglePicker() {
|
||||
if (pickingMonth) pickingMonth = false
|
||||
else openPicker()
|
||||
}
|
||||
|
||||
function choosePickerMonth(year, month) {
|
||||
selectDay(year, month, CalendarModel.clampDay(year, month, selectedDay))
|
||||
}
|
||||
|
||||
function activate() {
|
||||
if (pickingMonth) choosePickerMonth(pickerYear, pickerMonth)
|
||||
else goToToday()
|
||||
}
|
||||
|
||||
function dismissPicker() {
|
||||
if (!pickingMonth) return false
|
||||
pickingMonth = false
|
||||
return true
|
||||
}
|
||||
|
||||
function selectedSummary() {
|
||||
var format = selectedYear === today.getFullYear() ? "dddd, MMMM d" : "dddd, MMMM d, yyyy"
|
||||
return Qt.formatDate(selectedDate, format)
|
||||
+ " · Day " + CalendarModel.dayOfYear(selectedYear, selectedMonth, selectedDay)
|
||||
+ " · " + CalendarModel.relativeDayLabel(selectedOffset)
|
||||
}
|
||||
|
||||
MonthNavigation {
|
||||
visible: !root.navigationAtBottom
|
||||
}
|
||||
|
||||
Item {
|
||||
width: root.width
|
||||
height: body.height
|
||||
|
||||
Item {
|
||||
id: body
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: days.width
|
||||
height: days.height
|
||||
|
||||
CalendarDays {
|
||||
id: days
|
||||
calendar: root
|
||||
visible: !root.pickingMonth
|
||||
}
|
||||
|
||||
CalendarMonthPicker {
|
||||
anchors.fill: parent
|
||||
calendar: root
|
||||
visible: root.pickingMonth
|
||||
}
|
||||
|
||||
WheelHandler {
|
||||
onWheel: function(event) {
|
||||
if (event.angleDelta.y === 0) return
|
||||
var step = event.angleDelta.y > 0 ? -1 : 1
|
||||
if (root.pickingMonth) root.pickerYear += step
|
||||
else root.moveMonth(step)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
width: root.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
textFormat: Text.PlainText
|
||||
elide: Text.ElideRight
|
||||
text: root.selectedSummary()
|
||||
color: root.mutedForeground
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
}
|
||||
|
||||
MonthNavigation {
|
||||
visible: root.navigationAtBottom
|
||||
}
|
||||
|
||||
component MonthNavigation: Item {
|
||||
width: root.width
|
||||
height: visible ? navigationLabel.implicitHeight + Style.space(10) : 0
|
||||
|
||||
Item {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: body.width
|
||||
height: parent.height
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: navigationLabel
|
||||
width: navigationLabel.width
|
||||
height: navigationLabel.implicitHeight + Style.space(6)
|
||||
radius: Style.cornerRadius
|
||||
color: navigationMouse.containsMouse ? Style.hoverFillFor(root.foreground, Color.accent) : "transparent"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: navigationLabel
|
||||
anchors.centerIn: parent
|
||||
width: Style.space(150)
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
textFormat: Text.PlainText
|
||||
text: root.pickingMonth
|
||||
? String(root.pickerYear)
|
||||
: Qt.formatDate(root.viewDate, "MMMM yyyy").toUpperCase()
|
||||
color: navigationMouse.containsMouse
|
||||
? Style.hoverStateColor(root.foreground, Color.accent)
|
||||
: Qt.darker(root.foreground, 1.4)
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
font.letterSpacing: 1
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: navigationMouse
|
||||
anchors.fill: navigationLabel
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.togglePicker()
|
||||
|
||||
PanelToolTip {
|
||||
visible: navigationMouse.containsMouse
|
||||
text: root.pickingMonth ? "Back to the days" : "Pick a month"
|
||||
fontFamily: root.fontFamily
|
||||
}
|
||||
}
|
||||
|
||||
PanelActionButton {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: -Style.space(8)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
iconText: ""
|
||||
tooltipText: root.pickingMonth ? "Previous year" : "Previous month"
|
||||
foreground: root.foreground
|
||||
fontFamily: root.fontFamily
|
||||
onClicked: root.pickingMonth ? root.moveYear(-1) : root.moveMonth(-1)
|
||||
}
|
||||
|
||||
PanelActionButton {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: -Style.space(8)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
iconText: ""
|
||||
tooltipText: root.pickingMonth ? "Next year" : "Next month"
|
||||
foreground: root.foreground
|
||||
fontFamily: root.fontFamily
|
||||
onClicked: root.pickingMonth ? root.moveYear(1) : root.moveMonth(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,3 +38,7 @@ CardHeader 1.0 CardHeader.qml
|
||||
StatRow 1.0 StatRow.qml
|
||||
CardIconButton 1.0 CardIconButton.qml
|
||||
Chip 1.0 Chip.qml
|
||||
CalendarModel 1.0 CalendarModel.js
|
||||
CalendarView 1.0 CalendarView.qml
|
||||
CalendarDays 1.0 CalendarDays.qml
|
||||
CalendarMonthPicker 1.0 CalendarMonthPicker.qml
|
||||
Reference in new issue
Block a user