LocationTab: add setting for first day of the week

Calendar: replace MonthGrid with custom solution to allow changing first
day of the week
This commit is contained in:
lysec
2025-10-19 16:46:53 +02:00
parent 8b5f06aec6
commit af7498155c
12 changed files with 185 additions and 44 deletions
+8
View File
@@ -631,6 +631,14 @@
"week-numbers": {
"label": "Wochennummern anzeigen",
"description": "Zeigt die Woche des Jahres (z.B. Woche 38) im Kalender an."
},
"first-day-of-week": {
"label": "Erster Tag der Woche",
"description": "Wählen Sie, welcher Tag die Kalenderwoche beginnt.",
"auto": "Systemstandard",
"monday": "Montag",
"saturday": "Samstag",
"sunday": "Sonntag"
}
}
},
+8
View File
@@ -631,6 +631,14 @@
"week-numbers": {
"label": "Show week numbers",
"description": "Displays the week of the year (e.g., Week 38) in the calendar."
},
"first-day-of-week": {
"label": "First day of week",
"description": "Choose which day starts the calendar week.",
"auto": "System default",
"monday": "Monday",
"saturday": "Saturday",
"sunday": "Sunday"
}
}
},
+8
View File
@@ -624,6 +624,14 @@
"week-numbers": {
"label": "Mostrar números de semana",
"description": "Muestra la semana del año (ej., Semana 38) en el calendario."
},
"first-day-of-week": {
"label": "Primer día de la semana",
"description": "Elige qué día comienza la semana del calendario.",
"auto": "Predeterminado del sistema",
"monday": "Lunes",
"saturday": "Sábado",
"sunday": "Domingo"
}
}
},
+8
View File
@@ -624,6 +624,14 @@
"week-numbers": {
"label": "Afficher les numéros de semaine",
"description": "Affiche la semaine de l'année (ex: Semaine 38) dans le calendrier."
},
"first-day-of-week": {
"label": "Premier jour de la semaine",
"description": "Choisissez quel jour commence la semaine du calendrier.",
"auto": "Par défaut du système",
"monday": "Lundi",
"saturday": "Samedi",
"sunday": "Dimanche"
}
}
},
+8
View File
@@ -586,6 +586,14 @@
"week-numbers": {
"label": "Mostrar números da semana",
"description": "Exibe a semana do ano (ex., Semana 38) no calendário."
},
"first-day-of-week": {
"label": "Primeiro dia da semana",
"description": "Escolha qual dia inicia a semana do calendário.",
"auto": "Padrão do sistema",
"monday": "Segunda-feira",
"saturday": "Sábado",
"sunday": "Domingo"
}
}
},
+8
View File
@@ -624,6 +624,14 @@
"week-numbers": {
"label": "显示周数",
"description": "在日历中显示一年中的第几周(例如:第 38 周)。"
},
"first-day-of-week": {
"label": "每周第一天",
"description": "选择日历每周的起始日。",
"auto": "系统默认",
"monday": "星期一",
"saturday": "星期六",
"sunday": "星期日"
}
}
},
+2 -1
View File
@@ -74,7 +74,8 @@
"weatherEnabled": true,
"useFahrenheit": false,
"use12hourFormat": false,
"showWeekNumberInCalendar": false
"showWeekNumberInCalendar": false,
"firstDayOfWeek": "auto"
},
"screenRecorder": {
"directory": "",
-1
View File
@@ -8,7 +8,6 @@ import qs.Commons
Singleton {
id: root
property bool isLoaded: false
property string langCode: ""
property string systemDetectedLangCode: ""
+1
View File
@@ -202,6 +202,7 @@ Singleton {
property bool useFahrenheit: false
property bool use12hourFormat: false
property bool showWeekNumberInCalendar: false
property string firstDayOfWeek: "auto" // "auto", "monday", "saturday", "sunday"
}
// screen recorder
+97 -30
View File
@@ -22,7 +22,24 @@ NPanel {
anchors.margins: Style.marginL
spacing: Style.marginM
readonly property int firstDayOfWeek: Qt.locale().firstDayOfWeek
readonly property int firstDayOfWeek: {
var setting = Settings.data.location.firstDayOfWeek
if (!setting)
return Qt.Monday
switch (setting) {
case "auto":
return Qt.locale().firstDayOfWeek
case "monday":
return Qt.Monday
case "saturday":
return 6 // Qt.Saturday
case "sunday":
return Qt.Sunday
default:
return Qt.Monday
}
}
property bool isCurrentMonth: checkIsCurrentMonth()
readonly property bool weatherReady: Settings.data.location.weatherEnabled && (LocationService.data.weather !== null)
@@ -278,7 +295,7 @@ NPanel {
}
}
// ... (rest of the file is unchanged) ...
// Weather forecast
RowLayout {
visible: weatherReady
Layout.fillWidth: true
@@ -446,38 +463,88 @@ NPanel {
}
}
}
MonthGrid {
GridLayout {
id: grid
Layout.fillWidth: true
Layout.fillHeight: true
spacing: Style.marginXXS
month: Time.date.getMonth()
year: Time.date.getFullYear()
locale: Qt.locale()
delegate: Item {
Rectangle {
width: Style.baseWidgetSize * 0.9
height: Style.baseWidgetSize * 0.9
anchors.centerIn: parent
radius: Style.radiusM
color: model.today ? Color.mSecondary : Color.transparent
NText {
anchors.centerIn: parent
text: model.day
color: {
if (model.today)
return Color.mOnSecondary
if (model.month === grid.month)
return Color.mOnSurface
return Color.mOnSurfaceVariant
}
opacity: model.month === grid.month ? 1.0 : 0.4
pointSize: Style.fontSizeM
font.weight: model.today ? Style.fontWeightBold : Style.fontWeightMedium
columns: 7
rowSpacing: Style.marginXXS
columnSpacing: Style.marginXXS
property int month: Time.date.getMonth()
property int year: Time.date.getFullYear()
Repeater {
model: 42 // 6 rows × 7 days
delegate: Item {
id: cellItem
Layout.fillWidth: true
Layout.fillHeight: true
required property int index
property int cellDay: {
let firstOfMonth = new Date(grid.year, grid.month, 1)
let firstDayOfWeek = content.firstDayOfWeek
let firstOfMonthDayOfWeek = firstOfMonth.getDay()
let daysBeforeFirst = (firstOfMonthDayOfWeek - firstDayOfWeek + 7) % 7
let startDate = new Date(grid.year, grid.month, 1 - daysBeforeFirst)
let currentDate = new Date(startDate)
currentDate.setDate(startDate.getDate() + cellItem.index)
return currentDate.getDate()
}
Behavior on color {
ColorAnimation {
duration: Style.animationFast
property int cellMonth: {
let firstOfMonth = new Date(grid.year, grid.month, 1)
let firstDayOfWeek = content.firstDayOfWeek
let firstOfMonthDayOfWeek = firstOfMonth.getDay()
let daysBeforeFirst = (firstOfMonthDayOfWeek - firstDayOfWeek + 7) % 7
let startDate = new Date(grid.year, grid.month, 1 - daysBeforeFirst)
let currentDate = new Date(startDate)
currentDate.setDate(startDate.getDate() + cellItem.index)
return currentDate.getMonth()
}
property int cellYear: {
let firstOfMonth = new Date(grid.year, grid.month, 1)
let firstDayOfWeek = content.firstDayOfWeek
let firstOfMonthDayOfWeek = firstOfMonth.getDay()
let daysBeforeFirst = (firstOfMonthDayOfWeek - firstDayOfWeek + 7) % 7
let startDate = new Date(grid.year, grid.month, 1 - daysBeforeFirst)
let currentDate = new Date(startDate)
currentDate.setDate(startDate.getDate() + cellItem.index)
return currentDate.getFullYear()
}
property bool isToday: cellDay === Time.date.getDate() && cellMonth === Time.date.getMonth() && cellYear === Time.date.getFullYear()
property bool isCurrentMonth: cellMonth === grid.month
Rectangle {
width: Style.baseWidgetSize * 0.9
height: Style.baseWidgetSize * 0.9
anchors.centerIn: parent
radius: Style.radiusM
color: parent.isToday ? Color.mSecondary : Color.transparent
NText {
anchors.centerIn: parent
text: cellItem.cellDay
color: {
if (cellItem.isToday)
return Color.mOnSecondary
if (cellItem.isCurrentMonth)
return Color.mOnSurface
return Color.mOnSurfaceVariant
}
opacity: cellItem.isCurrentMonth ? 1.0 : 0.5
pointSize: Style.fontSizeM
font.weight: cellItem.isToday ? Style.fontWeightBold : Style.fontWeightSemiBold
}
Behavior on color {
ColorAnimation {
duration: Style.animationFast
}
}
}
}
+16 -12
View File
@@ -204,20 +204,24 @@ ColumnLayout {
Layout.fillWidth: true
label: I18n.tr("settings.general.language.select.label")
description: I18n.tr("settings.general.language.select.description")
model: [
{ "key": "", "name": I18n.tr("settings.general.language.select.auto-detect") + " (" + I18n.systemDetectedLangCode + ")" }
].concat(I18n.availableLanguages.map(function(langCode) {
return { "key": langCode, "name": langCode }
}))
model: [{
"key": "",
"name": I18n.tr("settings.general.language.select.auto-detect") + " (" + I18n.systemDetectedLangCode + ")"
}].concat(I18n.availableLanguages.map(function (langCode) {
return {
"key": langCode,
"name": langCode
}
}))
currentKey: Settings.data.general.language
onSelected: key => {
Settings.data.general.language = key
if (key === "") {
I18n.detectLanguage() // Re-detect system language if "Automatic" is selected
} else {
I18n.setLanguage(key) // Set specific language
}
}
Settings.data.general.language = key
if (key === "") {
I18n.detectLanguage() // Re-detect system language if "Automatic" is selected
} else {
I18n.setLanguage(key) // Set specific language
}
}
}
}
+21
View File
@@ -117,6 +117,27 @@ ColumnLayout {
checked: Settings.data.location.showWeekNumberInCalendar
onToggled: checked => Settings.data.location.showWeekNumberInCalendar = checked
}
NComboBox {
label: I18n.tr("settings.location.date-time.first-day-of-week.label")
description: I18n.tr("settings.location.date-time.first-day-of-week.description")
minimumWidth: 220 * Style.uiScaleRatio
model: [{
"key": "auto",
"name": I18n.tr("settings.location.date-time.first-day-of-week.auto")
}, {
"key": "monday",
"name": I18n.tr("settings.location.date-time.first-day-of-week.monday")
}, {
"key": "saturday",
"name": I18n.tr("settings.location.date-time.first-day-of-week.saturday")
}, {
"key": "sunday",
"name": I18n.tr("settings.location.date-time.first-day-of-week.sunday")
}]
currentKey: Settings.data.location.firstDayOfWeek
onSelected: key => Settings.data.location.firstDayOfWeek = key
}
}
NDivider {