diff --git a/.config/hypr/default_settings.json b/.config/hypr/default_settings.json index 21fa2e7..1cbe374 100644 --- a/.config/hypr/default_settings.json +++ b/.config/hypr/default_settings.json @@ -6,6 +6,8 @@ "wallpaperDir": "", "language": "us", "kbOptions": "grp:alt_shift_toggle", + "timeFormat": "HH:mm:ss", + "dateFormat": "dddd, MMMM dd", "monitors": [], "keybinds": [ {"type":"bind","mods":"ALT","key":"F4","dispatcher":"exec","command":"hyprctl dispatch killactive"}, diff --git a/.config/hypr/scripts/quickshell/Config.qml b/.config/hypr/scripts/quickshell/Config.qml index 05fd499..bfeda7f 100644 --- a/.config/hypr/scripts/quickshell/Config.qml +++ b/.config/hypr/scripts/quickshell/Config.qml @@ -92,6 +92,9 @@ Item { property string weatherApiKey: "" property string weatherCityId: "" + property string dateFormat: "dddd, MMMM dd" + property string timeFormat: "HH:mm:ss" + property var keybindsData: [] signal keybindsLoaded() @@ -109,7 +112,9 @@ Item { "wallpaperDir": config.wallpaperDir, "language": config.language, "kbOptions": config.kbOptions, - "workspaceCount": config.workspaceCount + "workspaceCount": config.workspaceCount, + "dateFormat": config.dateFormat, + "timeFormat": config.timeFormat }; config.updateJsonBulk(configObj); @@ -194,6 +199,8 @@ Item { if (config.rawSettings.wallpaperDir !== undefined) config.wallpaperDir = config.rawSettings.wallpaperDir; if (config.rawSettings.language !== undefined && config.rawSettings.language !== "") config.language = config.rawSettings.language; if (config.rawSettings.kbOptions !== undefined) config.kbOptions = config.rawSettings.kbOptions; + if (config.rawSettings.dateFormat !== undefined) config.dateFormat = config.rawSettings.dateFormat; + if (config.rawSettings.timeFormat !== undefined) config.timeFormat = config.rawSettings.timeFormat; if (config.rawSettings.workspaceCount !== undefined) { config.workspaceCount = config.rawSettings.workspaceCount; config.initialWorkspaceCount = config.rawSettings.workspaceCount; diff --git a/.config/hypr/scripts/quickshell/TopBar.qml b/.config/hypr/scripts/quickshell/TopBar.qml index fd873f2..ab451d7 100644 --- a/.config/hypr/scripts/quickshell/TopBar.qml +++ b/.config/hypr/scripts/quickshell/TopBar.qml @@ -178,6 +178,12 @@ Variants { wsDaemon.running = false; wsDaemon.running = true; } + if (parsed.dateFormat !== undefined && barWindow.dateFormat !== parsed.dateFormat) { + barWindow.dateFormat = parsed.dateFormat; + } + if (parsed.timeFormat !== undefined && barWindow.timeFormat !== parsed.timeFormat) { + barWindow.timeFormat = parsed.timeFormat; + } } } catch (e) {} } @@ -223,6 +229,9 @@ Variants { property bool isDataReady: fastPollerLoaded Timer { interval: 600; running: true; onTriggered: barWindow.isDataReady = true } + property string timeFormat: "HH:mm:ss" + property string dateFormat: "dddd, MMMM dd" + property string timeStr: "" property string fullDateStr: "" property int typeInIndex: 0 @@ -557,8 +566,8 @@ Variants { interval: 1000; running: true; repeat: true; triggeredOnStart: true onTriggered: { let d = new Date(); - barWindow.timeStr = Qt.formatDateTime(d, "HH:mm:ss"); - barWindow.fullDateStr = Qt.formatDateTime(d, "dddd, MMMM dd"); + barWindow.timeStr = d.toLocaleTimeString(Qt.locale(), barWindow.timeFormat); + barWindow.fullDateStr = d.toLocaleDateString(Qt.locale(), barWindow.dateFormat); if (barWindow.typeInIndex >= barWindow.fullDateStr.length) { barWindow.typeInIndex = barWindow.fullDateStr.length; } diff --git a/.config/hypr/scripts/quickshell/settings/SettingsPopup.qml b/.config/hypr/scripts/quickshell/settings/SettingsPopup.qml index f1a2bfb..77f8ac6 100644 --- a/.config/hypr/scripts/quickshell/settings/SettingsPopup.qml +++ b/.config/hypr/scripts/quickshell/settings/SettingsPopup.qml @@ -880,6 +880,7 @@ Item { { tab: 0, boxIndex: 4, label: "Layout shortcut", desc: "Toggle combination", icon: "󰯍", color: "teal" }, { tab: 0, boxIndex: 5, label: "Wallpaper directory",desc: "Absolute source path", icon: "󰋩", color: "mauve" }, { tab: 0, boxIndex: 6, label: "Workspaces", desc: "Static count in topbar", icon: "󰽿", color: "red" }, + { tab: 0, boxIndex: 7, label: "Datetime format", desc: "Topbar datetime format", icon: "󰃰", color: "peach" }, { tab: 1, boxIndex: 1, label: "API Key", desc: "OpenWeather API key", icon: "󰌆", color: "blue" }, { tab: 1, boxIndex: 2, label: "City ID", desc: "OpenWeather city ID", icon: "󰖐", color: "blue" }, { tab: 1, boxIndex: 3, label: "Temperature Unit", desc: "Celsius / Fahrenheit / K", icon: "󰔄", color: "blue" } @@ -1759,6 +1760,151 @@ Item { } } } + + // ── Box 7: Datetime format ─────────────────────────── + Rectangle { + id: box7 + Layout.fillWidth: true + Layout.preferredHeight: col7wp.implicitHeight + root.s(32) + radius: root.s(12) + + property bool isActive: root.highlightedBox === 7 + color: isActive ? root.mauve : root.surface0 + border.color: isActive ? root.mauve : root.surface1 + border.width: 1 + Behavior on color { ColorAnimation { duration: 220; easing.type: Easing.OutExpo } } + + MouseArea { anchors.fill: parent; onClicked: root.highlightedBox = 7; z: -1 } + + ColumnLayout { + id: col7wp + anchors.top: parent.top; anchors.left: parent.left; anchors.right: parent.right; anchors.margins: root.s(16) + RowLayout { + Layout.fillWidth: true; spacing: root.s(14) + Item { + Layout.preferredWidth: root.s(22); Layout.alignment: Qt.AlignTop; Layout.topMargin: root.s(2) + Text { + anchors.top: parent.top; anchors.horizontalCenter: parent.horizontalCenter + text: "󰃰"; font.family: "Iosevka Nerd Font"; font.pixelSize: root.s(18) + color: box7.isActive ? root.base : root.mauve + Behavior on color { ColorAnimation { duration: 220; easing.type: Easing.OutExpo } } + } + } + ColumnLayout { + Layout.fillWidth: true; Layout.alignment: Qt.AlignTop; spacing: root.s(3) + Text { + text: "Datetime format"; font.family: "Inter"; font.weight: Font.Medium; font.pixelSize: root.s(14) + color: box7.isActive ? root.base : root.text; Layout.fillWidth: true + Behavior on color { ColorAnimation { duration: 220; easing.type: Easing.OutExpo } } + } + Text { + text: "Date format"; font.family: "Inter"; font.pixelSize: root.s(11) + color: box7.isActive ? Qt.alpha(root.base, 0.75) : Qt.alpha(root.subtext0, 0.7); Layout.fillWidth: true + Behavior on color { ColorAnimation { duration: 220; easing.type: Easing.OutExpo } } + } + Rectangle { + Layout.fillWidth: true; Layout.preferredHeight: root.s(34); Layout.topMargin: root.s(8) + radius: root.s(7) + color: box7.isActive ? Qt.alpha(root.base, 0.15) : root.surface0 + border.color: dateFormatInput.activeFocus + ? (box7.isActive ? root.base : root.mauve) + : (box7.isActive ? Qt.alpha(root.base, 0.3) : root.surface2) + border.width: 1 + Behavior on border.color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: 220; easing.type: Easing.OutExpo } } + TextInput { + id: dateFormatInput + anchors.fill: parent; anchors.margins: root.s(9) + verticalAlignment: TextInput.AlignVCenter + text: Config.dateFormat + font.family: "JetBrains Mono"; font.pixelSize: root.s(11) + color: box7.isActive ? root.base : root.text; clip: true; selectByMouse: true + Behavior on color { ColorAnimation { duration: 220; easing.type: Easing.OutExpo } } + Keys.onPressed: (event) => { + if (event.key === Qt.Key_Tab || event.key === Qt.Key_Down) { + if (pathSuggestModel.count > 0) { wpSuggestListView.incrementCurrentIndex(); event.accepted = true; } + } else if (event.key === Qt.Key_Backtab || event.key === Qt.Key_Up) { + if (pathSuggestModel.count > 0) { wpSuggestListView.decrementCurrentIndex(); event.accepted = true; } + } + } + Keys.onReturnPressed: (event) => dateFormatInputAccept(event) + Keys.onEnterPressed: (event) => dateFormatInputAccept(event) + function dateFormatInputAccept(event) { + if (pathSuggestModel.count > 0 && wpSuggestListView.currentIndex >= 0) { + let item = pathSuggestModel.get(wpSuggestListView.currentIndex); + if (item) { text = item.path; Config.dateFormat = text; } + } + pathSuggestModel.clear(); focus = false; event.accepted = true; + } + onActiveFocusChanged: { + if (activeFocus) { pathSuggestProc.query = text; pathSuggestProc.running = false; pathSuggestProc.running = true; } + } + onTextChanged: { + Config.dateFormat = text; + if (activeFocus) { pathSuggestProc.query = text; pathSuggestProc.running = false; pathSuggestProc.running = true; } + } + Text { + text: "Enter date format..."; color: box7.isActive ? Qt.alpha(root.base, 0.5) : root.subtext0 + visible: !parent.text && !parent.activeFocus; font: parent.font; anchors.verticalCenter: parent.verticalCenter + } + } + } + Text { + text: "Time format"; font.family: "Inter"; font.pixelSize: root.s(11) + color: box7.isActive ? Qt.alpha(root.base, 0.75) : Qt.alpha(root.subtext0, 0.7); Layout.fillWidth: true + Behavior on color { ColorAnimation { duration: 220; easing.type: Easing.OutExpo } } + } + Rectangle { + Layout.fillWidth: true; Layout.preferredHeight: root.s(34); Layout.topMargin: root.s(8) + radius: root.s(7) + color: box7.isActive ? Qt.alpha(root.base, 0.15) : root.surface0 + border.color: dateFormatInput.activeFocus + ? (box7.isActive ? root.base : root.mauve) + : (box7.isActive ? Qt.alpha(root.base, 0.3) : root.surface2) + border.width: 1 + Behavior on border.color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: 220; easing.type: Easing.OutExpo } } + TextInput { + id: timeFormatInput + anchors.fill: parent; anchors.margins: root.s(9) + verticalAlignment: TextInput.AlignVCenter + text: Config.timeFormat + font.family: "JetBrains Mono"; font.pixelSize: root.s(11) + color: box7.isActive ? root.base : root.text; clip: true; selectByMouse: true + Behavior on color { ColorAnimation { duration: 220; easing.type: Easing.OutExpo } } + Keys.onPressed: (event) => { + if (event.key === Qt.Key_Tab || event.key === Qt.Key_Down) { + if (pathSuggestModel.count > 0) { wpSuggestListView.incrementCurrentIndex(); event.accepted = true; } + } else if (event.key === Qt.Key_Backtab || event.key === Qt.Key_Up) { + if (pathSuggestModel.count > 0) { wpSuggestListView.decrementCurrentIndex(); event.accepted = true; } + } + } + Keys.onReturnPressed: (event) => timeFormatInputAccept(event) + Keys.onEnterPressed: (event) => timeFormatInputAccept(event) + function timeFormatInputAccept(event) { + if (pathSuggestModel.count > 0 && wpSuggestListView.currentIndex >= 0) { + let item = pathSuggestModel.get(wpSuggestListView.currentIndex); + if (item) { text = item.path; Config.timeFormat = text; } + } + pathSuggestModel.clear(); focus = false; event.accepted = true; + } + onActiveFocusChanged: { + if (activeFocus) { pathSuggestProc.query = text; pathSuggestProc.running = false; pathSuggestProc.running = true; } + } + onTextChanged: { + Config.timeFormat = text; + if (activeFocus) { pathSuggestProc.query = text; pathSuggestProc.running = false; pathSuggestProc.running = true; } + } + Text { + text: "Enter time format..."; color: box7.isActive ? Qt.alpha(root.base, 0.5) : root.subtext0 + visible: !parent.text && !parent.activeFocus; font: parent.font; anchors.verticalCenter: parent.verticalCenter + } + } + } + } + } + } + } } } }