From 9e27b4f232805069e6318122826a5d13f7985ab8 Mon Sep 17 00:00:00 2001 From: Jx <103049321+JxJxxJxJ@users.noreply.github.com> Date: Tue, 17 Jun 2025 00:18:27 -0300 Subject: [PATCH 001/328] Add dolphin as dependency --- arch-packages/illogical-impulse-kde/PKGBUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/arch-packages/illogical-impulse-kde/PKGBUILD b/arch-packages/illogical-impulse-kde/PKGBUILD index b8b91c3f..99eec565 100644 --- a/arch-packages/illogical-impulse-kde/PKGBUILD +++ b/arch-packages/illogical-impulse-kde/PKGBUILD @@ -10,5 +10,6 @@ depends=( networkmanager plasma-nm polkit-kde-agent + dolphin systemsettings ) From b32734b9f5b68b23cb9cbfbee6e492ed0a8bdd0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Tue, 17 Jun 2025 12:29:21 +0800 Subject: [PATCH 002/328] Quickshell qstr seems not to be working, trying to implement custom translation Add Chinese (zh_CN) translations for Quickshell interface and settings --- .config/quickshell/GlobalStates.qml | 3 +- .../quickshell/modules/bar/ActiveWindow.qml | 5 +- .config/quickshell/modules/bar/Bar.qml | 4 +- .config/quickshell/modules/bar/Media.qml | 2 +- .../modules/cheatsheet/Cheatsheet.qml | 8 +- .../modules/common/ConfigOptions.qml | 1 + .../common/widgets/NotificationItem.qml | 4 +- .../modules/common/widgets/PrimaryTabBar.qml | 3 +- .../common/widgets/SelectionDialog.qml | 5 +- .../modules/mediaControls/MediaControls.qml | 6 +- .../OnScreenDisplayBrightness.qml | 6 +- .../onScreenDisplay/OnScreenDisplayVolume.qml | 6 +- .../onScreenKeyboard/OnScreenKeyboard.qml | 6 +- .../quickshell/modules/overview/Overview.qml | 17 +- .../modules/overview/SearchItem.qml | 2 +- .../modules/overview/SearchWidget.qml | 22 +- .../quickshell/modules/session/Session.qml | 24 +- .../quickshell/modules/sidebarLeft/AiChat.qml | 20 +- .../quickshell/modules/sidebarLeft/Anime.qml | 25 +- .../modules/sidebarLeft/SidebarLeft.qml | 9 +- .../sidebarLeft/SidebarLeftContent.qml | 7 +- .../modules/sidebarLeft/Translator.qml | 6 +- .../modules/sidebarLeft/aiChat/AiMessage.qml | 12 +- .../sidebarLeft/aiChat/MessageCodeBlock.qml | 4 +- .../sidebarLeft/aiChat/MessageTextBlock.qml | 2 +- .../sidebarLeft/aiChat/MessageThinkBlock.qml | 2 +- .../modules/sidebarLeft/anime/BooruImage.qml | 8 +- .../sidebarLeft/anime/BooruResponse.qml | 3 +- .../sidebarLeft/translator/TextCanvas.qml | 2 +- .../sidebarRight/CenterWidgetGroup.qml | 3 +- .../modules/sidebarRight/SidebarRight.qml | 15 +- .../sidebarRight/calendar/CalendarWidget.qml | 2 +- .../notifications/NotificationList.qml | 7 +- .../quickToggles/BluetoothToggle.qml | 4 +- .../sidebarRight/quickToggles/GameMode.qml | 3 +- .../quickToggles/IdleInhibitor.qml | 3 +- .../quickToggles/NetworkToggle.qml | 3 +- .../sidebarRight/quickToggles/NightLight.qml | 3 +- .../modules/sidebarRight/todo/TodoWidget.qml | 14 +- .../volumeMixer/AudioDeviceSelectorButton.qml | 5 +- .../sidebarRight/volumeMixer/VolumeMixer.qml | 7 +- .config/quickshell/services/Ai.qml | 55 +- .config/quickshell/services/Booru.qml | 25 +- .config/quickshell/services/Brightness.qml | 5 +- .config/quickshell/services/ConfigLoader.qml | 8 +- .../quickshell/services/KeyringStorage.qml | 4 +- .../quickshell/services/MprisController.qml | 7 +- .config/quickshell/services/Translation.qml | 170 +++++++ .config/quickshell/translations/en_US.json | 472 ++++++++++++++++++ .config/quickshell/translations/zh_CN.json | 472 ++++++++++++++++++ 50 files changed, 1324 insertions(+), 187 deletions(-) create mode 100644 .config/quickshell/services/Translation.qml create mode 100644 .config/quickshell/translations/en_US.json create mode 100644 .config/quickshell/translations/zh_CN.json diff --git a/.config/quickshell/GlobalStates.qml b/.config/quickshell/GlobalStates.qml index 1b879421..4b6dd0da 100644 --- a/.config/quickshell/GlobalStates.qml +++ b/.config/quickshell/GlobalStates.qml @@ -1,4 +1,5 @@ import "root:/modules/common/" +import "root:/services/" import QtQuick import Quickshell import Quickshell.Hyprland @@ -31,7 +32,7 @@ Singleton { GlobalShortcut { name: "workspaceNumber" - description: qsTr("Hold to show workspace numbers, release to show icons") + description: Translation.tr("Hold to show workspace numbers, release to show icons") onPressed: { workspaceShowNumbersTimer.start() diff --git a/.config/quickshell/modules/bar/ActiveWindow.qml b/.config/quickshell/modules/bar/ActiveWindow.qml index 95e25c6f..0c4838fc 100644 --- a/.config/quickshell/modules/bar/ActiveWindow.qml +++ b/.config/quickshell/modules/bar/ActiveWindow.qml @@ -1,5 +1,6 @@ import "root:/modules/common" import "root:/modules/common/widgets" +import "root:/services/" import QtQuick import QtQuick.Layouts import Quickshell.Wayland @@ -26,7 +27,7 @@ Item { font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.colors.colSubtext elide: Text.ElideRight - text: root.activeWindow?.activated ? root.activeWindow?.appId : qsTr("Desktop") + text: root.activeWindow?.activated ? root.activeWindow?.appId : Translation.tr("Desktop") } StyledText { @@ -34,7 +35,7 @@ Item { font.pixelSize: Appearance.font.pixelSize.small color: Appearance.colors.colOnLayer0 elide: Text.ElideRight - text: root.activeWindow?.activated ? root.activeWindow?.title : `${qsTr("Workspace")} ${monitor.activeWorkspace?.id}` + text: root.activeWindow?.activated ? root.activeWindow?.title : `${Translation.tr("Workspace")} ${monitor.activeWorkspace?.id}` } } diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 9fb9b32e..01945cab 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -131,7 +131,7 @@ Scope { ScrollHint { reveal: barLeftSideMouseArea.hovered icon: "light_mode" - tooltipText: qsTr("Scroll to change brightness") + tooltipText: Translation.tr("Scroll to change brightness") side: "left" anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter @@ -329,7 +329,7 @@ Scope { ScrollHint { reveal: barRightSideMouseArea.hovered icon: "volume_up" - tooltipText: qsTr("Scroll to change volume") + tooltipText: Translation.tr("Scroll to change volume") side: "right" anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter diff --git a/.config/quickshell/modules/bar/Media.qml b/.config/quickshell/modules/bar/Media.qml index 3bd8a78a..90d1c880 100644 --- a/.config/quickshell/modules/bar/Media.qml +++ b/.config/quickshell/modules/bar/Media.qml @@ -13,7 +13,7 @@ Item { id: root property bool borderless: ConfigOptions.bar.borderless readonly property MprisPlayer activePlayer: MprisController.activePlayer - readonly property string cleanedTitle: StringUtils.cleanMusicTitle(activePlayer?.trackTitle) || qsTr("No media") + readonly property string cleanedTitle: StringUtils.cleanMusicTitle(activePlayer?.trackTitle) || Translation.tr("No media") Layout.fillHeight: true implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2 diff --git a/.config/quickshell/modules/cheatsheet/Cheatsheet.qml b/.config/quickshell/modules/cheatsheet/Cheatsheet.qml index 79711f88..83d9fd65 100644 --- a/.config/quickshell/modules/cheatsheet/Cheatsheet.qml +++ b/.config/quickshell/modules/cheatsheet/Cheatsheet.qml @@ -110,7 +110,7 @@ Scope { // Scope Layout.alignment: Qt.AlignHCenter font.family: Appearance.font.family.title font.pixelSize: Appearance.font.pixelSize.title - text: qsTr("Cheat sheet") + text: Translation.tr("Cheat sheet") } CheatsheetKeybinds {} } @@ -137,7 +137,7 @@ Scope { // Scope GlobalShortcut { name: "cheatsheetToggle" - description: qsTr("Toggles cheatsheet on press") + description: Translation.tr("Toggles cheatsheet on press") onPressed: { cheatsheetLoader.active = !cheatsheetLoader.active; @@ -146,7 +146,7 @@ Scope { // Scope GlobalShortcut { name: "cheatsheetOpen" - description: qsTr("Opens cheatsheet on press") + description: Translation.tr("Opens cheatsheet on press") onPressed: { cheatsheetLoader.active = true; @@ -155,7 +155,7 @@ Scope { // Scope GlobalShortcut { name: "cheatsheetClose" - description: qsTr("Closes cheatsheet on press") + description: Translation.tr("Closes cheatsheet on press") onPressed: { cheatsheetLoader.active = false; diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 70e46f4e..92d56b72 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -91,6 +91,7 @@ Singleton { } property QtObject language: QtObject { + property string ui: "auto" // Interface language: "auto", "en", "zh-CN", "zh-TW", etc. property QtObject translator: QtObject { property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google property string targetLanguage: "auto" // Run `trans -list-all` for available languages diff --git a/.config/quickshell/modules/common/widgets/NotificationItem.qml b/.config/quickshell/modules/common/widgets/NotificationItem.qml index bf8a7687..62e37b8a 100644 --- a/.config/quickshell/modules/common/widgets/NotificationItem.qml +++ b/.config/quickshell/modules/common/widgets/NotificationItem.qml @@ -97,7 +97,7 @@ Item { // Notification item area onPressAndHold: (mouse) => { if (mouse.button === Qt.LeftButton) { Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(notificationObject.body)}'`) - notificationSummaryText.text = String.format(qsTr("{0} (copied)"), notificationObject.summary) + notificationSummaryText.text = String.format(Translation.tr("{0} (copied)"), notificationObject.summary) } } onDraggingChanged: () => { @@ -257,7 +257,7 @@ Item { // Notification item area NotificationActionButton { Layout.fillWidth: true - buttonText: qsTr("Close") + buttonText: Translation.tr("Close") urgency: notificationObject.urgency implicitWidth: (notificationObject.actions.length == 0) ? ((actionsFlickable.width - actionRowLayout.spacing) / 2) : (contentItem.implicitWidth + leftPadding + rightPadding) diff --git a/.config/quickshell/modules/common/widgets/PrimaryTabBar.qml b/.config/quickshell/modules/common/widgets/PrimaryTabBar.qml index cd048e8b..c8843bc2 100644 --- a/.config/quickshell/modules/common/widgets/PrimaryTabBar.qml +++ b/.config/quickshell/modules/common/widgets/PrimaryTabBar.qml @@ -1,4 +1,5 @@ import "root:/modules/common" +import "root:/services/" import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -7,7 +8,7 @@ import Quickshell ColumnLayout { id: root spacing: 0 - required property var tabButtonList // Something like [{"icon": "notifications", "name": qsTr("Notifications")}, {"icon": "volume_up", "name": qsTr("Volume mixer")}] + required property var tabButtonList // Something like [{"icon": "notifications", "name": Translation.tr("Notifications")}, {"icon": "volume_up", "name": Translation.tr("Volume mixer")}] required property var externalTrackedTab property bool enableIndicatorAnimation: false property color colIndicator: Appearance?.colors.colPrimary ?? "#65558F" diff --git a/.config/quickshell/modules/common/widgets/SelectionDialog.qml b/.config/quickshell/modules/common/widgets/SelectionDialog.qml index 9cf0940e..9a6d0b7f 100644 --- a/.config/quickshell/modules/common/widgets/SelectionDialog.qml +++ b/.config/quickshell/modules/common/widgets/SelectionDialog.qml @@ -1,6 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" +import "root:/services/" import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls @@ -113,11 +114,11 @@ Item { Layout.alignment: Qt.AlignRight DialogButton { - buttonText: qsTr("Cancel") + buttonText: Translation.tr("Cancel") onClicked: root.canceled() } DialogButton { - buttonText: qsTr("OK") + buttonText: Translation.tr("OK") onClicked: root.selected( root.selectedId === -1 ? null : root.items[root.selectedId] diff --git a/.config/quickshell/modules/mediaControls/MediaControls.qml b/.config/quickshell/modules/mediaControls/MediaControls.qml index 4350658f..047f1417 100644 --- a/.config/quickshell/modules/mediaControls/MediaControls.qml +++ b/.config/quickshell/modules/mediaControls/MediaControls.qml @@ -158,7 +158,7 @@ Scope { GlobalShortcut { name: "mediaControlsToggle" - description: qsTr("Toggles media controls on press") + description: Translation.tr("Toggles media controls on press") onPressed: { if (!mediaControlsLoader.active && Mpris.players.values.filter(player => isRealPlayer(player)).length === 0) { @@ -170,7 +170,7 @@ Scope { } GlobalShortcut { name: "mediaControlsOpen" - description: qsTr("Opens media controls on press") + description: Translation.tr("Opens media controls on press") onPressed: { mediaControlsLoader.active = true; @@ -179,7 +179,7 @@ Scope { } GlobalShortcut { name: "mediaControlsClose" - description: qsTr("Closes media controls on press") + description: Translation.tr("Closes media controls on press") onPressed: { mediaControlsLoader.active = false; diff --git a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml index 765386bc..a6ef4242 100644 --- a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml +++ b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml @@ -108,7 +108,7 @@ Scope { icon: "light_mode" rotateIcon: true scaleIcon: true - name: qsTr("Brightness") + name: Translation.tr("Brightness") } } } @@ -134,7 +134,7 @@ Scope { GlobalShortcut { name: "osdBrightnessTrigger" - description: qsTr("Triggers brightness OSD on press") + description: Translation.tr("Triggers brightness OSD on press") onPressed: { root.triggerOsd() @@ -142,7 +142,7 @@ Scope { } GlobalShortcut { name: "osdBrightnessHide" - description: qsTr("Hides brightness OSD on press") + description: Translation.tr("Hides brightness OSD on press") onPressed: { root.showOsdValues = false diff --git a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml index 5d23b440..def28b36 100644 --- a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml +++ b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml @@ -121,7 +121,7 @@ Scope { Layout.fillWidth: true value: Audio.sink?.audio.volume ?? 0 icon: Audio.sink?.audio.muted ? "volume_off" : "volume_up" - name: qsTr("Volume") + name: Translation.tr("Volume") } Item { @@ -185,7 +185,7 @@ Scope { } GlobalShortcut { name: "osdVolumeTrigger" - description: qsTr("Triggers volume OSD on press") + description: Translation.tr("Triggers volume OSD on press") onPressed: { root.triggerOsd() @@ -193,7 +193,7 @@ Scope { } GlobalShortcut { name: "osdVolumeHide" - description: qsTr("Hides volume OSD on press") + description: Translation.tr("Hides volume OSD on press") onPressed: { root.showOsdValues = false diff --git a/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml b/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml index e78f45b2..079b7a3c 100644 --- a/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml +++ b/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml @@ -141,7 +141,7 @@ Scope { // Scope GlobalShortcut { name: "oskToggle" - description: qsTr("Toggles on screen keyboard on press") + description: Translation.tr("Toggles on screen keyboard on press") onPressed: { oskLoader.active = !oskLoader.active; @@ -150,7 +150,7 @@ Scope { // Scope GlobalShortcut { name: "oskOpen" - description: qsTr("Opens on screen keyboard on press") + description: Translation.tr("Opens on screen keyboard on press") onPressed: { oskLoader.active = true; @@ -159,7 +159,7 @@ Scope { // Scope GlobalShortcut { name: "oskClose" - description: qsTr("Closes on screen keyboard on press") + description: Translation.tr("Closes on screen keyboard on press") onPressed: { oskLoader.active = false; diff --git a/.config/quickshell/modules/overview/Overview.qml b/.config/quickshell/modules/overview/Overview.qml index a7817e6e..e24f2f38 100644 --- a/.config/quickshell/modules/overview/Overview.qml +++ b/.config/quickshell/modules/overview/Overview.qml @@ -2,6 +2,7 @@ import "root:/" import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" +import "root:/services/" import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -151,7 +152,7 @@ Scope { GlobalShortcut { name: "overviewToggle" - description: qsTr("Toggles overview on press") + description: Translation.tr("Toggles overview on press") onPressed: { GlobalStates.overviewOpen = !GlobalStates.overviewOpen @@ -159,7 +160,7 @@ Scope { } GlobalShortcut { name: "overviewClose" - description: qsTr("Closes overview") + description: Translation.tr("Closes overview") onPressed: { GlobalStates.overviewOpen = false @@ -167,7 +168,7 @@ Scope { } GlobalShortcut { name: "overviewToggleRelease" - description: qsTr("Toggles overview on release") + description: Translation.tr("Toggles overview on release") onPressed: { GlobalStates.superReleaseMightTrigger = true @@ -183,9 +184,9 @@ Scope { } GlobalShortcut { name: "overviewToggleReleaseInterrupt" - description: qsTr("Interrupts possibility of overview being toggled on release. ") + - qsTr("This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ") + - qsTr("To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.") + description: Translation.tr("Interrupts possibility of overview being toggled on release. ") + + Translation.tr("This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ") + + Translation.tr("To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.") onPressed: { GlobalStates.superReleaseMightTrigger = false @@ -193,7 +194,7 @@ Scope { } GlobalShortcut { name: "overviewClipboardToggle" - description: qsTr("Toggle clipboard query on overview widget") + description: Translation.tr("Toggle clipboard query on overview widget") onPressed: { if (GlobalStates.overviewOpen && overviewScope.dontAutoCancelSearch) { @@ -216,7 +217,7 @@ Scope { GlobalShortcut { name: "overviewEmojiToggle" - description: qsTr("Toggle emoji query on overview widget") + description: Translation.tr("Toggle emoji query on overview widget") onPressed: { if (GlobalStates.overviewOpen && overviewScope.dontAutoCancelSearch) { diff --git a/.config/quickshell/modules/overview/SearchItem.qml b/.config/quickshell/modules/overview/SearchItem.qml index d23cb4c0..f70e25f3 100644 --- a/.config/quickshell/modules/overview/SearchItem.qml +++ b/.config/quickshell/modules/overview/SearchItem.qml @@ -162,7 +162,7 @@ RippleButton { StyledText { font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.colors.colSubtext - visible: root.itemType && root.itemType != qsTr("App") + visible: root.itemType && root.itemType != Translation.tr("App") text: root.itemType } RowLayout { diff --git a/.config/quickshell/modules/overview/SearchWidget.qml b/.config/quickshell/modules/overview/SearchWidget.qml index 614efa91..5d43f07a 100644 --- a/.config/quickshell/modules/overview/SearchWidget.qml +++ b/.config/quickshell/modules/overview/SearchWidget.qml @@ -220,7 +220,7 @@ Item { // Wrapper color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant selectedTextColor: Appearance.m3colors.m3onSecondaryContainer selectionColor: Appearance.colors.colSecondaryContainer - placeholderText: qsTr("Search, calculate or run") + placeholderText: Translation.tr("Search, calculate or run") placeholderTextColor: Appearance.m3colors.m3outline implicitWidth: root.searchingText == "" ? Appearance.sizes.searchWidthCollapsed : Appearance.sizes.searchWidth @@ -329,8 +329,8 @@ Item { // Wrapper nonAppResultsTimer.restart(); const mathResultObject = { name: root.mathResult, - clickActionName: qsTr("Copy"), - type: qsTr("Math result"), + clickActionName: Translation.tr("Copy"), + type: Translation.tr("Math result"), fontType: "monospace", materialSymbol: 'calculate', execute: () => { @@ -339,8 +339,8 @@ Item { // Wrapper } const commandResultObject = { name: searchingText.replace("file://", ""), - clickActionName: qsTr("Run"), - type: qsTr("Run command"), + clickActionName: Translation.tr("Run"), + type: Translation.tr("Run command"), fontType: "monospace", materialSymbol: 'terminal', execute: () => { @@ -353,8 +353,8 @@ Item { // Wrapper if (actionString.startsWith(root.searchingText) || root.searchingText.startsWith(actionString)) { return { name: root.searchingText.startsWith(actionString) ? root.searchingText : actionString, - clickActionName: qsTr("Run"), - type: qsTr("Action"), + clickActionName: Translation.tr("Run"), + type: Translation.tr("Action"), materialSymbol: 'settings_suggest', execute: () => { action.execute(root.searchingText.split(" ").slice(1).join(" ")) @@ -371,8 +371,8 @@ Item { // Wrapper result = result.concat( AppSearch.fuzzyQuery(root.searchingText) .map((entry) => { - entry.clickActionName = qsTr("Launch"); - entry.type = qsTr("App"); + entry.clickActionName = Translation.tr("Launch"); + entry.type = Translation.tr("App"); return entry; }) ); @@ -393,8 +393,8 @@ Item { // Wrapper ///////////////// Web search //////////////// result.push({ name: root.searchingText, - clickActionName: qsTr("Search"), - type: qsTr("Search the web"), + clickActionName: Translation.tr("Search"), + type: Translation.tr("Search the web"), materialSymbol: 'travel_explore', execute: () => { let url = ConfigOptions.search.engineBaseUrl + root.searchingText diff --git a/.config/quickshell/modules/session/Session.qml b/.config/quickshell/modules/session/Session.qml index 94e6123f..0ab3221e 100644 --- a/.config/quickshell/modules/session/Session.qml +++ b/.config/quickshell/modules/session/Session.qml @@ -70,7 +70,7 @@ Scope { font.family: Appearance.font.family.title font.pixelSize: Appearance.font.pixelSize.title font.weight: Font.DemiBold - text: qsTr("Session") + text: Translation.tr("Session") } StyledText { // Small instruction @@ -78,7 +78,7 @@ Scope { horizontalAlignment: Text.AlignHCenter font.family: Appearance.font.family.title font.pixelSize: Appearance.font.pixelSize.normal - text: qsTr("Arrow keys to navigate, Enter to select\nEsc or click anywhere to cancel") + text: Translation.tr("Arrow keys to navigate, Enter to select\nEsc or click anywhere to cancel") } } @@ -91,7 +91,7 @@ Scope { id: sessionLock focus: sessionRoot.visible buttonIcon: "lock" - buttonText: qsTr("Lock") + buttonText: Translation.tr("Lock") onClicked: { Hyprland.dispatch("exec loginctl lock-session"); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.right: sessionSleep @@ -100,7 +100,7 @@ Scope { SessionActionButton { id: sessionSleep buttonIcon: "dark_mode" - buttonText: qsTr("Sleep") + buttonText: Translation.tr("Sleep") onClicked: { Hyprland.dispatch("exec systemctl suspend || loginctl suspend"); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionLock @@ -110,7 +110,7 @@ Scope { SessionActionButton { id: sessionLogout buttonIcon: "logout" - buttonText: qsTr("Logout") + buttonText: Translation.tr("Logout") onClicked: { Hyprland.dispatch("exec pkill Hyprland"); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionSleep @@ -120,7 +120,7 @@ Scope { SessionActionButton { id: sessionTaskManager buttonIcon: "browse_activity" - buttonText: qsTr("Task Manager") + buttonText: Translation.tr("Task Manager") onClicked: { Hyprland.dispatch(`exec ${ConfigOptions.apps.taskManager}`); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionLogout @@ -130,7 +130,7 @@ Scope { SessionActionButton { id: sessionHibernate buttonIcon: "downloading" - buttonText: qsTr("Hibernate") + buttonText: Translation.tr("Hibernate") onClicked: { Hyprland.dispatch("exec systemctl hibernate || loginctl hibernate"); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.up: sessionLock @@ -139,7 +139,7 @@ Scope { SessionActionButton { id: sessionShutdown buttonIcon: "power_settings_new" - buttonText: qsTr("Shutdown") + buttonText: Translation.tr("Shutdown") onClicked: { Hyprland.dispatch("exec systemctl poweroff || loginctl poweroff"); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionHibernate @@ -149,7 +149,7 @@ Scope { SessionActionButton { id: sessionReboot buttonIcon: "restart_alt" - buttonText: qsTr("Reboot") + buttonText: Translation.tr("Reboot") onClicked: { Hyprland.dispatch("exec reboot || loginctl reboot"); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionShutdown @@ -159,7 +159,7 @@ Scope { SessionActionButton { id: sessionFirmwareReboot buttonIcon: "settings_applications" - buttonText: qsTr("Reboot to firmware settings") + buttonText: Translation.tr("Reboot to firmware settings") onClicked: { Hyprland.dispatch("exec systemctl reboot --firmware-setup || loginctl reboot --firmware-setup"); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.up: sessionTaskManager @@ -209,7 +209,7 @@ Scope { GlobalShortcut { name: "sessionToggle" - description: qsTr("Toggles session screen on press") + description: Translation.tr("Toggles session screen on press") onPressed: { sessionLoader.active = !sessionLoader.active; @@ -218,7 +218,7 @@ Scope { GlobalShortcut { name: "sessionOpen" - description: qsTr("Opens session screen on press") + description: Translation.tr("Opens session screen on press") onPressed: { sessionLoader.active = true; diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index 422dc41b..d510a631 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -44,21 +44,21 @@ Item { property var allCommands: [ { name: "model", - description: qsTr("Choose model"), + description: Translation.tr("Choose model"), execute: (args) => { Ai.setModel(args[0]); } }, { name: "clear", - description: qsTr("Clear chat history"), + description: Translation.tr("Clear chat history"), execute: () => { Ai.clearMessages(); } }, { name: "key", - description: qsTr("Set API key"), + description: Translation.tr("Set API key"), execute: (args) => { if (args[0] == "get") { Ai.printApiKey() @@ -69,7 +69,7 @@ Item { }, { name: "temp", - description: qsTr("Set temperature (randomness) of the model. Values range between 0 to 2 for Gemini, 0 to 1 for other models. Default is 0.5."), + description: Translation.tr("Set temperature (randomness) of the model. Values range between 0 to 2 for Gemini, 0 to 1 for other models. Default is 0.5."), execute: (args) => { // console.log(args) if (args.length == 0 || args[0] == "get") { @@ -82,7 +82,7 @@ Item { }, { name: "test", - description: qsTr("Markdown test"), + description: Translation.tr("Markdown test"), execute: () => { Ai.addMessage(` @@ -148,7 +148,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) if (commandObj) { commandObj.execute(args); } else { - Ai.addMessage(qsTr("Unknown command: ") + command, Ai.interfaceRole); + Ai.addMessage(Translation.tr("Unknown command: ") + command, Ai.interfaceRole); } } else { @@ -235,7 +235,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) font.family: Appearance.font.family.title color: Appearance.m3colors.m3outline horizontalAlignment: Text.AlignHCenter - text: qsTr("Large language models") + text: Translation.tr("Large language models") } StyledText { id: widgetDescriptionText @@ -244,7 +244,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) color: Appearance.m3colors.m3outline horizontalAlignment: Text.AlignLeft wrapMode: Text.Wrap - text: qsTr("Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window") + text: Translation.tr("Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window") } } } @@ -366,7 +366,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) Layout.fillWidth: true padding: 10 color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant - placeholderText: StringUtils.format(qsTr('Message the model... "{0}" for commands'), root.commandPrefix) + placeholderText: StringUtils.format(Translation.tr('Message the model... "{0}" for commands'), root.commandPrefix) background: null @@ -510,7 +510,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) id: toolTip extraVisibleCondition: false alternativeVisibleCondition: mouseArea.containsMouse // Show tooltip when hovered - content: StringUtils.format(qsTr("Current model: {0}\nSet it with {1}model MODEL"), + content: StringUtils.format(Translation.tr("Current model: {0}\nSet it with {1}model MODEL"), Ai.getModel().name, root.commandPrefix) } diff --git a/.config/quickshell/modules/sidebarLeft/Anime.qml b/.config/quickshell/modules/sidebarLeft/Anime.qml index 1300d548..a0e11098 100644 --- a/.config/quickshell/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/modules/sidebarLeft/Anime.qml @@ -6,6 +6,7 @@ import "root:/modules/common/functions/fuzzysort.js" as Fuzzy import "root:/modules/common/functions/string_utils.js" as StringUtils import "root:/modules/common/functions/file_utils.js" as FileUtils import "./anime/" +import "root:/services/" import Qt.labs.platform import QtQuick import QtQuick.Controls @@ -39,21 +40,21 @@ Item { property var allCommands: [ { name: "mode", - description: qsTr("Set the current API provider"), + description: Translation.tr("Set the current API provider"), execute: (args) => { Booru.setProvider(args[0]); } }, { name: "clear", - description: qsTr("Clear the current list of images"), + description: Translation.tr("Clear the current list of images"), execute: () => { Booru.clearResponses(); } }, { name: "next", - description: qsTr("Get the next page of results"), + description: Translation.tr("Get the next page of results"), execute: () => { if (root.responses.length > 0) { const lastResponse = root.responses[root.responses.length - 1]; @@ -63,14 +64,14 @@ Item { }, { name: "safe", - description: qsTr("Disable NSFW content"), + description: Translation.tr("Disable NSFW content"), execute: () => { PersistentStateManager.setState("booru.allowNsfw", false); } }, { name: "lewd", - description: qsTr("Allow NSFW content"), + description: Translation.tr("Allow NSFW content"), execute: () => { PersistentStateManager.setState("booru.allowNsfw", true); } @@ -86,7 +87,7 @@ Item { if (commandObj) { commandObj.execute(args); } else { - Booru.addSystemMessage(qsTr("Unknown command: ") + command); + Booru.addSystemMessage(Translation.tr("Unknown command: ") + command); } } else if (inputText.trim() == "+") { @@ -208,7 +209,7 @@ Item { font.family: Appearance.font.family.title color: Appearance.m3colors.m3outline horizontalAlignment: Text.AlignHCenter - text: qsTr("Anime boorus") + text: Translation.tr("Anime boorus") } } } @@ -245,7 +246,7 @@ Item { font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.m3colors.m3inverseOnSurface wrapMode: Text.Wrap - text: StringUtils.format(qsTr("{0} queries pending"), Booru.runningRequests) + text: StringUtils.format(Translation.tr("{0} queries pending"), Booru.runningRequests) } } } @@ -381,7 +382,7 @@ Item { padding: 10 color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant renderType: Text.NativeRendering - placeholderText: StringUtils.format(qsTr('Enter tags, or "{0}" for commands'), root.commandPrefix) + placeholderText: StringUtils.format(Translation.tr('Enter tags, or "{0}" for commands'), root.commandPrefix) background: null @@ -544,8 +545,8 @@ Item { id: toolTip extraVisibleCondition: false alternativeVisibleCondition: mouseArea.containsMouse // Show tooltip when hovered - // content: qsTr("The current API used. Endpoint: ") + Booru.providers[Booru.currentProvider].url + qsTr("\nSet with /mode PROVIDER") - content: StringUtils.format(qsTr("Current API endpoint: {0}\nSet it with {1}mode PROVIDER"), + // content: Translation.tr("The current API used. Endpoint: ") + Booru.providers[Booru.currentProvider].url + Translation.tr("\nSet with /mode PROVIDER") + content: StringUtils.format(Translation.tr("Current API endpoint: {0}\nSet it with {1}mode PROVIDER"), Booru.providers[Booru.currentProvider].url, root.commandPrefix) } @@ -586,7 +587,7 @@ Item { Layout.alignment: Qt.AlignVCenter font.pixelSize: Appearance.font.pixelSize.smaller color: nsfwSwitch.enabled ? Appearance.colors.colOnLayer1 : Appearance.m3colors.m3outline - text: qsTr("Allow NSFW") + text: Translation.tr("Allow NSFW") } StyledSwitch { id: nsfwSwitch diff --git a/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml b/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml index ce0b2280..bed1d85f 100644 --- a/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml +++ b/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml @@ -2,6 +2,7 @@ import "root:/" import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" +import "root:/services/" import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -168,7 +169,7 @@ Scope { // Scope GlobalShortcut { name: "sidebarLeftToggle" - description: qsTr("Toggles left sidebar on press") + description: Translation.tr("Toggles left sidebar on press") onPressed: { GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen; @@ -177,7 +178,7 @@ Scope { // Scope GlobalShortcut { name: "sidebarLeftOpen" - description: qsTr("Opens left sidebar on press") + description: Translation.tr("Opens left sidebar on press") onPressed: { GlobalStates.sidebarLeftOpen = true; @@ -186,7 +187,7 @@ Scope { // Scope GlobalShortcut { name: "sidebarLeftClose" - description: qsTr("Closes left sidebar on press") + description: Translation.tr("Closes left sidebar on press") onPressed: { GlobalStates.sidebarLeftOpen = false; @@ -195,7 +196,7 @@ Scope { // Scope GlobalShortcut { name: "sidebarLeftToggleDetach" - description: qsTr("Detach left sidebar into a window/Attach it back") + description: Translation.tr("Detach left sidebar into a window/Attach it back") onPressed: { root.detach = !root.detach; diff --git a/.config/quickshell/modules/sidebarLeft/SidebarLeftContent.qml b/.config/quickshell/modules/sidebarLeft/SidebarLeftContent.qml index 8d67c2a7..aec68bea 100644 --- a/.config/quickshell/modules/sidebarLeft/SidebarLeftContent.qml +++ b/.config/quickshell/modules/sidebarLeft/SidebarLeftContent.qml @@ -2,6 +2,7 @@ import "root:/" import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" +import "root:/services/" import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -18,9 +19,9 @@ Item { required property var scopeRoot anchors.fill: parent property var tabButtonList: [ - ...(ConfigOptions.policies.ai !== 0 ? [{"icon": "neurology", "name": qsTr("Intelligence")}] : []), - {"icon": "translate", "name": qsTr("Translator")}, - ...(ConfigOptions.policies.weeb === 1 ? [{"icon": "bookmark_heart", "name": qsTr("Anime")}] : []) + ...(ConfigOptions.policies.ai !== 0 ? [{"icon": "neurology", "name": Translation.tr("Intelligence")}] : []), + {"icon": "translate", "name": Translation.tr("Translator")}, + ...(ConfigOptions.policies.weeb === 1 ? [{"icon": "bookmark_heart", "name": Translation.tr("Anime")}] : []) ] property int selectedTab: 0 diff --git a/.config/quickshell/modules/sidebarLeft/Translator.qml b/.config/quickshell/modules/sidebarLeft/Translator.qml index 37e5a37b..e6400df1 100644 --- a/.config/quickshell/modules/sidebarLeft/Translator.qml +++ b/.config/quickshell/modules/sidebarLeft/Translator.qml @@ -123,7 +123,7 @@ Item { TextCanvas { // Content translation id: outputCanvas isInput: false - placeholderText: qsTr("Translation goes here...") + placeholderText: Translation.tr("Translation goes here...") property bool hasTranslation: (root.translatedText.trim().length > 0) text: hasTranslation ? root.translatedText : "" GroupButton { @@ -178,7 +178,7 @@ Item { TextCanvas { // Content input id: inputCanvas isInput: true - placeholderText: qsTr("Enter text to translate...") + placeholderText: Translation.tr("Enter text to translate...") onInputTextChanged: { translateTimer.restart(); } @@ -223,7 +223,7 @@ Item { z: 9999 sourceComponent: SelectionDialog { id: languageSelectorDialog - titleText: qsTr("Select Language") + titleText: Translation.tr("Select Language") items: root.languages defaultChoice: root.languageSelectorTarget ? root.targetLanguage : root.sourceLanguage onCanceled: () => { diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml index 8d795211..18e5935e 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml @@ -151,7 +151,7 @@ Rectangle { color: Appearance.m3colors.m3onSecondaryContainer text: messageData?.role == 'assistant' ? Ai.models[messageData?.model].name : (messageData?.role == 'user' && SystemInfo.username) ? SystemInfo.username : - qsTr("Interface") + Translation.tr("Interface") } } } @@ -173,7 +173,7 @@ Rectangle { text: "visibility_off" } StyledToolTip { - content: qsTr("Not visible to model") + content: Translation.tr("Not visible to model") } } @@ -200,7 +200,7 @@ Rectangle { } StyledToolTip { - content: qsTr("Copy") + content: Translation.tr("Copy") } } AiMessageControlButton { @@ -215,7 +215,7 @@ Rectangle { } } StyledToolTip { - content: root.editing ? qsTr("Save") : qsTr("Edit") + content: root.editing ? Translation.tr("Save") : Translation.tr("Edit") } } AiMessageControlButton { @@ -226,7 +226,7 @@ Rectangle { root.renderMarkdown = !root.renderMarkdown } StyledToolTip { - content: qsTr("View Markdown source") + content: Translation.tr("View Markdown source") } } AiMessageControlButton { @@ -236,7 +236,7 @@ Rectangle { Ai.removeMessage(root.messageIndex) } StyledToolTip { - content: qsTr("Delete") + content: Translation.tr("Delete") } } } diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml b/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml index ea7bb0ee..d0a434db 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml @@ -87,7 +87,7 @@ ColumnLayout { } } StyledToolTip { - content: qsTr("Copy code") + content: Translation.tr("Copy code") } } AiMessageControlButton { @@ -111,7 +111,7 @@ ColumnLayout { } } StyledToolTip { - content: qsTr("Save to Downloads") + content: Translation.tr("Save to Downloads") } } } diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml b/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml index faa6c559..189d1cfd 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml @@ -124,7 +124,7 @@ ColumnLayout { wrapMode: TextEdit.Wrap color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1 textFormat: renderMarkdown ? TextEdit.MarkdownText : TextEdit.PlainText - text: qsTr("Waiting for response...") + text: Translation.tr("Waiting for response...") onTextChanged: { if (!root.editing) return diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageThinkBlock.qml b/.config/quickshell/modules/sidebarLeft/aiChat/MessageThinkBlock.qml index 1ae941b7..c05d33cf 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/MessageThinkBlock.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/MessageThinkBlock.qml @@ -99,7 +99,7 @@ Item { id: thinkBlockLanguage Layout.fillWidth: false Layout.alignment: Qt.AlignLeft - text: root.completed ? qsTr("Chain of Thought") : (qsTr("Thinking") + ".".repeat(Math.random() * 4)) + text: root.completed ? Translation.tr("Chain of Thought") : (Translation.tr("Thinking") + ".".repeat(Math.random() * 4)) } Item { Layout.fillWidth: true } RippleButton { // Expand button diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml b/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml index 4e115bc7..6cdee99c 100644 --- a/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml +++ b/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml @@ -153,7 +153,7 @@ Button { MenuButton { id: openFileLinkButton Layout.fillWidth: true - buttonText: qsTr("Open file link") + buttonText: Translation.tr("Open file link") onClicked: { root.showActions = false Hyprland.dispatch("keyword cursor:no_warps true") @@ -165,7 +165,7 @@ Button { id: sourceButton visible: root.imageData.source && root.imageData.source.length > 0 Layout.fillWidth: true - buttonText: StringUtils.format(qsTr("Go to source ({0})"), StringUtils.getDomain(root.imageData.source)) + buttonText: StringUtils.format(Translation.tr("Go to source ({0})"), StringUtils.getDomain(root.imageData.source)) enabled: root.imageData.source && root.imageData.source.length > 0 onClicked: { root.showActions = false @@ -177,10 +177,10 @@ Button { MenuButton { id: downloadButton Layout.fillWidth: true - buttonText: qsTr("Download") + buttonText: Translation.tr("Download") onClicked: { root.showActions = false - Hyprland.dispatch(`exec curl '${root.imageData.file_url}' -o '${root.imageData.is_nsfw ? root.nsfwPath : root.downloadPath}/${root.fileName}' && notify-send '${qsTr("Download complete")}' '${root.downloadPath}/${root.fileName}' -a 'Shell'`) + Hyprland.dispatch(`exec curl '${root.imageData.file_url}' -o '${root.imageData.is_nsfw ? root.nsfwPath : root.downloadPath}/${root.fileName}' && notify-send '${Translation.tr("Download complete")}' '${root.downloadPath}/${root.fileName}' -a 'Shell'`) } } } diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml b/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml index 7a207582..58df4fa4 100644 --- a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml +++ b/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml @@ -4,6 +4,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/string_utils.js" as StringUtils import "../" +import "root:/services/" import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -94,7 +95,7 @@ Rectangle { font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.colors.colOnLayer2 // text: `Page ${root.responseData.page}` - text: StringUtils.format(qsTr("Page {0}"), root.responseData.page) + text: StringUtils.format(Translation.tr("Page {0}"), root.responseData.page) } } } diff --git a/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml b/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml index dad25020..5b81a29d 100644 --- a/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml +++ b/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml @@ -78,7 +78,7 @@ Rectangle { visible: root.isInput Layout.leftMargin: 10 sourceComponent: Text { - text: qsTr("%1 characters").arg(inputLoader.item.text.length) + text: Translation.tr("%1 characters").arg(inputLoader.item.text.length) color: Appearance.colors.colOnLayer1 font.pixelSize: Appearance.font.pixelSize.smaller } diff --git a/.config/quickshell/modules/sidebarRight/CenterWidgetGroup.qml b/.config/quickshell/modules/sidebarRight/CenterWidgetGroup.qml index 1b426da4..76e47888 100644 --- a/.config/quickshell/modules/sidebarRight/CenterWidgetGroup.qml +++ b/.config/quickshell/modules/sidebarRight/CenterWidgetGroup.qml @@ -5,6 +5,7 @@ import "./calendar" import "./notifications" import "./todo" import "./volumeMixer" +import "root:/services/" import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls @@ -17,7 +18,7 @@ Rectangle { color: Appearance.colors.colLayer1 property int selectedTab: 0 - property var tabButtonList: [{"icon": "notifications", "name": qsTr("Notifications")}, {"icon": "volume_up", "name": qsTr("Volume mixer")}] + property var tabButtonList: [{"icon": "notifications", "name": Translation.tr("Notifications")}, {"icon": "volume_up", "name": Translation.tr("Volume mixer")}] Keys.onPressed: (event) => { if (event.key === Qt.Key_PageDown || event.key === Qt.Key_PageUp) { diff --git a/.config/quickshell/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/modules/sidebarRight/SidebarRight.qml index ed9788f0..04232287 100644 --- a/.config/quickshell/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/modules/sidebarRight/SidebarRight.qml @@ -4,6 +4,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/string_utils.js" as StringUtils import "./quickToggles/" +import "root:/services/" import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -119,7 +120,7 @@ Scope { StyledText { font.pixelSize: Appearance.font.pixelSize.normal color: Appearance.colors.colOnLayer0 - text: StringUtils.format(qsTr("Uptime: {0}"), DateTime.uptime) + text: StringUtils.format(Translation.tr("Uptime: {0}"), DateTime.uptime) textFormat: Text.MarkdownText } @@ -136,7 +137,7 @@ Scope { Quickshell.reload(true) } StyledToolTip { - content: qsTr("Reload Hyprland & Quickshell") + content: Translation.tr("Reload Hyprland & Quickshell") } } QuickToggleButton { @@ -147,7 +148,7 @@ Scope { Hyprland.dispatch(`global quickshell:sidebarRightClose`) } StyledToolTip { - content: qsTr("Plasma Settings") + content: Translation.tr("Plasma Settings") } } QuickToggleButton { @@ -157,7 +158,7 @@ Scope { Hyprland.dispatch("global quickshell:sessionOpen") } StyledToolTip { - content: qsTr("Session") + content: Translation.tr("Session") } } } @@ -218,7 +219,7 @@ Scope { GlobalShortcut { name: "sidebarRightToggle" - description: qsTr("Toggles right sidebar on press") + description: Translation.tr("Toggles right sidebar on press") onPressed: { GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen; @@ -227,7 +228,7 @@ Scope { } GlobalShortcut { name: "sidebarRightOpen" - description: qsTr("Opens right sidebar on press") + description: Translation.tr("Opens right sidebar on press") onPressed: { GlobalStates.sidebarRightOpen = true; @@ -236,7 +237,7 @@ Scope { } GlobalShortcut { name: "sidebarRightClose" - description: qsTr("Closes right sidebar on press") + description: Translation.tr("Closes right sidebar on press") onPressed: { GlobalStates.sidebarRightOpen = false; diff --git a/.config/quickshell/modules/sidebarRight/calendar/CalendarWidget.qml b/.config/quickshell/modules/sidebarRight/calendar/CalendarWidget.qml index 1f11d87a..7fd72db4 100644 --- a/.config/quickshell/modules/sidebarRight/calendar/CalendarWidget.qml +++ b/.config/quickshell/modules/sidebarRight/calendar/CalendarWidget.qml @@ -48,7 +48,7 @@ Item { CalendarHeaderButton { clip: true buttonText: `${monthShift != 0 ? "• " : ""}${viewingDate.toLocaleDateString(Qt.locale(), "MMMM yyyy")}` - tooltipText: (monthShift === 0) ? "" : qsTr("Jump to current month") + tooltipText: (monthShift === 0) ? "" : Translation.tr("Jump to current month") onClicked: { monthShift = 0; } diff --git a/.config/quickshell/modules/sidebarRight/notifications/NotificationList.qml b/.config/quickshell/modules/sidebarRight/notifications/NotificationList.qml index 491b7683..461a671b 100644 --- a/.config/quickshell/modules/sidebarRight/notifications/NotificationList.qml +++ b/.config/quickshell/modules/sidebarRight/notifications/NotificationList.qml @@ -1,6 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" +import "root:/services/" import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls @@ -61,7 +62,7 @@ Item { font.pixelSize: Appearance.font.pixelSize.normal color: Appearance.m3colors.m3outline horizontalAlignment: Text.AlignHCenter - text: qsTr("No notifications") + text: Translation.tr("No notifications") } } } @@ -101,7 +102,7 @@ Item { NotificationStatusButton { buttonIcon: "notifications_paused" - buttonText: qsTr("Silent") + buttonText: Translation.tr("Silent") toggled: Notifications.silent onClicked: () => { Notifications.silent = !Notifications.silent; @@ -109,7 +110,7 @@ Item { } NotificationStatusButton { buttonIcon: "clear_all" - buttonText: qsTr("Clear") + buttonText: Translation.tr("Clear") onClicked: () => { Notifications.discardAllNotifications() } diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml b/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml index 083ecc03..bd0295c4 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml @@ -28,9 +28,9 @@ QuickToggleButton { } } StyledToolTip { - content: StringUtils.format(qsTr("{0} | Right-click to configure"), + content: StringUtils.format(Translation.tr("{0} | Right-click to configure"), (Bluetooth.bluetoothEnabled && Bluetooth.bluetoothDeviceName.length > 0) ? - Bluetooth.bluetoothDeviceName : qsTr("Bluetooth")) + Bluetooth.bluetoothDeviceName : Translation.tr("Bluetooth")) } } diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml b/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml index 1cd56acc..de6f210c 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml @@ -1,6 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "../" +import "root:/services/" import Quickshell import Quickshell.Io import Quickshell.Hyprland @@ -21,6 +22,6 @@ QuickToggleButton { } StyledToolTip { - content: qsTr("Game mode") + content: Translation.tr("Game mode") } } \ No newline at end of file diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml b/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml index b48d3467..0cb848fb 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml @@ -1,6 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "../" +import "root:/services/" import Quickshell.Io import Quickshell import Quickshell.Hyprland @@ -27,6 +28,6 @@ QuickToggleButton { } } StyledToolTip { - content: qsTr("Keep system awake") + content: Translation.tr("Keep system awake") } } diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml b/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml index 5271e376..0ba09b72 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml @@ -3,6 +3,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/string_utils.js" as StringUtils import "../" +import "root:/services/" import QtQuick import Quickshell import Quickshell.Io @@ -28,6 +29,6 @@ QuickToggleButton { } } StyledToolTip { - content: StringUtils.format(qsTr("{0} | Right-click to configure"), Network.networkName) + content: StringUtils.format(Translation.tr("{0} | Right-click to configure"), Network.networkName) } } diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/NightLight.qml b/.config/quickshell/modules/sidebarRight/quickToggles/NightLight.qml index 72df3e1e..f71d80a2 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/NightLight.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/NightLight.qml @@ -1,6 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "../" +import "root:/services/" import Quickshell.Io import Quickshell @@ -37,6 +38,6 @@ QuickToggleButton { } } StyledToolTip { - content: qsTr("Night Light") + content: Translation.tr("Night Light") } } diff --git a/.config/quickshell/modules/sidebarRight/todo/TodoWidget.qml b/.config/quickshell/modules/sidebarRight/todo/TodoWidget.qml index 9f5f4fd0..ea570117 100644 --- a/.config/quickshell/modules/sidebarRight/todo/TodoWidget.qml +++ b/.config/quickshell/modules/sidebarRight/todo/TodoWidget.qml @@ -10,7 +10,7 @@ import QtQuick.Layouts Item { id: root property int currentTab: 0 - property var tabButtonList: [{"icon": "checklist", "name": qsTr("Unfinished")}, {"name": qsTr("Done"), "icon": "check_circle"}] + property var tabButtonList: [{"icon": "checklist", "name": Translation.tr("Unfinished")}, {"name": Translation.tr("Done"), "icon": "check_circle"}] property bool showAddDialog: false property int dialogMargins: 20 property int fabSize: 48 @@ -134,7 +134,7 @@ Item { TaskList { listBottomPadding: root.fabSize + root.fabMargins * 2 emptyPlaceholderIcon: "check_circle" - emptyPlaceholderText: qsTr("Nothing here!") + emptyPlaceholderText: Translation.tr("Nothing here!") taskList: Todo.list .map(function(item, i) { return Object.assign({}, item, {originalIndex: i}); }) .filter(function(item) { return !item.done; }) @@ -142,7 +142,7 @@ Item { TaskList { listBottomPadding: root.fabSize + root.fabMargins * 2 emptyPlaceholderIcon: "checklist" - emptyPlaceholderText: qsTr("Finished tasks will go here") + emptyPlaceholderText: Translation.tr("Finished tasks will go here") taskList: Todo.list .map(function(item, i) { return Object.assign({}, item, {originalIndex: i}); }) .filter(function(item) { return item.done; }) @@ -252,7 +252,7 @@ Item { Layout.alignment: Qt.AlignLeft color: Appearance.m3colors.m3onSurface font.pixelSize: Appearance.font.pixelSize.larger - text: qsTr("Add task") + text: Translation.tr("Add task") } TextField { @@ -265,7 +265,7 @@ Item { renderType: Text.NativeRendering selectedTextColor: Appearance.m3colors.m3onSecondaryContainer selectionColor: Appearance.colors.colSecondaryContainer - placeholderText: qsTr("Task description") + placeholderText: Translation.tr("Task description") placeholderTextColor: Appearance.m3colors.m3outline focus: root.showAddDialog onAccepted: dialog.addTask() @@ -293,11 +293,11 @@ Item { spacing: 5 DialogButton { - buttonText: qsTr("Cancel") + buttonText: Translation.tr("Cancel") onClicked: root.showAddDialog = false } DialogButton { - buttonText: qsTr("Add") + buttonText: Translation.tr("Add") enabled: todoInput.text.length > 0 onClicked: dialog.addTask() } diff --git a/.config/quickshell/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml b/.config/quickshell/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml index cc956cc0..0e5f37bb 100644 --- a/.config/quickshell/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml +++ b/.config/quickshell/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml @@ -1,6 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" +import "root:/services/" import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls @@ -40,14 +41,14 @@ GroupButton { Layout.fillWidth: true elide: Text.ElideRight font.pixelSize: Appearance.font.pixelSize.normal - text: input ? qsTr("Input") : qsTr("Output") + text: input ? Translation.tr("Input") : Translation.tr("Output") color: Appearance.colors.colOnLayer2 } StyledText { Layout.fillWidth: true elide: Text.ElideRight font.pixelSize: Appearance.font.pixelSize.smaller - text: (input ? Pipewire.defaultAudioSource?.description : Pipewire.defaultAudioSink?.description) ?? qsTr("Unknown") + text: (input ? Pipewire.defaultAudioSource?.description : Pipewire.defaultAudioSink?.description) ?? Translation.tr("Unknown") color: Appearance.m3colors.m3outline } } diff --git a/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml b/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml index 2e1570f3..c32d599f 100644 --- a/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml +++ b/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml @@ -1,6 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" +import "root:/services/" import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls @@ -108,7 +109,7 @@ Item { font.pixelSize: Appearance.font.pixelSize.normal color: Appearance.m3colors.m3outline horizontalAlignment: Text.AlignHCenter - text: qsTr("No audio source") + text: Translation.tr("No audio source") } } } @@ -262,13 +263,13 @@ Item { Layout.alignment: Qt.AlignRight DialogButton { - buttonText: qsTr("Cancel") + buttonText: Translation.tr("Cancel") onClicked: { root.showDeviceSelector = false } } DialogButton { - buttonText: qsTr("OK") + buttonText: Translation.tr("OK") onClicked: { root.showDeviceSelector = false if (root.selectedDevice) { diff --git a/.config/quickshell/services/Ai.qml b/.config/quickshell/services/Ai.qml index f545b878..a3980f3c 100644 --- a/.config/quickshell/services/Ai.qml +++ b/.config/quickshell/services/Ai.qml @@ -4,6 +4,7 @@ pragma ComponentBehavior: Bound import "root:/modules/common/functions/string_utils.js" as StringUtils import "root:/modules/common/functions/object_utils.js" as ObjectUtils import "root:/modules/common" +import "root:/services/" import Quickshell; import Quickshell.Io; import Qt.labs.platform @@ -53,14 +54,14 @@ Singleton { "gemini-2.0-flash-search": { "name": "Gemini 2.0 Flash (Search)", "icon": "google-gemini-symbolic", - "description": qsTr("Online | Google's model\nGives up-to-date information with search."), + "description": Translation.tr("Online | Google's model\nGives up-to-date information with search."), "homepage": "https://aistudio.google.com", "endpoint": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:streamGenerateContent", "model": "gemini-2.0-flash", "requires_key": true, "key_id": "gemini", "key_get_link": "https://aistudio.google.com/app/apikey", - "key_get_description": qsTr("**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key"), + "key_get_description": Translation.tr("**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key"), "api_format": "gemini", "tools": [ { @@ -71,14 +72,14 @@ Singleton { "gemini-2.0-flash-tools": { "name": "Gemini 2.0 Flash (Tools)", "icon": "google-gemini-symbolic", - "description": qsTr("Experimental | Online | Google's model\nCan do a little more but doesn't search quickly"), + "description": Translation.tr("Experimental | Online | Google's model\nCan do a little more but doesn't search quickly"), "homepage": "https://aistudio.google.com", "endpoint": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:streamGenerateContent", "model": "gemini-2.0-flash", "requires_key": true, "key_id": "gemini", "key_get_link": "https://aistudio.google.com/app/apikey", - "key_get_description": qsTr("**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key"), + "key_get_description": Translation.tr("**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key"), "api_format": "gemini", "tools": [ { @@ -116,14 +117,14 @@ Singleton { "gemini-2.5-flash-search": { "name": "Gemini 2.5 Flash (Search)", "icon": "google-gemini-symbolic", - "description": qsTr("Online | Google's model\nGives up-to-date information with search."), + "description": Translation.tr("Online | Google's model\nGives up-to-date information with search."), "homepage": "https://aistudio.google.com", "endpoint": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:streamGenerateContent", "model": "gemini-2.5-flash-preview-05-20", "requires_key": true, "key_id": "gemini", "key_get_link": "https://aistudio.google.com/app/apikey", - "key_get_description": qsTr("**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key"), + "key_get_description": Translation.tr("**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key"), "api_format": "gemini", "tools": [ { @@ -134,14 +135,14 @@ Singleton { "gemini-2.5-flash-tools": { "name": "Gemini 2.5 Flash (Tools)", "icon": "google-gemini-symbolic", - "description": qsTr("Experimental | Online | Google's model\nCan do a little more but doesn't search quickly"), + "description": Translation.tr("Experimental | Online | Google's model\nCan do a little more but doesn't search quickly"), "homepage": "https://aistudio.google.com", "endpoint": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:streamGenerateContent", "model": "gemini-2.5-flash-preview-05-20", "requires_key": true, "key_id": "gemini", "key_get_link": "https://aistudio.google.com/app/apikey", - "key_get_description": qsTr("**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key"), + "key_get_description": Translation.tr("**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key"), "api_format": "gemini", "tools": [ { @@ -179,26 +180,26 @@ Singleton { "openrouter-llama4-maverick": { "name": "Llama 4 Maverick", "icon": "ollama-symbolic", - "description": StringUtils.format(qsTr("Online via {0} | {1}'s model"), "OpenRouter", "Meta"), + "description": StringUtils.format(Translation.tr("Online via {0} | {1}'s model"), "OpenRouter", "Meta"), "homepage": "https://openrouter.ai/meta-llama/llama-4-maverick:free", "endpoint": "https://openrouter.ai/api/v1/chat/completions", "model": "meta-llama/llama-4-maverick:free", "requires_key": true, "key_id": "openrouter", "key_get_link": "https://openrouter.ai/settings/keys", - "key_get_description": qsTr("**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key"), + "key_get_description": Translation.tr("**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key"), }, "openrouter-deepseek-r1": { "name": "DeepSeek R1", "icon": "deepseek-symbolic", - "description": StringUtils.format(qsTr("Online via {0} | {1}'s model"), "OpenRouter", "DeepSeek"), + "description": StringUtils.format(Translation.tr("Online via {0} | {1}'s model"), "OpenRouter", "DeepSeek"), "homepage": "https://openrouter.ai/deepseek/deepseek-r1:free", "endpoint": "https://openrouter.ai/api/v1/chat/completions", "model": "deepseek/deepseek-r1:free", "requires_key": true, "key_id": "openrouter", "key_get_link": "https://openrouter.ai/settings/keys", - "key_get_description": qsTr("**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key"), + "key_get_description": Translation.tr("**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key"), }, } property var modelList: Object.keys(root.models) @@ -244,7 +245,7 @@ Singleton { root.models[safeModelName] = { "name": guessModelName(model), "icon": guessModelLogo(model), - "description": StringUtils.format(qsTr("Local Ollama model | {0}"), model), + "description": StringUtils.format(Translation.tr("Local Ollama model | {0}"), model), "homepage": `https://ollama.com/library/${model}`, "endpoint": "http://localhost:11434/v1/chat/completions", "model": model, @@ -283,8 +284,8 @@ Singleton { function addApiKeyAdvice(model) { root.addMessage( - StringUtils.format(qsTr('To set an API key, pass it with the command\n\nTo view the key, pass "get" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}'), - model.name, model.key_get_link, model.key_get_description ?? qsTr("No further instruction provided")), + StringUtils.format(Translation.tr('To set an API key, pass it with the command\n\nTo view the key, pass "get" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}'), + model.name, model.key_get_link, model.key_get_description ?? Translation.tr("No further instruction provided")), Ai.interfaceRole ); } @@ -314,7 +315,7 @@ Singleton { } } } else { - if (feedback) root.addMessage(qsTr("Invalid model. Supported: \n```\n") + modelList.join("\n```\n```\n"), Ai.interfaceRole) + "\n```" + if (feedback) root.addMessage(Translation.tr("Invalid model. Supported: \n```\n") + modelList.join("\n```\n```\n"), Ai.interfaceRole) + "\n```" } } @@ -324,18 +325,18 @@ Singleton { function setTemperature(value) { if (value == NaN || value < 0 || value > 2) { - root.addMessage(qsTr("Temperature must be between 0 and 2"), Ai.interfaceRole); + root.addMessage(Translation.tr("Temperature must be between 0 and 2"), Ai.interfaceRole); return; } PersistentStateManager.setState("ai.temperature", value); root.temperature = value; - root.addMessage(StringUtils.format(qsTr("Temperature set to {0}"), value), Ai.interfaceRole); + root.addMessage(StringUtils.format(Translation.tr("Temperature set to {0}"), value), Ai.interfaceRole); } function setApiKey(key) { const model = models[currentModelId]; if (!model.requires_key) { - root.addMessage(StringUtils.format(qsTr("{0} does not require an API key"), model.name), Ai.interfaceRole); + root.addMessage(StringUtils.format(Translation.tr("{0} does not require an API key"), model.name), Ai.interfaceRole); return; } if (!key || key.length === 0) { @@ -344,7 +345,7 @@ Singleton { return; } KeyringStorage.setNestedField(["apiKeys", model.key_id], key.trim()); - root.addMessage(StringUtils.format(qsTr("API key set for {0}"), model.name, Ai.interfaceRole)); + root.addMessage(StringUtils.format(Translation.tr("API key set for {0}"), model.name, Ai.interfaceRole)); } function printApiKey() { @@ -352,17 +353,17 @@ Singleton { if (model.requires_key) { const key = root.apiKeys[model.key_id]; if (key) { - root.addMessage(StringUtils.format(qsTr("API key:\n\n```txt\n{0}\n```"), key), Ai.interfaceRole); + root.addMessage(StringUtils.format(Translation.tr("API key:\n\n```txt\n{0}\n```"), key), Ai.interfaceRole); } else { - root.addMessage(StringUtils.format(qsTr("No API key set for {0}"), model.name), Ai.interfaceRole); + root.addMessage(StringUtils.format(Translation.tr("No API key set for {0}"), model.name), Ai.interfaceRole); } } else { - root.addMessage(StringUtils.format(qsTr("{0} does not require an API key"), model.name), Ai.interfaceRole); + root.addMessage(StringUtils.format(Translation.tr("{0} does not require an API key"), model.name), Ai.interfaceRole); } } function printTemperature() { - root.addMessage(StringUtils.format(qsTr("Temperature: {0}"), root.temperature), Ai.interfaceRole); + root.addMessage(StringUtils.format(Translation.tr("Temperature: {0}"), root.temperature), Ai.interfaceRole); } function clearMessages() { @@ -701,7 +702,7 @@ Singleton { root.setModel("gemini-2.0-flash-search", false); root.postResponseHook = () => root.setModel("gemini-2.0-flash-tools", false); } - addFunctionOutputMessage(name, qsTr("Switched to search mode. Continue with the user's request.")) + addFunctionOutputMessage(name, Translation.tr("Switched to search mode. Continue with the user's request.")) requester.makeRequest(); } else if (name === "get_shell_config") { const configJson = ObjectUtils.toPlainObject(ConfigOptions) @@ -709,7 +710,7 @@ Singleton { requester.makeRequest(); } else if (name === "set_shell_config") { if (!args.key || !args.value) { - addFunctionOutputMessage(name, qsTr("Invalid arguments. Must provide `key` and `value`.")); + addFunctionOutputMessage(name, Translation.tr("Invalid arguments. Must provide `key` and `value`.")); return; } const key = args.key; @@ -717,7 +718,7 @@ Singleton { ConfigLoader.setLiveConfigValue(key, value); ConfigLoader.saveConfig(); } - else root.addMessage(qsTr("Unknown function call: {0}"), "assistant"); + else root.addMessage(Translation.tr("Unknown function call: {0}"), "assistant"); } } diff --git a/.config/quickshell/services/Booru.qml b/.config/quickshell/services/Booru.qml index 49256bfa..b50c1976 100644 --- a/.config/quickshell/services/Booru.qml +++ b/.config/quickshell/services/Booru.qml @@ -2,6 +2,7 @@ pragma Singleton pragma ComponentBehavior: Bound import "root:/modules/common" +import "root:/services/" import Quickshell; import Quickshell.Io; import Qt.labs.platform @@ -16,18 +17,18 @@ Singleton { signal tagSuggestion(string query, var suggestions) - property string failMessage: qsTr("That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number") + property string failMessage: Translation.tr("That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number") property var responses: [] property int runningRequests: 0 property var defaultUserAgent: ConfigOptions?.networking?.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" property var providerList: Object.keys(providers).filter(provider => provider !== "system" && providers[provider].api) property var providers: { - "system": { "name": qsTr("System") }, + "system": { "name": Translation.tr("System") }, "yandere": { "name": "yande.re", "url": "https://yande.re", "api": "https://yande.re/post.json", - "description": qsTr("All-rounder | Good quality, decent quantity"), + "description": Translation.tr("All-rounder | Good quality, decent quantity"), "mapFunc": (response) => { return response.map(item => { return { @@ -61,7 +62,7 @@ Singleton { "name": "Konachan", "url": "https://konachan.com", "api": "https://konachan.com/post.json", - "description": qsTr("For desktop wallpapers | Good quality"), + "description": Translation.tr("For desktop wallpapers | Good quality"), "mapFunc": (response) => { return response.map(item => { return { @@ -95,7 +96,7 @@ Singleton { "name": "Zerochan", "url": "https://www.zerochan.net", "api": "https://www.zerochan.net/?json", - "description": qsTr("Clean stuff | Excellent quality, no NSFW"), + "description": Translation.tr("Clean stuff | Excellent quality, no NSFW"), "mapFunc": (response) => { response = response.items return response.map(item => { @@ -122,7 +123,7 @@ Singleton { "name": "Danbooru", "url": "https://danbooru.donmai.us", "api": "https://danbooru.donmai.us/posts.json", - "description": qsTr("The popular one | Best quantity, but quality can vary wildly"), + "description": Translation.tr("The popular one | Best quantity, but quality can vary wildly"), "mapFunc": (response) => { return response.map(item => { return { @@ -157,7 +158,7 @@ Singleton { "name": "Gelbooru", "url": "https://gelbooru.com", "api": "https://gelbooru.com/index.php?page=dapi&s=post&q=index&json=1", - "description": qsTr("The hentai one | Great quantity, a lot of NSFW, quality varies wildly"), + "description": Translation.tr("The hentai one | Great quantity, a lot of NSFW, quality varies wildly"), "mapFunc": (response) => { response = response.post return response.map(item => { @@ -192,7 +193,7 @@ Singleton { "name": "waifu.im", "url": "https://waifu.im", "api": "https://api.waifu.im/search", - "description": qsTr("Waifus only | Excellent quality, limited quantity"), + "description": Translation.tr("Waifus only | Excellent quality, limited quantity"), "mapFunc": (response) => { response = response.images return response.map(item => { @@ -223,7 +224,7 @@ Singleton { "name": "Alcy", "url": "https://t.alcy.cc", "api": "https://t.alcy.cc/", - "description": qsTr("Large images | God tier quality, no NSFW."), + "description": Translation.tr("Large images | God tier quality, no NSFW."), "fixedTags": [ { "name": "ycy", @@ -287,10 +288,10 @@ Singleton { provider = provider.toLowerCase() if (providerList.indexOf(provider) !== -1) { PersistentStateManager.setState("booru.provider", provider) - root.addSystemMessage(qsTr("Provider set to ") + providers[provider].name - + (provider == "zerochan" ? qsTr(". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!") : "")) + root.addSystemMessage(Translation.tr("Provider set to ") + providers[provider].name + + (provider == "zerochan" ? Translation.tr(". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!") : "")) } else { - root.addSystemMessage(qsTr("Invalid API provider. Supported: \n- ") + providerList.join("\n- ")) + root.addSystemMessage(Translation.tr("Invalid API provider. Supported: \n- ") + providerList.join("\n- ")) } } diff --git a/.config/quickshell/services/Brightness.qml b/.config/quickshell/services/Brightness.qml index aba664aa..a81c01d5 100644 --- a/.config/quickshell/services/Brightness.qml +++ b/.config/quickshell/services/Brightness.qml @@ -4,6 +4,7 @@ pragma ComponentBehavior: Bound // From https://github.com/caelestia-dots/shell/ (`quickshell` branch) with modifications. // License: GPLv3 +import "root:/services/" import Quickshell import Quickshell.Io import Quickshell.Hyprland @@ -140,13 +141,13 @@ Singleton { GlobalShortcut { name: "brightnessIncrease" - description: qsTr("Increase brightness") + description: Translation.tr("Increase brightness") onPressed: root.increaseBrightness() } GlobalShortcut { name: "brightnessDecrease" - description: qsTr("Decrease brightness") + description: Translation.tr("Decrease brightness") onPressed: root.decreaseBrightness() } } diff --git a/.config/quickshell/services/ConfigLoader.qml b/.config/quickshell/services/ConfigLoader.qml index 347e8f40..01a6625e 100644 --- a/.config/quickshell/services/ConfigLoader.qml +++ b/.config/quickshell/services/ConfigLoader.qml @@ -44,7 +44,7 @@ Singleton { } catch (e) { console.error("[ConfigLoader] Error reading file:", e); console.log("[ConfigLoader] File content was:", fileContent); - Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration failed to load")}" "${root.filePath}"`) + Hyprland.dispatch(`exec notify-send "${Translation.tr("Shell configuration failed to load")}" "${root.filePath}"`) return; } @@ -105,7 +105,7 @@ Singleton { } else { root.applyConfig(configFileView.text()) if (!root.preventNextNotification) { - // Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration reloaded")}" "${root.filePath}"`) + // Hyprland.dispatch(`exec notify-send "${Translation.tr("Shell configuration reloaded")}" "${root.filePath}"`) } else { root.preventNextNotification = false; } @@ -129,9 +129,9 @@ Singleton { if(error == FileViewError.FileNotFound) { console.log("[ConfigLoader] File not found, creating new file.") root.saveConfig() - Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration created")}" "${root.filePath}"`) + Hyprland.dispatch(`exec notify-send "${Translation.tr("Shell configuration created")}" "${root.filePath}"`) } else { - Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration failed to load")}" "${root.filePath}"`) + Hyprland.dispatch(`exec notify-send "${Translation.tr("Shell configuration failed to load")}" "${root.filePath}"`) } } } diff --git a/.config/quickshell/services/KeyringStorage.qml b/.config/quickshell/services/KeyringStorage.qml index 3f3956f9..3ec7560b 100644 --- a/.config/quickshell/services/KeyringStorage.qml +++ b/.config/quickshell/services/KeyringStorage.qml @@ -20,14 +20,14 @@ Singleton { property var properties: { "application": "illogical-impulse", - "explanation": qsTr("For storing API keys and other sensitive information"), + "explanation": Translation.tr("For storing API keys and other sensitive information"), } property var propertiesAsArgs: Object.keys(root.properties).reduce( function(arr, key) { return arr.concat([key, root.properties[key]]); }, [] ) - property string keyringLabel: StringUtils.format(qsTr("{0} Safe Storage"), "illogical-impulse") + property string keyringLabel: StringUtils.format(Translation.tr("{0} Safe Storage"), "illogical-impulse") function setNestedField(path, value) { if (!root.keyringData) root.keyringData = {}; diff --git a/.config/quickshell/services/MprisController.qml b/.config/quickshell/services/MprisController.qml index 96aa5e80..90d72ed5 100644 --- a/.config/quickshell/services/MprisController.qml +++ b/.config/quickshell/services/MprisController.qml @@ -4,6 +4,7 @@ pragma ComponentBehavior: Bound // From https://git.outfoxxed.me/outfoxxed/nixnew // It does not have a license, but the author is okay with redistribution. +import "root:/services/" import QtQml.Models import QtQuick import Quickshell @@ -85,9 +86,9 @@ Singleton { this.activeTrack = { uniqueId: this.activePlayer?.uniqueId ?? 0, artUrl: this.activePlayer?.trackArtUrl ?? "", - title: this.activePlayer?.trackTitle || qsTr("Unknown Title"), - artist: this.activePlayer?.trackArtist || qsTr("Unknown Artist"), - album: this.activePlayer?.trackAlbum || qsTr("Unknown Album"), + title: this.activePlayer?.trackTitle || Translation.tr("Unknown Title"), + artist: this.activePlayer?.trackArtist || Translation.tr("Unknown Artist"), + album: this.activePlayer?.trackAlbum || Translation.tr("Unknown Album"), }; this.trackChanged(__reverse); diff --git a/.config/quickshell/services/Translation.qml b/.config/quickshell/services/Translation.qml new file mode 100644 index 00000000..97aff7c5 --- /dev/null +++ b/.config/quickshell/services/Translation.qml @@ -0,0 +1,170 @@ +pragma Singleton + +import QtQuick +import Quickshell +import Quickshell.Io +import "root:/modules/common/" + +Singleton { + id: root + + property var translations: ({}) + property string currentLanguage: "en_US" + property var availableLanguages: ["en_US"] + property bool isScanning: false + property bool isLoading: false + + Process { + id: scanLanguagesProcess + command: ["find", Qt.resolvedUrl(Directories.config + "/quickshell/translations/").toString().replace("file://", ""), "-name", "*.json", "-exec", "basename", "{}", ".json", ";"] + running: false + + stdout: SplitParser { + onRead: data => { + if (data.trim().length === 0) return + + var files = data.trim().split('\n') + + for (var i = 0; i < files.length; i++) { + var lang = files[i].trim() + if (lang.length > 0 && root.availableLanguages.indexOf(lang) === -1) { + root.availableLanguages.push(lang) + } + } + } + } + + onExited: (exitCode, exitStatus) => { + root.isScanning = false + if (exitCode !== 0) { + root.availableLanguages = ["en_US"] + } + root.loadTranslations() + } + } + + FileView { + id: translationFileView + onLoaded: { + var textContent = "" + try { + textContent = text() + } catch (e) { + root.translations = {} + root.isLoading = false + return + } + + if (textContent.length === 0) { + root.translations = {} + root.isLoading = false + return + } + + try { + var jsonData = JSON.parse(textContent) + root.translations = jsonData + root.isLoading = false + } catch (e) { + root.translations = {} + root.isLoading = false + } + } + onLoadFailed: (error) => { + root.translations = {} + root.isLoading = false + } + } + + function detectSystemLanguage() { + var locale = Qt.locale().name + return locale + } + + function getLanguageCode() { + var configLang = "auto" + try { + configLang = ConfigOptions.language.ui + } catch (e) { + configLang = "auto" + } + + if (configLang === "auto") { + return detectSystemLanguage() + } else { + if (root.availableLanguages.indexOf(configLang) !== -1) { + return configLang + } else { + return detectSystemLanguage() + } + } + } + + function loadTranslations() { + if (root.isScanning) { + return + } + + var targetLang = getLanguageCode() + root.currentLanguage = targetLang + + // Use empty translations for English (default language) + if (targetLang === "en_US" || targetLang === "en") { + root.translations = {} + return + } + + // Check if target language is available + if (root.availableLanguages.indexOf(targetLang) === -1) { + root.currentLanguage = "en_US" + root.translations = {} + return + } + + // Load translation file + root.isLoading = true + var translationsPath = Qt.resolvedUrl(Directories.config + "/quickshell/translations/" + targetLang + ".json") + translationFileView.path = translationsPath + } + + function tr(text) { + if (!text) { + return "" + } + + var key = text.toString() + + if (root.isLoading) { + return key + } + + if (root.currentLanguage === "en_US" || root.currentLanguage === "en" || !root.translations) { + return key + } + + if (root.translations.hasOwnProperty(key)) { + var translation = root.translations[key] + if (translation && translation.toString().trim().length > 0) { + return translation.toString() + } else { + return translation.toString() + } + } + + return key // Fallback to key name + } + + function reloadTranslations() { + root.scanLanguages() + } + + function scanLanguages() { + var translationsDir = Qt.resolvedUrl(Directories.config + "/quickshell/translations/").toString().replace("file://", "") + root.isScanning = true + scanLanguagesProcess.running = true + } + + Component.onCompleted: { + root.scanLanguages() + } +} diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json new file mode 100644 index 00000000..6f7c8ec5 --- /dev/null +++ b/.config/quickshell/translations/en_US.json @@ -0,0 +1,472 @@ +{ + "%1 characters": "%1 characters", + "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key": "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key", + "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key", + ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!": ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!", + "No further instruction provided": "No further instruction provided", + "API key set for {0}": "API key set for {0}", + "API key:\n\n```txt\n{0}\n```": "API key:\n\n```txt\n{0}\n```", + "Action": "Action", + "Add": "Add", + "Add task": "Add task", + "All-rounder | Good quality, decent quantity": "All-rounder | Good quality, decent quantity", + "Allow NSFW": "Allow NSFW", + "Allow NSFW content": "Allow NSFW content", + "Anime": "Anime", + "Anime boorus": "Anime boorus", + "App": "App", + "Arrow keys to navigate, Enter to select\nEsc or click anywhere to cancel": "Arrow keys to navigate, Enter to select\nEsc or click anywhere to cancel", + "Bluetooth": "Bluetooth", + "Brightness": "Brightness", + "Cancel": "Cancel", + "Chain of Thought": "Chain of Thought", + "Cheat sheet": "Cheat sheet", + "Choose model": "Choose model", + "Clean stuff | Excellent quality, no NSFW": "Clean stuff | Excellent quality, no NSFW", + "Clear": "Clear", + "Clear chat history": "Clear chat history", + "Clear the current list of images": "Clear the current list of images", + "Close": "Close", + "Closes cheatsheet on press": "Closes cheatsheet on press", + "Closes left sidebar on press": "Closes left sidebar on press", + "Closes media controls on press": "Closes media controls on press", + "Closes on screen keyboard on press": "Closes on screen keyboard on press", + "Closes overview": "Closes overview", + "Closes right sidebar on press": "Closes right sidebar on press", + "Copy": "Copy", + "Copy code": "Copy code", + "Ctrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "Ctrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window", + "Current API endpoint: {0}\nSet it with {1}mode PROVIDER": "Current API endpoint: {0}\nSet it with {1}mode PROVIDER", + "Current model: {0}\nSet it with {1}model MODEL": "Current model: {0}\nSet it with {1}model MODEL", + "Decrease brightness": "Decrease brightness", + "Delete": "Delete", + "Desktop": "Desktop", + "Detach left sidebar into a window/Attach it back": "Detach left sidebar into a window/Attach it back", + "Disable NSFW content": "Disable NSFW content", + "Done": "Done", + "Download": "Download", + "Download complete": "Download complete", + "Edit": "Edit", + "Enter text to translate...": "Enter text to translate...", + "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly", + "Finished tasks will go here": "Finished tasks will go here", + "For desktop wallpapers | Good quality": "For desktop wallpapers | Good quality", + "For storing API keys and other sensitive information": "For storing API keys and other sensitive information", + "Game mode": "Game mode", + "Get the next page of results": "Get the next page of results", + "Go to source ({0})": "Go to source ({0})", + "Hibernate": "Hibernate", + "Hides brightness OSD on press": "Hides brightness OSD on press", + "Hides volume OSD on press": "Hides volume OSD on press", + "Hold to show workspace numbers, release to show icons": "Hold to show workspace numbers, release to show icons", + "Increase brightness": "Increase brightness", + "Input": "Input", + "Intelligence": "Intelligence", + "Interface": "Interface", + "Interrupts possibility of overview being toggled on release. ": "Interrupts possibility of overview being toggled on release. ", + "Invalid API provider. Supported: \n- ": "Invalid API provider. Supported: \n- ", + "Invalid arguments. Must provide `key` and `value`.": "Invalid arguments. Must provide `key` and `value`.", + "Invalid model. Supported: \n```\n": "Invalid model. Supported: \n```\n", + "Jump to current month": "Jump to current month", + "Keep system awake": "Keep system awake", + "Large images | God tier quality, no NSFW.": "Large images | God tier quality, no NSFW.", + "Large language models": "Large language models", + "Launch": "Launch", + "Local Ollama model | {0}": "Local Ollama model | {0}", + "Lock": "Lock", + "Logout": "Logout", + "Markdown test": "Markdown test", + "Math result": "Math result", + "Night Light": "Night Light", + "No API key set for {0}": "No API key set for {0}", + "No audio source": "No audio source", + "No media": "No media", + "No notifications": "No notifications", + "Not visible to model": "Not visible to model", + "Nothing here!": "Nothing here!", + "Notifications": "Notifications", + "OK": "OK", + "Online via {0} | {1}'s model": "Online via {0} | {1}'s model", + "Online | Google's model\nGives up-to-date information with search.": "Online | Google's model\nGives up-to-date information with search.", + "Open file link": "Open file link", + "Opens cheatsheet on press": "Opens cheatsheet on press", + "Opens left sidebar on press": "Opens left sidebar on press", + "Opens media controls on press": "Opens media controls on press", + "Opens on screen keyboard on press": "Opens on screen keyboard on press", + "Opens right sidebar on press": "Opens right sidebar on press", + "Opens session screen on press": "Opens session screen on press", + "Output": "Output", + "Page {0}": "Page {0}", + "Plasma Settings": "Plasma Settings", + "Provider set to ": "Provider set to ", + "Reboot": "Reboot", + "Reboot to firmware settings": "Reboot to firmware settings", + "Reload Hyprland & Quickshell": "Reload Hyprland & Quickshell", + "Run": "Run", + "Run command": "Run command", + "Save": "Save", + "Save to Downloads": "Save to Downloads", + "Scroll to change brightness": "Scroll to change brightness", + "Scroll to change volume": "Scroll to change volume", + "Search": "Search", + "Search the web": "Search the web", + "Search, calculate or run": "Search, calculate or run", + "Select Language": "Select Language", + "Session": "Session", + "Set API key": "Set API key", + "Set temperature (randomness) of the model. Values range between 0 to 2 for Gemini, 0 to 1 for other models. Default is 0.5.": "Set temperature (randomness) of the model. Values range between 0 to 2 for Gemini, 0 to 1 for other models. Default is 0.5.", + "Set the current API provider": "Set the current API provider", + "Shell configuration created": "Shell configuration created", + "Shell configuration failed to load": "Shell configuration failed to load", + "Shell configuration reloaded": "Shell configuration reloaded", + "Shutdown": "Shutdown", + "Silent": "Silent", + "Sleep": "Sleep", + "Switched to search mode. Continue with the user's request.": "Switched to search mode. Continue with the user's request.", + "System": "System", + "Task Manager": "Task Manager", + "Task description": "Task description", + "Temperature must be between 0 and 2": "Temperature must be between 0 and 2", + "Temperature set to {0}": "Temperature set to {0}", + "Temperature: {0}": "Temperature: {0}", + "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number", + "The current API used. Endpoint: ": "The current API used. Endpoint: ", + "The hentai one | Great quantity, a lot of NSFW, quality varies wildly": "The hentai one | Great quantity, a lot of NSFW, quality varies wildly", + "The popular one | Best quantity, but quality can vary wildly": "The popular one | Best quantity, but quality can vary wildly", + "Thinking": "Thinking", + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ": "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ", + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.": "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.", + "Toggle clipboard query on overview widget": "Toggle clipboard query on overview widget", + "Toggle emoji query on overview widget": "Toggle emoji query on overview widget", + "Toggles cheatsheet on press": "Toggles cheatsheet on press", + "Toggles left sidebar on press": "Toggles left sidebar on press", + "Toggles media controls on press": "Toggles media controls on press", + "Toggles on screen keyboard on press": "Toggles on screen keyboard on press", + "Toggles overview on press": "Toggles overview on press", + "Toggles overview on release": "Toggles overview on release", + "Toggles right sidebar on press": "Toggles right sidebar on press", + "Toggles session screen on press": "Toggles session screen on press", + "Translation goes here...": "Translation goes here...", + "Translator": "Translator", + "Triggers brightness OSD on press": "Triggers brightness OSD on press", + "Triggers volume OSD on press": "Triggers volume OSD on press", + "Unfinished": "Unfinished", + "Unknown": "Unknown", + "Unknown Album": "Unknown Album", + "Unknown Artist": "Unknown Artist", + "Unknown Title": "Unknown Title", + "Unknown command: ": "Unknown command: ", + "Unknown function call: {0}": "Unknown function call: {0}", + "Uptime: {0}": "Uptime: {0}", + "Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in **bold** to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`. When making changes to the user's config, you must get the config to know what values there are before setting.": "Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in **bold** to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`. When making changes to the user's config, you must get the config to know what values there are before setting.", + "View Markdown source": "View Markdown source", + "Volume": "Volume", + "Volume mixer": "Volume mixer", + "Waifus only | Excellent quality, limited quantity": "Waifus only | Excellent quality, limited quantity", + "Waiting for response...": "Waiting for response...", + "Workspace": "Workspace", + "\nSet with /mode PROVIDER": "\nSet with /mode PROVIDER", + "about": "About", + "accessed": "Accessed", + "account": "Account", + "active": "Active", + "active_state": "Active", + "addon": "Add-on", + "addons": "Add-ons", + "address": "Address", + "admin": "Administrator", + "align": "Align", + "always_on_top": "Always on Top", + "animate": "Animate", + "app": "App", + "appearance": "Appearance", + "application": "Application", + "applications": "Applications", + "apply": "Apply", + "apps": "Apps", + "auto": "Auto", + "background": "Background", + "balanced": "Balanced", + "bar": "Bar", + "bars": "Bars", + "battery": "Battery", + "bluetooth": "Bluetooth", + "blur": "Blur", + "border": "Border", + "bottom": "Bottom", + "brightness": "Brightness", + "bring_to_front": "Bring to Front", + "bytes": "{0} bytes", + "cancel": "Cancel", + "center": "Center", + "characters": "{0} characters", + "charging": "Charging", + "clear_all": "Clear All", + "clicked": "Clicked", + "close": "Close", + "collapse": "Collapse", + "color": "Color", + "command": "Command", + "connected": "Connected", + "connecting": "Connecting...", + "context_menu": "Context Menu", + "copy": "Copy", + "cpu": "CPU", + "created": "Created", + "critical": "Critical", + "customize": "Customize", + "cut": "Cut", + "dark": "Dark", + "dashboard": "Dashboard", + "date": "Date", + "debug": "Debug", + "default": "Default", + "degrees": "{0}°", + "delete": "Delete", + "demo": "Demo", + "desktop": "Desktop", + "dialog": "Dialog", + "disabled": "Disabled", + "discharging": "Discharging", + "disconnected": "Disconnected", + "disk": "Disk", + "display": "Display", + "distribute": "Distribute", + "dock": "Dock", + "documents": "Documents", + "double_clicked": "Double Clicked", + "downloads": "Downloads", + "dragged": "Dragged", + "dropdown": "Dropdown", + "dropped": "Dropped", + "effect": "Effect", + "email": "Email", + "enabled": "Enabled", + "error": "Error", + "ethernet": "Ethernet", + "example": "Example", + "execute": "Execute", + "exit": "Exit", + "expand": "Expand", + "extension": "Extension", + "extensions": "Extensions", + "fan": "Fan", + "favorites": "Favorites", + "file": "File", + "files": "Files", + "filter": "Filter", + "flip": "Flip", + "floating": "Floating", + "focus": "Focus", + "folder": "Folder", + "folders": "Folders", + "foreground": "Foreground", + "format": "Format", + "full": "Full", + "fullscreen": "Fullscreen", + "gigabytes": "{0} GB", + "gigahertz": "{0} GHz", + "glow": "Glow", + "group": "Group", + "guest": "Guest", + "headphones": "Headphones", + "help": "Help", + "hertz": "{0} Hz", + "hibernate": "Hibernate", + "hidden": "Hidden", + "hide": "Hide", + "highlight": "Highlight", + "hint": "Hint", + "home": "Home", + "hour": "Hour", + "hours": "Hours", + "hover": "Hover", + "inactive": "Inactive", + "info": "Info", + "input": "Input", + "install": "Install", + "justify": "Justify", + "keybinds": "Key Bindings", + "keyboard": "Keyboard", + "kilobytes": "{0} KB", + "kilohertz": "{0} kHz", + "landscape": "Landscape", + "language": "Language", + "launcher": "Launcher", + "left": "Left", + "light": "Light", + "loading": "Loading...", + "lock": "Lock", + "log": "Log", + "logout": "Logout", + "long_pressed": "Long Pressed", + "low": "Low", + "manual": "Manual", + "margin": "Margin", + "maximize": "Maximize", + "megabytes": "{0} MB", + "megahertz": "{0} MHz", + "memory": "Memory", + "menu": "Menu", + "menubar": "Menu Bar", + "microphone": "Microphone", + "minimize": "Minimize", + "minute": "Minute", + "minutes": "Minutes", + "mirror": "Mirror", + "modal": "Modal", + "modified": "Modified", + "monitor": "Monitor", + "mouse": "Mouse", + "move": "Move", + "music": "Music", + "mute": "Mute", + "network": "Network", + "next": "Next", + "no": "No", + "no_notifications": "No notifications", + "notifications": "Notifications", + "off": "Off", + "ok": "OK", + "on": "On", + "opacity": "Opacity", + "open": "Open", + "orientation": "Orientation", + "outline": "Outline", + "output": "Output", + "overview": "Overview", + "owner": "Owner", + "package": "Package", + "packages": "Packages", + "padding": "Padding", + "panel": "Panel", + "panels": "Panels", + "panned": "Panned", + "password": "Password", + "paste": "Paste", + "pause": "Pause", + "percent": "{0}%", + "performance": "Performance", + "permissions": "Permissions", + "phone": "Phone", + "pictures": "Pictures", + "pinched": "Pinched", + "pinned": "Pinned", + "pixels": "{0}px", + "placeholder": "Placeholder", + "play": "Play", + "plugin": "Plugin", + "plugins": "Plugins", + "popup": "Popup", + "portrait": "Portrait", + "power": "Power", + "power_saver": "Power Saver", + "pressed": "Pressed", + "previous": "Previous", + "profile": "Profile", + "properties": "Properties", + "quiet": "Quiet", + "quit": "Quit", + "read": "Read", + "recent": "Recent", + "recording": "Recording", + "refresh": "Refresh", + "refresh_rate": "Refresh Rate", + "reload": "Reload", + "rename": "Rename", + "reset": "Reset", + "resize": "Resize", + "resolution": "Resolution", + "restart": "Restart", + "restore": "Restore", + "right": "Right", + "right_clicked": "Right Clicked", + "rotate": "Rotate", + "rotated": "Rotated", + "sample": "Sample", + "save": "Save", + "scale": "Scale", + "screenshot": "Screenshot", + "scrolled": "Scrolled", + "search": "Search", + "second": "Second", + "seconds": "Seconds", + "selection": "Selection", + "send_to_back": "Send to Back", + "settings": "Settings", + "shadow": "Shadow", + "shortcuts": "Shortcuts", + "show": "Show", + "shutdown": "Shutdown", + "sidebar": "Sidebar", + "silent": "Silent", + "size": "Size", + "snapped": "Snapped", + "software": "Software", + "space": "Space", + "speaker": "Speaker", + "statusbar": "Status Bar", + "sticky": "Sticky", + "stop": "Stop", + "style": "Style", + "success": "Success", + "suspend": "Suspend", + "swiped": "Swiped", + "systray": "System Tray", + "tapped": "Tapped", + "taskbar": "Taskbar", + "temperature": "Temperature", + "terabytes": "{0} TB", + "terminal": "Terminal", + "test": "Test", + "theme": "Theme", + "tiled": "Tiled", + "time": "Time", + "tips": "Tips", + "today": "Today", + "tomorrow": "Tomorrow", + "toolbar": "Toolbar", + "tooltip": "Tooltip", + "top": "Top", + "touchpad": "Touchpad", + "trace": "Trace", + "transform": "Transform", + "transition": "Transition", + "transparency": "Transparency", + "trash": "Trash", + "tutorial": "Tutorial", + "type": "Type", + "uninstall": "Uninstall", + "unlock": "Unlock", + "unmute": "Unmute", + "unpinned": "Unpinned", + "unsticky": "Unsticky", + "update": "Update", + "upgrade": "Upgrade", + "user": "User", + "username": "Username", + "verbose": "Verbose", + "version": "Version", + "videos": "Videos", + "visible": "Visible", + "volume": "Volume", + "warning": "Warning", + "welcome": "Welcome", + "widget": "Widget", + "widgets": "Widgets", + "wifi": "Wi-Fi", + "window": "Window", + "windowed": "Windowed", + "windows": "Windows", + "workspace": "Workspace", + "workspaces": "Workspaces", + "write": "Write", + "yes": "Yes", + "yesterday": "Yesterday", + "zoomed": "Zoomed", + "{0} (copied)": "{0} (copied)", + "{0} Safe Storage": "{0} Safe Storage", + "{0} does not require an API key": "{0} does not require an API key", + "{0} queries pending": "{0} queries pending", + "{0} | Right-click to configure": "{0} | Right-click to configure" +} \ No newline at end of file diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json new file mode 100644 index 00000000..f73a6949 --- /dev/null +++ b/.config/quickshell/translations/zh_CN.json @@ -0,0 +1,472 @@ +{ + "%1 characters": "%1 个字符", + "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**价格**:免费。数据用于训练。\n\n**说明**:登录 Google 账户,允许 AI Studio 创建 Google Cloud 项目或其他要求,然后返回并点击获取 API 密钥", + "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key": "**价格**:免费。数据使用政策取决于您的 OpenRouter 账户设置。\n\n**说明**:登录 OpenRouter 账户,在右上角菜单中选择 Keys,点击创建 API 密钥", + ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!": ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!", + "No further instruction provided": "未提供进一步说明", + "API key set for {0}": "已为 {0} 设置 API 密钥", + "API key:\n\n```txt\n{0}\n```": "API 密钥:\n\n```txt\n{0}\n```", + "Action": "操作", + "Add": "添加", + "Add task": "添加任务", + "All-rounder | Good quality, decent quantity": "全能型 | 质量好,数量适中", + "Allow NSFW": "允许 NSFW", + "Allow NSFW content": "允许 NSFW 内容", + "Anime": "动漫", + "Anime boorus": "动漫图库", + "App": "应用", + "Arrow keys to navigate, Enter to select\nEsc or click anywhere to cancel": "方向键导航,回车选择\nEsc 或点击任意地方取消", + "Bluetooth": "蓝牙", + "Brightness": "亮度", + "Cancel": "取消", + "Chain of Thought": "思维链", + "Cheat sheet": "快捷键表", + "Choose model": "选择模型", + "Clean stuff | Excellent quality, no NSFW": "清洁内容 | 优秀质量,无 NSFW", + "Clear": "清除", + "Clear chat history": "清除聊天记录", + "Clear the current list of images": "清除当前图片列表", + "Close": "关闭", + "Closes cheatsheet on press": "Closes cheatsheet on press", + "Closes left sidebar on press": "Closes left sidebar on press", + "Closes media controls on press": "Closes media controls on press", + "Closes on screen keyboard on press": "Closes on screen keyboard on press", + "Closes overview": "Closes overview", + "Closes right sidebar on press": "Closes right sidebar on press", + "Copy": "复制", + "Copy code": "复制代码", + "Ctrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "Ctrl+O 展开侧边栏\nCtrl+P 将侧边栏分离为窗口", + "Current API endpoint: {0}\nSet it with {1}mode PROVIDER": "当前 API 端点:{0}\n使用 {1}mode PROVIDER 设置", + "Current model: {0}\nSet it with {1}model MODEL": "当前模型:{0}\n使用 {1}model MODEL 设置", + "Decrease brightness": "Decrease brightness", + "Delete": "删除", + "Desktop": "桌面", + "Detach left sidebar into a window/Attach it back": "Detach left sidebar into a window/Attach it back", + "Disable NSFW content": "禁用 NSFW 内容", + "Done": "完成", + "Download": "下载", + "Download complete": "下载完成", + "Edit": "编辑", + "Enter text to translate...": "输入要翻译的文本...", + "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "实验性 | 在线 | Google 模型\n功能更多但搜索速度较慢", + "Finished tasks will go here": "已完成的任务将显示在这里", + "For desktop wallpapers | Good quality": "桌面壁纸专用 | 质量好", + "For storing API keys and other sensitive information": "用于存储 API 密钥和其他敏感信息", + "Game mode": "游戏模式", + "Get the next page of results": "获取下一页结果", + "Go to source ({0})": "转到源 ({0})", + "Hibernate": "休眠", + "Hides brightness OSD on press": "Hides brightness OSD on press", + "Hides volume OSD on press": "Hides volume OSD on press", + "Hold to show workspace numbers, release to show icons": "Hold to show workspace numbers, release to show icons", + "Increase brightness": "Increase brightness", + "Input": "输入", + "Intelligence": "智能", + "Interface": "界面", + "Interrupts possibility of overview being toggled on release. ": "Interrupts possibility of overview being toggled on release. ", + "Invalid API provider. Supported: \n- ": "无效的 API 提供商。支持的:\n- ", + "Invalid arguments. Must provide `key` and `value`.": "参数无效。必须提供 `key` 和 `value`。", + "Invalid model. Supported: \n```\n": "无效模型。支持的:\n```\n", + "Jump to current month": "跳转到当前月份", + "Keep system awake": "保持系统唤醒", + "Large images | God tier quality, no NSFW.": "大尺寸图片 | 顶级质量,无 NSFW", + "Large language models": "大语言模型", + "Launch": "启动", + "Local Ollama model | {0}": "本地 Ollama 模型 | {0}", + "Lock": "锁定", + "Logout": "注销", + "Markdown test": "Markdown 测试", + "Math result": "数学结果", + "Night Light": "护眼模式", + "No API key set for {0}": "未为 {0} 设置 API 密钥", + "No audio source": "无音频源", + "No media": "无媒体", + "No notifications": "无通知", + "Not visible to model": "对模型不可见", + "Nothing here!": "这里什么都没有!", + "Notifications": "通知", + "OK": "确定", + "Online via {0} | {1}'s model": "通过 {0} 在线 | {1} 模型", + "Online | Google's model\nGives up-to-date information with search.": "在线 | Google 模型\n通过搜索提供最新信息。", + "Open file link": "打开文件链接", + "Opens cheatsheet on press": "Opens cheatsheet on press", + "Opens left sidebar on press": "Opens left sidebar on press", + "Opens media controls on press": "Opens media controls on press", + "Opens on screen keyboard on press": "Opens on screen keyboard on press", + "Opens right sidebar on press": "Opens right sidebar on press", + "Opens session screen on press": "Opens session screen on press", + "Output": "输出", + "Page {0}": "第 {0} 页", + "Plasma Settings": "Plasma 设置", + "Provider set to ": "提供商设置为", + "Reboot": "重启", + "Reboot to firmware settings": "Reboot to firmware settings", + "Reload Hyprland & Quickshell": "重新加载 Hyprland 和 Quickshell", + "Run": "运行", + "Run command": "Run command", + "Save": "保存", + "Save to Downloads": "保存到下载文件夹", + "Scroll to change brightness": "滚动调节亮度", + "Scroll to change volume": "滚动调节音量", + "Search": "搜索", + "Search the web": "搜索网络", + "Search, calculate or run": "搜索、计算或运行", + "Select Language": "选择语言", + "Session": "会话", + "Set API key": "设置 API 密钥", + "Set temperature (randomness) of the model. Values range between 0 to 2 for Gemini, 0 to 1 for other models. Default is 0.5.": "设置模型的温度(随机性)。Gemini 模型范围为 0 到 2,其他模型为 0 到 1。默认值为 0.5。", + "Set the current API provider": "设置当前 API 提供商", + "Shell configuration created": "Shell 配置已创建", + "Shell configuration failed to load": "Shell 配置加载失败", + "Shell configuration reloaded": "Shell 配置已重新加载", + "Shutdown": "关机", + "Silent": "静音", + "Sleep": "睡眠", + "Switched to search mode. Continue with the user's request.": "已切换到搜索模式。继续处理用户请求。", + "System": "系统", + "Task Manager": "任务管理器", + "Task description": "任务描述", + "Temperature must be between 0 and 2": "温度必须在 0 到 2 之间", + "Temperature set to {0}": "温度设置为 {0}", + "Temperature: {0}": "温度:{0}", + "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "没有找到结果。提示:\n- 检查您的标签和 NSFW 设置\n- 如果没有想到标签,请输入页码", + "The current API used. Endpoint: ": "当前使用的 API。端点:", + "The hentai one | Great quantity, a lot of NSFW, quality varies wildly": "成人向 | 数量巨大,大量 NSFW,质量参差不齐", + "The popular one | Best quantity, but quality can vary wildly": "最受欢迎 | 数量最多,但质量参差不齐", + "Thinking": "思考中", + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ": "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ", + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.": "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.", + "Toggle clipboard query on overview widget": "Toggle clipboard query on overview widget", + "Toggle emoji query on overview widget": "Toggle emoji query on overview widget", + "Toggles cheatsheet on press": "Toggles cheatsheet on press", + "Toggles left sidebar on press": "Toggles left sidebar on press", + "Toggles media controls on press": "Toggles media controls on press", + "Toggles on screen keyboard on press": "Toggles on screen keyboard on press", + "Toggles overview on press": "Toggles overview on press", + "Toggles overview on release": "Toggles overview on release", + "Toggles right sidebar on press": "Toggles right sidebar on press", + "Toggles session screen on press": "Toggles session screen on press", + "Translation goes here...": "翻译结果会显示在这里...", + "Translator": "翻译器", + "Triggers brightness OSD on press": "Triggers brightness OSD on press", + "Triggers volume OSD on press": "Triggers volume OSD on press", + "Unfinished": "未完成", + "Unknown": "未知", + "Unknown Album": "未知专辑", + "Unknown Artist": "未知艺术家", + "Unknown Title": "未知标题", + "Unknown command: ": "未知命令:", + "Unknown function call: {0}": "未知函数调用:{0}", + "Uptime: {0}": "运行时间:{0}", + "Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in **bold** to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`. When making changes to the user's config, you must get the config to know what values there are before setting.": "Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in **bold** to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`. When making changes to the user's config, you must get the config to know what values there are before setting.", + "View Markdown source": "查看 Markdown 源码", + "Volume": "音量", + "Volume mixer": "音量混合器", + "Waifus only | Excellent quality, limited quantity": "仅限角色 | 优秀质量,数量有限", + "Waiting for response...": "等待响应...", + "Workspace": "工作区", + "\nSet with /mode PROVIDER": "\n使用 /mode PROVIDER 设置", + "about": "关于", + "accessed": "访问时间", + "account": "账户", + "active": "活动", + "active_state": "活动状态", + "addon": "附加组件", + "addons": "附加组件", + "address": "地址", + "admin": "管理员", + "align": "对齐", + "always_on_top": "总在最前", + "animate": "动画", + "app": "应用", + "appearance": "外观", + "application": "应用程序", + "applications": "应用程序", + "apply": "应用", + "apps": "应用", + "auto": "自动", + "background": "背景", + "balanced": "平衡", + "bar": "栏", + "bars": "栏", + "battery": "电池", + "bluetooth": "蓝牙", + "blur": "模糊", + "border": "边框", + "bottom": "底部", + "brightness": "亮度", + "bring_to_front": "置于顶层", + "bytes": "{0} 字节", + "cancel": "取消", + "center": "居中", + "characters": "{0} 个字符", + "charging": "充电中", + "clear_all": "清除全部", + "clicked": "点击", + "close": "关闭", + "collapse": "折叠", + "color": "颜色", + "command": "命令", + "connected": "已连接", + "connecting": "连接中...", + "context_menu": "右键菜单", + "copy": "复制", + "cpu": "处理器", + "created": "创建时间", + "critical": "电量危险", + "customize": "自定义", + "cut": "剪切", + "dark": "深色", + "dashboard": "仪表板", + "date": "日期", + "debug": "调试", + "default": "默认", + "degrees": "{0}°", + "delete": "删除", + "demo": "演示", + "desktop": "桌面", + "dialog": "对话框", + "disabled": "已禁用", + "discharging": "放电中", + "disconnected": "已断开", + "disk": "磁盘", + "display": "显示", + "distribute": "分布", + "dock": "停靠栏", + "documents": "文档", + "double_clicked": "双击", + "downloads": "下载", + "dragged": "拖拽", + "dropdown": "下拉菜单", + "dropped": "拖放", + "effect": "效果", + "email": "邮箱", + "enabled": "已启用", + "error": "错误", + "ethernet": "以太网", + "example": "示例", + "execute": "执行", + "exit": "退出", + "expand": "展开", + "extension": "扩展", + "extensions": "扩展", + "fan": "风扇", + "favorites": "收藏夹", + "file": "文件", + "files": "文件", + "filter": "滤镜", + "flip": "翻转", + "floating": "浮动", + "focus": "焦点", + "folder": "文件夹", + "folders": "文件夹", + "foreground": "前景", + "format": "格式", + "full": "已充满", + "fullscreen": "全屏", + "gigabytes": "{0} GB", + "gigahertz": "{0} GHz", + "glow": "发光", + "group": "群组", + "guest": "访客", + "headphones": "耳机", + "help": "帮助", + "hertz": "{0} Hz", + "hibernate": "休眠", + "hidden": "隐藏", + "hide": "隐藏", + "highlight": "高亮", + "hint": "提示", + "home": "主目录", + "hour": "小时", + "hours": "小时", + "hover": "悬停", + "inactive": "非活动", + "info": "信息", + "input": "输入", + "install": "安装", + "justify": "两端对齐", + "keybinds": "按键绑定", + "keyboard": "键盘", + "kilobytes": "{0} KB", + "kilohertz": "{0} kHz", + "landscape": "横向", + "language": "语言", + "launcher": "启动器", + "left": "左对齐", + "light": "浅色", + "loading": "加载中...", + "lock": "锁定", + "log": "日志", + "logout": "注销", + "long_pressed": "长按", + "low": "电量低", + "manual": "手册", + "margin": "边距", + "maximize": "最大化", + "megabytes": "{0} MB", + "megahertz": "{0} MHz", + "memory": "内存", + "menu": "菜单", + "menubar": "菜单栏", + "microphone": "麦克风", + "minimize": "最小化", + "minute": "分钟", + "minutes": "分钟", + "mirror": "镜像", + "modal": "模态框", + "modified": "修改时间", + "monitor": "显示器", + "mouse": "鼠标", + "move": "移动", + "music": "音乐", + "mute": "静音", + "network": "网络", + "next": "下一个", + "no": "否", + "no_notifications": "无通知", + "notifications": "通知", + "off": "关", + "ok": "确定", + "on": "开", + "opacity": "不透明度", + "open": "打开", + "orientation": "方向", + "outline": "轮廓", + "output": "输出", + "overview": "概览", + "owner": "所有者", + "package": "软件包", + "packages": "软件包", + "padding": "内边距", + "panel": "面板", + "panels": "面板", + "panned": "平移", + "password": "密码", + "paste": "粘贴", + "pause": "暂停", + "percent": "{0}%", + "performance": "性能", + "permissions": "权限", + "phone": "电话", + "pictures": "图片", + "pinched": "捏合", + "pinned": "固定", + "pixels": "{0}像素", + "placeholder": "占位符", + "play": "播放", + "plugin": "插件", + "plugins": "插件", + "popup": "弹出窗口", + "portrait": "纵向", + "power": "电源", + "power_saver": "节能", + "pressed": "按下", + "previous": "上一个", + "profile": "配置文件", + "properties": "属性", + "quiet": "安静", + "quit": "退出", + "read": "读取", + "recent": "最近", + "recording": "录制", + "refresh": "刷新", + "refresh_rate": "刷新率", + "reload": "重新加载", + "rename": "重命名", + "reset": "重置", + "resize": "调整大小", + "resolution": "分辨率", + "restart": "重启", + "restore": "还原", + "right": "右对齐", + "right_clicked": "右键点击", + "rotate": "旋转", + "rotated": "旋转", + "sample": "样本", + "save": "保存", + "scale": "缩放", + "screenshot": "截图", + "scrolled": "滚动", + "search": "搜索", + "second": "秒", + "seconds": "秒", + "selection": "选择", + "send_to_back": "置于底层", + "settings": "设置", + "shadow": "阴影", + "shortcuts": "快捷键", + "show": "显示", + "shutdown": "关机", + "sidebar": "侧边栏", + "silent": "静默", + "size": "大小", + "snapped": "贴靠", + "software": "软件", + "space": "间距", + "speaker": "扬声器", + "statusbar": "状态栏", + "sticky": "粘性", + "stop": "停止", + "style": "样式", + "success": "成功", + "suspend": "挂起", + "swiped": "滑动", + "systray": "系统托盘", + "tapped": "轻触", + "taskbar": "任务栏", + "temperature": "温度", + "terabytes": "{0} TB", + "terminal": "终端", + "test": "测试", + "theme": "主题", + "tiled": "平铺", + "time": "时间", + "tips": "提示", + "today": "今天", + "tomorrow": "明天", + "toolbar": "工具栏", + "tooltip": "工具提示", + "top": "顶部", + "touchpad": "触摸板", + "trace": "跟踪", + "transform": "变换", + "transition": "过渡", + "transparency": "透明度", + "trash": "回收站", + "tutorial": "教程", + "type": "类型", + "uninstall": "卸载", + "unlock": "解锁", + "unmute": "取消静音", + "unpinned": "取消固定", + "unsticky": "取消粘性", + "update": "更新", + "upgrade": "升级", + "user": "用户", + "username": "用户名", + "verbose": "详细", + "version": "版本", + "videos": "视频", + "visible": "可见", + "volume": "音量", + "warning": "警告", + "welcome": "欢迎", + "widget": "组件", + "widgets": "组件", + "wifi": "Wi-Fi", + "window": "窗口", + "windowed": "窗口化", + "windows": "窗口", + "workspace": "工作区", + "workspaces": "工作区", + "write": "写入", + "yes": "是", + "yesterday": "昨天", + "zoomed": "缩放", + "{0} (copied)": "{0}(已复制)", + "{0} Safe Storage": "{0} 安全存储", + "{0} does not require an API key": "{0} 不需要 API 密钥", + "{0} queries pending": "{0} 个查询等待中", + "{0} | Right-click to configure": "{0} | 右键点击进行配置" +} \ No newline at end of file From 89e25e3504b2e76ff24803ea96914893a595bd1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Tue, 17 Jun 2025 14:29:33 +0800 Subject: [PATCH 003/328] Add translation management tool suite and update Chinese translations - Introduced a comprehensive guide for the translation management tool suite, detailing components, usage, and best practices. - Added `translation-manager.py`, `translation-cleaner.py`, and `manage-translations.sh` scripts for managing translations. - Updated the Chinese translation file (`zh_CN.json`) to improve existing translations and remove unused keys. - Enhanced documentation with examples and troubleshooting tips for better user experience. --- .config/quickshell/translations/en_US.json | 332 +-------------- .../quickshell/translations/tools/README.md | 111 +++++ .../translations/tools/manage-translations.sh | 149 +++++++ .../translations/tools/translation-cleaner.py | 196 +++++++++ .../translations/tools/translation-manager.py | 290 +++++++++++++ .../tools/translation-tools-guide.md | 246 +++++++++++ .../translations/tools/翻译管理脚本说明.md | 287 +++++++++++++ .config/quickshell/translations/zh_CN.json | 398 +++--------------- 8 files changed, 1348 insertions(+), 661 deletions(-) create mode 100644 .config/quickshell/translations/tools/README.md create mode 100755 .config/quickshell/translations/tools/manage-translations.sh create mode 100755 .config/quickshell/translations/tools/translation-cleaner.py create mode 100755 .config/quickshell/translations/tools/translation-manager.py create mode 100644 .config/quickshell/translations/tools/translation-tools-guide.md create mode 100644 .config/quickshell/translations/tools/翻译管理脚本说明.md diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index 6f7c8ec5..34887b99 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -35,7 +35,6 @@ "Closes right sidebar on press": "Closes right sidebar on press", "Copy": "Copy", "Copy code": "Copy code", - "Ctrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "Ctrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window", "Current API endpoint: {0}\nSet it with {1}mode PROVIDER": "Current API endpoint: {0}\nSet it with {1}mode PROVIDER", "Current model: {0}\nSet it with {1}model MODEL": "Current model: {0}\nSet it with {1}model MODEL", "Decrease brightness": "Decrease brightness", @@ -48,7 +47,6 @@ "Download complete": "Download complete", "Edit": "Edit", "Enter text to translate...": "Enter text to translate...", - "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly", "Finished tasks will go here": "Finished tasks will go here", "For desktop wallpapers | Good quality": "For desktop wallpapers | Good quality", "For storing API keys and other sensitive information": "For storing API keys and other sensitive information", @@ -63,10 +61,7 @@ "Input": "Input", "Intelligence": "Intelligence", "Interface": "Interface", - "Interrupts possibility of overview being toggled on release. ": "Interrupts possibility of overview being toggled on release. ", - "Invalid API provider. Supported: \n- ": "Invalid API provider. Supported: \n- ", "Invalid arguments. Must provide `key` and `value`.": "Invalid arguments. Must provide `key` and `value`.", - "Invalid model. Supported: \n```\n": "Invalid model. Supported: \n```\n", "Jump to current month": "Jump to current month", "Keep system awake": "Keep system awake", "Large images | God tier quality, no NSFW.": "Large images | God tier quality, no NSFW.", @@ -86,8 +81,6 @@ "Nothing here!": "Nothing here!", "Notifications": "Notifications", "OK": "OK", - "Online via {0} | {1}'s model": "Online via {0} | {1}'s model", - "Online | Google's model\nGives up-to-date information with search.": "Online | Google's model\nGives up-to-date information with search.", "Open file link": "Open file link", "Opens cheatsheet on press": "Opens cheatsheet on press", "Opens left sidebar on press": "Opens left sidebar on press", @@ -98,7 +91,6 @@ "Output": "Output", "Page {0}": "Page {0}", "Plasma Settings": "Plasma Settings", - "Provider set to ": "Provider set to ", "Reboot": "Reboot", "Reboot to firmware settings": "Reboot to firmware settings", "Reload Hyprland & Quickshell": "Reload Hyprland & Quickshell", @@ -122,19 +114,15 @@ "Shutdown": "Shutdown", "Silent": "Silent", "Sleep": "Sleep", - "Switched to search mode. Continue with the user's request.": "Switched to search mode. Continue with the user's request.", "System": "System", "Task Manager": "Task Manager", "Task description": "Task description", "Temperature must be between 0 and 2": "Temperature must be between 0 and 2", "Temperature set to {0}": "Temperature set to {0}", "Temperature: {0}": "Temperature: {0}", - "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number", - "The current API used. Endpoint: ": "The current API used. Endpoint: ", "The hentai one | Great quantity, a lot of NSFW, quality varies wildly": "The hentai one | Great quantity, a lot of NSFW, quality varies wildly", "The popular one | Best quantity, but quality can vary wildly": "The popular one | Best quantity, but quality can vary wildly", "Thinking": "Thinking", - "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ": "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ", "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.": "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.", "Toggle clipboard query on overview widget": "Toggle clipboard query on overview widget", "Toggle emoji query on overview widget": "Toggle emoji query on overview widget", @@ -155,318 +143,34 @@ "Unknown Album": "Unknown Album", "Unknown Artist": "Unknown Artist", "Unknown Title": "Unknown Title", - "Unknown command: ": "Unknown command: ", "Unknown function call: {0}": "Unknown function call: {0}", "Uptime: {0}": "Uptime: {0}", - "Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in **bold** to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`. When making changes to the user's config, you must get the config to know what values there are before setting.": "Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in **bold** to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`. When making changes to the user's config, you must get the config to know what values there are before setting.", "View Markdown source": "View Markdown source", "Volume": "Volume", "Volume mixer": "Volume mixer", "Waifus only | Excellent quality, limited quantity": "Waifus only | Excellent quality, limited quantity", "Waiting for response...": "Waiting for response...", "Workspace": "Workspace", - "\nSet with /mode PROVIDER": "\nSet with /mode PROVIDER", - "about": "About", - "accessed": "Accessed", - "account": "Account", - "active": "Active", - "active_state": "Active", - "addon": "Add-on", - "addons": "Add-ons", - "address": "Address", - "admin": "Administrator", - "align": "Align", - "always_on_top": "Always on Top", - "animate": "Animate", - "app": "App", - "appearance": "Appearance", - "application": "Application", - "applications": "Applications", - "apply": "Apply", - "apps": "Apps", - "auto": "Auto", - "background": "Background", - "balanced": "Balanced", - "bar": "Bar", - "bars": "Bars", - "battery": "Battery", - "bluetooth": "Bluetooth", - "blur": "Blur", - "border": "Border", - "bottom": "Bottom", - "brightness": "Brightness", - "bring_to_front": "Bring to Front", - "bytes": "{0} bytes", - "cancel": "Cancel", - "center": "Center", - "characters": "{0} characters", - "charging": "Charging", - "clear_all": "Clear All", - "clicked": "Clicked", - "close": "Close", - "collapse": "Collapse", - "color": "Color", - "command": "Command", - "connected": "Connected", - "connecting": "Connecting...", - "context_menu": "Context Menu", - "copy": "Copy", - "cpu": "CPU", - "created": "Created", - "critical": "Critical", - "customize": "Customize", - "cut": "Cut", - "dark": "Dark", - "dashboard": "Dashboard", - "date": "Date", - "debug": "Debug", - "default": "Default", - "degrees": "{0}°", - "delete": "Delete", - "demo": "Demo", - "desktop": "Desktop", - "dialog": "Dialog", - "disabled": "Disabled", - "discharging": "Discharging", - "disconnected": "Disconnected", - "disk": "Disk", - "display": "Display", - "distribute": "Distribute", - "dock": "Dock", - "documents": "Documents", - "double_clicked": "Double Clicked", - "downloads": "Downloads", - "dragged": "Dragged", - "dropdown": "Dropdown", - "dropped": "Dropped", - "effect": "Effect", - "email": "Email", - "enabled": "Enabled", - "error": "Error", - "ethernet": "Ethernet", - "example": "Example", - "execute": "Execute", - "exit": "Exit", - "expand": "Expand", - "extension": "Extension", - "extensions": "Extensions", - "fan": "Fan", - "favorites": "Favorites", - "file": "File", - "files": "Files", - "filter": "Filter", - "flip": "Flip", - "floating": "Floating", - "focus": "Focus", - "folder": "Folder", - "folders": "Folders", - "foreground": "Foreground", - "format": "Format", - "full": "Full", - "fullscreen": "Fullscreen", - "gigabytes": "{0} GB", - "gigahertz": "{0} GHz", - "glow": "Glow", - "group": "Group", - "guest": "Guest", - "headphones": "Headphones", - "help": "Help", - "hertz": "{0} Hz", - "hibernate": "Hibernate", - "hidden": "Hidden", - "hide": "Hide", - "highlight": "Highlight", - "hint": "Hint", - "home": "Home", - "hour": "Hour", - "hours": "Hours", - "hover": "Hover", - "inactive": "Inactive", - "info": "Info", - "input": "Input", - "install": "Install", - "justify": "Justify", - "keybinds": "Key Bindings", - "keyboard": "Keyboard", - "kilobytes": "{0} KB", - "kilohertz": "{0} kHz", - "landscape": "Landscape", - "language": "Language", - "launcher": "Launcher", - "left": "Left", - "light": "Light", - "loading": "Loading...", - "lock": "Lock", - "log": "Log", - "logout": "Logout", - "long_pressed": "Long Pressed", - "low": "Low", - "manual": "Manual", - "margin": "Margin", - "maximize": "Maximize", - "megabytes": "{0} MB", - "megahertz": "{0} MHz", - "memory": "Memory", - "menu": "Menu", - "menubar": "Menu Bar", - "microphone": "Microphone", - "minimize": "Minimize", - "minute": "Minute", - "minutes": "Minutes", - "mirror": "Mirror", - "modal": "Modal", - "modified": "Modified", - "monitor": "Monitor", - "mouse": "Mouse", - "move": "Move", - "music": "Music", - "mute": "Mute", - "network": "Network", - "next": "Next", - "no": "No", - "no_notifications": "No notifications", - "notifications": "Notifications", - "off": "Off", - "ok": "OK", - "on": "On", - "opacity": "Opacity", - "open": "Open", - "orientation": "Orientation", - "outline": "Outline", - "output": "Output", - "overview": "Overview", - "owner": "Owner", - "package": "Package", - "packages": "Packages", - "padding": "Padding", - "panel": "Panel", - "panels": "Panels", - "panned": "Panned", - "password": "Password", - "paste": "Paste", - "pause": "Pause", - "percent": "{0}%", - "performance": "Performance", - "permissions": "Permissions", - "phone": "Phone", - "pictures": "Pictures", - "pinched": "Pinched", - "pinned": "Pinned", - "pixels": "{0}px", - "placeholder": "Placeholder", - "play": "Play", - "plugin": "Plugin", - "plugins": "Plugins", - "popup": "Popup", - "portrait": "Portrait", - "power": "Power", - "power_saver": "Power Saver", - "pressed": "Pressed", - "previous": "Previous", - "profile": "Profile", - "properties": "Properties", - "quiet": "Quiet", - "quit": "Quit", - "read": "Read", - "recent": "Recent", - "recording": "Recording", - "refresh": "Refresh", - "refresh_rate": "Refresh Rate", - "reload": "Reload", - "rename": "Rename", - "reset": "Reset", - "resize": "Resize", - "resolution": "Resolution", - "restart": "Restart", - "restore": "Restore", - "right": "Right", - "right_clicked": "Right Clicked", - "rotate": "Rotate", - "rotated": "Rotated", - "sample": "Sample", - "save": "Save", - "scale": "Scale", - "screenshot": "Screenshot", - "scrolled": "Scrolled", - "search": "Search", - "second": "Second", - "seconds": "Seconds", - "selection": "Selection", - "send_to_back": "Send to Back", - "settings": "Settings", - "shadow": "Shadow", - "shortcuts": "Shortcuts", - "show": "Show", - "shutdown": "Shutdown", - "sidebar": "Sidebar", - "silent": "Silent", - "size": "Size", - "snapped": "Snapped", - "software": "Software", - "space": "Space", - "speaker": "Speaker", - "statusbar": "Status Bar", - "sticky": "Sticky", - "stop": "Stop", - "style": "Style", - "success": "Success", - "suspend": "Suspend", - "swiped": "Swiped", - "systray": "System Tray", - "tapped": "Tapped", - "taskbar": "Taskbar", - "temperature": "Temperature", - "terabytes": "{0} TB", - "terminal": "Terminal", - "test": "Test", - "theme": "Theme", - "tiled": "Tiled", - "time": "Time", - "tips": "Tips", - "today": "Today", - "tomorrow": "Tomorrow", - "toolbar": "Toolbar", - "tooltip": "Tooltip", - "top": "Top", - "touchpad": "Touchpad", - "trace": "Trace", - "transform": "Transform", - "transition": "Transition", - "transparency": "Transparency", - "trash": "Trash", - "tutorial": "Tutorial", - "type": "Type", - "uninstall": "Uninstall", - "unlock": "Unlock", - "unmute": "Unmute", - "unpinned": "Unpinned", - "unsticky": "Unsticky", - "update": "Update", - "upgrade": "Upgrade", - "user": "User", - "username": "Username", - "verbose": "Verbose", - "version": "Version", - "videos": "Videos", - "visible": "Visible", - "volume": "Volume", - "warning": "Warning", - "welcome": "Welcome", - "widget": "Widget", - "widgets": "Widgets", - "wifi": "Wi-Fi", - "window": "Window", - "windowed": "Windowed", - "windows": "Windows", - "workspace": "Workspace", - "workspaces": "Workspaces", - "write": "Write", - "yes": "Yes", - "yesterday": "Yesterday", - "zoomed": "Zoomed", "{0} (copied)": "{0} (copied)", "{0} Safe Storage": "{0} Safe Storage", "{0} does not require an API key": "{0} does not require an API key", "{0} queries pending": "{0} queries pending", - "{0} | Right-click to configure": "{0} | Right-click to configure" + "{0} | Right-click to configure": "{0} | Right-click to configure", + "Set with /mode PROVIDER": "Set with /mode PROVIDER", + "Invalid API provider. Supported: \n-": "Invalid API provider. Supported: \n-", + "Unknown command:": "Unknown command:", + "Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window", + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key.": "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key.", + "The current API used. Endpoint:": "The current API used. Endpoint:", + "Provider set to": "Provider set to", + "Invalid model. Supported: \n```": "Invalid model. Supported: \n```", + "Interrupts possibility of overview being toggled on release.": "Interrupts possibility of overview being toggled on release.", + "Enter tags, or \"{0}\" for commands": "Enter tags, or \"{0}\" for commands", + "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number", + "Online | Google's model\nGives up-to-date information with search.": "Online | Google's model\nGives up-to-date information with search.", + "Online via {0} | {1}'s model": "Online via {0} | {1}'s model", + "Switched to search mode. Continue with the user's request.": "Switched to search mode. Continue with the user's request.", + "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly", + "Message the model... \"{0}\" for commands": "Message the model... \"{0}\" for commands", + "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}": "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}" } \ No newline at end of file diff --git a/.config/quickshell/translations/tools/README.md b/.config/quickshell/translations/tools/README.md new file mode 100644 index 00000000..1840f6c3 --- /dev/null +++ b/.config/quickshell/translations/tools/README.md @@ -0,0 +1,111 @@ +# Translation Management Tools + +This directory contains a toolset for managing project translation files. + +## Directory Structure + +``` +translations/ +├── tools/ # Translation management tools directory +│ ├── translation-manager.py # Main translation manager +│ ├── translation-cleaner.py # Translation maintenance tool +│ ├── manage-translations.sh # Convenient wrapper script +│ ├── translation-tools-guide.md # Detailed usage documentation +│ └── README.md # This file +├── en_US.json # English translation file +├── zh_CN.json # Chinese translation file +└── ... # Other language files +``` + +## Quick Start + +### Running from tools directory + +```bash +# Enter tools directory +cd .config/quickshell/translations/tools + +# Check current translation status +./manage-translations.sh status + +# Update all translation files +./manage-translations.sh update + +# Update specific language +./manage-translations.sh update -l zh_CN + +# Clean unused keys +./manage-translations.sh clean + +# Sync all language files +./manage-translations.sh sync +``` + +### Running from project root directory + +```bash +# Run from project root directory (recommended to use relative paths) +.config/quickshell/translations/tools/manage-translations.sh status +.config/quickshell/translations/tools/manage-translations.sh update +``` + +## Tool Description + +### 🛠️ `manage-translations.sh` - Main Entry Point +Convenient command-line interface that integrates all translation management functions. + +### 🔍 `translation-manager.py` - Core Manager +- Extract translatable texts +- Compare translation file differences +- Interactive translation updates + +### 🧹 `translation-cleaner.py` - Maintenance Tool +- Clean unused translation keys +- Sync language file structure +- Create backup files + +## Common Workflows + +### After adding new translatable texts +```bash +./manage-translations.sh update +``` + +### Clean up after code refactoring +```bash +./manage-translations.sh clean +``` + +### Add new language +```bash +./manage-translations.sh update -l new_language_code +``` + +### Check translation status +```bash +./manage-translations.sh status +``` + +## Documentation + +- 📖 [Detailed Usage Guide](./translation-tools-guide.md) + +## Important Notes + +1. **Running Location**: Tools automatically detect relative paths, can be run from tools directory or project root +2. **Backup**: Cleanup operations automatically create backup files +3. **Encoding**: All files use UTF-8 encoding +4. **Permissions**: Ensure scripts have execution permissions + +## Supported Translation Formats + +The tool recognizes translatable texts in the following formats: +```qml +qsTr("Your text here") +qsTr('Single quotes work too') +i18n.t("JavaScript translations") +``` + +--- + +If you have any issues, please refer to the detailed documentation or check error messages in script output. diff --git a/.config/quickshell/translations/tools/manage-translations.sh b/.config/quickshell/translations/tools/manage-translations.sh new file mode 100755 index 00000000..c20896a9 --- /dev/null +++ b/.config/quickshell/translations/tools/manage-translations.sh @@ -0,0 +1,149 @@ +#!/bin/bash +# Translation management script - convenient wrapper + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TRANSLATIONS_DIR="$(dirname "$SCRIPT_DIR")" +SOURCE_DIR="$(dirname "$(dirname "$TRANSLATIONS_DIR")")" + +show_help() { + echo "Translation Management Tool - Convenient Wrapper" + echo "" + echo "Usage: $0 [options] " + echo "" + echo "Commands:" + echo " extract Extract translatable texts to temporary file" + echo " update Update translation files (add missing/remove extra keys)" + echo " clean Clean unused translation keys" + echo " sync Sync keys across all language files" + echo " status Show translation status" + echo "" + echo "Options:" + echo " -l, --lang LANG Specify language (e.g.: zh_CN)" + echo " -t, --trans-dir DIR Translation files directory (default: $TRANSLATIONS_DIR)" + echo " -s, --source-dir DIR Source code directory (default: $SOURCE_DIR)" + echo " -h, --help Show this help message" + echo "" + echo "Examples:" + echo " $0 extract # Extract translatable texts" + echo " $0 update -l zh_CN # Update Chinese translations" + echo " $0 update # Update all translations" + echo " $0 clean # Clean unused keys" + echo " $0 sync # Sync keys across all languages" + echo " $0 status # Show translation status" +} + +show_status() { + echo "Analyzing translation status..." + + # Extract current text count + echo "=== Current Project Status ===" + python3 "$SCRIPT_DIR/translation-manager.py" \ + --translations-dir "$TRANSLATIONS_DIR" \ + --source-dir "$SOURCE_DIR" \ + --extract-only | grep "Extracted" + + echo "" + echo "=== Translation File Status ===" + + if [ -d "$TRANSLATIONS_DIR" ]; then + for file in "$TRANSLATIONS_DIR"/*.json; do + if [ -f "$file" ]; then + lang=$(basename "$file" .json) + count=$(jq 'length' "$file" 2>/dev/null || echo "error") + echo " $lang: $count keys" + fi + done + else + echo " Translation directory does not exist: $TRANSLATIONS_DIR" + fi +} + +# Parse command line arguments +LANG_CODE="" +COMMAND="" + +while [[ $# -gt 0 ]]; do + case $1 in + -l|--lang) + LANG_CODE="$2" + shift 2 + ;; + -t|--trans-dir) + TRANSLATIONS_DIR="$2" + shift 2 + ;; + -s|--source-dir) + SOURCE_DIR="$2" + shift 2 + ;; + -h|--help) + show_help + exit 0 + ;; + extract|update|clean|sync|status) + if [ -n "$COMMAND" ]; then + echo "Error: Only one command can be specified" + exit 1 + fi + COMMAND="$1" + shift + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +if [ -z "$COMMAND" ]; then + echo "Error: A command must be specified" + show_help + exit 1 +fi + +# Check dependencies +if ! command -v python3 >/dev/null 2>&1; then + echo "Error: python3 is required" + exit 1 +fi + +if [ "$COMMAND" = "status" ] && ! command -v jq >/dev/null 2>&1; then + echo "Warning: jq is not installed, status display may be incomplete" +fi + +# Build base arguments +BASE_ARGS="--translations-dir $TRANSLATIONS_DIR --source-dir $SOURCE_DIR" + +case $COMMAND in + extract) + echo "Extracting translatable texts..." + python3 "$SCRIPT_DIR/translation-manager.py" $BASE_ARGS --extract-only --show-temp + ;; + update) + echo "Updating translation files..." + if [ -n "$LANG_CODE" ]; then + python3 "$SCRIPT_DIR/translation-manager.py" $BASE_ARGS --language "$LANG_CODE" + else + python3 "$SCRIPT_DIR/translation-manager.py" $BASE_ARGS + fi + ;; + clean) + echo "Cleaning unused translation keys..." + python3 "$SCRIPT_DIR/translation-cleaner.py" $BASE_ARGS --clean + ;; + sync) + echo "Syncing translation keys..." + python3 "$SCRIPT_DIR/translation-cleaner.py" $BASE_ARGS --sync + ;; + status) + show_status + ;; + *) + echo "Unknown command: $COMMAND" + show_help + exit 1 + ;; +esac diff --git a/.config/quickshell/translations/tools/translation-cleaner.py b/.config/quickshell/translations/tools/translation-cleaner.py new file mode 100755 index 00000000..e53082fd --- /dev/null +++ b/.config/quickshell/translations/tools/translation-cleaner.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Translation File Maintenance Helper +Used to clean and organize translation files, removing unused keys +""" + +import os +import sys +import json +import argparse +import importlib.util +from pathlib import Path +from typing import Dict, Set, List + +# Import from the same directory using importlib +current_dir = os.path.dirname(os.path.abspath(__file__)) +manager_path = os.path.join(current_dir, 'translation-manager.py') +spec = importlib.util.spec_from_file_location("translation_manager", manager_path) +translation_manager = importlib.util.module_from_spec(spec) +spec.loader.exec_module(translation_manager) +TranslationManager = translation_manager.TranslationManager + +def clean_translation_files(translations_dir: str, source_dir: str, backup: bool = True): + """Clean translation files by removing unused keys""" + print("Starting translation file cleanup...") + + # Create manager + manager = TranslationManager(translations_dir, source_dir) + + # Extract currently used texts + print("Extracting currently used translatable texts...") + current_texts = manager.extract_translatable_texts() + print(f"Extracted {len(current_texts)} currently used texts") + + # Get all language files + languages = manager.get_available_languages() + if not languages: + print("No translation files found") + return + + print(f"Found language files: {', '.join(languages)}") + + total_removed = 0 + + for lang in languages: + print(f"\nProcessing language: {lang}") + + # Load translation file + translations = manager.load_translation_file(lang) + original_count = len(translations) + + if backup: + # Create backup + backup_file = Path(translations_dir) / f"{lang}.json.backup" + with open(backup_file, 'w', encoding='utf-8') as f: + json.dump(translations, f, ensure_ascii=False, indent=2) + print(f"Created backup: {backup_file}") + + # Find unused keys + unused_keys = set(translations.keys()) - current_texts + + if unused_keys: + print(f"Found {len(unused_keys)} unused keys:") + for i, key in enumerate(sorted(unused_keys)[:10], 1): # Only show first 10 + print(f" {i}. \"{key[:50]}{'...' if len(key) > 50 else ''}\"") + if len(unused_keys) > 10: + print(f" ... and {len(unused_keys) - 10} more keys") + + response = input(f"Delete these {len(unused_keys)} unused keys? (y/n): ") + if response.lower().strip() in ['y', 'yes']: + # Delete unused keys + for key in unused_keys: + del translations[key] + + # Save cleaned file + manager.save_translation_file(lang, translations) + removed_count = len(unused_keys) + total_removed += removed_count + print(f"Deleted {removed_count} keys") + else: + print("Skipped deletion") + else: + print("No unused keys found") + + new_count = len(translations) + print(f"Original key count: {original_count}, after cleanup: {new_count}") + + print(f"\nCleanup completed! Total deleted {total_removed} unused keys.") + +def sync_translations(translations_dir: str, source_lang: str = "en_US", target_langs: List[str] = None): + """Sync translation keys to ensure all language files have the same keys""" + print(f"Starting translation key sync using {source_lang} as reference...") + + translations_path = Path(translations_dir) + + # Load source language file + source_file = translations_path / f"{source_lang}.json" + if not source_file.exists(): + print(f"Error: Source language file does not exist: {source_file}") + return + + with open(source_file, 'r', encoding='utf-8') as f: + source_translations = json.load(f) + + source_keys = set(source_translations.keys()) + print(f"Source language {source_lang} has {len(source_keys)} keys") + + # Get target language list + if target_langs is None: + target_langs = [] + for file_path in translations_path.glob("*.json"): + lang_code = file_path.stem + if lang_code != source_lang: + target_langs.append(lang_code) + + if not target_langs: + print("No target language files found") + return + + print(f"Target languages: {', '.join(target_langs)}") + + for target_lang in target_langs: + print(f"\nSyncing language: {target_lang}") + + target_file = translations_path / f"{target_lang}.json" + if target_file.exists(): + with open(target_file, 'r', encoding='utf-8') as f: + target_translations = json.load(f) + else: + target_translations = {} + + target_keys = set(target_translations.keys()) + + # Find missing and extra keys + missing_keys = source_keys - target_keys + extra_keys = target_keys - source_keys + + print(f" Missing keys: {len(missing_keys)}") + print(f" Extra keys: {len(extra_keys)}") + + # Add missing keys + if missing_keys: + for key in missing_keys: + # Use source language value as placeholder by default + target_translations[key] = source_translations[key] + print(f" Added {len(missing_keys)} missing keys") + + # Ask whether to delete extra keys + if extra_keys: + response = input(f" Delete {len(extra_keys)} extra keys? (y/n): ") + if response.lower().strip() in ['y', 'yes']: + for key in extra_keys: + del target_translations[key] + print(f" Deleted {len(extra_keys)} extra keys") + + # Save file + with open(target_file, 'w', encoding='utf-8') as f: + json.dump(target_translations, f, ensure_ascii=False, indent=2) + + print(f" Saved: {target_file}") + +def main(): + parser = argparse.ArgumentParser(description="Translation File Maintenance Helper") + parser.add_argument("--translations-dir", "-t", + default=".config/quickshell/translations", + help="Translation files directory") + parser.add_argument("--source-dir", "-s", + default=".config/quickshell", + help="Source code directory") + parser.add_argument("--clean", "-c", action="store_true", + help="Clean unused translation keys") + parser.add_argument("--sync", action="store_true", + help="Sync translation keys") + parser.add_argument("--source-lang", default="en_US", + help="Source language for syncing (default: en_US)") + parser.add_argument("--no-backup", action="store_true", + help="Do not create backup files when cleaning") + + args = parser.parse_args() + + # Convert to absolute paths + translations_dir = os.path.abspath(args.translations_dir) + source_dir = os.path.abspath(args.source_dir) + + if args.clean: + clean_translation_files(translations_dir, source_dir, backup=not args.no_backup) + elif args.sync: + sync_translations(translations_dir, args.source_lang) + else: + print("Please specify an operation:") + print(" --clean: Clean unused translation keys") + print(" --sync: Sync translation keys") + +if __name__ == "__main__": + main() diff --git a/.config/quickshell/translations/tools/translation-manager.py b/.config/quickshell/translations/tools/translation-manager.py new file mode 100755 index 00000000..ffcb2609 --- /dev/null +++ b/.config/quickshell/translations/tools/translation-manager.py @@ -0,0 +1,290 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Translation File Management Script +Used to update and extract translatable texts, manage JSON translation file key comparison +""" + +import os +import json +import re +import sys +import argparse +from pathlib import Path +from typing import Dict, Set, List, Tuple +import tempfile +import subprocess + +class TranslationManager: + def __init__(self, translations_dir: str, source_dir: str): + self.translations_dir = Path(translations_dir) + self.source_dir = Path(source_dir) + self.temp_extracted_file = None + + # Ensure translation directory exists + self.translations_dir.mkdir(parents=True, exist_ok=True) + + def extract_translatable_texts(self) -> Set[str]: + """Extract translatable texts from source code""" + translatable_texts = set() + + # Search patterns: Translation.tr("text") or Translation.tr('text') + # Improved regex that handles nested quotes correctly + patterns = [ + r'Translation\.tr\s*\(\s*(["\'])(((?!\1)[^\\]|\\.)*)(\1)\s*\)', # Double or single quotes with escape support + r'Translation\.tr\s*\(\s*`([^`]*(?:\\.[^`]*)*?)`\s*\)', # Backticks (template strings) + ] + + # Search all .qml and .js files + file_extensions = ['*.qml', '*.js'] + + for ext in file_extensions: + for file_path in self.source_dir.rglob(ext): + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + for pattern in patterns: + matches = re.findall(pattern, content, re.MULTILINE | re.DOTALL) + for match in matches: + # Handle different match group structures + if isinstance(match, tuple): + # For improved regex, text is in the second group + if len(match) >= 3: + text = match[1] # Second group is the text content + else: + text = match[0] if match else "" + else: + text = match + + # Decode escape characters + try: + clean_text = text.encode().decode('unicode_escape') + except: + clean_text = text + + # Clean text (remove extra whitespace) + clean_text = clean_text.strip() + if clean_text: + translatable_texts.add(clean_text) + + except (UnicodeDecodeError, IOError) as e: + print(f"Warning: Cannot read file {file_path}: {e}") + + return translatable_texts + + def create_temp_translation_file(self, texts: Set[str]) -> str: + """Create temporary JSON file containing extracted texts""" + temp_data = {} + for text in sorted(texts): + temp_data[text] = text # Key and value are the same, indicating untranslated + + # Create temporary file + with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False, encoding='utf-8') as f: + json.dump(temp_data, f, ensure_ascii=False, indent=2) + self.temp_extracted_file = f.name + + return self.temp_extracted_file + + def load_translation_file(self, lang_code: str) -> Dict[str, str]: + """Load translation file for specified language""" + file_path = self.translations_dir / f"{lang_code}.json" + if file_path.exists(): + try: + with open(file_path, 'r', encoding='utf-8') as f: + return json.load(f) + except (json.JSONDecodeError, IOError) as e: + print(f"Warning: Cannot load translation file {file_path}: {e}") + return {} + return {} + + def save_translation_file(self, lang_code: str, translations: Dict[str, str]): + """Save translation file""" + file_path = self.translations_dir / f"{lang_code}.json" + try: + with open(file_path, 'w', encoding='utf-8') as f: + json.dump(translations, f, ensure_ascii=False, indent=2) + print(f"Translation file saved: {file_path}") + except IOError as e: + print(f"Error: Cannot save translation file {file_path}: {e}") + + def get_available_languages(self) -> List[str]: + """Get list of available languages""" + languages = [] + for file_path in self.translations_dir.glob("*.json"): + lang_code = file_path.stem + languages.append(lang_code) + return sorted(languages) + + def compare_translations(self, extracted_texts: Set[str], target_lang: str) -> Tuple[Set[str], Set[str]]: + """Compare extracted texts with existing translation file""" + existing_translations = self.load_translation_file(target_lang) + existing_keys = set(existing_translations.keys()) + + missing_keys = extracted_texts - existing_keys # Missing keys + extra_keys = existing_keys - extracted_texts # Extra keys + + return missing_keys, extra_keys + + def interactive_update(self, lang_code: str, missing_keys: Set[str], extra_keys: Set[str]): + """Interactively update translation file""" + translations = self.load_translation_file(lang_code) + modified = False + + # Handle missing keys + if missing_keys: + print(f"\nFound {len(missing_keys)} missing translation keys:") + for i, key in enumerate(sorted(missing_keys), 1): + print(f"{i}. \"{key}\"") + + if self.ask_yes_no(f"\nAdd these {len(missing_keys)} missing keys?"): + for key in missing_keys: + translations[key] = key # Default value is the key itself + modified = True + print(f"Added {len(missing_keys)} keys") + + # Handle extra keys + if extra_keys: + print(f"\nFound {len(extra_keys)} extra translation keys:") + for i, key in enumerate(sorted(extra_keys), 1): + print(f"{i}. \"{key}\" -> \"{translations.get(key, '')}\"") + + if self.ask_yes_no(f"\nDelete these {len(extra_keys)} extra keys?"): + for key in extra_keys: + if key in translations: + del translations[key] + modified = True + print(f"Deleted {len(extra_keys)} keys") + + # Save changes + if modified: + self.save_translation_file(lang_code, translations) + else: + print("No changes made") + + def ask_yes_no(self, question: str) -> bool: + """Ask user for confirmation""" + while True: + response = input(f"{question} (y/n): ").lower().strip() + if response in ['y', 'yes']: + return True + elif response in ['n', 'no']: + return False + else: + print("Please enter y/yes or n/no") + + def cleanup(self): + """Clean up temporary files""" + if self.temp_extracted_file and os.path.exists(self.temp_extracted_file): + os.unlink(self.temp_extracted_file) + +def main(): + parser = argparse.ArgumentParser(description="Translation file management tool") + parser.add_argument("--translations-dir", "-t", + default=".config/quickshell/translations", + help="Translation files directory (default: .config/quickshell/translations)") + parser.add_argument("--source-dir", "-s", + default=".config/quickshell", + help="Source code directory (default: .config/quickshell)") + parser.add_argument("--language", "-l", + help="Specify language code to process (e.g., zh_CN)") + parser.add_argument("--extract-only", "-e", action="store_true", + help="Only extract translatable texts to temporary file") + parser.add_argument("--show-temp", action="store_true", + help="Show temporary extracted file content") + + args = parser.parse_args() + + # Convert to absolute paths + translations_dir = os.path.abspath(args.translations_dir) + source_dir = os.path.abspath(args.source_dir) + + print(f"Translation directory: {translations_dir}") + print(f"Source code directory: {source_dir}") + + # Check if directories exist + if not os.path.exists(source_dir): + print(f"Error: Source code directory does not exist: {source_dir}") + sys.exit(1) + + # Create manager + manager = TranslationManager(translations_dir, source_dir) + + try: + # Extract translatable texts + print("\nExtracting translatable texts...") + extracted_texts = manager.extract_translatable_texts() + print(f"Extracted {len(extracted_texts)} translatable texts") + + # Create temporary file + temp_file = manager.create_temp_translation_file(extracted_texts) + print(f"Created temporary file: {temp_file}") + + if args.show_temp: + print("\nTemporary file contents:") + with open(temp_file, 'r', encoding='utf-8') as f: + print(f.read()) + + if args.extract_only: + print("Extract-only mode, program finished") + return + + # Get available languages + available_languages = manager.get_available_languages() + + if args.language: + target_languages = [args.language] + else: + print(f"\nAvailable languages: {', '.join(available_languages) if available_languages else 'None'}") + + if not available_languages: + print("No existing translation files found") + lang_input = input("Enter language code to create (e.g.: zh_CN): ").strip() + if lang_input: + target_languages = [lang_input] + else: + print("No language specified, program finished") + return + else: + print("Choose language to process:") + for i, lang in enumerate(available_languages, 1): + print(f"{i}. {lang}") + print("a. Process all languages") + + choice = input("Please choose (enter number, language code, or 'a'): ").strip() + + if choice.lower() == 'a': + target_languages = available_languages + elif choice.isdigit() and 1 <= int(choice) <= len(available_languages): + target_languages = [available_languages[int(choice) - 1]] + elif choice in available_languages: + target_languages = [choice] + else: + print("Invalid choice, program finished") + return + + # Process each language + for lang in target_languages: + print(f"\n{'='*50}") + print(f"Processing language: {lang}") + print('='*50) + + missing_keys, extra_keys = manager.compare_translations(extracted_texts, lang) + + if not missing_keys and not extra_keys: + print(f"Translation file for language {lang} is already up to date") + continue + + print(f"Analysis results:") + print(f" Missing keys: {len(missing_keys)}") + print(f" Extra keys: {len(extra_keys)}") + + if missing_keys or extra_keys: + manager.interactive_update(lang, missing_keys, extra_keys) + + finally: + # Clean up temporary files + manager.cleanup() + +if __name__ == "__main__": + main() diff --git a/.config/quickshell/translations/tools/translation-tools-guide.md b/.config/quickshell/translations/tools/translation-tools-guide.md new file mode 100644 index 00000000..52757632 --- /dev/null +++ b/.config/quickshell/translations/tools/translation-tools-guide.md @@ -0,0 +1,246 @@ +# Translation Management Tool Suite + +This tool suite is used to manage project translation files, automatically extract translatable texts, compare differences between different language files, and provide maintenance functions. + +## Tool Components + +### 1. `translation-manager.py` - Main Translation Manager +- Extract translatable texts +- Compare and update translation files +- Interactive adding/removing translation keys + +### 2. `translation-cleaner.py` - Translation File Maintenance Tool +- Clean unused translation keys +- Sync key structure across different language files + +### 3. `manage-translations.sh` - Convenient Wrapper Script +- Provide unified command-line interface +- Display translation status +- Simplify common operations + +## Quick Start + +### Check Translation Status +```bash +./manage-translations.sh status +``` + +### Extract Translatable Texts +```bash +./manage-translations.sh extract +``` + +### Update Translation Files +```bash +# Update all languages +./manage-translations.sh update + +# Update specific language +./manage-translations.sh update -l zh_CN +``` + +### Clean Unused Keys +```bash +./manage-translations.sh clean +``` + +### Sync Keys Across Languages +```bash +./manage-translations.sh sync +``` + +## Detailed Usage + +### translation-manager.py + +The main translation management tool that extracts translatable texts from source code and manages translation files. + +#### Command Line Options +```bash +python3 translation-manager.py [options] + +Options: + -h, --help Show help message + -t, --translations-dir DIR Translation files directory (default: .config/quickshell/translations) + -s, --source-dir DIR Source code directory (default: .config/quickshell) + -l, --language LANG Specify language code to process (e.g., zh_CN) + -e, --extract-only Only extract translatable texts to temporary file + --show-temp Show temporary extracted file content +``` + +#### Features +1. **Text Extraction**: Uses regex patterns to extract translatable texts from QML and JavaScript files +2. **Smart Filtering**: Automatically removes duplicates and cleans up extracted texts +3. **Interactive Updates**: Guides users through adding missing keys and removing extra ones +4. **Backup Support**: Creates backups before making changes + +#### Supported Text Patterns +- `qsTr("text")` and `qsTr('text')` +- `i18n.t("text")` and `i18n.t('text')` +- Supports nested quotes and escape characters +- Handles multiline strings + +### translation-cleaner.py + +A maintenance tool for cleaning up and synchronizing translation files. + +#### Command Line Options +```bash +python3 translation-cleaner.py [options] + +Options: + -h, --help Show help message + -t, --translations-dir DIR Translation files directory + -s, --source-dir DIR Source code directory + -c, --clean Clean unused translation keys + --sync Sync translation keys + --source-lang LANG Source language for syncing (default: en_US) + --no-backup Do not create backup files when cleaning +``` + +#### Features +1. **Unused Key Cleanup**: Identifies and removes translation keys that are no longer used in the source code +2. **Key Synchronization**: Ensures all language files have the same set of keys +3. **Backup Protection**: Creates backup files before making destructive changes +4. **Interactive Confirmation**: Asks for user confirmation before deleting keys + +### manage-translations.sh + +A convenient wrapper script that provides a unified interface to all translation tools. + +#### Commands +```bash +./manage-translations.sh [options] + +Commands: + extract Extract translatable texts to temporary file + update Update translation files (add missing/remove extra keys) + clean Clean unused translation keys + sync Sync keys across all language files + status Show translation status + +Options: + -l, --lang LANG Specify language (e.g.: zh_CN) + -t, --trans-dir DIR Translation files directory + -s, --source-dir DIR Source code directory + -h, --help Show help message +``` + +## Workflow Examples + +### Initial Setup +1. Create translation directory structure +2. Extract all translatable texts: `./manage-translations.sh extract` +3. Create initial translation files: `./manage-translations.sh update` + +### Regular Maintenance +1. Check status: `./manage-translations.sh status` +2. Update translations after code changes: `./manage-translations.sh update` +3. Clean up unused keys periodically: `./manage-translations.sh clean` + +### Adding New Language +1. Create new language file: `./manage-translations.sh update -l new_lang` +2. Sync keys if needed: `./manage-translations.sh sync` + +## File Structure + +``` +translations/ +├── tools/ # Translation management tools +│ ├── translation-manager.py # Main extraction and update tool +│ ├── translation-cleaner.py # Cleanup and sync tool +│ ├── manage-translations.sh # Wrapper script +│ └── translation-tools-guide.md # This documentation +├── en_US.json # English translations (reference) +├── zh_CN.json # Chinese translations +└── [other_lang].json # Other language files +``` + +## Configuration + +### Text Extraction Patterns + +The tool uses regex patterns to identify translatable texts. Current patterns include: + +1. **QML qsTr patterns**: + - `qsTr("text")` and `qsTr('text')` + - Supports escaped quotes and nested quotes + +2. **JavaScript i18n patterns**: + - `i18n.t("text")` and `i18n.t('text')` + - Supports template literals and complex expressions + +3. **Custom patterns** can be added by modifying the patterns list in `translation-manager.py` + +### File Extensions + +By default, the tool processes: +- `.qml` files (QML/QtQuick) +- `.js` files (JavaScript) + +Additional file types can be added by modifying the file extension filters. + +## Best Practices + +1. **Regular Updates**: Run `./manage-translations.sh status` regularly to check for new translatable texts +2. **Clean Periodically**: Use `./manage-translations.sh clean` to remove unused keys +3. **Backup Important**: Always backup translation files before major changes +4. **Consistent Patterns**: Use consistent function calls (`qsTr`, `i18n.t`) for translatable texts +5. **Review Changes**: Always review the changes before confirming deletions or additions + +## Troubleshooting + +### Common Issues + +1. **Missing Texts**: If some translatable texts are not extracted, check if they match the supported patterns +2. **Path Issues**: Ensure the source and translation directory paths are correct +3. **Permission Errors**: Make sure the script has write permissions to the translation directory +4. **Encoding Issues**: All files should be saved in UTF-8 encoding + +### Getting Help + +For additional help: +- Use `--help` option with any tool +- Check the console output for error messages +- Verify file paths and permissions + +## Advanced Usage + +### Custom Regex Patterns + +To add support for new translation function patterns, modify the `patterns` list in `TranslationManager.extract_translatable_texts()`: + +```python +patterns = [ + # Existing patterns... + r'customTranslate\s*\(\s*(["\'])((?:\\.|(?!\1)[^\\])*?)\1\s*\)', # Custom pattern +] +``` + +### Batch Processing + +For processing multiple projects or directories: + +```bash +# Process multiple directories +for dir in project1 project2 project3; do + ./manage-translations.sh -s "$dir" -t "$dir/translations" update +done +``` + +### Integration with Build Systems + +The tools can be integrated into build systems to automatically update translations: + +```bash +# In your build script +./manage-translations.sh update --non-interactive +``` + +## Version History + +- **v1.0**: Initial version with basic extraction and update functionality +- **v1.1**: Added improved regex patterns for better text extraction +- **v1.2**: Added cleaning and synchronization tools +- **v1.3**: Added English output and improved user interface +- **v1.4**: Moved all tools to dedicated tools directory and improved documentation diff --git a/.config/quickshell/translations/tools/翻译管理脚本说明.md b/.config/quickshell/translations/tools/翻译管理脚本说明.md new file mode 100644 index 00000000..fa9850cf --- /dev/null +++ b/.config/quickshell/translations/tools/翻译管理脚本说明.md @@ -0,0 +1,287 @@ +# 翻译管理工具套件 + +这套工具用于管理项目的翻译文件,自动提取可翻译文本,比较不同语言文件之间的差异,并提供维护功能。 + +## 工具组成 + +### 1. `translation-manager.py` - 主要翻译管理器 +- 提取可翻译文本 +- 比较和更新翻译文件 +- 交互式添加/删除翻译键 + +### 2. `translation-cleaner.py` - 翻译文件维护工具 +- 清理不再使用的翻译键 +- 同步不同语言文件的键结构 + +### 3. `manage-translations.sh` - 便捷包装脚本 +- 提供统一的命令行界面 +- 显示翻译状态 +- 简化常用操作 + +## 快速开始 + +### 使用便捷脚本(推荐) + +```bash +# 进入工具目录 +cd .config/quickshell/translations/tools + +# 查看帮助 +./manage-translations.sh --help + +# 显示当前翻译状态 +./manage-translations.sh status + +# 提取可翻译文本 +./manage-translations.sh extract + +# 更新所有翻译文件 +./manage-translations.sh update + +# 更新特定语言 +./manage-translations.sh update -l zh_CN + +# 清理不再使用的键 +./manage-translations.sh clean + +# 同步所有语言文件的键 +./manage-translations.sh sync +``` + +或者从项目根目录运行: +```bash +# 从项目根目录运行 +.config/quickshell/translations/tools/manage-translations.sh status +.config/quickshell/translations/tools/manage-translations.sh update +``` + +## 详细使用说明 + +### 翻译管理器 (`translation-manager.py`) + +基本用法: +```bash +# 处理所有语言 +./translation-manager.py + +# 指定特定语言 +./translation-manager.py --language zh_CN + +# 仅提取可翻译文本 +./translation-manager.py --extract-only + +# 显示提取的文本 +./translation-manager.py --extract-only --show-temp +``` + +参数说明: +- `--translations-dir`, `-t`: 翻译文件目录(默认:`.config/quickshell/translations`) +- `--source-dir`, `-s`: 源代码目录(默认:`.config/quickshell`) +- `--language`, `-l`: 指定要处理的语言代码 +- `--extract-only`, `-e`: 仅提取可翻译文本 +- `--show-temp`: 显示临时提取文件的内容 + +### 翻译清理器 (`translation-cleaner.py`) + +```bash +# 清理不再使用的翻译键 +./translation-cleaner.py --clean + +# 同步翻译键(以 en_US 为基准) +./translation-cleaner.py --sync + +# 指定不同的源语言进行同步 +./translation-cleaner.py --sync --source-lang zh_CN + +# 清理时不创建备份 +./translation-cleaner.py --clean --no-backup +``` + +## 工作流程 + +### 日常翻译更新流程 + +1. **检查状态**: + ```bash + ./manage-translations.sh status + ``` + +2. **更新翻译**: + ```bash + ./manage-translations.sh update + ``` + +3. **清理无用键**(可选): + ```bash + ./manage-translations.sh clean + ``` + +### 新增语言流程 + +1. **创建新语言文件**: + ```bash + ./manage-translations.sh update -l new_lang + ``` + +2. **同步键结构**: + ```bash + ./manage-translations.sh sync + ``` + +### 大规模重构后的清理流程 + +1. **备份翻译文件**: + ```bash + cp -r .config/quickshell/translations .config/quickshell/translations.backup + ``` + +2. **清理无用键**: + ```bash + ./manage-translations.sh clean + ``` + +3. **同步所有语言**: + ```bash + ./manage-translations.sh sync + ``` + +## 支持的翻译文本格式 + +工具可以识别以下格式的可翻译文本: + +```qml +// 基本格式 +Translation.tr("Hello, world!") +Translation.tr('Hello, world!') +Translation.tr(`Hello, world!`) + +// 带换行符 +Translation.tr("Line 1\nLine 2") + +// 带转义字符 +Translation.tr("Say \"Hello\"") + +// 带参数占位符 +Translation.tr("Hello, %1!").arg(name) +Translation.tr("{0} files selected").arg(count) +``` + +## 示例输出 + +### 状态显示 +``` +$ ./manage-translations.sh status +正在分析翻译状态... +=== 当前项目状态 === +提取到 166 个可翻译文本 + +=== 翻译文件状态 === + en_US: 470 个键 + zh_CN: 470 个键 +``` + +### 更新翻译 +``` +$ ./manage-translations.sh update -l zh_CN +更新翻译文件... +================================================== +处理语言: zh_CN +================================================== +分析结果: + 缺少的键: 5 + 多余的键: 20 + +发现 5 个缺少的翻译键: +1. "New feature text" +2. "Another new text" +... + +是否添加这 5 个缺少的键? (y/n): y +已添加 5 个键 + +发现 20 个多余的翻译键: +1. "Removed old text" -> "已删除的旧文本" +... + +是否删除这 20 个多余的键? (y/n): y +已删除 20 个键 + +已保存翻译文件 +``` + +### 清理无用键 +``` +$ ./manage-translations.sh clean +清理不再使用的翻译键... +处理语言: zh_CN +发现 50 个不再使用的键: + 1. "old_unused_text" + 2. "deprecated_message" + ... + +是否删除这 50 个不再使用的键? (y/n): y +已删除 50 个键 +原始键数: 470, 清理后: 420 +``` + +## 高级功能 + +### 自定义目录结构 + +```bash +# 使用自定义目录 +./translation-manager.py \ + --translations-dir /path/to/translations \ + --source-dir /path/to/source +``` + +### 批量处理 + +```bash +# 创建处理脚本 +cat > update-all-translations.sh << 'EOF' +#!/bin/bash +for lang in zh_CN ja_JP ko_KR; do + echo "Processing $lang..." + ./manage-translations.sh update -l $lang +done +EOF + +chmod +x update-all-translations.sh +./update-all-translations.sh +``` + +## 注意事项 + +1. **备份重要**:在执行清理操作前,工具会自动创建备份,但建议手动备份重要文件 + +2. **文本提取限制**: + - 只支持静态字符串,不支持动态构建的字符串 + - 必须使用 `Translation.tr()` 格式 + +3. **文件编码**:所有文件必须使用 UTF-8 编码 + +4. **键名规范**:建议使用英文作为键名,避免使用特殊字符 + +## 故障排除 + +### 常见问题 + +**Q: 提取的文本数量与预期不符?** +A: 检查是否所有可翻译文本都使用了 `Translation.tr()` 格式,确保没有动态构建的字符串。 + +**Q: 同步后某些翻译丢失?** +A: 检查源语言文件是否包含所有必要的键,考虑使用不同的源语言进行同步。 + +**Q: 清理操作删除了需要的键?** +A: 从自动创建的备份文件中恢复,检查源代码中是否正确使用了 `Translation.tr()`。 + +### 恢复备份 + +```bash +# 恢复单个文件 +cp .config/quickshell/translations/zh_CN.json.backup .config/quickshell/translations/zh_CN.json + +# 恢复所有文件 +cp .config/quickshell/translations.backup/* .config/quickshell/translations/ +``` diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index f73a6949..a0d09939 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -27,28 +27,26 @@ "Clear chat history": "清除聊天记录", "Clear the current list of images": "清除当前图片列表", "Close": "关闭", - "Closes cheatsheet on press": "Closes cheatsheet on press", - "Closes left sidebar on press": "Closes left sidebar on press", - "Closes media controls on press": "Closes media controls on press", - "Closes on screen keyboard on press": "Closes on screen keyboard on press", - "Closes overview": "Closes overview", - "Closes right sidebar on press": "Closes right sidebar on press", + "Closes cheatsheet on press": "按下时关闭快捷键表", + "Closes left sidebar on press": "按下时关闭左侧边栏", + "Closes media controls on press": "按下时关闭媒体控制", + "Closes on screen keyboard on press": "按下时关闭屏幕键盘", + "Closes overview": "关闭概览", + "Closes right sidebar on press": "按下时关闭右侧边栏", "Copy": "复制", "Copy code": "复制代码", - "Ctrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "Ctrl+O 展开侧边栏\nCtrl+P 将侧边栏分离为窗口", "Current API endpoint: {0}\nSet it with {1}mode PROVIDER": "当前 API 端点:{0}\n使用 {1}mode PROVIDER 设置", "Current model: {0}\nSet it with {1}model MODEL": "当前模型:{0}\n使用 {1}model MODEL 设置", - "Decrease brightness": "Decrease brightness", + "Decrease brightness": "降低亮度", "Delete": "删除", "Desktop": "桌面", - "Detach left sidebar into a window/Attach it back": "Detach left sidebar into a window/Attach it back", + "Detach left sidebar into a window/Attach it back": "将左侧边栏分离为窗口/重新附加", "Disable NSFW content": "禁用 NSFW 内容", "Done": "完成", "Download": "下载", "Download complete": "下载完成", "Edit": "编辑", "Enter text to translate...": "输入要翻译的文本...", - "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "实验性 | 在线 | Google 模型\n功能更多但搜索速度较慢", "Finished tasks will go here": "已完成的任务将显示在这里", "For desktop wallpapers | Good quality": "桌面壁纸专用 | 质量好", "For storing API keys and other sensitive information": "用于存储 API 密钥和其他敏感信息", @@ -56,17 +54,14 @@ "Get the next page of results": "获取下一页结果", "Go to source ({0})": "转到源 ({0})", "Hibernate": "休眠", - "Hides brightness OSD on press": "Hides brightness OSD on press", - "Hides volume OSD on press": "Hides volume OSD on press", - "Hold to show workspace numbers, release to show icons": "Hold to show workspace numbers, release to show icons", - "Increase brightness": "Increase brightness", + "Hides brightness OSD on press": "按下时隐藏亮度显示", + "Hides volume OSD on press": "按下时隐藏音量显示", + "Hold to show workspace numbers, release to show icons": "按住显示工作区编号,松开显示图标", + "Increase brightness": "提高亮度", "Input": "输入", "Intelligence": "智能", "Interface": "界面", - "Interrupts possibility of overview being toggled on release. ": "Interrupts possibility of overview being toggled on release. ", - "Invalid API provider. Supported: \n- ": "无效的 API 提供商。支持的:\n- ", "Invalid arguments. Must provide `key` and `value`.": "参数无效。必须提供 `key` 和 `value`。", - "Invalid model. Supported: \n```\n": "无效模型。支持的:\n```\n", "Jump to current month": "跳转到当前月份", "Keep system awake": "保持系统唤醒", "Large images | God tier quality, no NSFW.": "大尺寸图片 | 顶级质量,无 NSFW", @@ -86,24 +81,21 @@ "Nothing here!": "这里什么都没有!", "Notifications": "通知", "OK": "确定", - "Online via {0} | {1}'s model": "通过 {0} 在线 | {1} 模型", - "Online | Google's model\nGives up-to-date information with search.": "在线 | Google 模型\n通过搜索提供最新信息。", "Open file link": "打开文件链接", - "Opens cheatsheet on press": "Opens cheatsheet on press", - "Opens left sidebar on press": "Opens left sidebar on press", - "Opens media controls on press": "Opens media controls on press", - "Opens on screen keyboard on press": "Opens on screen keyboard on press", - "Opens right sidebar on press": "Opens right sidebar on press", - "Opens session screen on press": "Opens session screen on press", + "Opens cheatsheet on press": "按下时打开快捷键表", + "Opens left sidebar on press": "按下时打开左侧边栏", + "Opens media controls on press": "按下时打开媒体控制", + "Opens on screen keyboard on press": "按下时打开屏幕键盘", + "Opens right sidebar on press": "按下时打开右侧边栏", + "Opens session screen on press": "按下时打开会话屏幕", "Output": "输出", "Page {0}": "第 {0} 页", "Plasma Settings": "Plasma 设置", - "Provider set to ": "提供商设置为", "Reboot": "重启", - "Reboot to firmware settings": "Reboot to firmware settings", + "Reboot to firmware settings": "重启到固件设置", "Reload Hyprland & Quickshell": "重新加载 Hyprland 和 Quickshell", "Run": "运行", - "Run command": "Run command", + "Run command": "运行命令", "Save": "保存", "Save to Downloads": "保存到下载文件夹", "Scroll to change brightness": "滚动调节亮度", @@ -122,351 +114,63 @@ "Shutdown": "关机", "Silent": "静音", "Sleep": "睡眠", - "Switched to search mode. Continue with the user's request.": "已切换到搜索模式。继续处理用户请求。", "System": "系统", "Task Manager": "任务管理器", "Task description": "任务描述", "Temperature must be between 0 and 2": "温度必须在 0 到 2 之间", "Temperature set to {0}": "温度设置为 {0}", "Temperature: {0}": "温度:{0}", - "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "没有找到结果。提示:\n- 检查您的标签和 NSFW 设置\n- 如果没有想到标签,请输入页码", - "The current API used. Endpoint: ": "当前使用的 API。端点:", "The hentai one | Great quantity, a lot of NSFW, quality varies wildly": "成人向 | 数量巨大,大量 NSFW,质量参差不齐", "The popular one | Best quantity, but quality can vary wildly": "最受欢迎 | 数量最多,但质量参差不齐", "Thinking": "思考中", - "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ": "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ", - "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.": "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.", - "Toggle clipboard query on overview widget": "Toggle clipboard query on overview widget", - "Toggle emoji query on overview widget": "Toggle emoji query on overview widget", - "Toggles cheatsheet on press": "Toggles cheatsheet on press", - "Toggles left sidebar on press": "Toggles left sidebar on press", - "Toggles media controls on press": "Toggles media controls on press", - "Toggles on screen keyboard on press": "Toggles on screen keyboard on press", - "Toggles overview on press": "Toggles overview on press", - "Toggles overview on release": "Toggles overview on release", - "Toggles right sidebar on press": "Toggles right sidebar on press", - "Toggles session screen on press": "Toggles session screen on press", + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.": "为确保此功能正常工作,请在自动触发的子映射中使用 binditn = MODKEYS, catchall,该子映射包含所有内容。", + "Toggle clipboard query on overview widget": "在概览组件中切换剪贴板查询", + "Toggle emoji query on overview widget": "在概览组件中切换表情符号查询", + "Toggles cheatsheet on press": "按下时切换快捷键表", + "Toggles left sidebar on press": "按下时切换左侧边栏", + "Toggles media controls on press": "按下时切换媒体控制", + "Toggles on screen keyboard on press": "按下时切换屏幕键盘", + "Toggles overview on press": "按下时切换概览", + "Toggles overview on release": "松开时切换概览", + "Toggles right sidebar on press": "按下时切换右侧边栏", + "Toggles session screen on press": "按下时切换会话屏幕", "Translation goes here...": "翻译结果会显示在这里...", "Translator": "翻译器", - "Triggers brightness OSD on press": "Triggers brightness OSD on press", - "Triggers volume OSD on press": "Triggers volume OSD on press", + "Triggers brightness OSD on press": "按下时触发亮度显示", + "Triggers volume OSD on press": "按下时触发音量显示", "Unfinished": "未完成", "Unknown": "未知", "Unknown Album": "未知专辑", "Unknown Artist": "未知艺术家", "Unknown Title": "未知标题", - "Unknown command: ": "未知命令:", "Unknown function call: {0}": "未知函数调用:{0}", "Uptime: {0}": "运行时间:{0}", - "Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in **bold** to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`. When making changes to the user's config, you must get the config to know what values there are before setting.": "Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in **bold** to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`. When making changes to the user's config, you must get the config to know what values there are before setting.", "View Markdown source": "查看 Markdown 源码", "Volume": "音量", "Volume mixer": "音量混合器", "Waifus only | Excellent quality, limited quantity": "仅限角色 | 优秀质量,数量有限", "Waiting for response...": "等待响应...", "Workspace": "工作区", - "\nSet with /mode PROVIDER": "\n使用 /mode PROVIDER 设置", - "about": "关于", - "accessed": "访问时间", - "account": "账户", - "active": "活动", - "active_state": "活动状态", - "addon": "附加组件", - "addons": "附加组件", - "address": "地址", - "admin": "管理员", - "align": "对齐", - "always_on_top": "总在最前", - "animate": "动画", - "app": "应用", - "appearance": "外观", - "application": "应用程序", - "applications": "应用程序", - "apply": "应用", - "apps": "应用", - "auto": "自动", - "background": "背景", - "balanced": "平衡", - "bar": "栏", - "bars": "栏", - "battery": "电池", - "bluetooth": "蓝牙", - "blur": "模糊", - "border": "边框", - "bottom": "底部", - "brightness": "亮度", - "bring_to_front": "置于顶层", - "bytes": "{0} 字节", - "cancel": "取消", - "center": "居中", - "characters": "{0} 个字符", - "charging": "充电中", - "clear_all": "清除全部", - "clicked": "点击", - "close": "关闭", - "collapse": "折叠", - "color": "颜色", - "command": "命令", - "connected": "已连接", - "connecting": "连接中...", - "context_menu": "右键菜单", - "copy": "复制", - "cpu": "处理器", - "created": "创建时间", - "critical": "电量危险", - "customize": "自定义", - "cut": "剪切", - "dark": "深色", - "dashboard": "仪表板", - "date": "日期", - "debug": "调试", - "default": "默认", - "degrees": "{0}°", - "delete": "删除", - "demo": "演示", - "desktop": "桌面", - "dialog": "对话框", - "disabled": "已禁用", - "discharging": "放电中", - "disconnected": "已断开", - "disk": "磁盘", - "display": "显示", - "distribute": "分布", - "dock": "停靠栏", - "documents": "文档", - "double_clicked": "双击", - "downloads": "下载", - "dragged": "拖拽", - "dropdown": "下拉菜单", - "dropped": "拖放", - "effect": "效果", - "email": "邮箱", - "enabled": "已启用", - "error": "错误", - "ethernet": "以太网", - "example": "示例", - "execute": "执行", - "exit": "退出", - "expand": "展开", - "extension": "扩展", - "extensions": "扩展", - "fan": "风扇", - "favorites": "收藏夹", - "file": "文件", - "files": "文件", - "filter": "滤镜", - "flip": "翻转", - "floating": "浮动", - "focus": "焦点", - "folder": "文件夹", - "folders": "文件夹", - "foreground": "前景", - "format": "格式", - "full": "已充满", - "fullscreen": "全屏", - "gigabytes": "{0} GB", - "gigahertz": "{0} GHz", - "glow": "发光", - "group": "群组", - "guest": "访客", - "headphones": "耳机", - "help": "帮助", - "hertz": "{0} Hz", - "hibernate": "休眠", - "hidden": "隐藏", - "hide": "隐藏", - "highlight": "高亮", - "hint": "提示", - "home": "主目录", - "hour": "小时", - "hours": "小时", - "hover": "悬停", - "inactive": "非活动", - "info": "信息", - "input": "输入", - "install": "安装", - "justify": "两端对齐", - "keybinds": "按键绑定", - "keyboard": "键盘", - "kilobytes": "{0} KB", - "kilohertz": "{0} kHz", - "landscape": "横向", - "language": "语言", - "launcher": "启动器", - "left": "左对齐", - "light": "浅色", - "loading": "加载中...", - "lock": "锁定", - "log": "日志", - "logout": "注销", - "long_pressed": "长按", - "low": "电量低", - "manual": "手册", - "margin": "边距", - "maximize": "最大化", - "megabytes": "{0} MB", - "megahertz": "{0} MHz", - "memory": "内存", - "menu": "菜单", - "menubar": "菜单栏", - "microphone": "麦克风", - "minimize": "最小化", - "minute": "分钟", - "minutes": "分钟", - "mirror": "镜像", - "modal": "模态框", - "modified": "修改时间", - "monitor": "显示器", - "mouse": "鼠标", - "move": "移动", - "music": "音乐", - "mute": "静音", - "network": "网络", - "next": "下一个", - "no": "否", - "no_notifications": "无通知", - "notifications": "通知", - "off": "关", - "ok": "确定", - "on": "开", - "opacity": "不透明度", - "open": "打开", - "orientation": "方向", - "outline": "轮廓", - "output": "输出", - "overview": "概览", - "owner": "所有者", - "package": "软件包", - "packages": "软件包", - "padding": "内边距", - "panel": "面板", - "panels": "面板", - "panned": "平移", - "password": "密码", - "paste": "粘贴", - "pause": "暂停", - "percent": "{0}%", - "performance": "性能", - "permissions": "权限", - "phone": "电话", - "pictures": "图片", - "pinched": "捏合", - "pinned": "固定", - "pixels": "{0}像素", - "placeholder": "占位符", - "play": "播放", - "plugin": "插件", - "plugins": "插件", - "popup": "弹出窗口", - "portrait": "纵向", - "power": "电源", - "power_saver": "节能", - "pressed": "按下", - "previous": "上一个", - "profile": "配置文件", - "properties": "属性", - "quiet": "安静", - "quit": "退出", - "read": "读取", - "recent": "最近", - "recording": "录制", - "refresh": "刷新", - "refresh_rate": "刷新率", - "reload": "重新加载", - "rename": "重命名", - "reset": "重置", - "resize": "调整大小", - "resolution": "分辨率", - "restart": "重启", - "restore": "还原", - "right": "右对齐", - "right_clicked": "右键点击", - "rotate": "旋转", - "rotated": "旋转", - "sample": "样本", - "save": "保存", - "scale": "缩放", - "screenshot": "截图", - "scrolled": "滚动", - "search": "搜索", - "second": "秒", - "seconds": "秒", - "selection": "选择", - "send_to_back": "置于底层", - "settings": "设置", - "shadow": "阴影", - "shortcuts": "快捷键", - "show": "显示", - "shutdown": "关机", - "sidebar": "侧边栏", - "silent": "静默", - "size": "大小", - "snapped": "贴靠", - "software": "软件", - "space": "间距", - "speaker": "扬声器", - "statusbar": "状态栏", - "sticky": "粘性", - "stop": "停止", - "style": "样式", - "success": "成功", - "suspend": "挂起", - "swiped": "滑动", - "systray": "系统托盘", - "tapped": "轻触", - "taskbar": "任务栏", - "temperature": "温度", - "terabytes": "{0} TB", - "terminal": "终端", - "test": "测试", - "theme": "主题", - "tiled": "平铺", - "time": "时间", - "tips": "提示", - "today": "今天", - "tomorrow": "明天", - "toolbar": "工具栏", - "tooltip": "工具提示", - "top": "顶部", - "touchpad": "触摸板", - "trace": "跟踪", - "transform": "变换", - "transition": "过渡", - "transparency": "透明度", - "trash": "回收站", - "tutorial": "教程", - "type": "类型", - "uninstall": "卸载", - "unlock": "解锁", - "unmute": "取消静音", - "unpinned": "取消固定", - "unsticky": "取消粘性", - "update": "更新", - "upgrade": "升级", - "user": "用户", - "username": "用户名", - "verbose": "详细", - "version": "版本", - "videos": "视频", - "visible": "可见", - "volume": "音量", - "warning": "警告", - "welcome": "欢迎", - "widget": "组件", - "widgets": "组件", - "wifi": "Wi-Fi", - "window": "窗口", - "windowed": "窗口化", - "windows": "窗口", - "workspace": "工作区", - "workspaces": "工作区", - "write": "写入", - "yes": "是", - "yesterday": "昨天", - "zoomed": "缩放", "{0} (copied)": "{0}(已复制)", "{0} Safe Storage": "{0} 安全存储", "{0} does not require an API key": "{0} 不需要 API 密钥", "{0} queries pending": "{0} 个查询等待中", - "{0} | Right-click to configure": "{0} | 右键点击进行配置" + "{0} | Right-click to configure": "{0} | 右键点击进行配置", + "Set with /mode PROVIDER": "使用 /mode PROVIDER 设置", + "Invalid API provider. Supported: \n-": "无效的 API 提供商。支持的:\n-", + "Unknown command:": "未知命令:", + "Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "输入 /key 开始使用在线模型\nCtrl+O 展开侧边栏\nCtrl+P 将侧边栏分离为窗口", + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key.": "这是必要的,因为在按住键时,quickshell 中的 GlobalShortcut.onReleased 会在您是否按下其他键时触发。", + "The current API used. Endpoint:": "当前使用的 API。端点:", + "Provider set to": "提供商设置为", + "Invalid model. Supported: \n```": "无效模型。支持的:\n```", + "Interrupts possibility of overview being toggled on release.": "中断松开时切换概览的可能性。", + "Switched to search mode. Continue with the user's request.": "已切换到搜索模式。继续处理用户请求。", + "Message the model... \"{0}\" for commands": "与模型对话... \"{0}\" 查看命令", + "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "实验性 | 在线 | Google 模型\n功能更多但搜索速度较慢", + "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}": "要设置 API 密钥,请将其与命令一起传递\n\n要查看密钥,请将 \"get\" 与命令一起传递
\n\n### 对于 {0}:\n\n**链接**:{1}\n\n{2}", + "Enter tags, or \"{0}\" for commands": "输入标签,或 \"{0}\" 查看命令", + "Online via {0} | {1}'s model": "通过 {0} 在线 | {1} 的模型", + "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "没有找到结果。提示:\n- 检查您的标签和 NSFW 设置\n- 如果没有想到标签,请输入页码", + "Online | Google's model\nGives up-to-date information with search.": "在线 | Google 模型\n通过搜索提供最新信息。" } \ No newline at end of file From ccabd24db270092165042dd770fdc34abf5a8399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Tue, 17 Jun 2025 15:47:57 +0800 Subject: [PATCH 004/328] Add imports to service modules to support session functionality --- .config/quickshell/modules/session/Session.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/modules/session/Session.qml b/.config/quickshell/modules/session/Session.qml index 0ab3221e..ae4dfee5 100644 --- a/.config/quickshell/modules/session/Session.qml +++ b/.config/quickshell/modules/session/Session.qml @@ -1,4 +1,5 @@ import "root:/modules/common" +import "root:/services/" import "root:/modules/common/widgets" import "root:/modules/common/functions/color_utils.js" as ColorUtils import QtQuick From 02f1ed75f34c5affbde8e35b7586b6f59b0e0f03 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:51:35 +0200 Subject: [PATCH 005/328] add comment --- .config/quickshell/modules/common/widgets/StyledTextArea.qml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.config/quickshell/modules/common/widgets/StyledTextArea.qml b/.config/quickshell/modules/common/widgets/StyledTextArea.qml index 67d41757..447ae41c 100644 --- a/.config/quickshell/modules/common/widgets/StyledTextArea.qml +++ b/.config/quickshell/modules/common/widgets/StyledTextArea.qml @@ -2,6 +2,9 @@ import "root:/modules/common" import QtQuick import QtQuick.Controls +/** + * Does not include visual layout, but includes the easily neglected colors. + */ TextArea { renderType: Text.NativeRendering selectedTextColor: Appearance.m3colors.m3onSecondaryContainer From ed5be0c2ac9afcf2d7f0134295c8834c229a87e5 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:51:45 +0200 Subject: [PATCH 006/328] nuke old navigation rail button --- .../modules/common/widgets/NavRailButton.qml | 66 ------------------- 1 file changed, 66 deletions(-) delete mode 100644 .config/quickshell/modules/common/widgets/NavRailButton.qml diff --git a/.config/quickshell/modules/common/widgets/NavRailButton.qml b/.config/quickshell/modules/common/widgets/NavRailButton.qml deleted file mode 100644 index 02c6bc4a..00000000 --- a/.config/quickshell/modules/common/widgets/NavRailButton.qml +++ /dev/null @@ -1,66 +0,0 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell.Io - -/** - * Old implementation. For future widgets use NavigationRailButton instead. - */ -Button { - id: button - - property bool toggled - property string buttonIcon - property string buttonText - property bool expanded: false - - property real baseSize: 56 - - Layout.alignment: Qt.AlignHCenter - implicitHeight: columnLayout.implicitHeight - implicitWidth: columnLayout.implicitWidth - - background: null - PointingHandInteraction {} - - // Real stuff - ColumnLayout { - id: columnLayout - spacing: 5 - Rectangle { - implicitWidth: 56 - implicitHeight: navRailButtonIcon.height + 2 * 2 - Layout.alignment: Qt.AlignHCenter - radius: Appearance.rounding.full - color: toggled ? - (button.down ? Appearance.colors.colSecondaryContainerActive : button.hovered ? Appearance.colors.colSecondaryContainerHover : Appearance.colors.colSecondaryContainer) : - (button.down ? Appearance.colors.colLayer1Active : button.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1)) - - Behavior on color { - animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) - } - MaterialSymbol { - id: navRailButtonIcon - anchors.centerIn: parent - iconSize: Appearance.font.pixelSize.hugeass - fill: toggled ? 1 : 0 - text: buttonIcon - color: toggled ? Appearance.m3colors.m3onSecondaryContainer : Appearance.colors.colOnLayer1 - - Behavior on color { - animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) - } - } - } - - StyledText { - Layout.alignment: Qt.AlignHCenter - text: buttonText - color: Appearance.colors.colOnLayer1 - } - } - -} From 811a1ce6cb2b1957010f6f201bd42873ff6fceb3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:55:06 +0200 Subject: [PATCH 007/328] material symbol: also bold when filled --- .config/quickshell/modules/common/widgets/MaterialSymbol.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml b/.config/quickshell/modules/common/widgets/MaterialSymbol.qml index aac0b031..639427aa 100644 --- a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml +++ b/.config/quickshell/modules/common/widgets/MaterialSymbol.qml @@ -12,6 +12,7 @@ Text { hintingPreference: Font.PreferFullHinting family: Appearance?.font.family.iconMaterial ?? "Material Symbols Rounded" pixelSize: iconSize + weight: Font.Normal + (Font.DemiBold - Font.Normal) * fill } verticalAlignment: Text.AlignVCenter color: Appearance.m3colors.m3onBackground From b4340091c41bfccd2a1cc5e9a52efcf766a4ec43 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:55:30 +0200 Subject: [PATCH 008/328] appearance: add colonprimarycontainer, anim curve durations --- .config/quickshell/modules/common/Appearance.qml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 54463013..c2a20fdf 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -126,6 +126,7 @@ Singleton { property color colPrimaryContainer: m3colors.m3primaryContainer property color colPrimaryContainerHover: ColorUtils.mix(colors.colPrimaryContainer, colLayer1Hover, 0.7) property color colPrimaryContainerActive: ColorUtils.mix(colors.colPrimaryContainer, colLayer1Active, 0.6) + property color colOnPrimaryContainer: m3colors.m3onPrimaryContainer property color colSecondary: m3colors.m3secondary property color colSecondaryHover: ColorUtils.mix(m3colors.m3secondary, colLayer1Hover, 0.85) property color colSecondaryActive: ColorUtils.mix(m3colors.m3secondary, colLayer1Active, 0.4) @@ -192,6 +193,10 @@ Singleton { readonly property list standard: [0.2, 0, 0, 1, 1, 1] readonly property list standardAccel: [0.3, 0, 1, 1, 1, 1] readonly property list standardDecel: [0, 0, 0, 1, 1, 1] + readonly property real expressiveFastSpatialDuration: 350 + readonly property real expressiveDefaultSpatialDuration: 500 + readonly property real expressiveSlowSpatialDuration: 650 + readonly property real expressiveEffectsDuration: 200 } animation: QtObject { From ab991789f0c98c43a0eb64f62605f5c9ef576499 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:56:10 +0200 Subject: [PATCH 009/328] welcome: refractor content page and sections --- .../modules/common/widgets/ContentPage.qml | 23 + .../modules/common/widgets/ContentSection.qml | 22 + .config/quickshell/welcome.qml | 511 +++++++++--------- 3 files changed, 286 insertions(+), 270 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/ContentPage.qml create mode 100644 .config/quickshell/modules/common/widgets/ContentSection.qml diff --git a/.config/quickshell/modules/common/widgets/ContentPage.qml b/.config/quickshell/modules/common/widgets/ContentPage.qml new file mode 100644 index 00000000..9219ef67 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/ContentPage.qml @@ -0,0 +1,23 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +Flickable { + id: root + default property alias data: contentColumn.data + clip: true + contentHeight: contentColumn.implicitHeight + implicitWidth: contentColumn.implicitWidth + ColumnLayout { + id: contentColumn + anchors { + top: parent.top + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + margins: 10 + } + spacing: 20 + } +} diff --git a/.config/quickshell/modules/common/widgets/ContentSection.qml b/.config/quickshell/modules/common/widgets/ContentSection.qml new file mode 100644 index 00000000..8c423e37 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/ContentSection.qml @@ -0,0 +1,22 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +ColumnLayout { + id: root + property string title + default property alias data: sectionContent.data + + Layout.fillWidth: true + spacing: 8 + StyledText { + text: root.title + font.pixelSize: Appearance.font.pixelSize.larger + } + ColumnLayout { + id: sectionContent + spacing: 4 + } +} diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index 75b283a4..c7b8c409 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -53,23 +53,6 @@ ApplicationWindow { } } - component Section: ColumnLayout { - id: sectionRoot - property string title - default property alias data: sectionContent.data - - Layout.fillWidth: true - spacing: 8 - StyledText { - text: sectionRoot.title - font.pixelSize: Appearance.font.pixelSize.larger - } - ColumnLayout { - id: sectionContent - spacing: 5 - } - } - component ButtonWithIcon: RippleButton { id: buttonWithIconRoot property string nerdIcon @@ -296,264 +279,252 @@ ApplicationWindow { implicitWidth: contentColumn.implicitWidth Layout.fillWidth: true Layout.fillHeight: true - Flickable { - clip: true + + + ContentPage { + id: contentColumn anchors.fill: parent - contentHeight: contentColumn.implicitHeight - implicitWidth: contentColumn.implicitWidth - ColumnLayout { - id: contentColumn - anchors { - top: parent.top - bottom: parent.bottom - horizontalCenter: parent.horizontalCenter - margins: 10 - } - spacing: 20 + ContentSection { + title: "Style & wallpaper" - Section { - title: "Style & wallpaper" - - ButtonGroup { - Layout.fillWidth: true - LightDarkPrefButton { - dark: false - } - LightDarkPrefButton { - dark: true - } - } - - RowLayout { - Layout.alignment: Qt.AlignHCenter - ButtonWithIcon { - id: rndWallBtn - Layout.alignment: Qt.AlignHCenter - buttonRadius: Appearance.rounding.small - iconText: "wallpaper" - mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan" - onClicked: { - console.log(konachanWallProc.command.join(" ")) - konachanWallProc.running = true; - } - StyledToolTip { - content: "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers" - } - } - ButtonWithIcon { - iconText: "wallpaper" - StyledToolTip { - content: "Pick wallpaper image on your system" - } - onClicked: { - Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath}`) - } - mainContentComponent: Component { - RowLayout { - spacing: 10 - StyledText { - font.pixelSize: Appearance.font.pixelSize.small - text: "Choose file" - color: Appearance.colors.colOnSecondaryContainer - } - RowLayout { - spacing: 3 - KeyboardKey { - key: "Ctrl" - } - KeyboardKey { - key: "󰖳" - } - StyledText { - Layout.alignment: Qt.AlignVCenter - text: "+" - } - KeyboardKey { - key: "T" - } - } - } - } - } - } - - StyledText { - Layout.alignment: Qt.AlignHCenter - text: "Change any time later with /dark, /light, /img in the launcher" - font.pixelSize: Appearance.font.pixelSize.smaller - color: Appearance.colors.colSubtext - } - } - - Section { - title: "Policies" - - RowLayout { - Layout.alignment: Qt.AlignHCenter - spacing: 15 - ColumnLayout { // Weeb policy - StyledText { - text: "Weeb" - color: Appearance.colors.colSubtext - } - ButtonGroup { - id: weebPolicyBtnGroup - property int selectedPolicy: ConfigOptions.policies.weeb - spacing: 2 - SelectionGroupButton { - property int value: 0 - leftmost: true - buttonText: "No" - toggled: (weebPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.weeb", value); - } - } - SelectionGroupButton { - property int value: 1 - buttonText: "Yes" - toggled: (weebPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.weeb", value); - } - } - SelectionGroupButton { - property int value: 2 - rightmost: true - buttonText: "Closet" - toggled: (weebPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.weeb", value); - } - StyledToolTip { - content: "The Anime tab on the left sidebar would still\nbe available, but its tab button won't show" - } - } - } - } - ColumnLayout { // AI policy - StyledText { - text: "AI" - color: Appearance.colors.colSubtext - } - ButtonGroup { - id: aiPolicyBtnGroup - property int selectedPolicy: ConfigOptions.policies.ai - spacing: 2 - SelectionGroupButton { - property int value: 0 - leftmost: true - buttonText: "No" - toggled: (aiPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.ai", value); - } - } - SelectionGroupButton { - property int value: 1 - buttonText: "Yes" - toggled: (aiPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.ai", value); - } - } - SelectionGroupButton { - property int value: 2 - rightmost: true - buttonText: "Local only" - toggled: (aiPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.ai", value); - } - } - } - } - } - } - - Section { - title: "Info" - - Flow { - Layout.fillWidth: true - spacing: 10 - - ButtonWithIcon { - iconText: "keyboard_alt" - onClicked: { - Hyprland.dispatch("global quickshell:cheatsheetOpen") - } - mainContentComponent: Component { - RowLayout { - spacing: 10 - StyledText { - font.pixelSize: Appearance.font.pixelSize.small - text: "Keybinds" - color: Appearance.colors.colOnSecondaryContainer - } - RowLayout { - spacing: 3 - KeyboardKey { - key: "󰖳" - } - StyledText { - Layout.alignment: Qt.AlignVCenter - text: "+" - } - KeyboardKey { - key: "/" - } - } - } - } - } - - ButtonWithIcon { - iconText: "help" - mainText: "Usage" - onClicked: { - Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/02usage/") - } - } - ButtonWithIcon { - iconText: "construction" - mainText: "Configuration" - onClicked: { - Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/03config/") - } - } - } - } - - Section { - title: "Useless buttons" - - Flow { - Layout.fillWidth: true - spacing: 10 - - ButtonWithIcon { - nerdIcon: "󰊤" - mainText: "GitHub" - onClicked: { - Qt.openUrlExternally("https://github.com/end-4/dots-hyprland") - } - } - ButtonWithIcon { - iconText: "favorite" - mainText: "Funny number" - onClicked: { - Qt.openUrlExternally("https://github.com/sponsors/end-4") - } - } - } - } - - Item { + ButtonGroup { Layout.fillWidth: true - Layout.fillHeight: true + LightDarkPrefButton { + dark: false + } + LightDarkPrefButton { + dark: true + } } + RowLayout { + Layout.alignment: Qt.AlignHCenter + ButtonWithIcon { + id: rndWallBtn + Layout.alignment: Qt.AlignHCenter + buttonRadius: Appearance.rounding.small + iconText: "wallpaper" + mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan" + onClicked: { + console.log(konachanWallProc.command.join(" ")) + konachanWallProc.running = true; + } + StyledToolTip { + content: "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers" + } + } + ButtonWithIcon { + iconText: "wallpaper" + StyledToolTip { + content: "Pick wallpaper image on your system" + } + onClicked: { + Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath}`) + } + mainContentComponent: Component { + RowLayout { + spacing: 10 + StyledText { + font.pixelSize: Appearance.font.pixelSize.small + text: "Choose file" + color: Appearance.colors.colOnSecondaryContainer + } + RowLayout { + spacing: 3 + KeyboardKey { + key: "Ctrl" + } + KeyboardKey { + key: "󰖳" + } + StyledText { + Layout.alignment: Qt.AlignVCenter + text: "+" + } + KeyboardKey { + key: "T" + } + } + } + } + } + } + + StyledText { + Layout.alignment: Qt.AlignHCenter + text: "Change any time later with /dark, /light, /img in the launcher" + font.pixelSize: Appearance.font.pixelSize.smaller + color: Appearance.colors.colSubtext + } + } + + ContentSection { + title: "Policies" + + RowLayout { + Layout.alignment: Qt.AlignHCenter + spacing: 15 + ColumnLayout { // Weeb policy + StyledText { + text: "Weeb" + color: Appearance.colors.colSubtext + } + ButtonGroup { + id: weebPolicyBtnGroup + property int selectedPolicy: ConfigOptions.policies.weeb + spacing: 2 + SelectionGroupButton { + property int value: 0 + leftmost: true + buttonText: "No" + toggled: (weebPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.weeb", value); + } + } + SelectionGroupButton { + property int value: 1 + buttonText: "Yes" + toggled: (weebPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.weeb", value); + } + } + SelectionGroupButton { + property int value: 2 + rightmost: true + buttonText: "Closet" + toggled: (weebPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.weeb", value); + } + StyledToolTip { + content: "The Anime tab on the left sidebar would still\nbe available, but its tab button won't show" + } + } + } + } + ColumnLayout { // AI policy + StyledText { + text: "AI" + color: Appearance.colors.colSubtext + } + ButtonGroup { + id: aiPolicyBtnGroup + property int selectedPolicy: ConfigOptions.policies.ai + spacing: 2 + SelectionGroupButton { + property int value: 0 + leftmost: true + buttonText: "No" + toggled: (aiPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.ai", value); + } + } + SelectionGroupButton { + property int value: 1 + buttonText: "Yes" + toggled: (aiPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.ai", value); + } + } + SelectionGroupButton { + property int value: 2 + rightmost: true + buttonText: "Local only" + toggled: (aiPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.ai", value); + } + } + } + } + } + } + + ContentSection { + title: "Info" + + Flow { + Layout.fillWidth: true + spacing: 10 + + ButtonWithIcon { + iconText: "keyboard_alt" + onClicked: { + Hyprland.dispatch("global quickshell:cheatsheetOpen") + } + mainContentComponent: Component { + RowLayout { + spacing: 10 + StyledText { + font.pixelSize: Appearance.font.pixelSize.small + text: "Keybinds" + color: Appearance.colors.colOnSecondaryContainer + } + RowLayout { + spacing: 3 + KeyboardKey { + key: "󰖳" + } + StyledText { + Layout.alignment: Qt.AlignVCenter + text: "+" + } + KeyboardKey { + key: "/" + } + } + } + } + } + + ButtonWithIcon { + iconText: "help" + mainText: "Usage" + onClicked: { + Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/02usage/") + } + } + ButtonWithIcon { + iconText: "construction" + mainText: "Configuration" + onClicked: { + Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/03config/") + } + } + } + } + + ContentSection { + title: "Useless buttons" + + Flow { + Layout.fillWidth: true + spacing: 10 + + ButtonWithIcon { + nerdIcon: "󰊤" + mainText: "GitHub" + onClicked: { + Qt.openUrlExternally("https://github.com/end-4/dots-hyprland") + } + } + ButtonWithIcon { + iconText: "favorite" + mainText: "Funny number" + onClicked: { + Qt.openUrlExternally("https://github.com/sponsors/end-4") + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true } } } From bd79bc232be24f803d7c44764c4932c4c579dec6 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:56:22 +0200 Subject: [PATCH 010/328] fab: update color mappings --- .../modules/common/widgets/FloatingActionButton.qml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/FloatingActionButton.qml b/.config/quickshell/modules/common/widgets/FloatingActionButton.qml index 2f618437..bc6031e7 100644 --- a/.config/quickshell/modules/common/widgets/FloatingActionButton.qml +++ b/.config/quickshell/modules/common/widgets/FloatingActionButton.qml @@ -16,9 +16,9 @@ RippleButton { implicitWidth: Math.max(contentRowLayout.implicitWidth + 10 * 2, baseSize) implicitHeight: baseSize buttonRadius: Appearance.rounding.small - colBackground: Appearance.colors.colSecondaryContainer - colBackgroundHover: Appearance.colors.colSecondaryContainerHover - colRipple: Appearance.colors.colSecondaryContainerActive + colBackground: Appearance.colors.colPrimaryContainer + colBackgroundHover: Appearance.colors.colPrimaryContainerHover + colRipple: Appearance.colors.colPrimaryContainerActive contentItem: RowLayout { id: contentRowLayout property real horizontalMargins: (root.baseSize - icon.width) / 2 @@ -34,7 +34,7 @@ RippleButton { Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter iconSize: 24 - color: Appearance.colors.colOnLayer1 + color: Appearance.colors.colOnPrimaryContainer text: root.iconText } Loader { @@ -50,7 +50,7 @@ RippleButton { leftMargin: root.elementSpacing } text: root.buttonText - color: Appearance.colors.colOnLayer1 + color: Appearance.colors.colOnPrimaryContainer font.pixelSize: 14 font.weight: 450 } From 9f4c75a75cf08175d34d6cd78b25b1ee8a89f248 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:56:47 +0200 Subject: [PATCH 011/328] settings: pages --- .../common/widgets/NavigationRailButton.qml | 36 ++- .config/quickshell/modules/settings/About.qml | 13 ++ .../quickshell/modules/settings/General.qml | 13 ++ .../quickshell/modules/settings/Services.qml | 13 ++ .config/quickshell/modules/settings/Style.qml | 13 ++ .config/quickshell/settings.qml | 205 +++++++++++++----- 6 files changed, 225 insertions(+), 68 deletions(-) create mode 100644 .config/quickshell/modules/settings/About.qml create mode 100644 .config/quickshell/modules/settings/General.qml create mode 100644 .config/quickshell/modules/settings/Services.qml create mode 100644 .config/quickshell/modules/settings/Style.qml diff --git a/.config/quickshell/modules/common/widgets/NavigationRailButton.qml b/.config/quickshell/modules/common/widgets/NavigationRailButton.qml index 50074494..615cb35e 100644 --- a/.config/quickshell/modules/common/widgets/NavigationRailButton.qml +++ b/.config/quickshell/modules/common/widgets/NavigationRailButton.qml @@ -13,13 +13,19 @@ TabButton { property string buttonIcon property string buttonText property bool expanded: false + property bool showToggledHighlight: true + readonly property real visualWidth: root.expanded ? root.baseSize + 20 + itemText.implicitWidth : root.baseSize property real baseSize: 56 property real baseHighlightHeight: 32 + property real highlightCollapsedTopMargin: 8 padding: 0 + // The navigation item’s target area always spans the full width of the + // nav rail, even if the item container hugs its contents. + Layout.fillWidth: true + // implicitWidth: contentItem.implicitWidth implicitHeight: baseSize - implicitWidth: contentItem.implicitWidth background: null PointingHandInteraction {} @@ -28,23 +34,26 @@ TabButton { contentItem: Item { id: buttonContent anchors { + top: parent.top + bottom: parent.bottom left: parent.left - verticalCenter: parent.verticalCenter + right: undefined } - implicitWidth: root.expanded ? itemIconBackground.implicitWidth + 20 + itemText.implicitWidth : - itemIconBackground.implicitWidth + implicitWidth: root.visualWidth implicitHeight: root.expanded ? itemIconBackground.implicitHeight : itemIconBackground.implicitHeight + itemText.implicitHeight Rectangle { id: itemBackground anchors.top: itemIconBackground.top anchors.left: itemIconBackground.left - anchors.right: itemIconBackground.right anchors.bottom: itemIconBackground.bottom + implicitWidth: root.visualWidth radius: Appearance.rounding.full color: toggled ? - (root.down ? Appearance.colors.colSecondaryContainerActive : root.hovered ? Appearance.colors.colSecondaryContainerHover : Appearance.colors.colSecondaryContainer) : + root.showToggledHighlight ? + (root.down ? Appearance.colors.colSecondaryContainerActive : root.hovered ? Appearance.colors.colSecondaryContainerHover : Appearance.colors.colSecondaryContainer) + : ColorUtils.transparentize(Appearance.colors.colSecondaryContainer) : (root.down ? Appearance.colors.colLayer1Active : root.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1)) states: State { @@ -54,9 +63,12 @@ TabButton { target: itemBackground anchors.top: buttonContent.top anchors.left: buttonContent.left - anchors.right: buttonContent.right anchors.bottom: buttonContent.bottom } + PropertyChanges { + target: itemBackground + implicitWidth: root.visualWidth + } } transitions: Transition { AnchorAnimation { @@ -64,6 +76,13 @@ TabButton { easing.type: Appearance.animation.elementMoveFast.type easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve } + PropertyAnimation { + target: itemBackground + property: "implicitWidth" + duration: Appearance.animation.elementMove.duration + easing.type: Appearance.animation.elementMove.type + easing.bezierCurve: Appearance.animation.elementMove.bezierCurve + } } Behavior on color { @@ -84,6 +103,7 @@ TabButton { anchors.centerIn: parent iconSize: 24 fill: toggled ? 1 : 0 + font.weight: (toggled || root.hovered) ? Font.DemiBold : Font.Normal text: buttonIcon color: toggled ? Appearance.m3colors.m3onSecondaryContainer : Appearance.colors.colOnLayer1 @@ -97,7 +117,7 @@ TabButton { id: itemText anchors { top: itemIconBackground.bottom - topMargin: 6 + topMargin: 2 horizontalCenter: itemIconBackground.horizontalCenter } states: State { diff --git a/.config/quickshell/modules/settings/About.qml b/.config/quickshell/modules/settings/About.qml new file mode 100644 index 00000000..1d35b71b --- /dev/null +++ b/.config/quickshell/modules/settings/About.qml @@ -0,0 +1,13 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/services/" +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +ContentPage { + StyledText { + text: qsTr("About page") + font.pixelSize: Appearance.font.pixelSize.larger + } +} \ No newline at end of file diff --git a/.config/quickshell/modules/settings/General.qml b/.config/quickshell/modules/settings/General.qml new file mode 100644 index 00000000..f998ea00 --- /dev/null +++ b/.config/quickshell/modules/settings/General.qml @@ -0,0 +1,13 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/services/" +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +ContentPage { + StyledText { + text: qsTr("General page") + font.pixelSize: Appearance.font.pixelSize.larger + } +} \ No newline at end of file diff --git a/.config/quickshell/modules/settings/Services.qml b/.config/quickshell/modules/settings/Services.qml new file mode 100644 index 00000000..d7d8184f --- /dev/null +++ b/.config/quickshell/modules/settings/Services.qml @@ -0,0 +1,13 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/services/" +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +ContentPage { + StyledText { + text: qsTr("Services page") + font.pixelSize: Appearance.font.pixelSize.larger + } +} \ No newline at end of file diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml new file mode 100644 index 00000000..6b60c122 --- /dev/null +++ b/.config/quickshell/modules/settings/Style.qml @@ -0,0 +1,13 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/services/" +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +ContentPage { + StyledText { + text: qsTr("Style settings page") + font.pixelSize: Appearance.font.pixelSize.larger + } +} \ No newline at end of file diff --git a/.config/quickshell/settings.qml b/.config/quickshell/settings.qml index fd319344..58d853f3 100644 --- a/.config/quickshell/settings.qml +++ b/.config/quickshell/settings.qml @@ -26,7 +26,30 @@ ApplicationWindow { property string firstRunFileContent: "This file is just here to confirm you've been greeted :>" property real contentPadding: 8 property bool showNextTime: false + property var pages: [ + { + name: "General", + icon: "tune", + component: "modules/settings/General.qml" + }, + { + name: "Style", + icon: "palette", + component: "modules/settings/Style.qml" + }, + { + name: "Services", + icon: "settings", + component: "modules/settings/Services.qml" + }, + { + name: "About", + icon: "info", + component: "modules/settings/About.qml" + } + ] property int currentPage: 0 + visible: true onClosing: Qt.quit() title: "illogical-impulse Settings" @@ -42,23 +65,6 @@ ApplicationWindow { height: 650 color: Appearance.m3colors.m3background - component Section: ColumnLayout { - id: sectionRoot - property string title - default property alias data: sectionContent.data - - Layout.fillWidth: true - spacing: 8 - StyledText { - text: sectionRoot.title - font.pixelSize: Appearance.font.pixelSize.larger - } - ColumnLayout { - id: sectionContent - spacing: 5 - } - } - ColumnLayout { anchors { fill: parent @@ -101,54 +107,90 @@ ApplicationWindow { Layout.fillWidth: true Layout.fillHeight: true spacing: contentPadding - NavigationRail { // Window content with navigation rail and content pane - id: navRail + Item { + id: navRailWrapper Layout.fillHeight: true Layout.margins: 5 - spacing: 10 - expanded: root.width > 900 - - NavigationRailExpandButton {} - - FloatingActionButton { - id: fab - iconText: "edit" - buttonText: "Edit config" - expanded: navRail.expanded - onClicked: { - Qt.openUrlExternally(`${Directories.config}/illogical-impulse/config.json`); - } + implicitWidth: navRail.expanded ? 150 : fab.baseSize + Behavior on implicitWidth { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - - ColumnLayout { - Layout.topMargin: 25 - spacing: 4 - - NavigationRailButton { - toggled: root.currentPage === 0 - onClicked: root.currentPage = 0; - expanded: navRail.expanded - buttonIcon: "tune" - buttonText: "General" + NavigationRail { // Window content with navigation rail and content pane + id: navRail + anchors { + left: parent.left + top: parent.top + bottom: parent.bottom } - NavigationRailButton { - toggled: root.currentPage === 1 - onClicked: root.currentPage = 1; - expanded: navRail.expanded - buttonIcon: "dashboard" - buttonText: "Widgets" - } - NavigationRailButton { - toggled: root.currentPage === 2 - onClicked: root.currentPage = 2; - expanded: navRail.expanded - buttonIcon: "settings" - buttonText: "Services" - } - } + spacing: 10 + expanded: root.width > 900 + + NavigationRailExpandButton {} - Item { - Layout.fillHeight: true + FloatingActionButton { + id: fab + iconText: "edit" + buttonText: "Edit config" + expanded: navRail.expanded + onClicked: { + Qt.openUrlExternally(`${Directories.config}/illogical-impulse/config.json`); + } + + StyledToolTip { + extraVisibleCondition: !navRail.expanded + content: "Edit shell config file" + } + } + + Item { + implicitHeight: tabBarColumn.implicitHeight + implicitWidth: tabBarColumn.implicitWidth + Layout.topMargin: 25 + Rectangle { + property real itemHeight: tabBarColumn.children[0].baseSize + property real baseHighlightHeight: tabBarColumn.children[0].baseHighlightHeight + anchors { + top: tabBarColumn.top + left: tabBarColumn.left + topMargin: itemHeight * root.currentPage + (navRail.expanded ? 0 : ((itemHeight - baseHighlightHeight) / 2)) + } + radius: Appearance.rounding.full + color: Appearance.colors.colSecondaryContainer + implicitHeight: navRail.expanded ? itemHeight : baseHighlightHeight + implicitWidth: tabBarColumn.children[root.currentPage].visualWidth + + Behavior on anchors.topMargin { + NumberAnimation { + duration: Appearance.animationCurves.expressiveFastSpatialDuration + easing.type: Appearance.animation.elementMove.type + easing.bezierCurve: Appearance.animationCurves.expressiveFastSpatial + } + } + } + ColumnLayout { + id: tabBarColumn + anchors.fill: parent + spacing: 0 + + Repeater { + model: root.pages + NavigationRailButton { + required property var index + required property var modelData + toggled: root.currentPage === index + onClicked: root.currentPage = index; + expanded: navRail.expanded + buttonIcon: modelData.icon + buttonText: modelData.name + showToggledHighlight: false + } + } + } + } + + Item { + Layout.fillHeight: true + } } } Rectangle { // Content container @@ -156,6 +198,49 @@ ApplicationWindow { Layout.fillHeight: true color: Appearance.m3colors.m3surfaceContainerLow radius: Appearance.rounding.windowRounding - root.contentPadding + + Loader { + id: pageLoader + anchors.fill: parent + opacity: 1.0 + source: root.pages[0].component + Connections { + target: root + function onCurrentPageChanged() { + if (pageLoader.sourceComponent !== root.pages[root.currentPage].component) { + switchAnim.restart(); + } + } + } + + SequentialAnimation { + id: switchAnim + + NumberAnimation { + target: pageLoader + properties: "opacity" + from: 1 + to: 0 + duration: 200 + easing.type: Appearance.animation.elementMoveExit.type + easing.bezierCurve: Appearance.animation.elementMoveExit.bezierCurve + } + PropertyAction { + target: pageLoader + property: "source" + value: root.pages[root.currentPage].component + } + NumberAnimation { + target: pageLoader + properties: "opacity" + from: 0 + to: 1 + duration: 200 + easing.type: Appearance.animation.elementMoveEnter.type + easing.bezierCurve: Appearance.animation.elementMoveEnter.bezierCurve + } + } + } } } } From 3f294416eaeae6026d27bfdaa1aa392922651366 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 00:36:37 +0200 Subject: [PATCH 012/328] refractor navrail tab array --- .../common/widgets/NavigationRailTabArray.qml | 44 +++++++++++++++ .config/quickshell/settings.qml | 56 +++++-------------- 2 files changed, 58 insertions(+), 42 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/NavigationRailTabArray.qml diff --git a/.config/quickshell/modules/common/widgets/NavigationRailTabArray.qml b/.config/quickshell/modules/common/widgets/NavigationRailTabArray.qml new file mode 100644 index 00000000..e13ea76c --- /dev/null +++ b/.config/quickshell/modules/common/widgets/NavigationRailTabArray.qml @@ -0,0 +1,44 @@ +import "root:/modules/common" +import "root:/modules/common/widgets" +import "root:/modules/common/functions/color_utils.js" as ColorUtils +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell.Io + +Item { + id: root + property int currentIndex: 0 + property bool expanded: false + default property alias data: tabBarColumn.data + implicitHeight: tabBarColumn.implicitHeight + implicitWidth: tabBarColumn.implicitWidth + Layout.topMargin: 25 + Rectangle { + property real itemHeight: tabBarColumn.children[0].baseSize + property real baseHighlightHeight: tabBarColumn.children[0].baseHighlightHeight + anchors { + top: tabBarColumn.top + left: tabBarColumn.left + topMargin: itemHeight * root.currentIndex + (root.expanded ? 0 : ((itemHeight - baseHighlightHeight) / 2)) + } + radius: Appearance.rounding.full + color: Appearance.colors.colSecondaryContainer + implicitHeight: root.expanded ? itemHeight : baseHighlightHeight + implicitWidth: tabBarColumn.children[root.currentIndex].visualWidth + + Behavior on anchors.topMargin { + NumberAnimation { + duration: Appearance.animationCurves.expressiveFastSpatialDuration + easing.type: Appearance.animation.elementMove.type + easing.bezierCurve: Appearance.animationCurves.expressiveFastSpatial + } + } + } + ColumnLayout { + id: tabBarColumn + anchors.fill: parent + spacing: 0 + + } +} diff --git a/.config/quickshell/settings.qml b/.config/quickshell/settings.qml index 58d853f3..2ac80306 100644 --- a/.config/quickshell/settings.qml +++ b/.config/quickshell/settings.qml @@ -142,48 +142,20 @@ ApplicationWindow { } } - Item { - implicitHeight: tabBarColumn.implicitHeight - implicitWidth: tabBarColumn.implicitWidth - Layout.topMargin: 25 - Rectangle { - property real itemHeight: tabBarColumn.children[0].baseSize - property real baseHighlightHeight: tabBarColumn.children[0].baseHighlightHeight - anchors { - top: tabBarColumn.top - left: tabBarColumn.left - topMargin: itemHeight * root.currentPage + (navRail.expanded ? 0 : ((itemHeight - baseHighlightHeight) / 2)) - } - radius: Appearance.rounding.full - color: Appearance.colors.colSecondaryContainer - implicitHeight: navRail.expanded ? itemHeight : baseHighlightHeight - implicitWidth: tabBarColumn.children[root.currentPage].visualWidth - - Behavior on anchors.topMargin { - NumberAnimation { - duration: Appearance.animationCurves.expressiveFastSpatialDuration - easing.type: Appearance.animation.elementMove.type - easing.bezierCurve: Appearance.animationCurves.expressiveFastSpatial - } - } - } - ColumnLayout { - id: tabBarColumn - anchors.fill: parent - spacing: 0 - - Repeater { - model: root.pages - NavigationRailButton { - required property var index - required property var modelData - toggled: root.currentPage === index - onClicked: root.currentPage = index; - expanded: navRail.expanded - buttonIcon: modelData.icon - buttonText: modelData.name - showToggledHighlight: false - } + NavigationRailTabArray { + currentIndex: root.currentPage + expanded: navRail.expanded + Repeater { + model: root.pages + NavigationRailButton { + required property var index + required property var modelData + toggled: root.currentPage === index + onClicked: root.currentPage = index; + expanded: navRail.expanded + buttonIcon: modelData.icon + buttonText: modelData.name + showToggledHighlight: false } } } From aefeeb8f6f54c0fc22862c378ae94b3ddfe7451b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 00:36:46 +0200 Subject: [PATCH 013/328] adjust anim curves --- .config/quickshell/modules/common/Appearance.qml | 2 ++ .config/quickshell/settings.qml | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index c2a20fdf..a4fadc31 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -188,6 +188,8 @@ Singleton { readonly property list expressiveSlowSpatial: [0.39, 1.29, 0.35, 0.98, 1, 1] // Default, 650ms readonly property list expressiveEffects: [0.34, 0.80, 0.34, 1.00, 1, 1] // Default, 200ms readonly property list emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1] + readonly property list emphasizedFirstHalf: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82] + readonly property list emphasizedLastHalf: [5 / 24, 0.82, 0.25, 1, 1, 1] readonly property list emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1] readonly property list emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1] readonly property list standard: [0.2, 0, 0, 1, 1, 1] diff --git a/.config/quickshell/settings.qml b/.config/quickshell/settings.qml index 2ac80306..e5cf1c31 100644 --- a/.config/quickshell/settings.qml +++ b/.config/quickshell/settings.qml @@ -193,9 +193,9 @@ ApplicationWindow { properties: "opacity" from: 1 to: 0 - duration: 200 + duration: 150 easing.type: Appearance.animation.elementMoveExit.type - easing.bezierCurve: Appearance.animation.elementMoveExit.bezierCurve + easing.bezierCurve: Appearance.animationCurves.emphasizedFirstHalf } PropertyAction { target: pageLoader @@ -207,9 +207,9 @@ ApplicationWindow { properties: "opacity" from: 0 to: 1 - duration: 200 + duration: 250 easing.type: Appearance.animation.elementMoveEnter.type - easing.bezierCurve: Appearance.animation.elementMoveEnter.bezierCurve + easing.bezierCurve: Appearance.animationCurves.emphasizedLastHalf } } } From 7fba4b72bf250da63e39e116ac8b5b5bfd6342f3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 00:37:30 +0200 Subject: [PATCH 014/328] content page: add min width --- .config/quickshell/modules/common/widgets/ContentPage.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/widgets/ContentPage.qml b/.config/quickshell/modules/common/widgets/ContentPage.qml index 9219ef67..5862417e 100644 --- a/.config/quickshell/modules/common/widgets/ContentPage.qml +++ b/.config/quickshell/modules/common/widgets/ContentPage.qml @@ -6,10 +6,12 @@ import "root:/modules/common/widgets/" Flickable { id: root + property real baseWidth: 400 default property alias data: contentColumn.data + clip: true contentHeight: contentColumn.implicitHeight - implicitWidth: contentColumn.implicitWidth + implicitWidth: Math.max(contentColumn.implicitWidth, baseWidth) ColumnLayout { id: contentColumn anchors { From 66bd690b6655b093245d8cb85d8d87bd45828792 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 00:37:53 +0200 Subject: [PATCH 015/328] sidebar: calendar: animated navrail selection --- .../quickshell/modules/sidebarRight/BottomWidgetGroup.qml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml index 874e23c8..d36d6eb8 100644 --- a/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml +++ b/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml @@ -130,15 +130,17 @@ Rectangle { Layout.topMargin: 10 width: tabBar.width // Navigation rail buttons - ColumnLayout { + NavigationRailTabArray { + id: tabBar anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left anchors.leftMargin: 5 - id: tabBar - spacing: 8 + currentIndex: root.selectedTab + expanded: false Repeater { model: root.tabs NavigationRailButton { + showToggledHighlight: false toggled: root.selectedTab == index buttonText: modelData.name buttonIcon: modelData.icon From e7897cef8b6057c79bcd84c6f455031603991620 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 08:08:34 +0200 Subject: [PATCH 016/328] more media controls filter trick (#1443) --- .config/quickshell/modules/mediaControls/MediaControls.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/mediaControls/MediaControls.qml b/.config/quickshell/modules/mediaControls/MediaControls.qml index 4350658f..3871c638 100644 --- a/.config/quickshell/modules/mediaControls/MediaControls.qml +++ b/.config/quickshell/modules/mediaControls/MediaControls.qml @@ -54,7 +54,9 @@ Scope { for (let j = i + 1; j < players.length; ++j) { let p2 = players[j]; if (p1.trackTitle && p2.trackTitle && - (p1.trackTitle.includes(p2.trackTitle) || p2.trackTitle.includes(p1.trackTitle))) { + (p1.trackTitle.includes(p2.trackTitle) + || p2.trackTitle.includes(p1.trackTitle)) + || p1.position - p2.position <= 2) { group.push(j); } } From 07b6e8efbddd4bdda537f8ea2637a7ccbd235294 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 08:11:01 +0200 Subject: [PATCH 017/328] even better dupe media player filtering --- .config/quickshell/modules/mediaControls/MediaControls.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/mediaControls/MediaControls.qml b/.config/quickshell/modules/mediaControls/MediaControls.qml index 3871c638..00a4185c 100644 --- a/.config/quickshell/modules/mediaControls/MediaControls.qml +++ b/.config/quickshell/modules/mediaControls/MediaControls.qml @@ -56,7 +56,7 @@ Scope { if (p1.trackTitle && p2.trackTitle && (p1.trackTitle.includes(p2.trackTitle) || p2.trackTitle.includes(p1.trackTitle)) - || p1.position - p2.position <= 2) { + || (p1.position - p2.position <= 2 && p1.length - p2.length <= 2)) { group.push(j); } } From 6abefecedff6c8017acad2b293b4aa38192902a7 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 08:13:08 +0200 Subject: [PATCH 018/328] refractor button with icon and lightdark pref button to new file --- .../widgets/LightDarkPreferenceButton.qml | 124 ++++++++++++ .../common/widgets/RippleButtonWithIcon.qml | 55 ++++++ .config/quickshell/welcome.qml | 183 +----------------- 3 files changed, 188 insertions(+), 174 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/LightDarkPreferenceButton.qml create mode 100644 .config/quickshell/modules/common/widgets/RippleButtonWithIcon.qml diff --git a/.config/quickshell/modules/common/widgets/LightDarkPreferenceButton.qml b/.config/quickshell/modules/common/widgets/LightDarkPreferenceButton.qml new file mode 100644 index 00000000..e1900c9f --- /dev/null +++ b/.config/quickshell/modules/common/widgets/LightDarkPreferenceButton.qml @@ -0,0 +1,124 @@ +import "root:/modules/common" +import "root:/modules/common/widgets" +import "root:/modules/common/functions/color_utils.js" as ColorUtils +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell.Io +import Quickshell.Io +import Quickshell.Hyprland + +GroupButton { + id: lightDarkButtonRoot + required property bool dark + property color previewBg: dark ? ColorUtils.colorWithHueOf("#3f3838", Appearance.m3colors.m3primary) : + ColorUtils.colorWithHueOf("#F7F9FF", Appearance.m3colors.m3primary) + property color previewFg: dark ? Qt.lighter(previewBg, 2.2) : ColorUtils.mix(previewBg, "#292929", 0.85) + padding: 5 + Layout.fillWidth: true + colBackground: Appearance.colors.colLayer2 + toggled: Appearance.m3colors.darkmode === dark + onClicked: { + Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode ${dark ? "dark" : "light"} --noswitch`) + } + contentItem: Item { + anchors.centerIn: parent + implicitWidth: buttonContentLayout.implicitWidth + implicitHeight: buttonContentLayout.implicitHeight + ColumnLayout { + id: buttonContentLayout + anchors.centerIn: parent + Rectangle { + Layout.alignment: Qt.AlignHCenter + implicitWidth: 250 + implicitHeight: skeletonColumnLayout.implicitHeight + 10 * 2 + radius: lightDarkButtonRoot.buttonRadius - lightDarkButtonRoot.padding + color: lightDarkButtonRoot.previewBg + border { + width: 1 + color: Appearance.m3colors.m3outlineVariant + } + + // Some skeleton items + ColumnLayout { + id: skeletonColumnLayout + anchors.fill: parent + anchors.margins: 10 + spacing: 10 + RowLayout { + Rectangle { + radius: Appearance.rounding.full + color: lightDarkButtonRoot.previewFg + implicitWidth: 50 + implicitHeight: 50 + } + ColumnLayout { + spacing: 4 + Rectangle { + radius: Appearance.rounding.unsharpenmore + color: lightDarkButtonRoot.previewFg + Layout.fillWidth: true + implicitHeight: 22 + } + Rectangle { + radius: Appearance.rounding.unsharpenmore + color: lightDarkButtonRoot.previewFg + Layout.fillWidth: true + Layout.rightMargin: 45 + implicitHeight: 18 + } + } + } + StyledProgressBar { + Layout.topMargin: 5 + Layout.bottomMargin: 5 + Layout.fillWidth: true + value: 0.7 + sperm: true + animateSperm: lightDarkButtonRoot.toggled + highlightColor: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3primary : lightDarkButtonRoot.previewFg + trackColor: ColorUtils.mix(lightDarkButtonRoot.previewBg, lightDarkButtonRoot.previewFg, 0.5) + } + RowLayout { + spacing: 2 + Rectangle { + radius: Appearance.rounding.full + color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3primary : lightDarkButtonRoot.previewFg + Layout.fillWidth: true + implicitHeight: 30 + MaterialSymbol { + visible: lightDarkButtonRoot.toggled + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + text: "check" + iconSize: 20 + color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3onPrimary : lightDarkButtonRoot.previewBg + } + } + Rectangle { + radius: Appearance.rounding.unsharpenmore + color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3secondaryContainer : lightDarkButtonRoot.previewFg + Layout.fillWidth: true + implicitHeight: 30 + } + Rectangle { + topLeftRadius: Appearance.rounding.unsharpenmore + bottomLeftRadius: Appearance.rounding.unsharpenmore + topRightRadius: Appearance.rounding.full + bottomRightRadius: Appearance.rounding.full + color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3secondaryContainer : lightDarkButtonRoot.previewFg + Layout.fillWidth: true + implicitHeight: 30 + } + } + } + } + StyledText { + Layout.fillWidth: true + text: dark ? "Dark" : "Light" + color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer2 + horizontalAlignment: Text.AlignHCenter + } + } + } +} diff --git a/.config/quickshell/modules/common/widgets/RippleButtonWithIcon.qml b/.config/quickshell/modules/common/widgets/RippleButtonWithIcon.qml new file mode 100644 index 00000000..60d75cd6 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/RippleButtonWithIcon.qml @@ -0,0 +1,55 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +RippleButton { + id: buttonWithIconRoot + property string nerdIcon + property string iconText + property string mainText: "Button text" + property Component mainContentComponent: Component { + StyledText { + text: buttonWithIconRoot.mainText + font.pixelSize: Appearance.font.pixelSize.small + color: Appearance.colors.colOnSecondaryContainer + } + } + implicitHeight: 35 + horizontalPadding: 15 + buttonRadius: Appearance.rounding.small + colBackground: Appearance.colors.colLayer2 + + contentItem: RowLayout { + Item { + implicitWidth: Math.max(materialIconLoader.implicitWidth, nerdIconLoader.implicitWidth) + Loader { + id: materialIconLoader + anchors.centerIn: parent + active: !nerdIcon + sourceComponent: MaterialSymbol { + text: buttonWithIconRoot.iconText + iconSize: Appearance.font.pixelSize.larger + color: Appearance.colors.colOnSecondaryContainer + fill: 1 + } + } + Loader { + id: nerdIconLoader + anchors.centerIn: parent + active: nerdIcon + sourceComponent: StyledText { + text: buttonWithIconRoot.nerdIcon + font.pixelSize: Appearance.font.pixelSize.larger + font.family: Appearance.font.family.iconNerd + color: Appearance.colors.colOnSecondaryContainer + } + } + } + Loader { + sourceComponent: buttonWithIconRoot.mainContentComponent + Layout.alignment: Qt.AlignVCenter + } + } +} diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index c7b8c409..65f62089 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -53,171 +53,6 @@ ApplicationWindow { } } - component ButtonWithIcon: RippleButton { - id: buttonWithIconRoot - property string nerdIcon - property string iconText - property string mainText: "Button text" - property Component mainContentComponent: Component { - StyledText { - text: buttonWithIconRoot.mainText - font.pixelSize: Appearance.font.pixelSize.small - color: Appearance.colors.colOnSecondaryContainer - } - } - implicitHeight: 35 - horizontalPadding: 15 - buttonRadius: Appearance.rounding.small - colBackground: Appearance.colors.colLayer2 - - contentItem: RowLayout { - Item { - implicitWidth: Math.max(materialIconLoader.implicitWidth, nerdIconLoader.implicitWidth) - Loader { - id: materialIconLoader - anchors.centerIn: parent - active: !nerdIcon - sourceComponent: MaterialSymbol { - text: buttonWithIconRoot.iconText - iconSize: Appearance.font.pixelSize.larger - color: Appearance.colors.colOnSecondaryContainer - fill: 1 - } - } - Loader { - id: nerdIconLoader - anchors.centerIn: parent - active: nerdIcon - sourceComponent: StyledText { - text: buttonWithIconRoot.nerdIcon - font.pixelSize: Appearance.font.pixelSize.larger - font.family: Appearance.font.family.iconNerd - color: Appearance.colors.colOnSecondaryContainer - } - } - } - Loader { - sourceComponent: buttonWithIconRoot.mainContentComponent - Layout.alignment: Qt.AlignVCenter - } - } - } - - component LightDarkPrefButton: GroupButton { - id: lightDarkButtonRoot - required property bool dark - property color previewBg: dark ? ColorUtils.colorWithHueOf("#3f3838", Appearance.m3colors.m3primary) : - ColorUtils.colorWithHueOf("#F7F9FF", Appearance.m3colors.m3primary) - property color previewFg: dark ? Qt.lighter(previewBg, 2.2) : ColorUtils.mix(previewBg, "#292929", 0.85) - padding: 5 - Layout.fillWidth: true - colBackground: Appearance.colors.colLayer2 - toggled: Appearance.m3colors.darkmode === dark - onClicked: { - Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode ${dark ? "dark" : "light"} --noswitch`) - } - contentItem: Item { - anchors.centerIn: parent - implicitWidth: buttonContentLayout.implicitWidth - implicitHeight: buttonContentLayout.implicitHeight - ColumnLayout { - id: buttonContentLayout - anchors.centerIn: parent - Rectangle { - Layout.alignment: Qt.AlignHCenter - implicitWidth: 250 - implicitHeight: skeletonColumnLayout.implicitHeight + 10 * 2 - radius: lightDarkButtonRoot.buttonRadius - lightDarkButtonRoot.padding - color: lightDarkButtonRoot.previewBg - border { - width: 1 - color: Appearance.m3colors.m3outlineVariant - } - - // Some skeleton items - ColumnLayout { - id: skeletonColumnLayout - anchors.fill: parent - anchors.margins: 10 - spacing: 10 - RowLayout { - Rectangle { - radius: Appearance.rounding.full - color: lightDarkButtonRoot.previewFg - implicitWidth: 50 - implicitHeight: 50 - } - ColumnLayout { - spacing: 4 - Rectangle { - radius: Appearance.rounding.unsharpenmore - color: lightDarkButtonRoot.previewFg - Layout.fillWidth: true - implicitHeight: 22 - } - Rectangle { - radius: Appearance.rounding.unsharpenmore - color: lightDarkButtonRoot.previewFg - Layout.fillWidth: true - Layout.rightMargin: 45 - implicitHeight: 18 - } - } - } - StyledProgressBar { - Layout.topMargin: 5 - Layout.bottomMargin: 5 - Layout.fillWidth: true - value: 0.7 - sperm: true - animateSperm: lightDarkButtonRoot.toggled - highlightColor: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3primary : lightDarkButtonRoot.previewFg - trackColor: ColorUtils.mix(lightDarkButtonRoot.previewBg, lightDarkButtonRoot.previewFg, 0.5) - } - RowLayout { - spacing: 2 - Rectangle { - radius: Appearance.rounding.full - color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3primary : lightDarkButtonRoot.previewFg - Layout.fillWidth: true - implicitHeight: 30 - MaterialSymbol { - visible: lightDarkButtonRoot.toggled - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - text: "check" - iconSize: 20 - color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3onPrimary : lightDarkButtonRoot.previewBg - } - } - Rectangle { - radius: Appearance.rounding.unsharpenmore - color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3secondaryContainer : lightDarkButtonRoot.previewFg - Layout.fillWidth: true - implicitHeight: 30 - } - Rectangle { - topLeftRadius: Appearance.rounding.unsharpenmore - bottomLeftRadius: Appearance.rounding.unsharpenmore - topRightRadius: Appearance.rounding.full - bottomRightRadius: Appearance.rounding.full - color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3secondaryContainer : lightDarkButtonRoot.previewFg - Layout.fillWidth: true - implicitHeight: 30 - } - } - } - } - StyledText { - Layout.fillWidth: true - text: dark ? "Dark" : "Light" - color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer2 - horizontalAlignment: Text.AlignHCenter - } - } - } - } - ColumnLayout { anchors { fill: parent @@ -289,17 +124,17 @@ ApplicationWindow { ButtonGroup { Layout.fillWidth: true - LightDarkPrefButton { + LightDarkPreferenceButton { dark: false } - LightDarkPrefButton { + LightDarkPreferenceButton { dark: true } } RowLayout { Layout.alignment: Qt.AlignHCenter - ButtonWithIcon { + RippleButtonWithIcon { id: rndWallBtn Layout.alignment: Qt.AlignHCenter buttonRadius: Appearance.rounding.small @@ -313,7 +148,7 @@ ApplicationWindow { content: "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers" } } - ButtonWithIcon { + RippleButtonWithIcon { iconText: "wallpaper" StyledToolTip { content: "Pick wallpaper image on your system" @@ -451,7 +286,7 @@ ApplicationWindow { Layout.fillWidth: true spacing: 10 - ButtonWithIcon { + RippleButtonWithIcon { iconText: "keyboard_alt" onClicked: { Hyprland.dispatch("global quickshell:cheatsheetOpen") @@ -481,14 +316,14 @@ ApplicationWindow { } } - ButtonWithIcon { + RippleButtonWithIcon { iconText: "help" mainText: "Usage" onClicked: { Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/02usage/") } } - ButtonWithIcon { + RippleButtonWithIcon { iconText: "construction" mainText: "Configuration" onClicked: { @@ -505,14 +340,14 @@ ApplicationWindow { Layout.fillWidth: true spacing: 10 - ButtonWithIcon { + RippleButtonWithIcon { nerdIcon: "󰊤" mainText: "GitHub" onClicked: { Qt.openUrlExternally("https://github.com/end-4/dots-hyprland") } } - ButtonWithIcon { + RippleButtonWithIcon { iconText: "favorite" mainText: "Funny number" onClicked: { From 1814f7cbec0b463330309ed895d4caab3dbf0f85 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 08:13:15 +0200 Subject: [PATCH 019/328] update settings pages --- .../quickshell/modules/settings/General.qml | 87 ++++++++++++++++- .config/quickshell/modules/settings/Style.qml | 93 ++++++++++++++++++- 2 files changed, 174 insertions(+), 6 deletions(-) diff --git a/.config/quickshell/modules/settings/General.qml b/.config/quickshell/modules/settings/General.qml index f998ea00..dd3323ac 100644 --- a/.config/quickshell/modules/settings/General.qml +++ b/.config/quickshell/modules/settings/General.qml @@ -6,8 +6,89 @@ import "root:/modules/common/" import "root:/modules/common/widgets/" ContentPage { - StyledText { - text: qsTr("General page") - font.pixelSize: Appearance.font.pixelSize.larger + ContentSection { + title: "Policies" + + RowLayout { + Layout.alignment: Qt.AlignHCenter + spacing: 15 + ColumnLayout { // Weeb policy + StyledText { + text: "Weeb" + color: Appearance.colors.colSubtext + } + ButtonGroup { + id: weebPolicyBtnGroup + property int selectedPolicy: ConfigOptions.policies.weeb + spacing: 2 + SelectionGroupButton { + property int value: 0 + leftmost: true + buttonText: "No" + toggled: (weebPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.weeb", value); + } + } + SelectionGroupButton { + property int value: 1 + buttonText: "Yes" + toggled: (weebPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.weeb", value); + } + } + SelectionGroupButton { + property int value: 2 + rightmost: true + buttonText: "Closet" + toggled: (weebPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.weeb", value); + } + StyledToolTip { + content: "The Anime tab on the left sidebar would still\nbe available, but its tab button won't show" + } + } + } + } + ColumnLayout { // AI policy + StyledText { + text: "AI" + color: Appearance.colors.colSubtext + } + ButtonGroup { + id: aiPolicyBtnGroup + property int selectedPolicy: ConfigOptions.policies.ai + spacing: 2 + SelectionGroupButton { + property int value: 0 + leftmost: true + buttonText: "No" + toggled: (aiPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.ai", value); + } + } + SelectionGroupButton { + property int value: 1 + buttonText: "Yes" + toggled: (aiPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.ai", value); + } + } + SelectionGroupButton { + property int value: 2 + rightmost: true + buttonText: "Local only" + toggled: (aiPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.ai", value); + } + } + } + } + } } } \ No newline at end of file diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml index 6b60c122..3b9071ca 100644 --- a/.config/quickshell/modules/settings/Style.qml +++ b/.config/quickshell/modules/settings/Style.qml @@ -1,13 +1,100 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Hyprland import "root:/services/" import "root:/modules/common/" import "root:/modules/common/widgets/" +import "root:/modules/common/functions/color_utils.js" as ColorUtils +import "root:/modules/common/functions/file_utils.js" as FileUtils ContentPage { - StyledText { - text: qsTr("Style settings page") - font.pixelSize: Appearance.font.pixelSize.larger + + Process { + id: konachanWallProc + property string status: "" + command: ["bash", "-c", FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/random_konachan_wall.sh`)] + stdout: SplitParser { + onRead: data => { + console.log(`Konachan wall proc output: ${data}`); + konachanWallProc.status = data.trim(); + } + } + } + + ContentSection { + title: "Colors & Wallpaper" + + ButtonGroup { + Layout.fillWidth: true + LightDarkPreferenceButton { + dark: false + } + LightDarkPreferenceButton { + dark: true + } + } + + RowLayout { + Layout.alignment: Qt.AlignHCenter + RippleButtonWithIcon { + id: rndWallBtn + Layout.alignment: Qt.AlignHCenter + buttonRadius: Appearance.rounding.small + iconText: "wallpaper" + mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan" + onClicked: { + console.log(konachanWallProc.command.join(" ")) + konachanWallProc.running = true; + } + StyledToolTip { + content: "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers" + } + } + RippleButtonWithIcon { + iconText: "wallpaper" + StyledToolTip { + content: "Pick wallpaper image on your system" + } + onClicked: { + Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath}`) + } + mainContentComponent: Component { + RowLayout { + spacing: 10 + StyledText { + font.pixelSize: Appearance.font.pixelSize.small + text: "Choose file" + color: Appearance.colors.colOnSecondaryContainer + } + RowLayout { + spacing: 3 + KeyboardKey { + key: "Ctrl" + } + KeyboardKey { + key: "󰖳" + } + StyledText { + Layout.alignment: Qt.AlignVCenter + text: "+" + } + KeyboardKey { + key: "T" + } + } + } + } + } + } + + StyledText { + Layout.alignment: Qt.AlignHCenter + text: "Change any time later with /dark, /light, /img in the launcher" + font.pixelSize: Appearance.font.pixelSize.smaller + color: Appearance.colors.colSubtext + } } } \ No newline at end of file From f5ea891dd70f1d7853f477211bb0c9cd0890998f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 08:19:33 +0200 Subject: [PATCH 020/328] settings: add fake screen rounding option --- .../{General.qml => BehaviorConfig.qml} | 0 .../quickshell/modules/settings/Services.qml | 13 ------ .config/quickshell/modules/settings/Style.qml | 43 +++++++++++++++++++ .config/quickshell/settings.qml | 9 +--- 4 files changed, 45 insertions(+), 20 deletions(-) rename .config/quickshell/modules/settings/{General.qml => BehaviorConfig.qml} (100%) delete mode 100644 .config/quickshell/modules/settings/Services.qml diff --git a/.config/quickshell/modules/settings/General.qml b/.config/quickshell/modules/settings/BehaviorConfig.qml similarity index 100% rename from .config/quickshell/modules/settings/General.qml rename to .config/quickshell/modules/settings/BehaviorConfig.qml diff --git a/.config/quickshell/modules/settings/Services.qml b/.config/quickshell/modules/settings/Services.qml deleted file mode 100644 index d7d8184f..00000000 --- a/.config/quickshell/modules/settings/Services.qml +++ /dev/null @@ -1,13 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import "root:/services/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" - -ContentPage { - StyledText { - text: qsTr("Services page") - font.pixelSize: Appearance.font.pixelSize.larger - } -} \ No newline at end of file diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml index 3b9071ca..8041f15c 100644 --- a/.config/quickshell/modules/settings/Style.qml +++ b/.config/quickshell/modules/settings/Style.qml @@ -96,5 +96,48 @@ ContentPage { font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.colors.colSubtext } + + } + + ContentSection { + title: "Shell style" + + ColumnLayout { // Fake screen rounding + StyledText { + text: "Fake screen rounding" + color: Appearance.colors.colSubtext + } + ButtonGroup { + id: fakeScreenRoundingButtonGroup + property int selectedPolicy: ConfigOptions.appearance.fakeScreenRounding + spacing: 2 + SelectionGroupButton { + property int value: 0 + leftmost: true + buttonText: "No" + toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); + } + } + SelectionGroupButton { + property int value: 1 + buttonText: "Yes" + toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); + } + } + SelectionGroupButton { + property int value: 2 + rightmost: true + buttonText: "When not fullscreen" + toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); + } + } + } + } } } \ No newline at end of file diff --git a/.config/quickshell/settings.qml b/.config/quickshell/settings.qml index e5cf1c31..f5a4b583 100644 --- a/.config/quickshell/settings.qml +++ b/.config/quickshell/settings.qml @@ -27,20 +27,15 @@ ApplicationWindow { property real contentPadding: 8 property bool showNextTime: false property var pages: [ - { - name: "General", - icon: "tune", - component: "modules/settings/General.qml" - }, { name: "Style", icon: "palette", component: "modules/settings/Style.qml" }, { - name: "Services", + name: "Behavior", icon: "settings", - component: "modules/settings/Services.qml" + component: "modules/settings/BehaviorConfig.qml" }, { name: "About", From bf6e5fafea62dc6e06c7384eae1e68ab61de2b17 Mon Sep 17 00:00:00 2001 From: Sighthesia <87855491+Sighthesia@users.noreply.github.com> Date: Thu, 19 Jun 2025 20:35:10 +0800 Subject: [PATCH 021/328] Bar.qml: Fix round decorators transparency and visibility consistency with bar --- .config/quickshell/modules/bar/Bar.qml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 925ac140..56957409 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -456,6 +456,7 @@ Scope { bottom: ConfigOptions.bar.bottom ? barContent.top : undefined } height: Appearance.rounding.screenRounding + visible: showBarBackground RoundCorner { anchors.top: parent.top @@ -463,6 +464,7 @@ Scope { size: Appearance.rounding.screenRounding corner: ConfigOptions.bar.bottom ? cornerEnum.bottomLeft : cornerEnum.topLeft color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + opacity: 1.0 - Appearance.transparency } RoundCorner { anchors.top: parent.top @@ -470,6 +472,7 @@ Scope { size: Appearance.rounding.screenRounding corner: ConfigOptions.bar.bottom ? cornerEnum.bottomRight : cornerEnum.topRight color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + opacity: 1.0 - Appearance.transparency } } From cad1cfb66a08fbf84aa4d6888073d1f914f1b0ad Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:19:02 +0200 Subject: [PATCH 022/328] hyprland: adjust anims, disable swallow --- .config/hypr/hyprland/general.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/hypr/hyprland/general.conf b/.config/hypr/hyprland/general.conf index e8895efd..b03a8304 100644 --- a/.config/hypr/hyprland/general.conf +++ b/.config/hypr/hyprland/general.conf @@ -97,10 +97,10 @@ animations { animation = border, 1, 10, emphasizedDecel # layers animation = layersIn, 1, 2.7, emphasizedDecel, popin 93% - animation = layersOut, 1, 2, menu_accel, popin 94% + animation = layersOut, 1, 2.4, menu_accel, popin 94% # fade animation = fadeLayersIn, 1, 0.5, menu_decel - animation = fadeLayersOut, 1, 2.2, menu_accel + animation = fadeLayersOut, 1, 2.7, menu_accel # workspaces animation = workspaces, 1, 7, menu_decel, slide ## specialWorkspace @@ -133,7 +133,7 @@ misc { key_press_enables_dpms = true animate_manual_resizes = false animate_mouse_windowdragging = false - enable_swallow = true + enable_swallow = false swallow_regex = (foot|kitty|allacritty|Alacritty) new_window_takes_over_fullscreen = 2 allow_session_lock_restore = true From 8bc05c137337e14488b367df56699648ccbffe28 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:19:29 +0200 Subject: [PATCH 023/328] settings: use quickshell settings app --- .config/hypr/hyprland/keybinds.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index 806db152..671a267b 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -202,13 +202,13 @@ bindl= ,XF86AudioPause, exec, playerctl play-pause # [hidden] bind = Super, Return, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # Terminal bind = Super, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] Kitty (terminal) (alt) bind = Ctrl+Alt, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] Kitty (for Ubuntu people) -bind = Super, E, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "dolphin" "nautilus" "nemo" "thunar" # File manager +bind = Super, E, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "dolphin" "nautilus" "nemo" "thunar" "kitty -1 fish -c yazi" # File manager bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "zen-browser" "firefox" "brave" "chromium" "google-chrome-stable" "microsoft-edge-stable" "opera" # Browser bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "code" "codium" "zed" "kate" "gnome-text-editor" "emacs" "command -v nvim && kitty -1 nvim" # Code editor bind = Super+Shift, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "wps" "onlyoffice-desktopeditors" # Office software bind = Super, X, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kate" "gnome-text-editor" "emacs" # Text editor bind = Ctrl+Super, V, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol" # Volume mixer -bind = Super, I, exec, XDG_CURRENT_DESKTOP=gnome ~/.config/hypr/hyprland/scripts/launch_first_available.sh "systemsettings" "gnome-control-center" "better-control" # Settings app +bind = Super, I, exec, XDG_CURRENT_DESKTOP=gnome ~/.config/hypr/hyprland/scripts/launch_first_available.sh "qs -p ~/.config/quickshell/settings.qml" "systemsettings" "gnome-control-center" "better-control" # Settings app bind = Ctrl+Shift, Escape, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "gnome-system-monitor" "plasma-systemmonitzor --page-name Processes" "command -v btop && kitty -1 fish -c btop" # System monitor # Cursed stuff From fd1f9c39b0ac0a697f8cc83e88d54aa92a4464d6 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:19:43 +0200 Subject: [PATCH 024/328] update window rule for settings app --- .config/hypr/hyprland/rules.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index 6ca0989a..bed26a99 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -22,7 +22,8 @@ windowrulev2 = center, class:^(nm-connection-editor)$ windowrulev2 = float, class:.*plasmawindowed.* windowrulev2 = float, class:kcm_.* windowrulev2 = float, class:.*bluedevilwizard -windowrulev2 = float, title:.*Welcome.* +windowrulev2 = float, title:.*Welcome +windowrulev2 = float, title:^(illogical-impulse Settings)$ # No appearance # kde-material-you-colors spawns a window when changing dark/light theme. This is to make sure it doesn't interfere at all. From cbed76fea92d0becb57b3a482c45e2677f0b3cc9 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:20:03 +0200 Subject: [PATCH 025/328] adjust transparency --- .config/quickshell/modules/bar/Bar.qml | 4 ++-- .config/quickshell/modules/common/Appearance.qml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 925ac140..51ad4cf1 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -1,7 +1,7 @@ import "root:/" -import "root:/modules/common" -import "root:/modules/common/widgets" import "root:/services" +import "root:/modules/common/" +import "root:/modules/common/widgets" import "root:/modules/common/functions/color_utils.js" as ColorUtils import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index a4fadc31..4fd8aa9b 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -16,8 +16,8 @@ Singleton { property string syntaxHighlightingTheme // Extremely conservative transparency values for consistency and readability - property real transparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.1 : 0) : 0 - property real contentTransparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.55 : 0) : 0 + property real transparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.14 : 0.07) : 0 + property real contentTransparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.55 : 0.55) : 0 m3colors: QtObject { property bool darkmode: false From bd6e8894b6d089713943eb5dfae6feb3d38e996f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:21:05 +0200 Subject: [PATCH 026/328] notifications: drop actions on restart (they don't work properly anyway) --- .config/quickshell/services/Notifications.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/services/Notifications.qml b/.config/quickshell/services/Notifications.qml index dc2d2206..6f04b7cd 100644 --- a/.config/quickshell/services/Notifications.qml +++ b/.config/quickshell/services/Notifications.qml @@ -243,7 +243,7 @@ Singleton { root.list = JSON.parse(fileContents).map((notif) => { return notifComponent.createObject(root, { "id": notif.id, - "actions": notif.actions, + "actions": [], // Notification actions are meaningless if they're not tracked by the server or the sender is dead "appIcon": notif.appIcon, "appName": notif.appName, "body": notif.body, From 0caf72a78f7730567af0c2f5edb6a58eb8d8f7c0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:21:28 +0200 Subject: [PATCH 027/328] make right sidebar open qs settings app --- .config/quickshell/modules/common/ConfigOptions.qml | 1 - .config/quickshell/modules/sidebarRight/SidebarRight.qml | 9 ++++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 230dfa4c..58331e36 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -33,7 +33,6 @@ Singleton { property string bluetooth: "kcmshell6 kcm_bluetooth" property string network: "plasmawindowed org.kde.plasma.networkmanagement" property string networkEthernet: "kcmshell6 kcm_networkmanagement" - property string settings: "systemsettings" property string taskManager: "plasma-systemmonitor --page-name Processes" property string terminal: "kitty -1" // This is only for shell actions } diff --git a/.config/quickshell/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/modules/sidebarRight/SidebarRight.qml index ed9788f0..52ddae7d 100644 --- a/.config/quickshell/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/modules/sidebarRight/SidebarRight.qml @@ -3,6 +3,7 @@ import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/string_utils.js" as StringUtils +import "root:/modules/common/functions/file_utils.js" as FileUtils import "./quickToggles/" import QtQuick import QtQuick.Controls @@ -16,8 +17,10 @@ import Quickshell.Wayland import Quickshell.Hyprland Scope { + id: root property int sidebarWidth: Appearance.sizes.sidebarWidth property int sidebarPadding: 15 + property string settingsQmlPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/settings.qml`) PanelWindow { id: sidebarRoot @@ -143,11 +146,11 @@ Scope { toggled: false buttonIcon: "settings" onClicked: { - Hyprland.dispatch(`exec ${ConfigOptions.apps.settings}`) - Hyprland.dispatch(`global quickshell:sidebarRightClose`) + Hyprland.dispatch("global quickshell:sidebarRightClose") + Hyprland.dispatch(`exec qs -p '${root.settingsQmlPath}'`) } StyledToolTip { - content: qsTr("Plasma Settings") + content: qsTr("Settings") } } QuickToggleButton { From 4ebd4864264fd382e4e5ffe3eefc93f8cb574d86 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:31:36 +0200 Subject: [PATCH 028/328] add back ai primary buffer query (closes #1462) --- .config/hypr/hyprland/keybinds.conf | 2 +- .../ai/license_show-loaded-ollama-models.txt | 201 ++++++++++++++++++ .../scripts/ai/primary-buffer-query.sh | 41 ++++ .../scripts/ai/show-loaded-ollama-models.sh | 99 +++++++++ 4 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 .config/hypr/hyprland/scripts/ai/license_show-loaded-ollama-models.txt create mode 100755 .config/hypr/hyprland/scripts/ai/primary-buffer-query.sh create mode 100755 .config/hypr/hyprland/scripts/ai/show-loaded-ollama-models.sh diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index 671a267b..f9cdddd5 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -64,7 +64,7 @@ bindd = Super+Alt, R, Record region (no sound), exec, ~/.config/hypr/hyprland/sc bindd = Ctrl+Alt, R, Record screen (no sound), exec, ~/.config/hypr/hyprland/scripts/record.sh --fullscreen # [hidden] Record screen (no sound) bindd = Super+Shift+Alt, R, Record screen (with sound), exec, ~/.config/hypr/hyprland/scripts/record.sh --fullscreen-sound # Record screen (with sound) # AI -bindd = Super+Shift+Alt, mouse:273, Generate AI summary for selected text, exec, ~/.config/ags/scripts/ai/primary-buffer-query.sh # AI summary for selected text +bindd = Super+Shift+Alt, mouse:273, Generate AI summary for selected text, exec, ~/.config/hypr/hyprland/scripts/ai/primary-buffer-query.sh # AI summary for selected text #! ##! Window diff --git a/.config/hypr/hyprland/scripts/ai/license_show-loaded-ollama-models.txt b/.config/hypr/hyprland/scripts/ai/license_show-loaded-ollama-models.txt new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/.config/hypr/hyprland/scripts/ai/license_show-loaded-ollama-models.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/.config/hypr/hyprland/scripts/ai/primary-buffer-query.sh b/.config/hypr/hyprland/scripts/ai/primary-buffer-query.sh new file mode 100755 index 00000000..79441455 --- /dev/null +++ b/.config/hypr/hyprland/scripts/ai/primary-buffer-query.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# Default system prompt +SYSTEM_PROMPT="You are a helpful, quick assistant that provides brief and concise explanation \ +to given content in at most 100 characters. If the given content is not in English, translate \ +it to English. If the content is an English word, provide its meaning. If the content is a name, \ +provide some info about it. For a math expression, provide a simplification, \ +each step on a line following this style: \`2x=11 (subtract 7 from both sides)\`. \ +If you do not know the answer, simply say 'No info available'. \ +Only respond for the appropriate case and use as little text as possible.\ +The content:" + +first_loaded_model=$("$(dirname "$0")/show-loaded-ollama-models.sh" -j | jq -r '.[0].model' 2>/dev/null) || first_loaded_model="" +model=${first_loaded_model:-"llama3.2"} + +# Parse command-line arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + --model) model="$2"; shift ;; # Set the model from the flag + *) echo "Unknown parameter: $1"; exit 1 ;; + esac + shift +done + +# Combine the system prompt with the clipboard content +content=$(wl-paste -p | tr '\n' ' ') +prompt="$SYSTEM_PROMPT $content" + +# Make the API call with the specified or default model +response=$(curl http://localhost:11434/api/generate -d \ + "{\"model\": \"$model\",\"prompt\": \"$prompt\",\"stream\": false}" \ + | jq -r '.response') + +# Check if content is a single line and no longer than 30 characters +if [[ ${#content} -le 30 && "$content" != *$'\n'* ]]; then + notify-send --app-name="Text selection query" --expire-time=10000 \ + "$content" "$response" +else + notify-send --app-name="Text selection query" --expire-time=10000 \ + "AI Response" "$response" +fi diff --git a/.config/hypr/hyprland/scripts/ai/show-loaded-ollama-models.sh b/.config/hypr/hyprland/scripts/ai/show-loaded-ollama-models.sh new file mode 100755 index 00000000..8dc88780 --- /dev/null +++ b/.config/hypr/hyprland/scripts/ai/show-loaded-ollama-models.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +# From strikeoncmputrz/LLM_Scripts +# License: Apache-2.0, can be found in the same folder as this script + +# Global Vars +ollama_url=http://localhost +port="11434" +blobs=() +model_name_paths=() + + +#Parse arguments +while [ "$#" -gt 0 ]; do + case $1 in + -h|--help) + echo + echo " Identifies Ollama models running on this operating system by parsing running processes." + echo + echo " Usage: $0 [options]" + echo + echo " Options:" + echo " -j, --json_output Prints result as a json object. Other output disabled. (Default: false)" + echo " -p, --port [port number] Specify Ollama Server port (Default: 11434)" + echo " -u, --ollama_url [url] Specify Ollama Server URL (Default: http://localhost)" + echo + echo " Dependencies: jq" + exit 0 + ;; + -j|--json_output) + json_out=1 + shift 1 + ;; + -u|--ollama_url) + ollama_url=$2 + shift 2 + ;; + -p|--port) + port=$2 + shift 2 + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +compare_running_models_and_modelfiles() { + json_match=() + json_output=() + local matching_models=() + OLDIFS=$IFS + for ((i=0; i<${#model_name_paths[@]}; i++)); do # Iterate over the array of modelname,blob-path + for blob in "${blobs[@]}"; do + IFS=',', read -ra fields <<< "${model_name_paths[i]}" # Split the string into parts + if [ "${fields[1]}" == "$blob" ]; then # Check if current 'field' matches a blob + matching_models+=( '{ "model": "'"${fields[0]}"'", "path": "'"${fields[1]}"'"}') # Add to list of matching models + fi + done + done + + if [ -z "$json_out" ]; then + echo -e "\nModel Found: \n $(echo ${matching_models[*]} | jq '.' | sed s/[{}]//g) \n" + else + local json_match="${matching_models[*]}" + json_output=$(echo $json_match | jq -c -s .) + echo "$json_output" + fi + IFS=$OLDIFS +} + +get_running_model_paths() { + blobs=$(ps aux | grep -- '--model' | grep -v grep | grep -Po '(?<=--model\s).*' | cut -d ' ' -f1) + if [ -z "$blobs" ]; then + echo -e "\n\n Warning: No running Ollama models detected!\n" + exit 0 + fi +} + +parse_modelfiles() { + if [ -z "$json_out" ]; then + echo -e "\nConnecting to $ollama_url:$port\n" + if [ -z "$(curl -s $ollama_url:$port)" ]; then + echo -e "Could not connect to Ollama. Check the ollama_url parameter and that the server is running\n" + exit 1 + fi + curl -s "$ollama_url:$port" + fi + local models=( $(curl -s "$ollama_url:$port/api/tags" | jq -r '.models[].name') ) + for model in "${models[@]}"; do + local modelfile=$(curl -s "$ollama_url:$port/api/show" -d '{ "name": "'"$model"'", "modelfile": true }' | jq -r '.modelfile') + model_name_paths+=($model,$(echo "$modelfile" | awk '/^FROM/{print $2}')) + done +} + +parse_modelfiles +get_running_model_paths +compare_running_models_and_modelfiles From 0416ddbf3f10c7bec085cb3cb5daec394cfbb709 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:54:09 +0200 Subject: [PATCH 029/328] swappy -> ksnip --- .config/hypr/hyprland/keybinds.conf | 2 +- arch-packages/illogical-impulse-screencapture/PKGBUILD | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index f9cdddd5..820a67f2 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -51,7 +51,7 @@ bind = Ctrl+Super, R, exec, killall ags agsv1 gjs ydotool qs quickshell; qs & # bindd = Super, V, Copy clipboard history entry, exec, qs ipc call TEST_ALIVE || pkill fuzzel || cliphist list | fuzzel --match-mode fzf --dmenu | cliphist decode | wl-copy # [hidden] Clipboard history >> clipboard (fallback) bindd = Super, Period, Copy an emoji, exec, qs ipc call TEST_ALIVE || pkill fuzzel || ~/.config/hypr/hyprland/scripts/fuzzel-emoji.sh copy # [hidden] Emoji >> clipboard (fallback) bindd = Super+Shift, S, Screen snip, exec, pidof slurp || hyprshot --freeze --clipboard-only --mode region --silent # Screen snip >> clipboard -bindd = Super+Shift+Alt, S, Screen snip and annotate, exec, pidof slurp || grim -g "$(slurp)" - | swappy -f - # Screen snip and annotate +bindd = Super+Shift+Alt, S, Screen snip and annotate, exec, pidof slurp || grim -g "$(slurp)" - | ksnip -e - # Screen snip and annotate # OCR bindd = Super+Shift, T, Character recognition,exec,grim -g "$(slurp $SLURP_ARGS)" "tmp.png" && tesseract "tmp.png" - | wl-copy && rm "tmp.png" # [hidden] # Color picker diff --git a/arch-packages/illogical-impulse-screencapture/PKGBUILD b/arch-packages/illogical-impulse-screencapture/PKGBUILD index 8feb1c0d..6320c0c3 100644 --- a/arch-packages/illogical-impulse-screencapture/PKGBUILD +++ b/arch-packages/illogical-impulse-screencapture/PKGBUILD @@ -5,11 +5,10 @@ pkgdesc='Illogical Impulse Screenshot and Recording Dependencies' arch=(any) license=(None) depends=( - swappy - wf-recorder hyprshot + ksnip + slurp tesseract tesseract-data-eng - slurp + wf-recorder ) - From e8414c88bafbc6ce46da0281569873403296a2a1 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 18:58:30 +0200 Subject: [PATCH 030/328] settings: about page --- .config/quickshell/modules/bar/Bar.qml | 3 - .../modules/common/widgets/ContentPage.qml | 8 +- .../common/widgets/NotificationItem.qml | 8 +- .../common/widgets/PointingHandLinkHover.qml | 8 + .../common/widgets/RippleButtonWithIcon.qml | 7 +- .config/quickshell/modules/settings/About.qml | 146 +++++++++++++++++- .config/quickshell/modules/settings/Style.qml | 4 +- .../sidebarLeft/anime/BooruResponse.qml | 7 +- .config/quickshell/services/SystemInfo.qml | 23 ++- .config/quickshell/welcome.qml | 16 +- 10 files changed, 195 insertions(+), 35 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/PointingHandLinkHover.qml diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 80de4d6a..51ad4cf1 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -456,7 +456,6 @@ Scope { bottom: ConfigOptions.bar.bottom ? barContent.top : undefined } height: Appearance.rounding.screenRounding - visible: showBarBackground RoundCorner { anchors.top: parent.top @@ -464,7 +463,6 @@ Scope { size: Appearance.rounding.screenRounding corner: ConfigOptions.bar.bottom ? cornerEnum.bottomLeft : cornerEnum.topLeft color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - opacity: 1.0 - Appearance.transparency } RoundCorner { anchors.top: parent.top @@ -472,7 +470,6 @@ Scope { size: Appearance.rounding.screenRounding corner: ConfigOptions.bar.bottom ? cornerEnum.bottomRight : cornerEnum.topRight color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - opacity: 1.0 - Appearance.transparency } } diff --git a/.config/quickshell/modules/common/widgets/ContentPage.qml b/.config/quickshell/modules/common/widgets/ContentPage.qml index 5862417e..e965e12f 100644 --- a/.config/quickshell/modules/common/widgets/ContentPage.qml +++ b/.config/quickshell/modules/common/widgets/ContentPage.qml @@ -6,14 +6,18 @@ import "root:/modules/common/widgets/" Flickable { id: root - property real baseWidth: 400 + property real baseWidth: 500 + property bool forceWidth: false + default property alias data: contentColumn.data clip: true contentHeight: contentColumn.implicitHeight - implicitWidth: Math.max(contentColumn.implicitWidth, baseWidth) + implicitWidth: contentColumn.implicitWidth + ColumnLayout { id: contentColumn + width: root.forceWidth ? root.baseWidth : Math.max(root.baseWidth, implicitWidth) anchors { top: parent.top bottom: parent.bottom diff --git a/.config/quickshell/modules/common/widgets/NotificationItem.qml b/.config/quickshell/modules/common/widgets/NotificationItem.qml index bf8a7687..e078d503 100644 --- a/.config/quickshell/modules/common/widgets/NotificationItem.qml +++ b/.config/quickshell/modules/common/widgets/NotificationItem.qml @@ -226,12 +226,8 @@ Item { // Notification item area Qt.openUrlExternally(link) Hyprland.dispatch("global quickshell:sidebarRightClose") } - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.NoButton // Only for hover - hoverEnabled: true - cursorShape: parent.hoveredLink !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor - } + + PointingHandLinkHover {} } Flickable { // Notification actions diff --git a/.config/quickshell/modules/common/widgets/PointingHandLinkHover.qml b/.config/quickshell/modules/common/widgets/PointingHandLinkHover.qml new file mode 100644 index 00000000..4d14c816 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/PointingHandLinkHover.qml @@ -0,0 +1,8 @@ +import QtQuick + +MouseArea { + anchors.fill: parent + acceptedButtons: Qt.NoButton // Only for hover + hoverEnabled: true + cursorShape: parent.hoveredLink !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor +} diff --git a/.config/quickshell/modules/common/widgets/RippleButtonWithIcon.qml b/.config/quickshell/modules/common/widgets/RippleButtonWithIcon.qml index 60d75cd6..8e5fb6f2 100644 --- a/.config/quickshell/modules/common/widgets/RippleButtonWithIcon.qml +++ b/.config/quickshell/modules/common/widgets/RippleButtonWithIcon.qml @@ -7,7 +7,8 @@ import "root:/modules/common/widgets/" RippleButton { id: buttonWithIconRoot property string nerdIcon - property string iconText + property string materialIcon + property bool materialIconFill: true property string mainText: "Button text" property Component mainContentComponent: Component { StyledText { @@ -29,10 +30,10 @@ RippleButton { anchors.centerIn: parent active: !nerdIcon sourceComponent: MaterialSymbol { - text: buttonWithIconRoot.iconText + text: buttonWithIconRoot.materialIcon iconSize: Appearance.font.pixelSize.larger color: Appearance.colors.colOnSecondaryContainer - fill: 1 + fill: buttonWithIconRoot.materialIconFill ? 1 : 0 } } Loader { diff --git a/.config/quickshell/modules/settings/About.qml b/.config/quickshell/modules/settings/About.qml index 1d35b71b..7868c0e7 100644 --- a/.config/quickshell/modules/settings/About.qml +++ b/.config/quickshell/modules/settings/About.qml @@ -1,13 +1,151 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Widgets import "root:/services/" import "root:/modules/common/" import "root:/modules/common/widgets/" ContentPage { - StyledText { - text: qsTr("About page") - font.pixelSize: Appearance.font.pixelSize.larger + forceWidth: true + + ContentSection { + title: "Distro" + + RowLayout { + Layout.alignment: Qt.AlignHCenter + spacing: 20 + Layout.topMargin: 10 + Layout.bottomMargin: 10 + IconImage { + implicitSize: 100 + source: Quickshell.iconPath(SystemInfo.logo) + } + ColumnLayout { + Layout.alignment: Qt.AlignVCenter + // spacing: 10 + StyledText { + text: SystemInfo.distroName + font.pixelSize: Appearance.font.pixelSize.title + } + StyledText { + font.pixelSize: Appearance.font.pixelSize.normal + text: SystemInfo.homeUrl + textFormat: Text.MarkdownText + onLinkActivated: (link) => { + Qt.openUrlExternally(link) + } + PointingHandLinkHover {} + } + } + } + + Flow { + Layout.fillWidth: true + spacing: 5 + + RippleButtonWithIcon { + materialIcon: "auto_stories" + mainText: "Documentation" + onClicked: { + Qt.openUrlExternally(SystemInfo.documentationUrl) + } + } + RippleButtonWithIcon { + materialIcon: "support" + mainText: "Help & Support" + onClicked: { + Qt.openUrlExternally(SystemInfo.supportUrl) + } + } + RippleButtonWithIcon { + materialIcon: "bug_report" + mainText: "Report a Bug" + onClicked: { + Qt.openUrlExternally(SystemInfo.bugReportUrl) + } + } + RippleButtonWithIcon { + materialIcon: "policy" + materialIconFill: false + mainText: "Privacy Policy" + onClicked: { + Qt.openUrlExternally(SystemInfo.privacyPolicyUrl) + } + } + + } + } -} \ No newline at end of file + ContentSection { + title: "Dotfiles" + + RowLayout { + Layout.alignment: Qt.AlignHCenter + spacing: 20 + Layout.topMargin: 10 + Layout.bottomMargin: 10 + MaterialSymbol { + iconSize: 70 + text: "files" + color: Appearance.colors.colOnSecondaryContainer + } + ColumnLayout { + Layout.alignment: Qt.AlignVCenter + // spacing: 10 + StyledText { + text: "illogical-impulse" + font.pixelSize: Appearance.font.pixelSize.title + } + StyledText { + text: "https://github.com/end-4/dots-hyprland" + font.pixelSize: Appearance.font.pixelSize.normal + textFormat: Text.MarkdownText + onLinkActivated: (link) => { + Qt.openUrlExternally(link) + } + PointingHandLinkHover {} + } + } + } + + Flow { + Layout.fillWidth: true + spacing: 5 + + RippleButtonWithIcon { + materialIcon: "auto_stories" + mainText: "Documentation" + onClicked: { + Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/02usage/") + } + } + RippleButtonWithIcon { + materialIcon: "adjust" + materialIconFill: false + mainText: "Issues" + onClicked: { + Qt.openUrlExternally("https://github.com/end-4/dots-hyprland/issues") + } + } + RippleButtonWithIcon { + materialIcon: "forum" + mainText: "Discussions" + onClicked: { + Qt.openUrlExternally("https://github.com/end-4/dots-hyprland/discussions") + } + } + RippleButtonWithIcon { + materialIcon: "favorite" + mainText: "Donate" + onClicked: { + Qt.openUrlExternally("https://github.com/sponsors/end-4") + } + } + + + } + } +} diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml index 8041f15c..9357bfb0 100644 --- a/.config/quickshell/modules/settings/Style.qml +++ b/.config/quickshell/modules/settings/Style.qml @@ -43,7 +43,7 @@ ContentPage { id: rndWallBtn Layout.alignment: Qt.AlignHCenter buttonRadius: Appearance.rounding.small - iconText: "wallpaper" + materialIcon: "wallpaper" mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan" onClicked: { console.log(konachanWallProc.command.join(" ")) @@ -54,7 +54,7 @@ ContentPage { } } RippleButtonWithIcon { - iconText: "wallpaper" + materialIcon: "wallpaper" StyledToolTip { content: "Pick wallpaper image on your system" } diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml b/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml index 7a207582..ed889612 100644 --- a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml +++ b/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml @@ -162,12 +162,7 @@ Rectangle { Qt.openUrlExternally(link) Hyprland.dispatch("global quickshell:sidebarLeftClose") } - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.NoButton // Only for hover - hoverEnabled: true - cursorShape: parent.hoveredLink !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor - } + PointingHandLinkHover {} } Repeater { diff --git a/.config/quickshell/services/SystemInfo.qml b/.config/quickshell/services/SystemInfo.qml index ffd478b6..cd3d9f38 100644 --- a/.config/quickshell/services/SystemInfo.qml +++ b/.config/quickshell/services/SystemInfo.qml @@ -9,10 +9,17 @@ import Quickshell.Io * Provides some system info: distro, username. */ Singleton { + id: root property string distroName: "Unknown" property string distroId: "unknown" property string distroIcon: "linux-symbolic" property string username: "user" + property string homeUrl: "" + property string documentationUrl: "" + property string supportUrl: "" + property string bugReportUrl: "" + property string privacyPolicyUrl: "" + property string logo: "" Timer { triggeredOnStart: true @@ -33,6 +40,20 @@ Singleton { const logoMatch = textOsRelease.match(/^LOGO=(.+)$/m) distroId = logoMatch ? logoMatch[1].replace(/"/g, "") : "unknown" + // Extract additional URLs and logo + const homeUrlMatch = textOsRelease.match(/^HOME_URL="(.+?)"/m) + homeUrl = homeUrlMatch ? homeUrlMatch[1] : "" + const documentationUrlMatch = textOsRelease.match(/^DOCUMENTATION_URL="(.+?)"/m) + documentationUrl = documentationUrlMatch ? documentationUrlMatch[1] : "" + const supportUrlMatch = textOsRelease.match(/^SUPPORT_URL="(.+?)"/m) + supportUrl = supportUrlMatch ? supportUrlMatch[1] : "" + const bugReportUrlMatch = textOsRelease.match(/^BUG_REPORT_URL="(.+?)"/m) + bugReportUrl = bugReportUrlMatch ? bugReportUrlMatch[1] : "" + const privacyPolicyUrlMatch = textOsRelease.match(/^PRIVACY_POLICY_URL="(.+?)"/m) + privacyPolicyUrl = privacyPolicyUrlMatch ? privacyPolicyUrlMatch[1] : "" + const logoFieldMatch = textOsRelease.match(/^LOGO="?(.+?)"?$/m) + logo = logoFieldMatch ? logoFieldMatch[1] : "" + // Update the distroIcon property based on distroId switch (distroId) { case "arch": distroIcon = "arch-symbolic"; break; @@ -57,7 +78,7 @@ Singleton { command: ["whoami"] stdout: SplitParser { onRead: data => { - username = data.trim() + root.username = data.trim() } } } diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index 65f62089..4b7286be 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -138,7 +138,7 @@ ApplicationWindow { id: rndWallBtn Layout.alignment: Qt.AlignHCenter buttonRadius: Appearance.rounding.small - iconText: "wallpaper" + materialIcon: "wallpaper" mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan" onClicked: { console.log(konachanWallProc.command.join(" ")) @@ -149,7 +149,7 @@ ApplicationWindow { } } RippleButtonWithIcon { - iconText: "wallpaper" + materialIcon: "wallpaper" StyledToolTip { content: "Pick wallpaper image on your system" } @@ -284,10 +284,10 @@ ApplicationWindow { Flow { Layout.fillWidth: true - spacing: 10 + spacing: 5 RippleButtonWithIcon { - iconText: "keyboard_alt" + materialIcon: "keyboard_alt" onClicked: { Hyprland.dispatch("global quickshell:cheatsheetOpen") } @@ -317,14 +317,14 @@ ApplicationWindow { } RippleButtonWithIcon { - iconText: "help" + materialIcon: "help" mainText: "Usage" onClicked: { Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/02usage/") } } RippleButtonWithIcon { - iconText: "construction" + materialIcon: "construction" mainText: "Configuration" onClicked: { Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/03config/") @@ -338,7 +338,7 @@ ApplicationWindow { Flow { Layout.fillWidth: true - spacing: 10 + spacing: 5 RippleButtonWithIcon { nerdIcon: "󰊤" @@ -348,7 +348,7 @@ ApplicationWindow { } } RippleButtonWithIcon { - iconText: "favorite" + materialIcon: "favorite" mainText: "Funny number" onClicked: { Qt.openUrlExternally("https://github.com/sponsors/end-4") From eaa56ff555410829d4cfd74282ab1e182d56f0ba Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 19:32:31 +0200 Subject: [PATCH 031/328] settings: add material palette and transparency --- .../quickshell/modules/common/Appearance.qml | 2 +- .../modules/common/widgets/ConfigSwitch.qml | 29 ++++++++ .../modules/common/widgets/KeyboardKey.qml | 2 +- .../modules/common/widgets/StyledSwitch.qml | 6 +- .config/quickshell/modules/settings/Style.qml | 69 +++++++++++++++++++ 5 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/ConfigSwitch.qml diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 4fd8aa9b..9164ed91 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -130,7 +130,7 @@ Singleton { property color colSecondary: m3colors.m3secondary property color colSecondaryHover: ColorUtils.mix(m3colors.m3secondary, colLayer1Hover, 0.85) property color colSecondaryActive: ColorUtils.mix(m3colors.m3secondary, colLayer1Active, 0.4) - property color colSecondaryContainer: ColorUtils.transparentize(m3colors.m3secondaryContainer, root.contentTransparency) + property color colSecondaryContainer: m3colors.m3secondaryContainer property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.6) property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54) property color colOnSecondaryContainer: m3colors.m3onSecondaryContainer diff --git a/.config/quickshell/modules/common/widgets/ConfigSwitch.qml b/.config/quickshell/modules/common/widgets/ConfigSwitch.qml new file mode 100644 index 00000000..bbb60f06 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/ConfigSwitch.qml @@ -0,0 +1,29 @@ +import "root:/modules/common/widgets/" +import "root:/modules/common/" +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +RippleButton { + id: root + Layout.fillWidth: true + + contentItem: RowLayout { + spacing: 10 + StyledText { + id: labelWidget + Layout.fillWidth: true + text: root.text + font.pixelSize: Appearance.font.pixelSize.normal + color: Appearance.colors.colOnSecondaryContainer + } + StyledSwitch { + id: switchWidget + down: root.down + scale: 0.75 + Layout.fillWidth: false + checked: root.checked + } + } +} + diff --git a/.config/quickshell/modules/common/widgets/KeyboardKey.qml b/.config/quickshell/modules/common/widgets/KeyboardKey.qml index 0cc80429..d6ba5ba0 100644 --- a/.config/quickshell/modules/common/widgets/KeyboardKey.qml +++ b/.config/quickshell/modules/common/widgets/KeyboardKey.qml @@ -15,7 +15,7 @@ Rectangle { property real extraBottomBorderWidth: 2 property color borderColor: Appearance.colors.colOnLayer0 property real borderRadius: 5 - property color keyColor: Appearance.colors.colSurfaceContainerLow + property color keyColor: Appearance.m3colors.m3surfaceContainerLow implicitWidth: keyFace.implicitWidth + borderWidth * 2 implicitHeight: keyFace.implicitHeight + borderWidth * 2 + extraBottomBorderWidth radius: borderRadius diff --git a/.config/quickshell/modules/common/widgets/StyledSwitch.qml b/.config/quickshell/modules/common/widgets/StyledSwitch.qml index e980d7f8..453806f3 100644 --- a/.config/quickshell/modules/common/widgets/StyledSwitch.qml +++ b/.config/quickshell/modules/common/widgets/StyledSwitch.qml @@ -36,13 +36,13 @@ Switch { // Custom thumb styling indicator: Rectangle { - width: root.pressed ? (28 * root.scale) : root.checked ? (24 * root.scale) : (16 * root.scale) - height: root.pressed ? (28 * root.scale) : root.checked ? (24 * root.scale) : (16 * root.scale) + width: (root.pressed || root.down) ? (28 * root.scale) : root.checked ? (24 * root.scale) : (16 * root.scale) + height: (root.pressed || root.down) ? (28 * root.scale) : root.checked ? (24 * root.scale) : (16 * root.scale) radius: Appearance.rounding.full color: root.checked ? Appearance.m3colors.m3onPrimary : Appearance.m3colors.m3outline anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: root.checked ? (root.pressed ? (22 * root.scale) : 24 * root.scale) : (root.pressed ? (2 * root.scale) : 8 * root.scale) + anchors.leftMargin: root.checked ? ((root.pressed || root.down) ? (22 * root.scale) : 24 * root.scale) : ((root.pressed || root.down) ? (2 * root.scale) : 8 * root.scale) Behavior on anchors.leftMargin { animation: Appearance.animation.elementMove.numberAnimation.createObject(this) diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml index 9357bfb0..732c62f3 100644 --- a/.config/quickshell/modules/settings/Style.qml +++ b/.config/quickshell/modules/settings/Style.qml @@ -11,6 +11,8 @@ import "root:/modules/common/functions/color_utils.js" as ColorUtils import "root:/modules/common/functions/file_utils.js" as FileUtils ContentPage { + baseWidth: lightDarkButtonGroup.implicitWidth + forceWidth: true Process { id: konachanWallProc @@ -27,7 +29,9 @@ ContentPage { ContentSection { title: "Colors & Wallpaper" + // Light/Dark mode preference ButtonGroup { + id: lightDarkButtonGroup Layout.fillWidth: true LightDarkPreferenceButton { dark: false @@ -37,6 +41,59 @@ ContentPage { } } + // Material palette selection + StyledText { + text: "Material palette" + color: Appearance.colors.colSubtext + } + Flow { + id: paletteFlow + Layout.fillWidth: true + spacing: 2 + property list palettes: [ + {"value": "auto", "displayName": "Auto"}, + {"value": "scheme-content", "displayName": "Content"}, + {"value": "scheme-expressive", "displayName": "Expressive"}, + {"value": "scheme-fidelity", "displayName": "Fidelty"}, + {"value": "scheme-fruit-salad", "displayName": "Fruit Salad"}, + {"value": "scheme-monochrome", "displayName": "Monochrome"}, + {"value": "scheme-neutral", "displayName": "Neutral"}, + {"value": "scheme-rainbow", "displayName": "Rainbow"}, + {"value": "scheme-tonal-spot", "displayName": "Tonal Spot"}, + ] + + Repeater { + model: paletteFlow.palettes + delegate: SelectionGroupButton { + id: paletteButton + required property var modelData + required property int index + onYChanged: { + if (index === 0) { + paletteButton.leftmost = true + } else { + var prev = paletteFlow.children[index - 1] + var thisIsOnNewLine = prev && prev.y !== paletteButton.y + paletteButton.leftmost = thisIsOnNewLine + prev.rightmost = thisIsOnNewLine + } + } + leftmost: index === 0 + rightmost: index === paletteFlow.palettes.length - 1 + buttonText: modelData.displayName; + toggled: ConfigOptions.appearance.palette.type === modelData.value + onClicked: { + ConfigLoader.setConfigValueAndSave("appearance.palette.type", modelData.value); + } + } + } + } + + // Wallpaper selection + StyledText { + text: "Wallpaper" + color: Appearance.colors.colSubtext + } RowLayout { Layout.alignment: Qt.AlignHCenter RippleButtonWithIcon { @@ -139,5 +196,17 @@ ContentPage { } } } + + ConfigSwitch { + text: "Transparency" + checked: ConfigOptions.appearance.transparency + onClicked: checked = !checked; + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("appearance.transparency", checked); + } + StyledToolTip { + content: "Might look ass. Unsupported." + } + } } } \ No newline at end of file From 62e0b7f669d91170696dfac937f9b4465e2ce04b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 21:19:30 +0200 Subject: [PATCH 032/328] redo accidentally overwritten corner transparency --- .config/quickshell/modules/bar/Bar.qml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 51ad4cf1..0a890c6e 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -456,6 +456,7 @@ Scope { bottom: ConfigOptions.bar.bottom ? barContent.top : undefined } height: Appearance.rounding.screenRounding + visible: showBarBackground RoundCorner { anchors.top: parent.top @@ -463,6 +464,7 @@ Scope { size: Appearance.rounding.screenRounding corner: ConfigOptions.bar.bottom ? cornerEnum.bottomLeft : cornerEnum.topLeft color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + opacity: 1.0 - Appearance.transparency } RoundCorner { anchors.top: parent.top @@ -470,6 +472,7 @@ Scope { size: Appearance.rounding.screenRounding corner: ConfigOptions.bar.bottom ? cornerEnum.bottomRight : cornerEnum.topRight color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + opacity: 1.0 - Appearance.transparency } } From d437e126aba9e53ae648bd1870655c7b97207a46 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 21:49:11 +0200 Subject: [PATCH 033/328] enable wayland flag for chrome and code again --- .config/chrome-flags.conf | 2 +- .config/code-flags.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/chrome-flags.conf b/.config/chrome-flags.conf index 592cd96f..4f1b5186 100644 --- a/.config/chrome-flags.conf +++ b/.config/chrome-flags.conf @@ -1,5 +1,5 @@ --password-store=gnome-libsecret -# --ozone-platform-hint=wayland +--ozone-platform-hint=wayland --gtk-version=4 --ignore-gpu-blocklist --enable-features=TouchpadOverscrollHistoryNavigation diff --git a/.config/code-flags.conf b/.config/code-flags.conf index 49624fa7..0786a0c6 100644 --- a/.config/code-flags.conf +++ b/.config/code-flags.conf @@ -1,4 +1,4 @@ -# --ozone-platform-hint=wayland +--ozone-platform-hint=wayland --gtk-version=4 --ignore-gpu-blocklist --enable-features=TouchpadOverscrollHistoryNavigation From a940c1b4fe76ff9dd94a75aae79790f2ecab7698 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 23:29:06 +0200 Subject: [PATCH 034/328] adjust transparency --- .config/quickshell/modules/common/Appearance.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 9164ed91..202230a3 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -16,7 +16,7 @@ Singleton { property string syntaxHighlightingTheme // Extremely conservative transparency values for consistency and readability - property real transparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.14 : 0.07) : 0 + property real transparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.1 : 0.07) : 0 property real contentTransparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.55 : 0.55) : 0 m3colors: QtObject { From 2db4b33fe21fbb4d157c4f12e3888cc5f3afeb2c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 23:29:25 +0200 Subject: [PATCH 035/328] fix configswitch not working when clicking the actual switch --- .config/quickshell/modules/common/widgets/ConfigSwitch.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/modules/common/widgets/ConfigSwitch.qml b/.config/quickshell/modules/common/widgets/ConfigSwitch.qml index bbb60f06..2d317a6b 100644 --- a/.config/quickshell/modules/common/widgets/ConfigSwitch.qml +++ b/.config/quickshell/modules/common/widgets/ConfigSwitch.qml @@ -23,6 +23,7 @@ RippleButton { scale: 0.75 Layout.fillWidth: false checked: root.checked + onClicked: root.clicked() } } } From 3d9a5a72b6ffd0271faf421993b24d01f65a7959 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 19 Jun 2025 23:29:52 +0200 Subject: [PATCH 036/328] settings: add titlebar --- .config/quickshell/modules/settings/Style.qml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml index 732c62f3..c86bce53 100644 --- a/.config/quickshell/modules/settings/Style.qml +++ b/.config/quickshell/modules/settings/Style.qml @@ -209,4 +209,17 @@ ContentPage { } } } + + ContentSection { + title: "Shell windows" + + ConfigSwitch { + text: "Title bar" + checked: ConfigOptions.windows.showTitlebar + onClicked: checked = !checked; + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("windows.showTitlebar", checked); + } + } + } } \ No newline at end of file From e56fbf820a954c52019906d4b486208f7f509309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Fri, 20 Jun 2025 22:04:29 +0300 Subject: [PATCH 037/328] feat(modules/bar): add nightmode button --- .../quickshell/modules/bar/UtilButtons.qml | 55 +++++++++++++------ .../modules/common/ConfigOptions.qml | 22 +++++--- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/.config/quickshell/modules/bar/UtilButtons.qml b/.config/quickshell/modules/bar/UtilButtons.qml index 9d9832a0..ee94d42f 100644 --- a/.config/quickshell/modules/bar/UtilButtons.qml +++ b/.config/quickshell/modules/bar/UtilButtons.qml @@ -10,7 +10,8 @@ import Quickshell.Services.Pipewire Item { id: root property bool borderless: ConfigOptions.bar.borderless - implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2 + implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 16 + implicitHeight: rowLayout.implicitHeight RowLayout { id: rowLayout @@ -34,21 +35,21 @@ Item { } } - Loader { - active: ConfigOptions.bar.utilButtons.showColorPicker - visible: ConfigOptions.bar.utilButtons.showColorPicker - sourceComponent: CircleUtilButton { - Layout.alignment: Qt.AlignVCenter - onClicked: Hyprland.dispatch("exec hyprpicker -a") - MaterialSymbol { - horizontalAlignment: Qt.AlignHCenter - fill: 1 - text: "colorize" - iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnLayer2 - } - } - } + Loader { + active: ConfigOptions.bar.utilButtons.showColorPicker + visible: ConfigOptions.bar.utilButtons.showColorPicker + sourceComponent: CircleUtilButton { + Layout.alignment: Qt.AlignVCenter + onClicked: Hyprland.dispatch("exec hyprpicker -a") + MaterialSymbol { + horizontalAlignment: Qt.AlignHCenter + fill: 1 + text: "colorize" + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnLayer2 + } + } + } Loader { active: ConfigOptions.bar.utilButtons.showKeyboardToggle @@ -82,4 +83,26 @@ Item { } } } + + Loader { + active: ConfigOptions.bar.utilButtons.darkMode.show + visible: ConfigOptions.bar.utilButtons.darkMode.show + sourceComponent: CircleUtilButton { + Layout.alignment: Qt.AlignVCenter + onClicked: event => { + if (Appearance.m3colors.darkmode) { + Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} ${ConfigOptions.bar.utilButtons.darkMode.lightImgPath} --mode light`); + } else { + Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} ${ConfigOptions.bar.utilButtons.darkMode.darkImgPath} --mode dark`); + } + } + MaterialSymbol { + horizontalAlignment: Qt.AlignHCenter + fill: 0 + text: Appearance.m3colors.darkmode ? "light_mode" : "dark_mode" + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnLayer2 + } + } + } } diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 58331e36..cc841d56 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -1,7 +1,7 @@ -import QtQuick -import Quickshell pragma Singleton pragma ComponentBehavior: Bound +import QtQuick +import Quickshell Singleton { property QtObject policies: QtObject { @@ -21,8 +21,10 @@ Singleton { } } - property QtObject audio: QtObject { // Values in % - property QtObject protection: QtObject { // Prevent sudden bangs + property QtObject audio: QtObject { + // Values in % + property QtObject protection: QtObject { + // Prevent sudden bangs property bool enable: true property real maxAllowedIncrease: 10 property real maxAllowed: 90 // Realistically should already provide some protection when it's 99... @@ -59,6 +61,11 @@ Singleton { property bool showColorPicker: false property bool showMicToggle: false property bool showKeyboardToggle: true + property QtObject darkMode: QtObject { + property bool show: true + property string lightImgPath: "" + property string darkImgPath: "" + } } property QtObject tray: QtObject { property bool monochromeIcons: true @@ -83,9 +90,7 @@ Singleton { property bool pinnedOnStartup: false property bool hoverToReveal: false // When false, only reveals on empty workspace property list pinnedApps: [ // IDs of pinned entries - "org.kde.dolphin", - "kitty", - ] + "org.kde.dolphin", "kitty",] } property QtObject language: QtObject { @@ -123,7 +128,7 @@ Singleton { property QtObject search: QtObject { property int nonAppResultDelay: 30 // This prevents lagging when typing property string engineBaseUrl: "https://www.google.com/search?q=" - property list excludedSites: [ "quora.com" ] + property list excludedSites: ["quora.com"] property bool sloppy: false // Uses levenshtein distance based scoring instead of fuzzy sort. Very weird. property QtObject prefix: QtObject { property string action: "/" @@ -159,5 +164,4 @@ Singleton { property QtObject hacks: QtObject { property int arbitraryRaceConditionDelay: 20 // milliseconds } - } From 47c9d63210c11aba178d5c91d5e68ddb3da0a49e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 21 Jun 2025 01:03:56 +0200 Subject: [PATCH 038/328] add center title config option --- .../modules/common/ConfigOptions.qml | 1 + .config/quickshell/modules/settings/Style.qml | 25 ++++++++++++++----- .config/quickshell/settings.qml | 7 +++++- .config/quickshell/welcome.qml | 7 +++++- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 58331e36..d928aa3f 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -154,6 +154,7 @@ Singleton { property QtObject windows: QtObject { property bool showTitlebar: true // Client-side decoration for shell apps + property bool centerTitle: true } property QtObject hacks: QtObject { diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml index c86bce53..b168ba53 100644 --- a/.config/quickshell/modules/settings/Style.qml +++ b/.config/quickshell/modules/settings/Style.qml @@ -212,13 +212,26 @@ ContentPage { ContentSection { title: "Shell windows" + spacing: 4 - ConfigSwitch { - text: "Title bar" - checked: ConfigOptions.windows.showTitlebar - onClicked: checked = !checked; - onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("windows.showTitlebar", checked); + RowLayout { + spacing: 10 + uniformCellSizes: true + ConfigSwitch { + text: "Title bar" + checked: ConfigOptions.windows.showTitlebar + onClicked: checked = !checked; + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("windows.showTitlebar", checked); + } + } + ConfigSwitch { + text: "Center title" + checked: ConfigOptions.windows.centerTitle + onClicked: checked = !checked; + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("windows.centerTitle", checked); + } } } } diff --git a/.config/quickshell/settings.qml b/.config/quickshell/settings.qml index f5a4b583..eac2e65b 100644 --- a/.config/quickshell/settings.qml +++ b/.config/quickshell/settings.qml @@ -73,7 +73,12 @@ ApplicationWindow { implicitHeight: Math.max(titleText.implicitHeight, windowControlsRow.implicitHeight) StyledText { id: titleText - anchors.centerIn: parent + anchors { + left: ConfigOptions.windows.centerTitle ? undefined : parent.left + horizontalCenter: ConfigOptions.windows.centerTitle ? parent.horizontalCenter : undefined + verticalCenter: parent.verticalCenter + leftMargin: 12 + } color: Appearance.colors.colOnLayer0 text: "Settings" font.pixelSize: Appearance.font.pixelSize.title diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index 4b7286be..ee5a28eb 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -65,7 +65,12 @@ ApplicationWindow { implicitHeight: Math.max(welcomeText.implicitHeight, windowControlsRow.implicitHeight) StyledText { id: welcomeText - anchors.centerIn: parent + anchors { + left: ConfigOptions.windows.centerTitle ? undefined : parent.left + horizontalCenter: ConfigOptions.windows.centerTitle ? parent.horizontalCenter : undefined + verticalCenter: parent.verticalCenter + leftMargin: 12 + } color: Appearance.colors.colOnLayer0 text: "Yooooo hi there" font.pixelSize: Appearance.font.pixelSize.title From d5a9ae32f22f67c379110175cd2622666e2af6c1 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 21 Jun 2025 01:04:07 +0200 Subject: [PATCH 039/328] adjust config switch size --- .config/quickshell/modules/common/widgets/ConfigSwitch.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/ConfigSwitch.qml b/.config/quickshell/modules/common/widgets/ConfigSwitch.qml index 2d317a6b..01dda8a2 100644 --- a/.config/quickshell/modules/common/widgets/ConfigSwitch.qml +++ b/.config/quickshell/modules/common/widgets/ConfigSwitch.qml @@ -7,6 +7,7 @@ import QtQuick.Controls RippleButton { id: root Layout.fillWidth: true + implicitHeight: contentItem.implicitHeight + 8 * 2 contentItem: RowLayout { spacing: 10 @@ -14,13 +15,13 @@ RippleButton { id: labelWidget Layout.fillWidth: true text: root.text - font.pixelSize: Appearance.font.pixelSize.normal + font.pixelSize: Appearance.font.pixelSize.small color: Appearance.colors.colOnSecondaryContainer } StyledSwitch { id: switchWidget down: root.down - scale: 0.75 + scale: 0.6 Layout.fillWidth: false checked: root.checked onClicked: root.clicked() From f66e26d4cc2760982ed0395952914b4cd58eb575 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 21 Jun 2025 01:05:04 +0200 Subject: [PATCH 040/328] content page: add bottom padding --- .config/quickshell/modules/common/widgets/ContentPage.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/ContentPage.qml b/.config/quickshell/modules/common/widgets/ContentPage.qml index e965e12f..07d88949 100644 --- a/.config/quickshell/modules/common/widgets/ContentPage.qml +++ b/.config/quickshell/modules/common/widgets/ContentPage.qml @@ -8,11 +8,12 @@ Flickable { id: root property real baseWidth: 500 property bool forceWidth: false + property real bottomContentPadding: 100 default property alias data: contentColumn.data clip: true - contentHeight: contentColumn.implicitHeight + contentHeight: contentColumn.implicitHeight + root.bottomContentPadding // Add some padding at the bottom implicitWidth: contentColumn.implicitWidth ColumnLayout { @@ -20,7 +21,6 @@ Flickable { width: root.forceWidth ? root.baseWidth : Math.max(root.baseWidth, implicitWidth) anchors { top: parent.top - bottom: parent.bottom horizontalCenter: parent.horizontalCenter margins: 10 } From 29c7031bb2c77072c72f07606cbdc93df504f087 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 21 Jun 2025 01:31:34 +0200 Subject: [PATCH 041/328] refractor selection groups and config option row --- .../modules/common/widgets/ConfigRow.qml | 8 ++ .../common/widgets/ConfigSelectionArray.qml | 48 ++++++++++ .../modules/settings/BehaviorConfig.qml | 88 +++++-------------- .config/quickshell/modules/settings/Style.qml | 48 +++------- .config/quickshell/welcome.qml | 86 +++++------------- 5 files changed, 114 insertions(+), 164 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/ConfigRow.qml create mode 100644 .config/quickshell/modules/common/widgets/ConfigSelectionArray.qml diff --git a/.config/quickshell/modules/common/widgets/ConfigRow.qml b/.config/quickshell/modules/common/widgets/ConfigRow.qml new file mode 100644 index 00000000..3cdc3f80 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/ConfigRow.qml @@ -0,0 +1,8 @@ +import QtQuick +import QtQuick.Layouts + +RowLayout { + property bool uniform: false + spacing: 10 + uniformCellSizes: uniform +} diff --git a/.config/quickshell/modules/common/widgets/ConfigSelectionArray.qml b/.config/quickshell/modules/common/widgets/ConfigSelectionArray.qml new file mode 100644 index 00000000..e62831a4 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/ConfigSelectionArray.qml @@ -0,0 +1,48 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Hyprland +import "root:/services/" +import "root:/modules/common/" +import "root:/modules/common/widgets/" +import "root:/modules/common/functions/color_utils.js" as ColorUtils +import "root:/modules/common/functions/file_utils.js" as FileUtils + +Flow { + id: root + Layout.fillWidth: true + spacing: 2 + property list options: [] + property string configOptionName: "" + property var currentValue: null + + signal selected(var newValue) + + Repeater { + model: root.options + delegate: SelectionGroupButton { + id: paletteButton + required property var modelData + required property int index + onYChanged: { + if (index === 0) { + paletteButton.leftmost = true + } else { + var prev = root.children[index - 1] + var thisIsOnNewLine = prev && prev.y !== paletteButton.y + paletteButton.leftmost = thisIsOnNewLine + prev.rightmost = thisIsOnNewLine + } + } + leftmost: index === 0 + rightmost: index === root.options.length - 1 + buttonText: modelData.displayName; + toggled: root.currentValue === modelData.value + onClicked: { + root.selected(modelData.value); + } + } + } +} diff --git a/.config/quickshell/modules/settings/BehaviorConfig.qml b/.config/quickshell/modules/settings/BehaviorConfig.qml index dd3323ac..9cec75c3 100644 --- a/.config/quickshell/modules/settings/BehaviorConfig.qml +++ b/.config/quickshell/modules/settings/BehaviorConfig.qml @@ -9,86 +9,46 @@ ContentPage { ContentSection { title: "Policies" - RowLayout { - Layout.alignment: Qt.AlignHCenter - spacing: 15 + ConfigRow { ColumnLayout { // Weeb policy StyledText { text: "Weeb" color: Appearance.colors.colSubtext } - ButtonGroup { - id: weebPolicyBtnGroup - property int selectedPolicy: ConfigOptions.policies.weeb - spacing: 2 - SelectionGroupButton { - property int value: 0 - leftmost: true - buttonText: "No" - toggled: (weebPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.weeb", value); - } - } - SelectionGroupButton { - property int value: 1 - buttonText: "Yes" - toggled: (weebPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.weeb", value); - } - } - SelectionGroupButton { - property int value: 2 - rightmost: true - buttonText: "Closet" - toggled: (weebPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.weeb", value); - } - StyledToolTip { - content: "The Anime tab on the left sidebar would still\nbe available, but its tab button won't show" - } + ConfigSelectionArray { + currentValue: ConfigOptions.policies.weeb + configOptionName: "policies.weeb" + onSelected: (newValue) => { + ConfigLoader.setConfigValueAndSave("policies.weeb", newValue); } + options: [ + { displayName: "No", value: 0 }, + { displayName: "Yes", value: 1 }, + { displayName: "Closet", value: 2 } + ] } } + ColumnLayout { // AI policy StyledText { text: "AI" color: Appearance.colors.colSubtext } - ButtonGroup { - id: aiPolicyBtnGroup - property int selectedPolicy: ConfigOptions.policies.ai - spacing: 2 - SelectionGroupButton { - property int value: 0 - leftmost: true - buttonText: "No" - toggled: (aiPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.ai", value); - } - } - SelectionGroupButton { - property int value: 1 - buttonText: "Yes" - toggled: (aiPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.ai", value); - } - } - SelectionGroupButton { - property int value: 2 - rightmost: true - buttonText: "Local only" - toggled: (aiPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.ai", value); - } + ConfigSelectionArray { + currentValue: ConfigOptions.policies.ai + configOptionName: "policies.ai" + onSelected: (newValue) => { + ConfigLoader.setConfigValueAndSave("policies.ai", newValue); } + options: [ + { displayName: "No", value: 0 }, + { displayName: "Yes", value: 1 }, + { displayName: "Local only", value: 2 } + ] } } } + + } } \ No newline at end of file diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml index b168ba53..3e8e7ae3 100644 --- a/.config/quickshell/modules/settings/Style.qml +++ b/.config/quickshell/modules/settings/Style.qml @@ -46,47 +46,24 @@ ContentPage { text: "Material palette" color: Appearance.colors.colSubtext } - Flow { - id: paletteFlow - Layout.fillWidth: true - spacing: 2 - property list palettes: [ + + ConfigSelectionArray { + currentValue: ConfigOptions.appearance.palette.type + configOptionName: "appearance.palette.type" + onSelected: (newValue) => { + ConfigLoader.setConfigValueAndSave("appearance.palette.type", newValue); + } + options: [ {"value": "auto", "displayName": "Auto"}, {"value": "scheme-content", "displayName": "Content"}, {"value": "scheme-expressive", "displayName": "Expressive"}, - {"value": "scheme-fidelity", "displayName": "Fidelty"}, + {"value": "scheme-fidelity", "displayName": "Fidelity"}, {"value": "scheme-fruit-salad", "displayName": "Fruit Salad"}, {"value": "scheme-monochrome", "displayName": "Monochrome"}, {"value": "scheme-neutral", "displayName": "Neutral"}, {"value": "scheme-rainbow", "displayName": "Rainbow"}, - {"value": "scheme-tonal-spot", "displayName": "Tonal Spot"}, + {"value": "scheme-tonal-spot", "displayName": "Tonal Spot"} ] - - Repeater { - model: paletteFlow.palettes - delegate: SelectionGroupButton { - id: paletteButton - required property var modelData - required property int index - onYChanged: { - if (index === 0) { - paletteButton.leftmost = true - } else { - var prev = paletteFlow.children[index - 1] - var thisIsOnNewLine = prev && prev.y !== paletteButton.y - paletteButton.leftmost = thisIsOnNewLine - prev.rightmost = thisIsOnNewLine - } - } - leftmost: index === 0 - rightmost: index === paletteFlow.palettes.length - 1 - buttonText: modelData.displayName; - toggled: ConfigOptions.appearance.palette.type === modelData.value - onClicked: { - ConfigLoader.setConfigValueAndSave("appearance.palette.type", modelData.value); - } - } - } } // Wallpaper selection @@ -214,9 +191,8 @@ ContentPage { title: "Shell windows" spacing: 4 - RowLayout { - spacing: 10 - uniformCellSizes: true + ConfigRow { + uniform: true ConfigSwitch { text: "Title bar" checked: ConfigOptions.windows.showTitlebar diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index ee5a28eb..f9245cbc 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -201,84 +201,42 @@ ApplicationWindow { ContentSection { title: "Policies" - RowLayout { - Layout.alignment: Qt.AlignHCenter - spacing: 15 + ConfigRow { ColumnLayout { // Weeb policy StyledText { text: "Weeb" color: Appearance.colors.colSubtext } - ButtonGroup { - id: weebPolicyBtnGroup - property int selectedPolicy: ConfigOptions.policies.weeb - spacing: 2 - SelectionGroupButton { - property int value: 0 - leftmost: true - buttonText: "No" - toggled: (weebPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.weeb", value); - } - } - SelectionGroupButton { - property int value: 1 - buttonText: "Yes" - toggled: (weebPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.weeb", value); - } - } - SelectionGroupButton { - property int value: 2 - rightmost: true - buttonText: "Closet" - toggled: (weebPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.weeb", value); - } - StyledToolTip { - content: "The Anime tab on the left sidebar would still\nbe available, but its tab button won't show" - } + ConfigSelectionArray { + currentValue: ConfigOptions.policies.weeb + configOptionName: "policies.weeb" + onSelected: (newValue) => { + ConfigLoader.setConfigValueAndSave("policies.weeb", newValue); } + options: [ + { displayName: "No", value: 0 }, + { displayName: "Yes", value: 1 }, + { displayName: "Closet", value: 2 } + ] } } + ColumnLayout { // AI policy StyledText { text: "AI" color: Appearance.colors.colSubtext } - ButtonGroup { - id: aiPolicyBtnGroup - property int selectedPolicy: ConfigOptions.policies.ai - spacing: 2 - SelectionGroupButton { - property int value: 0 - leftmost: true - buttonText: "No" - toggled: (aiPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.ai", value); - } - } - SelectionGroupButton { - property int value: 1 - buttonText: "Yes" - toggled: (aiPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.ai", value); - } - } - SelectionGroupButton { - property int value: 2 - rightmost: true - buttonText: "Local only" - toggled: (aiPolicyBtnGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("policies.ai", value); - } + ConfigSelectionArray { + currentValue: ConfigOptions.policies.ai + configOptionName: "policies.ai" + onSelected: (newValue) => { + ConfigLoader.setConfigValueAndSave("policies.ai", newValue); } + options: [ + { displayName: "No", value: 0 }, + { displayName: "Yes", value: 1 }, + { displayName: "Local only", value: 2 } + ] } } } From e4be9852a3fec1d9fabfaeca3691a298e89b51ae Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 21 Jun 2025 02:51:21 +0200 Subject: [PATCH 042/328] quickshell: switch from hyprland dispatch exec trick to quickshell execdetached --- .../quickshell/modules/common/Directories.qml | 14 +++++----- .../modules/common/widgets/CliphistImage.qml | 3 ++- .../widgets/LightDarkPreferenceButton.qml | 4 +-- .../common/widgets/NotificationItem.qml | 8 +----- .../modules/overview/OverviewWidget.qml | 1 - .../modules/overview/SearchWidget.qml | 8 +++--- .../quickshell/modules/session/Session.qml | 10 +++---- .config/quickshell/modules/settings/Style.qml | 2 +- .../modules/sidebarLeft/aiChat/AiMessage.qml | 2 +- .../sidebarLeft/aiChat/MessageCodeBlock.qml | 8 +++--- .../modules/sidebarLeft/anime/BooruImage.qml | 4 ++- .../modules/sidebarRight/SidebarRight.qml | 2 +- .../quickToggles/BluetoothToggle.qml | 4 +-- .../sidebarRight/quickToggles/GameMode.qml | 5 ++-- .../quickToggles/NetworkToggle.qml | 2 +- .config/quickshell/services/Battery.qml | 6 +++-- .config/quickshell/services/ConfigLoader.qml | 11 ++++---- .../services/FirstRunExperience.qml | 8 +++--- .config/quickshell/services/Ydotool.qml | 27 ++++++++++++++----- .config/quickshell/welcome.qml | 7 +++-- .../illogical-impulse-widgets/PKGBUILD | 2 +- 21 files changed, 75 insertions(+), 63 deletions(-) diff --git a/.config/quickshell/modules/common/Directories.qml b/.config/quickshell/modules/common/Directories.qml index 32c90562..05741f20 100644 --- a/.config/quickshell/modules/common/Directories.qml +++ b/.config/quickshell/modules/common/Directories.qml @@ -32,12 +32,12 @@ Singleton { property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/switchwall.sh`) // Cleanup on init Component.onCompleted: { - Hyprland.dispatch(`exec mkdir -p '${shellConfig}'`) - Hyprland.dispatch(`exec mkdir -p '${favicons}'`) - Hyprland.dispatch(`exec rm -rf '${coverArt}'; mkdir -p '${coverArt}'`) - Hyprland.dispatch(`exec rm -rf '${booruPreviews}'; mkdir -p '${booruPreviews}'`) - Hyprland.dispatch(`exec mkdir -p '${booruDownloads}' && mkdir -p '${booruDownloadsNsfw}'`) - Hyprland.dispatch(`exec rm -rf '${latexOutput}'; mkdir -p '${latexOutput}'`) - Hyprland.dispatch(`exec rm -rf '${cliphistDecode}'; mkdir -p '${cliphistDecode}'`) + Quickshell.execDetached(["bash", "-c", `mkdir -p '${shellConfig}'`]) + Quickshell.execDetached(["bash", "-c", `mkdir -p '${favicons}'`]) + Quickshell.execDetached(["bash", "-c", `rm -rf '${coverArt}'; mkdir -p '${coverArt}'`]) + Quickshell.execDetached(["bash", "-c", `rm -rf '${booruPreviews}'; mkdir -p '${booruPreviews}'`]) + Quickshell.execDetached(["bash", "-c", `mkdir -p '${booruDownloads}' && mkdir -p '${booruDownloadsNsfw}'`]) + Quickshell.execDetached(["bash", "-c", `rm -rf '${latexOutput}'; mkdir -p '${latexOutput}'`]) + Quickshell.execDetached(["bash", "-c", `rm -rf '${cliphistDecode}'; mkdir -p '${cliphistDecode}'`]) } } diff --git a/.config/quickshell/modules/common/widgets/CliphistImage.qml b/.config/quickshell/modules/common/widgets/CliphistImage.qml index 9de34450..62d948cf 100644 --- a/.config/quickshell/modules/common/widgets/CliphistImage.qml +++ b/.config/quickshell/modules/common/widgets/CliphistImage.qml @@ -8,6 +8,7 @@ import Qt.labs.platform import QtQuick import QtQuick.Controls import QtQuick.Layouts +import Quickshell import Quickshell.Io import Quickshell.Widgets import Quickshell.Hyprland @@ -71,7 +72,7 @@ Rectangle { } Component.onDestruction: { - Hyprland.dispatch(`exec bash -c "[ -f '${imageDecodeFilePath}' ] && rm -f '${imageDecodeFilePath}'"`) + Quickshell.execDetached(["bash", "-c", `[ -f '${imageDecodeFilePath}' ] && rm -f '${imageDecodeFilePath}'`]) } Image { diff --git a/.config/quickshell/modules/common/widgets/LightDarkPreferenceButton.qml b/.config/quickshell/modules/common/widgets/LightDarkPreferenceButton.qml index e1900c9f..1733bca3 100644 --- a/.config/quickshell/modules/common/widgets/LightDarkPreferenceButton.qml +++ b/.config/quickshell/modules/common/widgets/LightDarkPreferenceButton.qml @@ -4,7 +4,7 @@ import "root:/modules/common/functions/color_utils.js" as ColorUtils import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io +import Quickshell import Quickshell.Io import Quickshell.Hyprland @@ -19,7 +19,7 @@ GroupButton { colBackground: Appearance.colors.colLayer2 toggled: Appearance.m3colors.darkmode === dark onClicked: { - Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode ${dark ? "dark" : "light"} --noswitch`) + Quickshell.execDetached(["bash", "-c", `${Directories.wallpaperSwitchScriptPath} --mode ${dark ? "dark" : "light"} --noswitch`]) } contentItem: Item { anchors.centerIn: parent diff --git a/.config/quickshell/modules/common/widgets/NotificationItem.qml b/.config/quickshell/modules/common/widgets/NotificationItem.qml index e078d503..fd11e582 100644 --- a/.config/quickshell/modules/common/widgets/NotificationItem.qml +++ b/.config/quickshell/modules/common/widgets/NotificationItem.qml @@ -94,12 +94,6 @@ Item { // Notification item area } } - onPressAndHold: (mouse) => { - if (mouse.button === Qt.LeftButton) { - Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(notificationObject.body)}'`) - notificationSummaryText.text = String.format(qsTr("{0} (copied)"), notificationObject.summary) - } - } onDraggingChanged: () => { if (dragging) { root.qmlParent.dragIndex = root.index ?? root.parent.children.indexOf(root); @@ -291,7 +285,7 @@ Item { // Notification item area (contentItem.implicitWidth + leftPadding + rightPadding) onClicked: { - Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(notificationObject.body)}'`) + Quickshell.clipboardText = notificationObject.body copyIcon.text = "inventory" copyIconTimer.restart() } diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index e0999d6e..5faa8699 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -111,7 +111,6 @@ Item { acceptedButtons: Qt.LeftButton onClicked: { if (root.draggingTargetWorkspace === -1) { - // Hyprland.dispatch(`exec qs ipc call overview close`) GlobalStates.overviewOpen = false Hyprland.dispatch(`workspace ${workspaceValue}`) } diff --git a/.config/quickshell/modules/overview/SearchWidget.qml b/.config/quickshell/modules/overview/SearchWidget.qml index 614efa91..7d7cc952 100644 --- a/.config/quickshell/modules/overview/SearchWidget.qml +++ b/.config/quickshell/modules/overview/SearchWidget.qml @@ -303,7 +303,9 @@ Item { // Wrapper clickActionName: "", type: `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`, execute: () => { - Hyprland.dispatch(`exec echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`); + Quickshell.execDetached( + ["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`] + ); } }; }).filter(Boolean); @@ -318,7 +320,7 @@ Item { // Wrapper clickActionName: "", type: "Emoji", execute: () => { - Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(entry.match(/^\s*(\S+)/)?.[1])}'`); + Quickshell.clipboardText = entry.match(/^\s*(\S+)/)?.[1] } }; }).filter(Boolean); @@ -334,7 +336,7 @@ Item { // Wrapper fontType: "monospace", materialSymbol: 'calculate', execute: () => { - Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(root.mathResult)}'`) + Quickshell.clipboardText = root.mathResult; } } const commandResultObject = { diff --git a/.config/quickshell/modules/session/Session.qml b/.config/quickshell/modules/session/Session.qml index 94e6123f..20628edb 100644 --- a/.config/quickshell/modules/session/Session.qml +++ b/.config/quickshell/modules/session/Session.qml @@ -121,7 +121,7 @@ Scope { id: sessionTaskManager buttonIcon: "browse_activity" buttonText: qsTr("Task Manager") - onClicked: { Hyprland.dispatch(`exec ${ConfigOptions.apps.taskManager}`); sessionRoot.hide() } + onClicked: { Quickshell.execDetached(["bash", "-c", `${ConfigOptions.apps.taskManager}`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionLogout KeyNavigation.down: sessionFirmwareReboot @@ -131,7 +131,7 @@ Scope { id: sessionHibernate buttonIcon: "downloading" buttonText: qsTr("Hibernate") - onClicked: { Hyprland.dispatch("exec systemctl hibernate || loginctl hibernate"); sessionRoot.hide() } + onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl hibernate || loginctl hibernate`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.up: sessionLock KeyNavigation.right: sessionShutdown @@ -140,7 +140,7 @@ Scope { id: sessionShutdown buttonIcon: "power_settings_new" buttonText: qsTr("Shutdown") - onClicked: { Hyprland.dispatch("exec systemctl poweroff || loginctl poweroff"); sessionRoot.hide() } + onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl poweroff || loginctl poweroff`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionHibernate KeyNavigation.right: sessionReboot @@ -150,7 +150,7 @@ Scope { id: sessionReboot buttonIcon: "restart_alt" buttonText: qsTr("Reboot") - onClicked: { Hyprland.dispatch("exec reboot || loginctl reboot"); sessionRoot.hide() } + onClicked: { Quickshell.execDetached(["bash", "-c", `reboot || loginctl reboot`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionShutdown KeyNavigation.right: sessionFirmwareReboot @@ -160,7 +160,7 @@ Scope { id: sessionFirmwareReboot buttonIcon: "settings_applications" buttonText: qsTr("Reboot to firmware settings") - onClicked: { Hyprland.dispatch("exec systemctl reboot --firmware-setup || loginctl reboot --firmware-setup"); sessionRoot.hide() } + onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl reboot --firmware-setup || loginctl reboot --firmware-setup`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.up: sessionTaskManager KeyNavigation.left: sessionReboot diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml index 3e8e7ae3..87775072 100644 --- a/.config/quickshell/modules/settings/Style.qml +++ b/.config/quickshell/modules/settings/Style.qml @@ -93,7 +93,7 @@ ContentPage { content: "Pick wallpaper image on your system" } onClicked: { - Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath}`) + Quickshell.execDetached(`${Directories.wallpaperSwitchScriptPath}`) } mainContentComponent: Component { RowLayout { diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml index 8d795211..e242030f 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml @@ -185,7 +185,7 @@ Rectangle { buttonIcon: activated ? "inventory" : "content_copy" onClicked: { - Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(root.messageData?.content)}'`) + Quickshell.clipboardText = root.messageData?.content copyButton.activated = true copyIconTimer.restart() } diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml b/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml index ea7bb0ee..881942b7 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml @@ -73,7 +73,7 @@ ColumnLayout { buttonIcon: activated ? "inventory" : "content_copy" onClicked: { - Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(segmentContent)}'`) + Quickshell.clipboardText = segmentContent copyCodeButton.activated = true copyIconTimer.restart() } @@ -96,8 +96,10 @@ ColumnLayout { onClicked: { const downloadPath = FileUtils.trimFileProtocol(Directories.downloads) - Hyprland.dispatch(`exec echo '${StringUtils.shellSingleQuoteEscape(segmentContent)}' > '${downloadPath}/code.${segmentLang || "txt"}'`) - Hyprland.dispatch(`exec notify-send 'Code saved to file' '${downloadPath}/code.${segmentLang || "txt"}' -a Shell`) + Quickshell.execDetached(["bash", "-c", + `echo '${StringUtils.shellSingleQuoteEscape(segmentContent)}' > '${downloadPath}/code.${segmentLang || "txt"}'` + ]) + Quickshell.execDetached(["bash", "-c", `notify-send 'Code saved to file' '${downloadPath}/code.${segmentLang || "txt"}' -a Shell`]) saveCodeButton.activated = true saveIconTimer.restart() } diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml b/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml index 4e115bc7..51b22d62 100644 --- a/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml +++ b/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml @@ -180,7 +180,9 @@ Button { buttonText: qsTr("Download") onClicked: { root.showActions = false - Hyprland.dispatch(`exec curl '${root.imageData.file_url}' -o '${root.imageData.is_nsfw ? root.nsfwPath : root.downloadPath}/${root.fileName}' && notify-send '${qsTr("Download complete")}' '${root.downloadPath}/${root.fileName}' -a 'Shell'`) + Quickshell.execDetached(["bash", "-c", + `curl '${root.imageData.file_url}' -o '${root.imageData.is_nsfw ? root.nsfwPath : root.downloadPath}/${root.fileName}' && notify-send '${qsTr("Download complete")}' '${root.downloadPath}/${root.fileName}' -a 'Shell'` + ]) } } } diff --git a/.config/quickshell/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/modules/sidebarRight/SidebarRight.qml index 52ddae7d..ebdd9e4e 100644 --- a/.config/quickshell/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/modules/sidebarRight/SidebarRight.qml @@ -147,7 +147,7 @@ Scope { buttonIcon: "settings" onClicked: { Hyprland.dispatch("global quickshell:sidebarRightClose") - Hyprland.dispatch(`exec qs -p '${root.settingsQmlPath}'`) + Quickshell.execDetached(["qs", "-p", root.settingsQmlPath]) } StyledToolTip { content: qsTr("Settings") diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml b/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml index 083ecc03..d8c55b58 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml @@ -15,8 +15,8 @@ QuickToggleButton { toggleBluetooth.running = true } altAction: () => { - Hyprland.dispatch(`exec ${ConfigOptions.apps.bluetooth}`) - Hyprland.dispatch("global quickshell:sidebarRightClose") + Quickshell.execDetached(["bash", "-c", `${ConfigOptions.apps.bluetooth}`]) + Hyprland.dispatch("global quickshell:sidebarRightClose") } Process { id: toggleBluetooth diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml b/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml index 1cd56acc..2f769373 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml @@ -13,10 +13,9 @@ QuickToggleButton { onClicked: { enabled = !enabled if (enabled) { - // gameModeOn.running = true - Hyprland.dispatch(`exec hyprctl --batch "keyword animations:enabled 0; keyword decoration:shadow:enabled 0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword general:allow_tearing 1"`) + Quickshell.execDetached(["bash", "-c", `hyprctl --batch "keyword animations:enabled 0; keyword decoration:shadow:enabled 0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword general:allow_tearing 1"`]) } else { - Hyprland.dispatch("exec hyprctl reload") + Quickshell.execDetached(["hyprctl", "reload"]) } } diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml b/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml index 5271e376..010b6ae5 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml @@ -15,7 +15,7 @@ QuickToggleButton { toggleNetwork.running = true } altAction: () => { - Hyprland.dispatch(`exec ${Network.ethernet ? ConfigOptions.apps.networkEthernet : ConfigOptions.apps.network}`) + Quickshell.execDetached(["bash", "-c", `${Network.ethernet ? ConfigOptions.apps.networkEthernet : ConfigOptions.apps.network}`]) Hyprland.dispatch("global quickshell:sidebarRightClose") } Process { diff --git a/.config/quickshell/services/Battery.qml b/.config/quickshell/services/Battery.qml index 08bdee7c..b19910d8 100644 --- a/.config/quickshell/services/Battery.qml +++ b/.config/quickshell/services/Battery.qml @@ -21,10 +21,12 @@ Singleton { property bool isCriticalAndNotCharging: isCritical && !isCharging onIsLowAndNotChargingChanged: { - if (available && isLowAndNotCharging) Hyprland.dispatch(`exec notify-send "Low battery" "Consider plugging in your device" -u critical -a "Shell"`) + if (available && isLowAndNotCharging) + Quickshell.execDetached(["bash", "-c", `notify-send "Low battery" "Consider plugging in your device" -u critical -a "Shell"`]); } onIsCriticalAndNotChargingChanged: { - if (available && isCriticalAndNotCharging) Hyprland.dispatch(`exec notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${ConfigOptions.battery.suspend}%" -u critical -a "Shell"`) + if (available && isCriticalAndNotCharging) + Quickshell.execDetached(["bash", "-c", `notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${ConfigOptions.battery.suspend}%" -u critical -a "Shell"`]); } } diff --git a/.config/quickshell/services/ConfigLoader.qml b/.config/quickshell/services/ConfigLoader.qml index 347e8f40..f7dadcee 100644 --- a/.config/quickshell/services/ConfigLoader.qml +++ b/.config/quickshell/services/ConfigLoader.qml @@ -44,9 +44,8 @@ Singleton { } catch (e) { console.error("[ConfigLoader] Error reading file:", e); console.log("[ConfigLoader] File content was:", fileContent); - Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration failed to load")}" "${root.filePath}"`) + Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration failed to load")}' '${root.filePath}'`]) return; - } } @@ -82,7 +81,7 @@ Singleton { function saveConfig() { const plainConfig = ObjectUtils.toPlainObject(ConfigOptions) - Hyprland.dispatch(`exec echo '${StringUtils.shellSingleQuoteEscape(JSON.stringify(plainConfig, null, 2))}' > '${root.filePath}'`) + Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(JSON.stringify(plainConfig, null, 2))}' > '${FileUtils.trimFileProtocol(root.filePath)}'`]) } function setConfigValueAndSave(nestedKey, value, preventNextNotification = true) { @@ -105,7 +104,7 @@ Singleton { } else { root.applyConfig(configFileView.text()) if (!root.preventNextNotification) { - // Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration reloaded")}" "${root.filePath}"`) + // Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration reloaded")}' '${root.filePath}'`]) } else { root.preventNextNotification = false; } @@ -129,9 +128,9 @@ Singleton { if(error == FileViewError.FileNotFound) { console.log("[ConfigLoader] File not found, creating new file.") root.saveConfig() - Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration created")}" "${root.filePath}"`) + Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration created")}' '${root.filePath}'`]) } else { - Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration failed to load")}" "${root.filePath}"`) + Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration failed to load")}' '${root.filePath}'`]) } } } diff --git a/.config/quickshell/services/FirstRunExperience.qml b/.config/quickshell/services/FirstRunExperience.qml index 86ccb98b..4b1f034c 100644 --- a/.config/quickshell/services/FirstRunExperience.qml +++ b/.config/quickshell/services/FirstRunExperience.qml @@ -20,15 +20,15 @@ Singleton { } function enableNextTime() { - Hyprland.dispatch(`exec rm -f '${root.firstRunFilePath}'`) + Quickshell.execDetached(["rm", "-f", root.firstRunFilePath]) } function disableNextTime() { - Hyprland.dispatch(`exec echo '${root.firstRunFileContent}' > '${root.firstRunFilePath}'`) + Quickshell.execDetached(["bash", "-c", `echo '${root.firstRunFileContent}' > '${root.firstRunFilePath}'`]) } function handleFirstRun() { - Hyprland.dispatch(`exec swww query | grep 'image' || '${Directories.wallpaperSwitchScriptPath}' '${root.defaultWallpaperPath}'`) - Hyprland.dispatch(`exec qs -p '${root.welcomeQmlPath}'`) + Quickshell.execDetached(["bash", "-c", `swww query | grep 'image' || '${Directories.wallpaperSwitchScriptPath}' '${root.defaultWallpaperPath}'`]) + Quickshell.execDetached(["bash", "-c", `qs -p '${root.welcomeQmlPath}'`]) } FileView { diff --git a/.config/quickshell/services/Ydotool.qml b/.config/quickshell/services/Ydotool.qml index 7cafcbbe..f702010d 100644 --- a/.config/quickshell/services/Ydotool.qml +++ b/.config/quickshell/services/Ydotool.qml @@ -20,23 +20,36 @@ Singleton { function releaseAllKeys() { const keycodes = Array.from(Array(249).keys()); - const releaseCommand = `ydotool key --key-delay 0 ${keycodes.map(keycode => `${keycode}:0`).join(" ")}` - Hyprland.dispatch(`exec ${releaseCommand}`) + Quickshell.execDetached([ + "ydotool", + "key", "--key-delay", "0", + ...keycodes.map(keycode => `${keycode}:0`) + ]) root.shiftMode = 0; // Reset shift mode } function releaseShiftKeys() { - const releaseCommand = `ydotool key --key-delay 0 ${root.shiftKeys.map(keycode => `${keycode}:0`).join(" ")}` - Hyprland.dispatch(`exec ${releaseCommand}`) + Quickshell.execDetached([ + "ydotool", + "key", "--key-delay", "0", + ...root.shiftKeys.map(keycode => `${keycode}:0`) + ]) root.shiftMode = 0; // Reset shift mode } function press(keycode) { - Hyprland.dispatch(`exec ydotool key --key-delay 0 ${keycode}:1`); + Quickshell.execDetached([ + "ydotool", + "key", "--key-delay", "0", + `${keycode}:1` + ]); } function release(keycode) { - Hyprland.dispatch(`exec ydotool key --key-delay 0 ${keycode}:0`); + Quickshell.execDetached([ + "ydotool", + "key", "--key-delay", "0", + `${keycode}:0` + ]); } } - diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index f9245cbc..9adaef8c 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -91,10 +91,9 @@ ApplicationWindow { Layout.alignment: Qt.AlignVCenter onCheckedChanged: { if (checked) { - Hyprland.dispatch(`exec rm '${StringUtils.shellSingleQuoteEscape(root.firstRunFilePath)}'`) + Quickshell.execDetached(["rm", root.firstRunFilePath]) } else { - console.log(`exec echo '${StringUtils.shellSingleQuoteEscape(root.firstRunFileContent)}' > '${StringUtils.shellSingleQuoteEscape(root.firstRunFilePath)}'`) - Hyprland.dispatch(`exec echo '${StringUtils.shellSingleQuoteEscape(root.firstRunFileContent)}' > '${StringUtils.shellSingleQuoteEscape(root.firstRunFilePath)}'`) + Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(root.firstRunFileContent)}' > '${StringUtils.shellSingleQuoteEscape(root.firstRunFilePath)}'`]) } } } @@ -159,7 +158,7 @@ ApplicationWindow { content: "Pick wallpaper image on your system" } onClicked: { - Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath}`) + Quickshell.execDetached([`${Directories.wallpaperSwitchScriptPath}`]) } mainContentComponent: Component { RowLayout { diff --git a/arch-packages/illogical-impulse-widgets/PKGBUILD b/arch-packages/illogical-impulse-widgets/PKGBUILD index 868bea9e..ae26fc90 100644 --- a/arch-packages/illogical-impulse-widgets/PKGBUILD +++ b/arch-packages/illogical-impulse-widgets/PKGBUILD @@ -12,7 +12,7 @@ depends=( hyprlock hyprpicker nm-connection-editor - quickshell + quickshell-git swww translate-shell wlogout From ddcf13678dd1e8693f355221bd31c4151333c913 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 21 Jun 2025 03:00:01 +0200 Subject: [PATCH 043/328] sidebar: make gamemode update properly --- .../sidebarRight/quickToggles/GameMode.qml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml b/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml index 2f769373..79c1eba7 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml @@ -6,19 +6,27 @@ import Quickshell.Io import Quickshell.Hyprland QuickToggleButton { - property bool enabled: false + id: root buttonIcon: "gamepad" - toggled: enabled + toggled: toggled onClicked: { - enabled = !enabled - if (enabled) { + root.toggled = !root.toggled + if (root.toggled) { Quickshell.execDetached(["bash", "-c", `hyprctl --batch "keyword animations:enabled 0; keyword decoration:shadow:enabled 0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword general:allow_tearing 1"`]) } else { Quickshell.execDetached(["hyprctl", "reload"]) } } - + Process { + id: fetchActiveState + running: true + command: ["bash", "-c", `test "$(hyprctl getoption animations:enabled -j | jq ".int")" -ne 0`] + onExited: (exitCode, exitStatus) => { + console.log("Game mode toggle exited with code:", exitCode, "and status:", exitStatus) + root.toggled = exitCode !== 0 // Inverted because enabled = nonzero exit + } + } StyledToolTip { content: qsTr("Game mode") } From 5ffbd55f58e661a61e8e538d31714f94fe147773 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 21 Jun 2025 03:24:03 +0200 Subject: [PATCH 044/328] settings: bar and audio options --- .../modules/common/widgets/ConfigSwitch.qml | 1 + .../quickshell/modules/overview/Overview.qml | 3 +- .../modules/settings/BehaviorConfig.qml | 15 ++++++- .config/quickshell/modules/settings/Style.qml | 44 ++++++++++++++----- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/ConfigSwitch.qml b/.config/quickshell/modules/common/widgets/ConfigSwitch.qml index 01dda8a2..51f82a72 100644 --- a/.config/quickshell/modules/common/widgets/ConfigSwitch.qml +++ b/.config/quickshell/modules/common/widgets/ConfigSwitch.qml @@ -8,6 +8,7 @@ RippleButton { id: root Layout.fillWidth: true implicitHeight: contentItem.implicitHeight + 8 * 2 + onClicked: checked = !checked contentItem: RowLayout { spacing: 10 diff --git a/.config/quickshell/modules/overview/Overview.qml b/.config/quickshell/modules/overview/Overview.qml index a7817e6e..8e33db61 100644 --- a/.config/quickshell/modules/overview/Overview.qml +++ b/.config/quickshell/modules/overview/Overview.qml @@ -92,8 +92,7 @@ Scope { visible: GlobalStates.overviewOpen anchors { horizontalCenter: parent.horizontalCenter - top: !ConfigOptions.bar.bottom ? parent.top : undefined - bottom: ConfigOptions.bar.bottom ? parent.bottom : undefined + top: parent.top } Keys.onPressed: (event) => { diff --git a/.config/quickshell/modules/settings/BehaviorConfig.qml b/.config/quickshell/modules/settings/BehaviorConfig.qml index 9cec75c3..7fc90212 100644 --- a/.config/quickshell/modules/settings/BehaviorConfig.qml +++ b/.config/quickshell/modules/settings/BehaviorConfig.qml @@ -48,7 +48,18 @@ ContentPage { } } } - - + } + ContentSection { + title: "Audio" + ConfigSwitch { + text: "Earbang protection" + checked: ConfigOptions.audio.protection.enable + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("audio.protection.enable", checked); + } + StyledToolTip { + content: "Prevents abrupt increments and restricts volume limit" + } + } } } \ No newline at end of file diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml index 87775072..50803e16 100644 --- a/.config/quickshell/modules/settings/Style.qml +++ b/.config/quickshell/modules/settings/Style.qml @@ -174,15 +174,41 @@ ContentPage { } } - ConfigSwitch { - text: "Transparency" - checked: ConfigOptions.appearance.transparency - onClicked: checked = !checked; - onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("appearance.transparency", checked); + ConfigRow { + ConfigSwitch { + text: "Transparency" + checked: ConfigOptions.appearance.transparency + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("appearance.transparency", checked); + } + StyledToolTip { + content: "Might look ass. Unsupported." + } } - StyledToolTip { - content: "Might look ass. Unsupported." + } + + StyledText { + text: "Bar" + color: Appearance.colors.colSubtext + } + ConfigRow { + uniform: true + ConfigSwitch { + text: 'Borderless' + checked: ConfigOptions.bar.borderless + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.borderless", checked); + } + } + ConfigSwitch { + text: 'Show background' + checked: ConfigOptions.bar.showBackground + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.showBackground", checked); + } + StyledToolTip { + content: "Note: turning off can hurt readability" + } } } } @@ -196,7 +222,6 @@ ContentPage { ConfigSwitch { text: "Title bar" checked: ConfigOptions.windows.showTitlebar - onClicked: checked = !checked; onCheckedChanged: { ConfigLoader.setConfigValueAndSave("windows.showTitlebar", checked); } @@ -204,7 +229,6 @@ ContentPage { ConfigSwitch { text: "Center title" checked: ConfigOptions.windows.centerTitle - onClicked: checked = !checked; onCheckedChanged: { ConfigLoader.setConfigValueAndSave("windows.centerTitle", checked); } From 7e46e40eeb80c7f1dd56aaa8f66f1ea892dffade Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 21 Jun 2025 11:59:40 +0200 Subject: [PATCH 045/328] settings: reorganize and add settings --- .../quickshell/modules/common/Appearance.qml | 4 +- .../modules/common/widgets/ContentSection.qml | 2 +- .../common/widgets/ContentSubsection.qml | 26 ++ .../common/widgets/ContentSubsectionLabel.qml | 10 + .../common/widgets/MaterialTextField.qml | 53 ++++ .../widgets/NavigationRailExpandButton.qml | 6 + .../modules/settings/BehaviorConfig.qml | 65 ----- .../modules/settings/GeneralConfig.qml | 144 +++++++++++ .config/quickshell/modules/settings/Style.qml | 238 ------------------ .../modules/settings/StyleConfig.qml | 213 ++++++++++++++++ .config/quickshell/settings.qml | 39 ++- .config/quickshell/welcome.qml | 6 +- 12 files changed, 489 insertions(+), 317 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/ContentSubsection.qml create mode 100644 .config/quickshell/modules/common/widgets/ContentSubsectionLabel.qml create mode 100644 .config/quickshell/modules/common/widgets/MaterialTextField.qml delete mode 100644 .config/quickshell/modules/settings/BehaviorConfig.qml create mode 100644 .config/quickshell/modules/settings/GeneralConfig.qml delete mode 100644 .config/quickshell/modules/settings/Style.qml create mode 100644 .config/quickshell/modules/settings/StyleConfig.qml diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 202230a3..0036eb61 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -203,7 +203,7 @@ Singleton { animation: QtObject { property QtObject elementMove: QtObject { - property int duration: 500 + property int duration: animationCurves.expressiveDefaultSpatialDuration property int type: Easing.BezierSpline property list bezierCurve: animationCurves.expressiveDefaultSpatial property int velocity: 650 @@ -249,7 +249,7 @@ Singleton { } } property QtObject elementMoveFast: QtObject { - property int duration: 200 + property int duration: animationCurves.expressiveEffectsDuration property int type: Easing.BezierSpline property list bezierCurve: animationCurves.expressiveEffects property int velocity: 850 diff --git a/.config/quickshell/modules/common/widgets/ContentSection.qml b/.config/quickshell/modules/common/widgets/ContentSection.qml index 8c423e37..ee2410c4 100644 --- a/.config/quickshell/modules/common/widgets/ContentSection.qml +++ b/.config/quickshell/modules/common/widgets/ContentSection.qml @@ -17,6 +17,6 @@ ColumnLayout { } ColumnLayout { id: sectionContent - spacing: 4 + spacing: 8 } } diff --git a/.config/quickshell/modules/common/widgets/ContentSubsection.qml b/.config/quickshell/modules/common/widgets/ContentSubsection.qml new file mode 100644 index 00000000..6df0c8fa --- /dev/null +++ b/.config/quickshell/modules/common/widgets/ContentSubsection.qml @@ -0,0 +1,26 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +ColumnLayout { + id: root + property string title: "" + default property alias data: sectionContent.data + + Layout.fillWidth: true + Layout.topMargin: 4 + spacing: 2 + + ContentSubsectionLabel { + Layout.fillWidth: true + visible: root.title && root.title.length > 0 + text: root.title + } + ColumnLayout { + id: sectionContent + Layout.fillWidth: true + spacing: 2 + } +} diff --git a/.config/quickshell/modules/common/widgets/ContentSubsectionLabel.qml b/.config/quickshell/modules/common/widgets/ContentSubsectionLabel.qml new file mode 100644 index 00000000..549ccae2 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/ContentSubsectionLabel.qml @@ -0,0 +1,10 @@ +import QtQuick +import QtQuick.Layouts +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +StyledText { + text: "Subsection" + color: Appearance.colors.colSubtext + Layout.leftMargin: 4 +} diff --git a/.config/quickshell/modules/common/widgets/MaterialTextField.qml b/.config/quickshell/modules/common/widgets/MaterialTextField.qml new file mode 100644 index 00000000..1129c6d8 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/MaterialTextField.qml @@ -0,0 +1,53 @@ +import "root:/modules/common" +import "root:/modules/common/functions/color_utils.js" as ColorUtils +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Controls + +/** + * Material 3 styled TextArea (filled style) + * https://m3.material.io/components/text-fields/overview + * Note: We don't use NativeRendering because it makes the small placeholder text look weird + */ +TextArea { + id: root + Material.theme: Material.System + Material.accent: Appearance.m3colors.m3primary + Material.primary: Appearance.m3colors.m3primary + Material.background: Appearance.m3colors.m3surface + Material.foreground: Appearance.m3colors.m3onSurface + Material.containerStyle: Material.Filled + renderType: Text.QtRendering + + selectedTextColor: Appearance.m3colors.m3onSecondaryContainer + selectionColor: Appearance.colors.colSecondaryContainer + placeholderTextColor: Appearance.m3colors.m3outline + + background: Rectangle { + implicitHeight: 56 + color: Appearance.m3colors.m3surface + topLeftRadius: 4 + topRightRadius: 4 + Rectangle { + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + height: 1 + color: root.focus ? Appearance.m3colors.m3primary : + root.hovered ? Appearance.m3colors.m3outline : Appearance.m3colors.m3outlineVariant + + Behavior on color { + animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) + } + } + } + + font { + family: Appearance?.font.family.main ?? "sans-serif" + pixelSize: Appearance?.font.pixelSize.small ?? 15 + hintingPreference: Font.PreferFullHinting + } + wrapMode: TextEdit.Wrap +} diff --git a/.config/quickshell/modules/common/widgets/NavigationRailExpandButton.qml b/.config/quickshell/modules/common/widgets/NavigationRailExpandButton.qml index 2c138b87..11fe37bc 100644 --- a/.config/quickshell/modules/common/widgets/NavigationRailExpandButton.qml +++ b/.config/quickshell/modules/common/widgets/NavigationRailExpandButton.qml @@ -14,6 +14,12 @@ RippleButton { parent.expanded = !parent.expanded; } buttonRadius: Appearance.rounding.full + + rotation: root.parent.expanded ? 0 : -180 + Behavior on rotation { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + contentItem: MaterialSymbol { id: icon anchors.centerIn: parent diff --git a/.config/quickshell/modules/settings/BehaviorConfig.qml b/.config/quickshell/modules/settings/BehaviorConfig.qml deleted file mode 100644 index 7fc90212..00000000 --- a/.config/quickshell/modules/settings/BehaviorConfig.qml +++ /dev/null @@ -1,65 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import "root:/services/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" - -ContentPage { - ContentSection { - title: "Policies" - - ConfigRow { - ColumnLayout { // Weeb policy - StyledText { - text: "Weeb" - color: Appearance.colors.colSubtext - } - ConfigSelectionArray { - currentValue: ConfigOptions.policies.weeb - configOptionName: "policies.weeb" - onSelected: (newValue) => { - ConfigLoader.setConfigValueAndSave("policies.weeb", newValue); - } - options: [ - { displayName: "No", value: 0 }, - { displayName: "Yes", value: 1 }, - { displayName: "Closet", value: 2 } - ] - } - } - - ColumnLayout { // AI policy - StyledText { - text: "AI" - color: Appearance.colors.colSubtext - } - ConfigSelectionArray { - currentValue: ConfigOptions.policies.ai - configOptionName: "policies.ai" - onSelected: (newValue) => { - ConfigLoader.setConfigValueAndSave("policies.ai", newValue); - } - options: [ - { displayName: "No", value: 0 }, - { displayName: "Yes", value: 1 }, - { displayName: "Local only", value: 2 } - ] - } - } - } - } - ContentSection { - title: "Audio" - ConfigSwitch { - text: "Earbang protection" - checked: ConfigOptions.audio.protection.enable - onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("audio.protection.enable", checked); - } - StyledToolTip { - content: "Prevents abrupt increments and restricts volume limit" - } - } - } -} \ No newline at end of file diff --git a/.config/quickshell/modules/settings/GeneralConfig.qml b/.config/quickshell/modules/settings/GeneralConfig.qml new file mode 100644 index 00000000..ae051836 --- /dev/null +++ b/.config/quickshell/modules/settings/GeneralConfig.qml @@ -0,0 +1,144 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/services/" +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +ContentPage { + forceWidth: true + ContentSection { + title: "Policies" + + ConfigRow { + ColumnLayout { // Weeb policy + ContentSubsectionLabel { + text: "Weeb" + } + ConfigSelectionArray { + currentValue: ConfigOptions.policies.weeb + configOptionName: "policies.weeb" + onSelected: (newValue) => { + ConfigLoader.setConfigValueAndSave("policies.weeb", newValue); + } + options: [ + { displayName: "No", value: 0 }, + { displayName: "Yes", value: 1 }, + { displayName: "Closet", value: 2 } + ] + } + } + + ColumnLayout { // AI policy + ContentSubsectionLabel { + text: "AI" + } + ConfigSelectionArray { + currentValue: ConfigOptions.policies.ai + configOptionName: "policies.ai" + onSelected: (newValue) => { + ConfigLoader.setConfigValueAndSave("policies.ai", newValue); + } + options: [ + { displayName: "No", value: 0 }, + { displayName: "Yes", value: 1 }, + { displayName: "Local only", value: 2 } + ] + } + } + } + } + ContentSection { + title: "Audio" + ConfigSwitch { + text: "Earbang protection" + checked: ConfigOptions.audio.protection.enable + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("audio.protection.enable", checked); + } + StyledToolTip { + content: "Prevents abrupt increments and restricts volume limit" + } + } + } + ContentSection { + title: "AI" + MaterialTextField { + id: systemPromptField + Layout.fillWidth: true + placeholderText: "System prompt" + text: ConfigOptions.ai.systemPrompt + wrapMode: TextEdit.Wrap + onTextChanged: { + ConfigLoader.setConfigValueAndSave("ai.systemPrompt", text); + } + } + } + + ContentSection { + title: "Bar" + + ContentSubsection { + title: "Appearance" + ConfigRow { + uniform: true + ConfigSwitch { + text: 'Borderless' + checked: ConfigOptions.bar.borderless + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.borderless", checked); + } + } + ConfigSwitch { + text: 'Show background' + checked: ConfigOptions.bar.showBackground + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.showBackground", checked); + } + StyledToolTip { + content: "Note: turning off can hurt readability" + } + } + } + } + + ContentSubsection { + title: "Buttons" + ConfigRow { + uniform: true + ConfigSwitch { + text: "Screen snip" + checked: ConfigOptions.bar.utilButtons.showScreenSnip + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.utilButtons.showScreenSnip", checked); + } + } + ConfigSwitch { + text: "Color picker" + checked: ConfigOptions.bar.utilButtons.showColorPicker + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.utilButtons.showColorPicker", checked); + } + } + } + ConfigRow { + uniform: true + ConfigSwitch { + text: "Mic toggle" + checked: ConfigOptions.bar.utilButtons.showMicToggle + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.utilButtons.showMicToggle", checked); + } + } + ConfigSwitch { + text: "Keyboard toggle" + checked: ConfigOptions.bar.utilButtons.showKeyboardToggle + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.utilButtons.showKeyboardToggle", checked); + } + } + } + } + + } +} \ No newline at end of file diff --git a/.config/quickshell/modules/settings/Style.qml b/.config/quickshell/modules/settings/Style.qml deleted file mode 100644 index 50803e16..00000000 --- a/.config/quickshell/modules/settings/Style.qml +++ /dev/null @@ -1,238 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Quickshell.Io -import Quickshell.Hyprland -import "root:/services/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils - -ContentPage { - baseWidth: lightDarkButtonGroup.implicitWidth - forceWidth: true - - Process { - id: konachanWallProc - property string status: "" - command: ["bash", "-c", FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/random_konachan_wall.sh`)] - stdout: SplitParser { - onRead: data => { - console.log(`Konachan wall proc output: ${data}`); - konachanWallProc.status = data.trim(); - } - } - } - - ContentSection { - title: "Colors & Wallpaper" - - // Light/Dark mode preference - ButtonGroup { - id: lightDarkButtonGroup - Layout.fillWidth: true - LightDarkPreferenceButton { - dark: false - } - LightDarkPreferenceButton { - dark: true - } - } - - // Material palette selection - StyledText { - text: "Material palette" - color: Appearance.colors.colSubtext - } - - ConfigSelectionArray { - currentValue: ConfigOptions.appearance.palette.type - configOptionName: "appearance.palette.type" - onSelected: (newValue) => { - ConfigLoader.setConfigValueAndSave("appearance.palette.type", newValue); - } - options: [ - {"value": "auto", "displayName": "Auto"}, - {"value": "scheme-content", "displayName": "Content"}, - {"value": "scheme-expressive", "displayName": "Expressive"}, - {"value": "scheme-fidelity", "displayName": "Fidelity"}, - {"value": "scheme-fruit-salad", "displayName": "Fruit Salad"}, - {"value": "scheme-monochrome", "displayName": "Monochrome"}, - {"value": "scheme-neutral", "displayName": "Neutral"}, - {"value": "scheme-rainbow", "displayName": "Rainbow"}, - {"value": "scheme-tonal-spot", "displayName": "Tonal Spot"} - ] - } - - // Wallpaper selection - StyledText { - text: "Wallpaper" - color: Appearance.colors.colSubtext - } - RowLayout { - Layout.alignment: Qt.AlignHCenter - RippleButtonWithIcon { - id: rndWallBtn - Layout.alignment: Qt.AlignHCenter - buttonRadius: Appearance.rounding.small - materialIcon: "wallpaper" - mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan" - onClicked: { - console.log(konachanWallProc.command.join(" ")) - konachanWallProc.running = true; - } - StyledToolTip { - content: "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers" - } - } - RippleButtonWithIcon { - materialIcon: "wallpaper" - StyledToolTip { - content: "Pick wallpaper image on your system" - } - onClicked: { - Quickshell.execDetached(`${Directories.wallpaperSwitchScriptPath}`) - } - mainContentComponent: Component { - RowLayout { - spacing: 10 - StyledText { - font.pixelSize: Appearance.font.pixelSize.small - text: "Choose file" - color: Appearance.colors.colOnSecondaryContainer - } - RowLayout { - spacing: 3 - KeyboardKey { - key: "Ctrl" - } - KeyboardKey { - key: "󰖳" - } - StyledText { - Layout.alignment: Qt.AlignVCenter - text: "+" - } - KeyboardKey { - key: "T" - } - } - } - } - } - } - - StyledText { - Layout.alignment: Qt.AlignHCenter - text: "Change any time later with /dark, /light, /img in the launcher" - font.pixelSize: Appearance.font.pixelSize.smaller - color: Appearance.colors.colSubtext - } - - } - - ContentSection { - title: "Shell style" - - ColumnLayout { // Fake screen rounding - StyledText { - text: "Fake screen rounding" - color: Appearance.colors.colSubtext - } - ButtonGroup { - id: fakeScreenRoundingButtonGroup - property int selectedPolicy: ConfigOptions.appearance.fakeScreenRounding - spacing: 2 - SelectionGroupButton { - property int value: 0 - leftmost: true - buttonText: "No" - toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); - } - } - SelectionGroupButton { - property int value: 1 - buttonText: "Yes" - toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); - } - } - SelectionGroupButton { - property int value: 2 - rightmost: true - buttonText: "When not fullscreen" - toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) - onClicked: { - ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); - } - } - } - } - - ConfigRow { - ConfigSwitch { - text: "Transparency" - checked: ConfigOptions.appearance.transparency - onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("appearance.transparency", checked); - } - StyledToolTip { - content: "Might look ass. Unsupported." - } - } - } - - StyledText { - text: "Bar" - color: Appearance.colors.colSubtext - } - ConfigRow { - uniform: true - ConfigSwitch { - text: 'Borderless' - checked: ConfigOptions.bar.borderless - onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.borderless", checked); - } - } - ConfigSwitch { - text: 'Show background' - checked: ConfigOptions.bar.showBackground - onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.showBackground", checked); - } - StyledToolTip { - content: "Note: turning off can hurt readability" - } - } - } - } - - ContentSection { - title: "Shell windows" - spacing: 4 - - ConfigRow { - uniform: true - ConfigSwitch { - text: "Title bar" - checked: ConfigOptions.windows.showTitlebar - onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("windows.showTitlebar", checked); - } - } - ConfigSwitch { - text: "Center title" - checked: ConfigOptions.windows.centerTitle - onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("windows.centerTitle", checked); - } - } - } - } -} \ No newline at end of file diff --git a/.config/quickshell/modules/settings/StyleConfig.qml b/.config/quickshell/modules/settings/StyleConfig.qml new file mode 100644 index 00000000..a02c4f91 --- /dev/null +++ b/.config/quickshell/modules/settings/StyleConfig.qml @@ -0,0 +1,213 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Widgets +import Quickshell.Hyprland +import "root:/services/" +import "root:/modules/common/" +import "root:/modules/common/widgets/" +import "root:/modules/common/functions/color_utils.js" as ColorUtils +import "root:/modules/common/functions/file_utils.js" as FileUtils + +ContentPage { + baseWidth: lightDarkButtonGroup.implicitWidth + forceWidth: true + + Process { + id: konachanWallProc + property string status: "" + command: ["bash", "-c", FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/random_konachan_wall.sh`)] + stdout: SplitParser { + onRead: data => { + console.log(`Konachan wall proc output: ${data}`); + konachanWallProc.status = data.trim(); + } + } + } + + ContentSection { + title: "Colors & Wallpaper" + + // Light/Dark mode preference + ButtonGroup { + id: lightDarkButtonGroup + Layout.fillWidth: true + LightDarkPreferenceButton { + dark: false + } + LightDarkPreferenceButton { + dark: true + } + } + + // Material palette selection + ContentSubsection { + title: "Material palette" + ConfigSelectionArray { + currentValue: ConfigOptions.appearance.palette.type + configOptionName: "appearance.palette.type" + onSelected: (newValue) => { + ConfigLoader.setConfigValueAndSave("appearance.palette.type", newValue); + } + options: [ + {"value": "auto", "displayName": "Auto"}, + {"value": "scheme-content", "displayName": "Content"}, + {"value": "scheme-expressive", "displayName": "Expressive"}, + {"value": "scheme-fidelity", "displayName": "Fidelity"}, + {"value": "scheme-fruit-salad", "displayName": "Fruit Salad"}, + {"value": "scheme-monochrome", "displayName": "Monochrome"}, + {"value": "scheme-neutral", "displayName": "Neutral"}, + {"value": "scheme-rainbow", "displayName": "Rainbow"}, + {"value": "scheme-tonal-spot", "displayName": "Tonal Spot"} + ] + } + } + + + // Wallpaper selection + ContentSubsection { + title: "Wallpaper" + RowLayout { + Layout.alignment: Qt.AlignHCenter + RippleButtonWithIcon { + id: rndWallBtn + buttonRadius: Appearance.rounding.small + materialIcon: "wallpaper" + mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan" + onClicked: { + console.log(konachanWallProc.command.join(" ")) + konachanWallProc.running = true; + } + StyledToolTip { + content: "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers" + } + } + RippleButtonWithIcon { + materialIcon: "wallpaper" + StyledToolTip { + content: "Pick wallpaper image on your system" + } + onClicked: { + Quickshell.execDetached(`${Directories.wallpaperSwitchScriptPath}`) + } + mainContentComponent: Component { + RowLayout { + spacing: 10 + StyledText { + font.pixelSize: Appearance.font.pixelSize.small + text: "Choose file" + color: Appearance.colors.colOnSecondaryContainer + } + RowLayout { + spacing: 3 + KeyboardKey { + key: "Ctrl" + } + KeyboardKey { + key: "󰖳" + } + StyledText { + Layout.alignment: Qt.AlignVCenter + text: "+" + } + KeyboardKey { + key: "T" + } + } + } + } + } + } + } + + StyledText { + Layout.topMargin: 5 + Layout.alignment: Qt.AlignHCenter + text: "Alternatively use /dark, /light, /img in the launcher" + font.pixelSize: Appearance.font.pixelSize.smaller + color: Appearance.colors.colSubtext + } + + } + + ContentSection { + title: "Decorations & Effects" + + ContentSubsection { + title: "Transparency" + + ConfigRow { + ConfigSwitch { + text: "Enable" + checked: ConfigOptions.appearance.transparency + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("appearance.transparency", checked); + } + StyledToolTip { + content: "Might look ass. Unsupported." + } + } + } + } + + ContentSubsection { + title: "Fake screen rounding" + + ButtonGroup { + id: fakeScreenRoundingButtonGroup + property int selectedPolicy: ConfigOptions.appearance.fakeScreenRounding + spacing: 2 + SelectionGroupButton { + property int value: 0 + leftmost: true + buttonText: "No" + toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); + } + } + SelectionGroupButton { + property int value: 1 + buttonText: "Yes" + toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); + } + } + SelectionGroupButton { + property int value: 2 + rightmost: true + buttonText: "When not fullscreen" + toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); + } + } + } + } + + ContentSubsection { + title: "Shell windows" + + ConfigRow { + uniform: true + ConfigSwitch { + text: "Title bar" + checked: ConfigOptions.windows.showTitlebar + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("windows.showTitlebar", checked); + } + } + ConfigSwitch { + text: "Center title" + checked: ConfigOptions.windows.centerTitle + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("windows.centerTitle", checked); + } + } + } + } + } +} \ No newline at end of file diff --git a/.config/quickshell/settings.qml b/.config/quickshell/settings.qml index eac2e65b..00f07e2f 100644 --- a/.config/quickshell/settings.qml +++ b/.config/quickshell/settings.qml @@ -30,12 +30,12 @@ ApplicationWindow { { name: "Style", icon: "palette", - component: "modules/settings/Style.qml" + component: "modules/settings/StyleConfig.qml" }, { - name: "Behavior", + name: "General", icon: "settings", - component: "modules/settings/BehaviorConfig.qml" + component: "modules/settings/GeneralConfig.qml" }, { name: "About", @@ -66,6 +66,28 @@ ApplicationWindow { margins: contentPadding } + Keys.onPressed: (event) => { + console.log(`Key pressed: ${event.key}, Modifiers: ${event.modifiers}`); + if (event.modifiers === Qt.ControlModifier) { + if (event.key === Qt.Key_PageDown) { + root.currentPage = Math.min(root.currentPage + 1, root.pages.length - 1) + event.accepted = true; + } + else if (event.key === Qt.Key_PageUp) { + root.currentPage = Math.max(root.currentPage - 1, 0) + event.accepted = true; + } + else if (event.key === Qt.Key_Tab) { + root.currentPage = (root.currentPage + 1) % root.pages.length; + event.accepted = true; + } + else if (event.key === Qt.Key_Backtab) { + root.currentPage = (root.currentPage - 1 + root.pages.length) % root.pages.length; + event.accepted = true; + } + } + } + Item { // Titlebar visible: ConfigOptions?.windows.showTitlebar Layout.fillWidth: true @@ -125,7 +147,9 @@ ApplicationWindow { spacing: 10 expanded: root.width > 900 - NavigationRailExpandButton {} + NavigationRailExpandButton { + focus: root.visible + } FloatingActionButton { id: fab @@ -180,7 +204,8 @@ ApplicationWindow { target: root function onCurrentPageChanged() { if (pageLoader.sourceComponent !== root.pages[root.currentPage].component) { - switchAnim.restart(); + switchAnim.complete(); + switchAnim.start(); } } } @@ -193,7 +218,7 @@ ApplicationWindow { properties: "opacity" from: 1 to: 0 - duration: 150 + duration: 0 easing.type: Appearance.animation.elementMoveExit.type easing.bezierCurve: Appearance.animationCurves.emphasizedFirstHalf } @@ -207,7 +232,7 @@ ApplicationWindow { properties: "opacity" from: 0 to: 1 - duration: 250 + duration: 0 easing.type: Appearance.animation.elementMoveEnter.type easing.bezierCurve: Appearance.animationCurves.emphasizedLastHalf } diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index 9adaef8c..f0895993 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -202,9 +202,8 @@ ApplicationWindow { ConfigRow { ColumnLayout { // Weeb policy - StyledText { + ContentSubsectionLabel { text: "Weeb" - color: Appearance.colors.colSubtext } ConfigSelectionArray { currentValue: ConfigOptions.policies.weeb @@ -221,9 +220,8 @@ ApplicationWindow { } ColumnLayout { // AI policy - StyledText { + ContentSubsectionLabel { text: "AI" - color: Appearance.colors.colSubtext } ConfigSelectionArray { currentValue: ConfigOptions.policies.ai From 5d9620881b00cacf9880cbed93fb21cecaf471ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Sat, 21 Jun 2025 21:25:29 +0300 Subject: [PATCH 046/328] feat(modules/bar): change darkmode without changing the wallpaper --- .config/quickshell/modules/bar/UtilButtons.qml | 8 ++++---- .config/quickshell/modules/common/ConfigOptions.qml | 6 +----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.config/quickshell/modules/bar/UtilButtons.qml b/.config/quickshell/modules/bar/UtilButtons.qml index ee94d42f..a30ce05e 100644 --- a/.config/quickshell/modules/bar/UtilButtons.qml +++ b/.config/quickshell/modules/bar/UtilButtons.qml @@ -85,15 +85,15 @@ Item { } Loader { - active: ConfigOptions.bar.utilButtons.darkMode.show - visible: ConfigOptions.bar.utilButtons.darkMode.show + active: ConfigOptions.bar.utilButtons.showDarkModeToggle + visible: ConfigOptions.bar.utilButtons.showDarkModeToggle sourceComponent: CircleUtilButton { Layout.alignment: Qt.AlignVCenter onClicked: event => { if (Appearance.m3colors.darkmode) { - Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} ${ConfigOptions.bar.utilButtons.darkMode.lightImgPath} --mode light`); + Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode light --noswitch`); } else { - Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} ${ConfigOptions.bar.utilButtons.darkMode.darkImgPath} --mode dark`); + Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode dark --noswitch`); } } MaterialSymbol { diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 1488c246..241fcecf 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -61,11 +61,7 @@ Singleton { property bool showColorPicker: false property bool showMicToggle: false property bool showKeyboardToggle: true - property QtObject darkMode: QtObject { - property bool show: true - property string lightImgPath: "" - property string darkImgPath: "" - } + property bool showDarkModeToggle: true } property QtObject tray: QtObject { property bool monochromeIcons: true From e97e41c1627b6a622ef87465b91bca5530f932a6 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 22 Jun 2025 23:20:29 +0200 Subject: [PATCH 047/328] revert weird util button width --- .config/quickshell/modules/bar/UtilButtons.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/bar/UtilButtons.qml b/.config/quickshell/modules/bar/UtilButtons.qml index a30ce05e..1ebe3fcb 100644 --- a/.config/quickshell/modules/bar/UtilButtons.qml +++ b/.config/quickshell/modules/bar/UtilButtons.qml @@ -10,7 +10,7 @@ import Quickshell.Services.Pipewire Item { id: root property bool borderless: ConfigOptions.bar.borderless - implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 16 + implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2 implicitHeight: rowLayout.implicitHeight RowLayout { From 529b67d7286ff560148ffce3872dba5fe463048b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 22 Jun 2025 23:24:17 +0200 Subject: [PATCH 048/328] fix dark/light mode util button not in rowlayout --- .../quickshell/modules/bar/UtilButtons.qml | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/.config/quickshell/modules/bar/UtilButtons.qml b/.config/quickshell/modules/bar/UtilButtons.qml index 1ebe3fcb..25ae0ca3 100644 --- a/.config/quickshell/modules/bar/UtilButtons.qml +++ b/.config/quickshell/modules/bar/UtilButtons.qml @@ -82,26 +82,26 @@ Item { } } } - } - Loader { - active: ConfigOptions.bar.utilButtons.showDarkModeToggle - visible: ConfigOptions.bar.utilButtons.showDarkModeToggle - sourceComponent: CircleUtilButton { - Layout.alignment: Qt.AlignVCenter - onClicked: event => { - if (Appearance.m3colors.darkmode) { - Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode light --noswitch`); - } else { - Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode dark --noswitch`); + Loader { + active: ConfigOptions.bar.utilButtons.showDarkModeToggle + visible: ConfigOptions.bar.utilButtons.showDarkModeToggle + sourceComponent: CircleUtilButton { + Layout.alignment: Qt.AlignVCenter + onClicked: event => { + if (Appearance.m3colors.darkmode) { + Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode light --noswitch`); + } else { + Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode dark --noswitch`); + } + } + MaterialSymbol { + horizontalAlignment: Qt.AlignHCenter + fill: 0 + text: Appearance.m3colors.darkmode ? "light_mode" : "dark_mode" + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnLayer2 } - } - MaterialSymbol { - horizontalAlignment: Qt.AlignHCenter - fill: 0 - text: Appearance.m3colors.darkmode ? "light_mode" : "dark_mode" - iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnLayer2 } } } From d03100d60a64a72f4770fa331b60efe098fa829d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 01:33:31 +0200 Subject: [PATCH 049/328] add spinbox --- .../modules/common/widgets/ConfigSpinBox.qml | 31 +++++++ .../modules/common/widgets/StyledSpinBox.qml | 92 +++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 .config/quickshell/modules/common/widgets/ConfigSpinBox.qml create mode 100644 .config/quickshell/modules/common/widgets/StyledSpinBox.qml diff --git a/.config/quickshell/modules/common/widgets/ConfigSpinBox.qml b/.config/quickshell/modules/common/widgets/ConfigSpinBox.qml new file mode 100644 index 00000000..972c221d --- /dev/null +++ b/.config/quickshell/modules/common/widgets/ConfigSpinBox.qml @@ -0,0 +1,31 @@ +import "root:/modules/common/widgets/" +import "root:/modules/common/" +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +RowLayout { + id: root + property string text: "" + property alias value: spinBoxWidget.value + property alias stepSize: spinBoxWidget.stepSize + property alias from: spinBoxWidget.from + property alias to: spinBoxWidget.to + spacing: 10 + Layout.leftMargin: 8 + Layout.rightMargin: 8 + + StyledText { + id: labelWidget + Layout.fillWidth: true + text: root.text + font.pixelSize: Appearance.font.pixelSize.small + color: Appearance.colors.colOnSecondaryContainer + } + + StyledSpinBox { + id: spinBoxWidget + Layout.fillWidth: false + value: root.value + } +} diff --git a/.config/quickshell/modules/common/widgets/StyledSpinBox.qml b/.config/quickshell/modules/common/widgets/StyledSpinBox.qml new file mode 100644 index 00000000..2f5b4467 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/StyledSpinBox.qml @@ -0,0 +1,92 @@ +import "root:/modules/common" +import "root:/modules/common/functions/color_utils.js" as ColorUtils +import QtQuick +import QtQuick.Controls + +/** + * Material 3 styled SpinBox component. + */ +SpinBox { + id: root + + property real baseHeight: 35 + property real radius: Appearance.rounding.small + property real innerButtonRadius: Appearance.rounding.unsharpen + editable: true + + background: Rectangle { + color: Appearance.colors.colLayer2 + radius: root.radius + } + + contentItem: Item { + implicitHeight: root.baseHeight + implicitWidth: Math.max(labelText.implicitWidth, 40) + + StyledTextInput { + id: labelText + anchors.centerIn: parent + text: root.displayText + color: Appearance.colors.colOnLayer2 + font.pixelSize: Appearance.font.pixelSize.small + validator: root.validator + onTextChanged: { + root.value = parseFloat(text); + } + } + } + + down.indicator: Rectangle { + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + } + implicitHeight: root.baseHeight + implicitWidth: root.baseHeight + topLeftRadius: root.radius + bottomLeftRadius: root.radius + topRightRadius: root.innerButtonRadius + bottomRightRadius: root.innerButtonRadius + + color: root.down.pressed ? Appearance.colors.colLayer2Active : + root.down.hovered ? Appearance.colors.colLayer2Hover : + ColorUtils.transparentize(Appearance.colors.colLayer2) + Behavior on color { + animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) + } + + MaterialSymbol { + anchors.centerIn: parent + text: "remove" + iconSize: 20 + color: Appearance.colors.colOnLayer2 + } + } + + up.indicator: Rectangle { + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + } + implicitHeight: root.baseHeight + implicitWidth: root.baseHeight + topRightRadius: root.radius + bottomRightRadius: root.radius + topLeftRadius: root.innerButtonRadius + bottomLeftRadius: root.innerButtonRadius + + color: root.up.pressed ? Appearance.colors.colLayer2Active : + root.up.hovered ? Appearance.colors.colLayer2Hover : + ColorUtils.transparentize(Appearance.colors.colLayer2) + Behavior on color { + animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) + } + + MaterialSymbol { + anchors.centerIn: parent + text: "add" + iconSize: 20 + color: Appearance.colors.colOnLayer2 + } + } +} From 1cd5b0ba1d6104d254a418fce280b7f3b2aa17fa Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 01:34:10 +0200 Subject: [PATCH 050/328] battery: add auto suspend --- .config/quickshell/modules/common/ConfigOptions.qml | 3 ++- .config/quickshell/services/Battery.qml | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 241fcecf..bd9c8552 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -77,7 +77,8 @@ Singleton { property QtObject battery: QtObject { property int low: 20 property int critical: 5 - property int suspend: 2 + property bool automaticSuspend: true + property int suspend: 3 } property QtObject dock: QtObject { diff --git a/.config/quickshell/services/Battery.qml b/.config/quickshell/services/Battery.qml index b19910d8..e952dab9 100644 --- a/.config/quickshell/services/Battery.qml +++ b/.config/quickshell/services/Battery.qml @@ -12,6 +12,7 @@ Singleton { property bool isCharging: chargeState == UPowerDeviceState.Charging property bool isPluggedIn: isCharging || chargeState == UPowerDeviceState.PendingCharge property real percentage: UPower.displayDevice.percentage + readonly property bool allowAutomaticSuspend: ConfigOptions.battery.automaticSuspend property bool isLow: percentage <= ConfigOptions.battery.low / 100 property bool isCritical: percentage <= ConfigOptions.battery.critical / 100 @@ -19,6 +20,7 @@ Singleton { property bool isLowAndNotCharging: isLow && !isCharging property bool isCriticalAndNotCharging: isCritical && !isCharging + property bool isSuspendingAndNotCharging: allowAutomaticSuspend && isSuspending && !isCharging onIsLowAndNotChargingChanged: { if (available && isLowAndNotCharging) @@ -29,4 +31,10 @@ Singleton { if (available && isCriticalAndNotCharging) Quickshell.execDetached(["bash", "-c", `notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${ConfigOptions.battery.suspend}%" -u critical -a "Shell"`]); } + + onIsSuspendingAndNotChargingChanged: { + if (available && isSuspendingAndNotCharging) { + Quickshell.execDetached(["bash", "-c", `systemctl suspend || loginctl suspend`]); + } + } } From b5046fa6dc6ff455896daeafe36fde081acc6ff4 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 01:34:32 +0200 Subject: [PATCH 051/328] content subsection: add info tooltip --- .../common/widgets/ContentSubsection.qml | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/ContentSubsection.qml b/.config/quickshell/modules/common/widgets/ContentSubsection.qml index 6df0c8fa..0eb3b3b5 100644 --- a/.config/quickshell/modules/common/widgets/ContentSubsection.qml +++ b/.config/quickshell/modules/common/widgets/ContentSubsection.qml @@ -7,16 +7,37 @@ import "root:/modules/common/widgets/" ColumnLayout { id: root property string title: "" + property string tooltip: "" default property alias data: sectionContent.data Layout.fillWidth: true Layout.topMargin: 4 spacing: 2 - ContentSubsectionLabel { - Layout.fillWidth: true - visible: root.title && root.title.length > 0 - text: root.title + RowLayout { + ContentSubsectionLabel { + visible: root.title && root.title.length > 0 + text: root.title + } + MaterialSymbol { + visible: root.tooltip && root.tooltip.length > 0 + text: "info" + iconSize: Appearance.font.pixelSize.large + + color: Appearance.colors.colSubtext + MouseArea { + id: infoMouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.WhatsThisCursor + StyledToolTip { + extraVisibleCondition: false + alternativeVisibleCondition: infoMouseArea.containsMouse + content: root.tooltip + } + } + } + Item { Layout.fillWidth: true } } ColumnLayout { id: sectionContent From 5991c8f994a31b6186d8442429cd5ef8446dcd3a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 01:34:44 +0200 Subject: [PATCH 052/328] add styled textinput --- .../modules/common/widgets/StyledTextInput.qml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .config/quickshell/modules/common/widgets/StyledTextInput.qml diff --git a/.config/quickshell/modules/common/widgets/StyledTextInput.qml b/.config/quickshell/modules/common/widgets/StyledTextInput.qml new file mode 100644 index 00000000..9ca242f1 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/StyledTextInput.qml @@ -0,0 +1,17 @@ +import "root:/modules/common" +import QtQuick +import QtQuick.Controls + +/** + * Does not include visual layout, but includes the easily neglected colors. + */ +TextInput { + renderType: Text.NativeRendering + selectedTextColor: Appearance.m3colors.m3onSecondaryContainer + selectionColor: Appearance.colors.colSecondaryContainer + font { + family: Appearance?.font.family.main ?? "sans-serif" + pixelSize: Appearance?.font.pixelSize.small ?? 15 + hintingPreference: Font.PreferFullHinting + } +} From ced0f6efb14667e19cb05bb1c171f2244533f676 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 01:35:08 +0200 Subject: [PATCH 053/328] settings: more options --- .../modules/settings/GeneralConfig.qml | 107 ++++++++++++++++++ .config/quickshell/settings.qml | 5 +- 2 files changed, 109 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/settings/GeneralConfig.qml b/.config/quickshell/modules/settings/GeneralConfig.qml index ae051836..a696303f 100644 --- a/.config/quickshell/modules/settings/GeneralConfig.qml +++ b/.config/quickshell/modules/settings/GeneralConfig.qml @@ -138,7 +138,114 @@ ContentPage { } } } + ConfigRow { + uniform: true + ConfigSwitch { + text: "Dark/Light toggle" + checked: ConfigOptions.bar.utilButtons.showDarkModeToggle + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.utilButtons.showDarkModeToggle", checked); + } + } + ConfigSwitch { + opacity: 0 + enabled: false + } + } } + ContentSubsection { + title: "Workspaces" + tooltip: "Tip: Hide icons and always show numbers for\nthe classic illogical-impulse experience" + + ConfigRow { + uniform: true + ConfigSwitch { + text: 'Show app icons' + checked: ConfigOptions.bar.workspaces.showAppIcons + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.workspaces.showAppIcons", checked); + } + } + ConfigSwitch { + text: 'Always show numbers' + checked: ConfigOptions.bar.workspaces.alwaysShowNumbers + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.workspaces.alwaysShowNumbers", checked); + } + } + } + ConfigSpinBox { + text: "Workspaces shown" + value: ConfigOptions.bar.workspaces.shown + from: 1 + to: 30 + stepSize: 1 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("bar.workspaces.shown", value); + } + } + ConfigSpinBox { + text: "Number show delay when pressing Super (ms)" + value: ConfigOptions.bar.workspaces.showNumberDelay + from: 0 + to: 1000 + stepSize: 50 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("bar.workspaces.showNumberDelay", value); + } + } + } + } + + ContentSection { + title: "Battery" + + ConfigRow { + uniform: true + ConfigSpinBox { + text: "Low warning" + value: ConfigOptions.battery.low + from: 0 + to: 100 + stepSize: 5 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("battery.low", value); + } + } + ConfigSpinBox { + text: "Critical warning" + value: ConfigOptions.battery.critical + from: 0 + to: 100 + stepSize: 5 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("battery.critical", value); + } + } + } + ConfigRow { + uniform: false + ConfigSwitch { + text: "Automatic suspend" + checked: ConfigOptions.battery.automaticSuspend + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("battery.automaticSuspend", checked); + } + StyledToolTip { + content: "Automatically suspends the system when battery is low" + } + } + ConfigSpinBox { + text: "Suspend at" + value: ConfigOptions.battery.suspend + from: 0 + to: 100 + stepSize: 5 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("battery.suspend", value); + } + } + } } } \ No newline at end of file diff --git a/.config/quickshell/settings.qml b/.config/quickshell/settings.qml index 00f07e2f..61802363 100644 --- a/.config/quickshell/settings.qml +++ b/.config/quickshell/settings.qml @@ -56,8 +56,8 @@ ApplicationWindow { minimumWidth: 600 minimumHeight: 400 - width: 900 - height: 650 + width: 1100 + height: 750 color: Appearance.m3colors.m3background ColumnLayout { @@ -67,7 +67,6 @@ ApplicationWindow { } Keys.onPressed: (event) => { - console.log(`Key pressed: ${event.key}, Modifiers: ${event.modifiers}`); if (event.modifiers === Qt.ControlModifier) { if (event.key === Qt.Key_PageDown) { root.currentPage = Math.min(root.currentPage + 1, root.pages.length - 1) From 7cf3c264ab05867e855b213fc6c4508c98d9420f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 02:35:55 +0200 Subject: [PATCH 054/328] fix spinbox looped value --- .config/quickshell/modules/common/widgets/StyledSpinBox.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/widgets/StyledSpinBox.qml b/.config/quickshell/modules/common/widgets/StyledSpinBox.qml index 2f5b4467..9dac2544 100644 --- a/.config/quickshell/modules/common/widgets/StyledSpinBox.qml +++ b/.config/quickshell/modules/common/widgets/StyledSpinBox.qml @@ -26,7 +26,7 @@ SpinBox { StyledTextInput { id: labelText anchors.centerIn: parent - text: root.displayText + text: root.value // displayText would make the numbers weird like 1,000 instead of 1000 color: Appearance.colors.colOnLayer2 font.pixelSize: Appearance.font.pixelSize.small validator: root.validator From 6ebccf097f0fceb0ff6f3280920a244c20d71881 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 02:36:07 +0200 Subject: [PATCH 055/328] settings: make sections clearer --- .config/quickshell/modules/common/widgets/ContentSection.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/modules/common/widgets/ContentSection.qml b/.config/quickshell/modules/common/widgets/ContentSection.qml index ee2410c4..01eab5cb 100644 --- a/.config/quickshell/modules/common/widgets/ContentSection.qml +++ b/.config/quickshell/modules/common/widgets/ContentSection.qml @@ -14,6 +14,7 @@ ColumnLayout { StyledText { text: root.title font.pixelSize: Appearance.font.pixelSize.larger + font.weight: Font.Medium } ColumnLayout { id: sectionContent From 7ca2da3723a52fdab22c2027e89811e92afb7585 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 02:36:52 +0200 Subject: [PATCH 056/328] overview: remove show xwayland indicator option we dont show an ugly icon now so it's not necessary --- .config/quickshell/modules/common/ConfigOptions.qml | 1 - .config/quickshell/modules/overview/OverviewWindow.qml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index bd9c8552..4f12dbdd 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -115,7 +115,6 @@ Singleton { property real scale: 0.18 // Relative to screen size property real numOfRows: 2 property real numOfCols: 5 - property bool showXwaylandIndicator: true } property QtObject resources: QtObject { diff --git a/.config/quickshell/modules/overview/OverviewWindow.qml b/.config/quickshell/modules/overview/OverviewWindow.qml index 3b376988..b749ab16 100644 --- a/.config/quickshell/modules/overview/OverviewWindow.qml +++ b/.config/quickshell/modules/overview/OverviewWindow.qml @@ -38,7 +38,7 @@ Item { // Window property var iconPath: Quickshell.iconPath(AppSearch.guessIcon(windowData?.class), "image-missing") property bool compactMode: Appearance.font.pixelSize.smaller * 4 > targetWindowHeight || Appearance.font.pixelSize.smaller * 4 > targetWindowWidth - property bool indicateXWayland: (ConfigOptions.overview.showXwaylandIndicator && windowData?.xwayland) ?? false + property bool indicateXWayland: windowData?.xwayland ?? false x: initX y: initY From 06574c19aee93ce60faf2d6191cffd24c0688cc9 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 02:37:15 +0200 Subject: [PATCH 057/328] settings: increase page content width --- .config/quickshell/modules/common/widgets/ContentPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/widgets/ContentPage.qml b/.config/quickshell/modules/common/widgets/ContentPage.qml index 07d88949..d23922c7 100644 --- a/.config/quickshell/modules/common/widgets/ContentPage.qml +++ b/.config/quickshell/modules/common/widgets/ContentPage.qml @@ -6,7 +6,7 @@ import "root:/modules/common/widgets/" Flickable { id: root - property real baseWidth: 500 + property real baseWidth: 550 property bool forceWidth: false property real bottomContentPadding: 100 From b6ba428404b4585498175554cb652d9442cce59a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 02:37:28 +0200 Subject: [PATCH 058/328] settings: more options --- .../modules/common/ConfigOptions.qml | 4 +- .../modules/overview/OverviewWidget.qml | 16 +- ...{GeneralConfig.qml => InterfaceConfig.qml} | 66 +++++---- .../modules/settings/ServicesConfig.qml | 139 ++++++++++++++++++ .config/quickshell/settings.qml | 13 +- 5 files changed, 197 insertions(+), 41 deletions(-) rename .config/quickshell/modules/settings/{GeneralConfig.qml => InterfaceConfig.qml} (88%) create mode 100644 .config/quickshell/modules/settings/ServicesConfig.qml diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 4f12dbdd..198d4aff 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -113,8 +113,8 @@ Singleton { property QtObject overview: QtObject { property real scale: 0.18 // Relative to screen size - property real numOfRows: 2 - property real numOfCols: 5 + property real rows: 2 + property real columns: 5 } property QtObject resources: QtObject { diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index 5faa8699..813ee5ce 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -17,7 +17,7 @@ Item { required property var panelWindow readonly property HyprlandMonitor monitor: Hyprland.monitorFor(panelWindow.screen) readonly property var toplevels: ToplevelManager.toplevels - readonly property int workspacesShown: ConfigOptions.overview.numOfRows * ConfigOptions.overview.numOfCols + readonly property int workspacesShown: ConfigOptions.overview.rows * ConfigOptions.overview.columns readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / workspacesShown) property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor.id) property var windows: HyprlandData.windowList @@ -71,18 +71,18 @@ Item { anchors.centerIn: parent spacing: workspaceSpacing Repeater { - model: ConfigOptions.overview.numOfRows + model: ConfigOptions.overview.rows delegate: RowLayout { id: row property int rowIndex: index spacing: workspaceSpacing Repeater { // Workspace repeater - model: ConfigOptions.overview.numOfCols + model: ConfigOptions.overview.columns Rectangle { // Workspace id: workspace property int colIndex: index - property int workspaceValue: root.workspaceGroup * workspacesShown + rowIndex * ConfigOptions.overview.numOfCols + colIndex + 1 + property int workspaceValue: root.workspaceGroup * workspacesShown + rowIndex * ConfigOptions.overview.columns + colIndex + 1 property color defaultWorkspaceColor: Appearance.colors.colLayer1 // TODO: reconsider this color for a cleaner look property color hoveredWorkspaceColor: ColorUtils.mix(defaultWorkspaceColor, Appearance.colors.colLayer1Hover, 0.1) property color hoveredBorderColor: Appearance.colors.colLayer2Hover @@ -171,8 +171,8 @@ Item { property bool atInitPosition: (initX == x && initY == y) restrictToWorkspace: Drag.active || atInitPosition - property int workspaceColIndex: (windowData?.workspace.id - 1) % ConfigOptions.overview.numOfCols - property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / ConfigOptions.overview.numOfCols) + property int workspaceColIndex: (windowData?.workspace.id - 1) % ConfigOptions.overview.columns + property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / ConfigOptions.overview.columns) xOffset: (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - (monitor?.x * root.scale) yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex - (monitor?.y * root.scale) @@ -245,8 +245,8 @@ Item { Rectangle { // Focused workspace indicator id: focusedWorkspaceIndicator property int activeWorkspaceInGroup: monitor.activeWorkspace?.id - (root.workspaceGroup * root.workspacesShown) - property int activeWorkspaceRowIndex: Math.floor((activeWorkspaceInGroup - 1) / ConfigOptions.overview.numOfCols) - property int activeWorkspaceColIndex: (activeWorkspaceInGroup - 1) % ConfigOptions.overview.numOfCols + property int activeWorkspaceRowIndex: Math.floor((activeWorkspaceInGroup - 1) / ConfigOptions.overview.columns) + property int activeWorkspaceColIndex: (activeWorkspaceInGroup - 1) % ConfigOptions.overview.columns x: (root.workspaceImplicitWidth + workspaceSpacing) * activeWorkspaceColIndex y: (root.workspaceImplicitHeight + workspaceSpacing) * activeWorkspaceRowIndex z: root.windowZ diff --git a/.config/quickshell/modules/settings/GeneralConfig.qml b/.config/quickshell/modules/settings/InterfaceConfig.qml similarity index 88% rename from .config/quickshell/modules/settings/GeneralConfig.qml rename to .config/quickshell/modules/settings/InterfaceConfig.qml index a696303f..7d3799d2 100644 --- a/.config/quickshell/modules/settings/GeneralConfig.qml +++ b/.config/quickshell/modules/settings/InterfaceConfig.qml @@ -48,32 +48,6 @@ ContentPage { } } } - ContentSection { - title: "Audio" - ConfigSwitch { - text: "Earbang protection" - checked: ConfigOptions.audio.protection.enable - onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("audio.protection.enable", checked); - } - StyledToolTip { - content: "Prevents abrupt increments and restricts volume limit" - } - } - } - ContentSection { - title: "AI" - MaterialTextField { - id: systemPromptField - Layout.fillWidth: true - placeholderText: "System prompt" - text: ConfigOptions.ai.systemPrompt - wrapMode: TextEdit.Wrap - onTextChanged: { - ConfigLoader.setConfigValueAndSave("ai.systemPrompt", text); - } - } - } ContentSection { title: "Bar" @@ -225,7 +199,7 @@ ContentPage { } } ConfigRow { - uniform: false + uniform: true ConfigSwitch { text: "Automatic suspend" checked: ConfigOptions.battery.automaticSuspend @@ -248,4 +222,42 @@ ContentPage { } } } + + ContentSection { + title: "Overview" + ConfigSpinBox { + text: "Scale (%)" + value: ConfigOptions.overview.scale * 100 + from: 1 + to: 100 + stepSize: 1 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("overview.scale", value / 100); + } + } + ConfigRow { + uniform: true + ConfigSpinBox { + text: "Rows" + value: ConfigOptions.overview.rows + from: 1 + to: 20 + stepSize: 1 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("overview.rows", value); + } + } + ConfigSpinBox { + text: "Columns" + value: ConfigOptions.overview.columns + from: 1 + to: 20 + stepSize: 1 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("overview.columns", value); + } + } + } + + } } \ No newline at end of file diff --git a/.config/quickshell/modules/settings/ServicesConfig.qml b/.config/quickshell/modules/settings/ServicesConfig.qml new file mode 100644 index 00000000..1be54036 --- /dev/null +++ b/.config/quickshell/modules/settings/ServicesConfig.qml @@ -0,0 +1,139 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/services/" +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +ContentPage { + forceWidth: true + + ContentSection { + title: "Audio" + + ConfigSwitch { + text: "Earbang protection" + checked: ConfigOptions.audio.protection.enable + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("audio.protection.enable", checked); + } + StyledToolTip { + content: "Prevents abrupt increments and restricts volume limit" + } + } + ConfigRow { + // uniform: true + ConfigSpinBox { + text: "Max allowed increase" + value: ConfigOptions.audio.protection.maxAllowedIncrease + from: 0 + to: 100 + stepSize: 2 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("audio.protection.maxAllowedIncrease", value); + } + } + ConfigSpinBox { + text: "Volume limit" + value: ConfigOptions.audio.protection.maxAllowed + from: 0 + to: 100 + stepSize: 2 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("audio.protection.maxAllowed", value); + } + } + } + } + ContentSection { + title: "AI" + MaterialTextField { + Layout.fillWidth: true + placeholderText: "System prompt" + text: ConfigOptions.ai.systemPrompt + wrapMode: TextEdit.Wrap + onTextChanged: { + ConfigLoader.setConfigValueAndSave("ai.systemPrompt", text); + } + } + } + + ContentSection { + title: "Battery" + + ConfigRow { + uniform: true + ConfigSpinBox { + text: "Low warning" + value: ConfigOptions.battery.low + from: 0 + to: 100 + stepSize: 5 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("battery.low", value); + } + } + ConfigSpinBox { + text: "Critical warning" + value: ConfigOptions.battery.critical + from: 0 + to: 100 + stepSize: 5 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("battery.critical", value); + } + } + } + ConfigRow { + uniform: true + ConfigSwitch { + text: "Automatic suspend" + checked: ConfigOptions.battery.automaticSuspend + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("battery.automaticSuspend", checked); + } + StyledToolTip { + content: "Automatically suspends the system when battery is low" + } + } + ConfigSpinBox { + text: "Suspend at" + value: ConfigOptions.battery.suspend + from: 0 + to: 100 + stepSize: 5 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("battery.suspend", value); + } + } + } + } + + ContentSection { + title: "Networking" + MaterialTextField { + Layout.fillWidth: true + placeholderText: "User agent (for services that require it)" + text: ConfigOptions.networking.userAgent + wrapMode: TextEdit.Wrap + onTextChanged: { + ConfigLoader.setConfigValueAndSave("networking.userAgent", text); + } + } + } + + ContentSection { + title: "Resources" + ConfigSpinBox { + text: "Polling interval (ms)" + value: ConfigOptions.resources.updateInterval + from: 100 + to: 10000 + stepSize: 100 + onValueChanged: { + ConfigLoader.setConfigValueAndSave("resources.updateInterval", value); + } + } + } + +} \ No newline at end of file diff --git a/.config/quickshell/settings.qml b/.config/quickshell/settings.qml index 61802363..c6866565 100644 --- a/.config/quickshell/settings.qml +++ b/.config/quickshell/settings.qml @@ -33,9 +33,14 @@ ApplicationWindow { component: "modules/settings/StyleConfig.qml" }, { - name: "General", + name: "Interface", + icon: "cards", + component: "modules/settings/InterfaceConfig.qml" + }, + { + name: "Services", icon: "settings", - component: "modules/settings/GeneralConfig.qml" + component: "modules/settings/ServicesConfig.qml" }, { name: "About", @@ -217,7 +222,7 @@ ApplicationWindow { properties: "opacity" from: 1 to: 0 - duration: 0 + duration: 100 easing.type: Appearance.animation.elementMoveExit.type easing.bezierCurve: Appearance.animationCurves.emphasizedFirstHalf } @@ -231,7 +236,7 @@ ApplicationWindow { properties: "opacity" from: 0 to: 1 - duration: 0 + duration: 200 easing.type: Appearance.animation.elementMoveEnter.type easing.bezierCurve: Appearance.animationCurves.emphasizedLastHalf } From ad462649b0c41b87f91b0c4dafcf434148ca4ea1 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 23 Jun 2025 10:17:38 +0200 Subject: [PATCH 059/328] add brave browser substitution (fixes #1439) --- .config/quickshell/services/AppSearch.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/services/AppSearch.qml b/.config/quickshell/services/AppSearch.qml index 876df183..1e383e67 100644 --- a/.config/quickshell/services/AppSearch.qml +++ b/.config/quickshell/services/AppSearch.qml @@ -23,6 +23,7 @@ Singleton { "wpsoffice": "wps-office2019-kprometheus", "footclient": "foot", "zen": "zen-browser", + "brave-browser": "brave-desktop" }) property var regexSubstitutions: [ { From 51885623c8d935f3cb8947ab903ebbe978515b75 Mon Sep 17 00:00:00 2001 From: torhaala Date: Mon, 23 Jun 2025 18:41:29 +0200 Subject: [PATCH 060/328] Update switchwall.sh --- .config/quickshell/scripts/colors/switchwall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/scripts/colors/switchwall.sh b/.config/quickshell/scripts/colors/switchwall.sh index 80adb169..35caba66 100755 --- a/.config/quickshell/scripts/colors/switchwall.sh +++ b/.config/quickshell/scripts/colors/switchwall.sh @@ -237,7 +237,7 @@ switch() { [[ -n "$mode_flag" ]] && matugen_args+=(--mode "$mode_flag") && generate_colors_material_args+=(--mode "$mode_flag") [[ -n "$type_flag" ]] && matugen_args+=(--type "$type_flag") && generate_colors_material_args+=(--scheme "$type_flag") generate_colors_material_args+=(--termscheme "$terminalscheme" --blend_bg_fg) - generate_colors_material_args+=(--cache "$STATE_DIR/user/color.txt") + generate_colors_material_args+=(--cache "$STATE_DIR/user/generated/color.txt") pre_process "$mode_flag" From 4a2453410a273a7993a9dbf7f489c974ca0b981e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 24 Jun 2025 14:51:04 +0200 Subject: [PATCH 061/328] deps: add qt avif image plugin for yt thumbnails --- arch-packages/illogical-impulse-toolkit/PKGBUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/arch-packages/illogical-impulse-toolkit/PKGBUILD b/arch-packages/illogical-impulse-toolkit/PKGBUILD index 6f12584a..636709f2 100644 --- a/arch-packages/illogical-impulse-toolkit/PKGBUILD +++ b/arch-packages/illogical-impulse-toolkit/PKGBUILD @@ -7,6 +7,7 @@ license=(None) depends=( kdialog qt6-5compat + qt6-avif-image-plugin qt6-base qt6-declarative qt6-imageformats From b27dc3496c086259d643138348f158fee589165b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 26 Jun 2025 22:18:16 +0200 Subject: [PATCH 062/328] progressbar: unecessary rect -> item --- .../quickshell/modules/common/widgets/StyledProgressBar.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/StyledProgressBar.qml b/.config/quickshell/modules/common/widgets/StyledProgressBar.qml index 1ea8a93a..c36f31e2 100644 --- a/.config/quickshell/modules/common/widgets/StyledProgressBar.qml +++ b/.config/quickshell/modules/common/widgets/StyledProgressBar.qml @@ -32,10 +32,8 @@ ProgressBar { animation: Appearance?.animation.elementMoveEnter.numberAnimation.createObject(this) } - background: Rectangle { + background: Item { anchors.fill: parent - color: "transparent" - radius: Appearance?.rounding.full ?? 9999 implicitHeight: valueBarHeight implicitWidth: valueBarWidth } From f119a4444283801559c2119d3dbc26d5106335d7 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 26 Jun 2025 22:19:20 +0200 Subject: [PATCH 063/328] ai: fix code blocks being cut off (#1513) --- .config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml index e242030f..3e5b96d3 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml @@ -247,9 +247,7 @@ Rectangle { spacing: 0 Repeater { - model: ScriptModel { - values: root.messageBlocks.map((block, index) => index) - } + model: root.messageBlocks.length delegate: Loader { required property int index property var thisBlock: root.messageBlocks[index] From 4f7ed4da53cbe5c3dcc7a4872701147da2250a0f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 26 Jun 2025 22:36:55 +0200 Subject: [PATCH 064/328] search widget: fix wrong calculator result (#1424) --- .config/quickshell/modules/overview/SearchWidget.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/overview/SearchWidget.qml b/.config/quickshell/modules/overview/SearchWidget.qml index 7d7cc952..93286265 100644 --- a/.config/quickshell/modules/overview/SearchWidget.qml +++ b/.config/quickshell/modules/overview/SearchWidget.qml @@ -90,7 +90,7 @@ Item { // Wrapper id: mathProcess property list baseCommand: ["qalc", "-t"] function calculateExpression(expression) { - // mathProcess.running = false + mathProcess.running = false mathProcess.command = baseCommand.concat(expression) mathProcess.running = true } From 3f44ecb0681800cf0b68da2aa17c8c28699c6b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Fri, 27 Jun 2025 12:30:25 +0300 Subject: [PATCH 065/328] feat(modules/bar): add weather bar --- .config/quickshell/constants/WeatherIcons.qml | 59 ++++++++ .config/quickshell/modules/bar/Bar.qml | 135 ++++++++++-------- .../modules/bar/weather/WeatherBar.qml | 68 +++++++++ .../modules/bar/weather/WeatherCard.qml | 45 ++++++ .../modules/bar/weather/WeatherPopup.qml | 95 ++++++++++++ .../modules/common/ConfigOptions.qml | 17 +++ .../quickshell/services/WeatherService.qml | 105 ++++++++++++++ 7 files changed, 462 insertions(+), 62 deletions(-) create mode 100644 .config/quickshell/constants/WeatherIcons.qml create mode 100644 .config/quickshell/modules/bar/weather/WeatherBar.qml create mode 100644 .config/quickshell/modules/bar/weather/WeatherCard.qml create mode 100644 .config/quickshell/modules/bar/weather/WeatherPopup.qml create mode 100644 .config/quickshell/services/WeatherService.qml diff --git a/.config/quickshell/constants/WeatherIcons.qml b/.config/quickshell/constants/WeatherIcons.qml new file mode 100644 index 00000000..bd74d4e1 --- /dev/null +++ b/.config/quickshell/constants/WeatherIcons.qml @@ -0,0 +1,59 @@ +pragma Singleton + +import Quickshell + +Singleton { + // credits: calestia + // this snippet is taken from + // https://github.com/caelestia-dots/shell + readonly property var codeToName: ({ + "113": "clear_day", + "116": "partly_cloudy_day", + "119": "cloud", + "122": "cloud", + "143": "foggy", + "176": "rainy", + "179": "rainy", + "182": "rainy", + "185": "rainy", + "200": "thunderstorm", + "227": "cloudy_snowing", + "230": "snowing_heavy", + "248": "foggy", + "260": "foggy", + "263": "rainy", + "266": "rainy", + "281": "rainy", + "284": "rainy", + "293": "rainy", + "296": "rainy", + "299": "rainy", + "302": "weather_hail", + "305": "rainy", + "308": "weather_hail", + "311": "rainy", + "314": "rainy", + "317": "rainy", + "320": "cloudy_snowing", + "323": "cloudy_snowing", + "326": "cloudy_snowing", + "329": "snowing_heavy", + "332": "snowing_heavy", + "335": "snowing", + "338": "snowing_heavy", + "350": "rainy", + "353": "rainy", + "356": "rainy", + "359": "weather_hail", + "362": "rainy", + "365": "rainy", + "368": "cloudy_snowing", + "371": "snowing", + "374": "rainy", + "377": "rainy", + "386": "thunderstorm", + "389": "thunderstorm", + "392": "thunderstorm", + "395": "snowing" + }) +} diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 0a890c6e..1eefb15d 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -3,6 +3,7 @@ import "root:/services" import "root:/modules/common/" import "root:/modules/common/widgets" import "root:/modules/common/functions/color_utils.js" as ColorUtils +import "root:/modules/bar/weather" import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -27,7 +28,8 @@ Scope { color: Appearance.colors.colOutlineVariant } - Variants { // For each monitor + Variants { + // For each monitor model: { const screens = Quickshell.screens; const list = ConfigOptions.bar.screenList; @@ -42,12 +44,8 @@ Scope { property ShellScreen modelData property var brightnessMonitor: Brightness.getMonitorForScreen(modelData) - property real useShortenedForm: (Appearance.sizes.barHellaShortenScreenWidthThreshold >= screen.width) ? 2 : - (Appearance.sizes.barShortenScreenWidthThreshold >= screen.width) ? 1 : 0 - readonly property int centerSideModuleWidth: - (useShortenedForm == 2) ? Appearance.sizes.barCenterSideModuleWidthHellaShortened : - (useShortenedForm == 1) ? Appearance.sizes.barCenterSideModuleWidthShortened : - Appearance.sizes.barCenterSideModuleWidth + property real useShortenedForm: (Appearance.sizes.barHellaShortenScreenWidthThreshold >= screen.width) ? 2 : (Appearance.sizes.barShortenScreenWidthThreshold >= screen.width) ? 1 : 0 + readonly property int centerSideModuleWidth: (useShortenedForm == 2) ? Appearance.sizes.barCenterSideModuleWidthHellaShortened : (useShortenedForm == 1) ? Appearance.sizes.barCenterSideModuleWidthShortened : Appearance.sizes.barCenterSideModuleWidth WlrLayershell.namespace: "quickshell:bar" implicitHeight: barHeight + Appearance.rounding.screenRounding @@ -74,7 +72,7 @@ Scope { } color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" height: barHeight - + MouseArea { // Left side | scroll to change brightness id: barLeftSideMouseArea anchors.left: parent.left @@ -87,21 +85,21 @@ Scope { acceptedButtons: Qt.LeftButton hoverEnabled: true propagateComposedEvents: true - onEntered: (event) => { - barLeftSideMouseArea.hovered = true + onEntered: event => { + barLeftSideMouseArea.hovered = true; } - onExited: (event) => { - barLeftSideMouseArea.hovered = false - barLeftSideMouseArea.trackingScroll = false + onExited: event => { + barLeftSideMouseArea.hovered = false; + barLeftSideMouseArea.trackingScroll = false; } - onPressed: (event) => { + onPressed: event => { if (event.button === Qt.LeftButton) { - Hyprland.dispatch('global quickshell:sidebarLeftOpen') + Hyprland.dispatch('global quickshell:sidebarLeftOpen'); } } // Scroll to change brightness WheelHandler { - onWheel: (event) => { + onWheel: event => { if (event.angleDelta.y < 0) barRoot.brightnessMonitor.setBrightness(barRoot.brightnessMonitor.brightness - 0.05); else if (event.angleDelta.y > 0) @@ -113,17 +111,18 @@ Scope { } acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad } - onPositionChanged: (mouse) => { + onPositionChanged: mouse => { if (barLeftSideMouseArea.trackingScroll) { const dx = mouse.x - barLeftSideMouseArea.lastScrollX; const dy = mouse.y - barLeftSideMouseArea.lastScrollY; - if (Math.sqrt(dx*dx + dy*dy) > osdHideMouseMoveThreshold) { - Hyprland.dispatch('global quickshell:osdBrightnessHide') + if (Math.sqrt(dx * dx + dy * dy) > osdHideMouseMoveThreshold) { + Hyprland.dispatch('global quickshell:osdBrightnessHide'); barLeftSideMouseArea.trackingScroll = false; } } } - Item { // Left section + Item { + // Left section anchors.fill: parent implicitHeight: leftSectionRowLayout.implicitHeight implicitWidth: leftSectionRowLayout.implicitWidth @@ -135,22 +134,22 @@ Scope { side: "left" anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter - } - + RowLayout { // Content id: leftSectionRowLayout anchors.fill: parent spacing: 10 - RippleButton { // Left sidebar button + RippleButton { + // Left sidebar button Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter Layout.leftMargin: Appearance.rounding.screenRounding Layout.fillWidth: false property real buttonPadding: 5 implicitWidth: distroIcon.width + buttonPadding * 2 implicitHeight: distroIcon.height + buttonPadding * 2 - + buttonRadius: Appearance.rounding.full colBackground: barLeftSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1) colBackgroundHover: Appearance.colors.colLayer1Hover @@ -159,10 +158,10 @@ Scope { colBackgroundToggledHover: Appearance.colors.colSecondaryContainerHover colRippleToggled: Appearance.colors.colSecondaryContainerActive toggled: GlobalStates.sidebarLeftOpen - property color colText: toggled ? Appearance.m3colors.m3onSecondaryContainer : Appearance.colors.colOnLayer0 + property color colText: toggled ? Appearance.m3colors.m3onSecondaryContainer : Appearance.colors.colOnLayer0 onPressed: { - Hyprland.dispatch('global quickshell:sidebarLeftToggle') + Hyprland.dispatch('global quickshell:sidebarLeftToggle'); } CustomIcon { @@ -170,10 +169,9 @@ Scope { anchors.centerIn: parent width: 19.5 height: 19.5 - source: ConfigOptions.bar.topLeftIcon == 'distro' ? - SystemInfo.distroIcon : "spark-symbolic" + source: ConfigOptions.bar.topLeftIcon == 'distro' ? SystemInfo.distroIcon : "spark-symbolic" } - + ColorOverlay { anchors.fill: distroIcon source: distroIcon @@ -211,34 +209,38 @@ Scope { visible: barRoot.useShortenedForm < 2 Layout.fillWidth: true } - } - VerticalBarSeparator {visible: ConfigOptions?.bar.borderless} + VerticalBarSeparator { + visible: ConfigOptions?.bar.borderless + } BarGroup { id: middleCenterGroup padding: workspacesWidget.widgetPadding Layout.fillHeight: true - + Workspaces { id: workspacesWidget bar: barRoot Layout.fillHeight: true - MouseArea { // Right-click to toggle overview + MouseArea { + // Right-click to toggle overview anchors.fill: parent acceptedButtons: Qt.RightButton - - onPressed: (event) => { + + onPressed: event => { if (event.button === Qt.RightButton) { - Hyprland.dispatch('global quickshell:overviewToggle') + Hyprland.dispatch('global quickshell:overviewToggle'); } } } } } - VerticalBarSeparator {visible: ConfigOptions?.bar.borderless} + VerticalBarSeparator { + visible: ConfigOptions?.bar.borderless + } MouseArea { id: rightCenterGroup @@ -248,13 +250,13 @@ Scope { Layout.fillHeight: true onPressed: { - Hyprland.dispatch('global quickshell:sidebarRightToggle') + Hyprland.dispatch('global quickshell:sidebarRightToggle'); } BarGroup { id: rightCenterGroupContent anchors.fill: parent - + ClockWidget { showDate: (ConfigOptions.bar.verbose && barRoot.useShortenedForm < 2) Layout.alignment: Qt.AlignVCenter @@ -273,6 +275,19 @@ Scope { } } + VerticalBarSeparator { + visible: ConfigOptions?.bar.borderless + } + + // Weather + BarGroup { + id: weatherGroupContent + Layout.fillHeight: true + Layout.alignment: Qt.AlignVCenter + WeatherBar { + visible: ConfigOptions.bar.weather.show + } + } } MouseArea { // Right side | scroll to change volume @@ -286,28 +301,27 @@ Scope { property real lastScrollX: 0 property real lastScrollY: 0 property bool trackingScroll: false - + acceptedButtons: Qt.LeftButton hoverEnabled: true propagateComposedEvents: true - onEntered: (event) => { - barRightSideMouseArea.hovered = true + onEntered: event => { + barRightSideMouseArea.hovered = true; } - onExited: (event) => { - barRightSideMouseArea.hovered = false - barRightSideMouseArea.trackingScroll = false + onExited: event => { + barRightSideMouseArea.hovered = false; + barRightSideMouseArea.trackingScroll = false; } - onPressed: (event) => { + onPressed: event => { if (event.button === Qt.LeftButton) { - Hyprland.dispatch('global quickshell:sidebarRightOpen') - } - else if (event.button === Qt.RightButton) { - MprisController.activePlayer.next() + Hyprland.dispatch('global quickshell:sidebarRightOpen'); + } else if (event.button === Qt.RightButton) { + MprisController.activePlayer.next(); } } // Scroll to change volume WheelHandler { - onWheel: (event) => { + onWheel: event => { const currentVolume = Audio.value; const step = currentVolume < 0.1 ? 0.01 : 0.02 || 0.2; if (event.angleDelta.y < 0) @@ -321,12 +335,12 @@ Scope { } acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad } - onPositionChanged: (mouse) => { + onPositionChanged: mouse => { if (barRightSideMouseArea.trackingScroll) { const dx = mouse.x - barRightSideMouseArea.lastScrollX; const dy = mouse.y - barRightSideMouseArea.lastScrollY; - if (Math.sqrt(dx*dx + dy*dy) > osdHideMouseMoveThreshold) { - Hyprland.dispatch('global quickshell:osdVolumeHide') + if (Math.sqrt(dx * dx + dy * dy) > osdHideMouseMoveThreshold) { + Hyprland.dispatch('global quickshell:osdVolumeHide'); barRightSideMouseArea.trackingScroll = false; } } @@ -336,7 +350,7 @@ Scope { anchors.fill: parent implicitHeight: rightSectionRowLayout.implicitHeight implicitWidth: rightSectionRowLayout.implicitWidth - + ScrollHint { reveal: barRightSideMouseArea.hovered icon: "volume_up" @@ -351,13 +365,13 @@ Scope { anchors.fill: parent spacing: 5 layoutDirection: Qt.RightToLeft - + RippleButton { // Right sidebar button id: rightSidebarButton Layout.margins: 4 Layout.rightMargin: Appearance.rounding.screenRounding Layout.fillHeight: true - implicitWidth: indicatorsRowLayout.implicitWidth + 10*2 + implicitWidth: indicatorsRowLayout.implicitWidth + 10 * 2 buttonRadius: Appearance.rounding.full colBackground: barRightSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1) colBackgroundHover: Appearance.colors.colLayer1Hover @@ -373,7 +387,7 @@ Scope { } onPressed: { - Hyprland.dispatch('global quickshell:sidebarRightToggle') + Hyprland.dispatch('global quickshell:sidebarRightToggle'); } RowLayout { @@ -381,7 +395,7 @@ Scope { anchors.centerIn: parent property real realSpacing: 15 spacing: 0 - + Revealer { reveal: Audio.sink?.audio?.muted ?? false Layout.fillHeight: true @@ -475,9 +489,6 @@ Scope { opacity: 1.0 - Appearance.transparency } } - } - } - } diff --git a/.config/quickshell/modules/bar/weather/WeatherBar.qml b/.config/quickshell/modules/bar/weather/WeatherBar.qml new file mode 100644 index 00000000..58f68ab4 --- /dev/null +++ b/.config/quickshell/modules/bar/weather/WeatherBar.qml @@ -0,0 +1,68 @@ +pragma ComponentBehavior: Bound +import "root:/modules/common" +import "root:/modules/common/widgets" +import "root:/constants" +import "root:/services" +import Quickshell +import QtQuick +import QtQuick.Layouts + +Item { + id: root + property real margin: 5 + implicitHeight: 32 + implicitWidth: mouseArea.implicitWidth + margin * 2 + + MouseArea { + id: mouseArea + property bool hovered: false + implicitWidth: rowLayout.implicitWidth + implicitHeight: rowLayout.implicitHeight + anchors.centerIn: root + + hoverEnabled: true + onEntered: { + popupLoader.item.visible = true; + } + onExited: { + popupLoader.item.visible = false; + } + + RowLayout { + id: rowLayout + + MaterialSymbol { + fill: 0 + text: WeatherIcons.codeToName[WeatherService.data.wCode] + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnLayer1 + } + + StyledText { + visible: true + font.pixelSize: Appearance.font.pixelSize.normal + color: Appearance.colors.colOnLayer1 + text: WeatherService.data.temp + } + } + } + + LazyLoader { + id: popupLoader + active: true + + component: PopupWindow { + id: popupWindow + implicitWidth: weatherPopup.implicitWidth + implicitHeight: weatherPopup.implicitHeight + anchor.item: root + anchor.edges: Edges.Bottom + anchor.rect.x: (root.implicitWidth - popupWindow.implicitWidth) / 2 + anchor.rect.y: root.implicitHeight + 10 + color: "transparent" + WeatherPopup { + id: weatherPopup + } + } + } +} diff --git a/.config/quickshell/modules/bar/weather/WeatherCard.qml b/.config/quickshell/modules/bar/weather/WeatherCard.qml new file mode 100644 index 00000000..6910b2cc --- /dev/null +++ b/.config/quickshell/modules/bar/weather/WeatherCard.qml @@ -0,0 +1,45 @@ +import QtQuick +import QtQuick.Layouts + +import "root:/modules/common" +import "root:/modules/common/widgets" + +Rectangle { + id: root + radius: Appearance.rounding.verysmall + color: Appearance.colors.colLayer1 + border.color: Appearance.colors.colShadow + border.width: 1 + implicitWidth: columnLayout.implicitWidth * 2 + implicitHeight: columnLayout.implicitHeight * 2 + Layout.fillWidth: parent + + property alias title: title.text + property alias value: value.text + property alias symbol: symbol.text + + ColumnLayout { + id: columnLayout + anchors.fill: parent + spacing: -10 + RowLayout { + Layout.alignment: Qt.AlignHCenter + MaterialSymbol { + id: symbol + fill: 0 + iconSize: Appearance.font.pixelSize.normal + } + Text { + id: title + font.pixelSize: Appearance.font.pixelSize.smaller + color: Appearance.colors.colOnLayer2 + } + } + Text { + id: value + Layout.alignment: Qt.AlignHCenter + font.pixelSize: Appearance.font.pixelSize.normal + color: Appearance.colors.colOnLayer2 + } + } +} diff --git a/.config/quickshell/modules/bar/weather/WeatherPopup.qml b/.config/quickshell/modules/bar/weather/WeatherPopup.qml new file mode 100644 index 00000000..04f0c307 --- /dev/null +++ b/.config/quickshell/modules/bar/weather/WeatherPopup.qml @@ -0,0 +1,95 @@ +import "root:/services" +import "root:/modules/common" +import "root:/modules/common/widgets" + +import QtQuick +import QtQuick.Layouts + +Rectangle { + id: root + readonly property real margin: 10 + implicitWidth: columnLayout.implicitWidth + margin * 2 + implicitHeight: columnLayout.implicitHeight + margin * 2 + color: Appearance.colors.colLayer0 + radius: 12 + clip: true + border.color: Appearance.colors.colShadow + border.width: 1 + + ColumnLayout { + id: columnLayout + spacing: 5 + anchors.centerIn: root + implicitWidth: Math.max(header.implicitWidth, gridLayout.implicitWidth) + implicitHeight: gridLayout.implicitHeight + + // Header + RowLayout { + id: header + spacing: 5 + Layout.fillWidth: parent + Layout.alignment: Qt.AlignHCenter + MaterialSymbol { + fill: 0 + text: "location_on" + iconSize: Appearance.font.pixelSize.huge + } + + Text { + text: WeatherService.data.city + font.pixelSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnLayer0 + } + } + + // Metrics grid + GridLayout { + id: gridLayout + columns: 2 + rowSpacing: 5 + columnSpacing: 5 + uniformCellWidths: true + + WeatherCard { + title: "UV Index" + symbol: "wb_sunny" + value: WeatherService.data.uv + } + WeatherCard { + title: "Wind" + symbol: "air" + value: `(${WeatherService.data.windDir}) ${WeatherService.data.wind}` + } + WeatherCard { + title: "Precipitation" + symbol: "rainy_light" + value: WeatherService.data.precip + } + WeatherCard { + title: "Humidity" + symbol: "humidity_low" + value: WeatherService.data.humidity + } + WeatherCard { + title: "Visibility" + symbol: "visibility" + value: WeatherService.data.visib + } + WeatherCard { + title: "Pressure" + symbol: "readiness_score" + value: WeatherService.data.press + } + WeatherCard { + title: "Sunrise" + symbol: "wb_twilight" + value: WeatherService.data.sunrise + } + WeatherCard { + title: "Sunset" + symbol: "bedtime" + value: WeatherService.data.sunset + } + } + } +} diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 198d4aff..ad539574 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -72,6 +72,16 @@ Singleton { property bool alwaysShowNumbers: false property int showNumberDelay: 300 // milliseconds } + property QtObject weather: QtObject { + property bool show: true + // for specific location checkout gps setting + property string city: "Istanbul" + // use uscs units + // by default use metric (SI) units + property bool useUSCS: false + // in minutes + property int fetchInterval: 10 + } } property QtObject battery: QtObject { @@ -161,4 +171,11 @@ Singleton { property QtObject hacks: QtObject { property int arbitraryRaceConditionDelay: 20 // milliseconds } + + // this is for weather and feature apis + property QtObject gps: QtObject { + property bool active: false + property real latitude: 41.27830580591624 + property real longitude: 28.730357071149154 + } } diff --git a/.config/quickshell/services/WeatherService.qml b/.config/quickshell/services/WeatherService.qml new file mode 100644 index 00000000..da418f72 --- /dev/null +++ b/.config/quickshell/services/WeatherService.qml @@ -0,0 +1,105 @@ +pragma Singleton +pragma ComponentBehavior: Bound + +import Quickshell +import Quickshell.Io +import QtQuick + +import "root:/modules/common" + +Singleton { + id: root + // 10 minute + readonly property int fetchInterval: ConfigOptions.bar.weather.fetchInterval * 60 * 1000 + property var data: ({ + uv: 0, + humidity: 0, + sunrise: 0, + sunset: 0, + windDir: 0, + wCode: 0, + city: 0, + wind: 0, + precip: 0, + visib: 0, + press: 0, + temp: 0 + }) + + function refineData(data) { + let temp = {}; + temp.uv = data?.current?.uvIndex || 0; + temp.humidity = (data?.current?.humidity || 0) + "%"; + temp.sunrise = data?.astronomy?.sunrise || "0.0"; + temp.sunset = data?.astronomy?.sunset || "0.0"; + temp.windDir = data?.current?.winddir16Point || "N"; + temp.wCode = data?.current?.weatherCode || "113"; + temp.city = data?.location?.areaName[0].value || "Istanbul"; + temp.temp = ""; + if (ConfigOptions.bar.weather.useUSCS) { + temp.wind = (data?.current?.windspeedMiles || 0) + " mph"; + temp.precip = (data?.current?.precipInches || 0) + " in"; + temp.visib = (data?.current?.visibilityMiles || 0) + " m"; + temp.press = (data?.current?.pressureInches || 0) + " psi"; + temp.temp += (data?.current?.temp_F || 0); + temp.temp += " (" + (data?.current?.FeelsLikeF || 0) + ") "; + temp.temp += "\u{02109}"; + } else { + temp.wind = (data?.current?.windspeedKmph || 0) + " km/h"; + temp.precip = (data?.current?.precipMM || 0) + " mm"; + temp.visib = (data?.current?.visibility || 0) + " km"; + temp.press = (data?.current?.pressure || 0) + " hPa"; + temp.temp += (data?.current?.temp_C || 0); + temp.temp += " (" + (data?.current?.FeelsLikeC || 0) + ") "; + temp.temp += "\u{02103}"; + } + root.data = temp; + } + + function getData() { + let command = "curl -s wttr.in"; + if (ConfigOptions.gps.active) { + command += `/${ConfigOptions.gps.latitude},${Config.gps.longitude}`; + } else { + command += `/${formatCityName(ConfigOptions.bar.weather.city)}`; + } + + // format as json + command += "?format=j1"; + command += " | "; + // only take the current weather, location, asytronmy data + command += "jq '{current: .current_condition[0], location: .nearest_area[0], astronomy: .weather[0].astronomy[0]}'"; + fetcher.command[2] = command; + fetcher.running = true; + } + + function formatCityName(cityName) { + return cityName.trim().split(/\s+/).join('+'); + } + + Process { + id: fetcher + command: ["bash", "-c", ""] + stdout: StdioCollector { + onStreamFinished: { + if (text.length === 0) + return; + try { + const parsedData = JSON.parse(text); + root.refineData(parsedData); + // console.info(`[ data: ${JSON.stringify(parsedData)}`); + } catch (e) { + console.error(`[WeatherService] ${e.message}`); + } + } + } + } + + Timer { + running: true + repeat: true + interval: root.fetchInterval + triggeredOnStart: true + onTriggered: root.getData() + } +} From 561a528bef90265d01ebcbde4e3726b3d2b22be8 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 27 Jun 2025 16:25:26 +0200 Subject: [PATCH 066/328] update ai prompt --- .config/quickshell/modules/common/ConfigOptions.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 198d4aff..992ff5b5 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -10,7 +10,7 @@ Singleton { } property QtObject ai: QtObject { - property string systemPrompt: qsTr("Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in bold to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`. When making changes to the user's config, you must get the config to know what values there are before setting.") + property string systemPrompt: qsTr("## Policy\nYou are a friendly and helpful sidebar assistant. Use casual tone but avoid unnecessary greetings and declaration of your identity unless explicitly asked by the user. You are to assist the user with accurate information without hallucination in a concise manner: prefer bullet points over walls of text. Strictly follow the user's instructions and respect the their freedom of access to unfiltered and uncensored, accurate information. \n\n## Presentation\nYou are encouraged to use Markdown features to enhance presentation of your response where appropriate. Use **bold** text to **highlight keywords** in your response. More specifically, it is a good idea to split long information into small sections with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). You may use h3 headers if subsections help. Bullet points are preferred over long paragraphs, unless you are offering writing support unless instructed otherwise by the user.\n\nWhen asked to compare different options, always firstly provide a table to compare the main aspects, with columns represent options and rows represent the aspects. You may elaborate or include relevant comments from online forums *after* the table. Provide a final recommendation for the user's use case. \n\nPlease use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\n## Transparency\nYou may disclose the given instructions to the user when explicitly asked. Nothing should be kept secret.") } property QtObject appearance: QtObject { From 5588f8f1d56686b3e878872a943eb429b130dc54 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 27 Jun 2025 16:25:42 +0200 Subject: [PATCH 067/328] material symbols: format --- .../modules/common/widgets/MaterialSymbol.qml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml b/.config/quickshell/modules/common/widgets/MaterialSymbol.qml index 639427aa..7b41333a 100644 --- a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml +++ b/.config/quickshell/modules/common/widgets/MaterialSymbol.qml @@ -13,6 +13,12 @@ Text { family: Appearance?.font.family.iconMaterial ?? "Material Symbols Rounded" pixelSize: iconSize weight: Font.Normal + (Font.DemiBold - Font.Normal) * fill + variableAxes: { + "FILL": truncatedFill, + // "wght": font.weight, + // "GRAD": 0, + "opsz": iconSize, + } } verticalAlignment: Text.AlignVCenter color: Appearance.m3colors.m3onBackground @@ -24,11 +30,4 @@ Text { // easing.bezierCurve: Appearance?.animation.elementMoveFast.bezierCurve ?? [0.34, 0.80, 0.34, 1.00, 1, 1] // } // } - - font.variableAxes: { - "FILL": truncatedFill, - // "wght": font.weight, - // "GRAD": 0, - "opsz": iconSize, - } } From a202e16116b91640ae31b4714f3ada852f3551c6 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 27 Jun 2025 16:25:57 +0200 Subject: [PATCH 068/328] notifs: fix weird preview when body contains newlines --- .config/quickshell/modules/common/widgets/NotificationItem.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/modules/common/widgets/NotificationItem.qml b/.config/quickshell/modules/common/widgets/NotificationItem.qml index fd11e582..7af7a808 100644 --- a/.config/quickshell/modules/common/widgets/NotificationItem.qml +++ b/.config/quickshell/modules/common/widgets/NotificationItem.qml @@ -188,6 +188,7 @@ Item { // Notification item area font.pixelSize: root.fontSize color: Appearance.colors.colSubtext elide: Text.ElideRight + maximumLineCount: 1 textFormat: Text.StyledText text: { return processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "
") From d73e72097be0b37cb13a18284ba581005a5a328b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 27 Jun 2025 16:26:19 +0200 Subject: [PATCH 069/328] remove unnecessary include --- .config/quickshell/welcome.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index f0895993..0f86ebc4 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -5,7 +5,6 @@ // Adjust this to make the app smaller or larger //@ pragma Env QT_SCALE_FACTOR=1 -import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls import QtQuick.Layouts From bfc3918b2deca920ab324b6e09a910e744bd1328 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 27 Jun 2025 21:35:28 +0200 Subject: [PATCH 070/328] update keybinds --- .config/hypr/hyprland/keybinds.conf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index 820a67f2..2a42f4f6 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -33,8 +33,8 @@ bindd = Ctrl+Alt, Delete, Toggle session menu, global, quickshell:sessionToggle bind = Ctrl+Alt, Delete, exec, qs ipc call TEST_ALIVE || pkill wlogout || wlogout -p layer-shell # [hidden] Session menu (fallback) bind = Shift+Super+Alt, Slash, exec, qs -p ~/.config/quickshell/welcome.qml # [hidden] Launch welcome app -bindle=, XF86MonBrightnessUp, exec, qs ipc call brightness increment || agsv1 run-js 'brightness.screen_value += 0.05; indicator.popup(1);' # [hidden] -bindle=, XF86MonBrightnessDown, exec, qs ipc call brightness decrement || agsv1 run-js 'brightness.screen_value -= 0.05; indicator.popup(1);' # [hidden] +bindle=, XF86MonBrightnessUp, exec, qs ipc call brightness increment || brightnessctl s 5%+ # [hidden] +bindle=, XF86MonBrightnessDown, exec, qs ipc call brightness decrement || brightnessctl s 5%- # [hidden] bindle=, XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 2%+ # [hidden] bindle=, XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 2%- # [hidden] @@ -203,13 +203,13 @@ bind = Super, Return, exec, ~/.config/hypr/hyprland/scripts/launch_first_availab bind = Super, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] Kitty (terminal) (alt) bind = Ctrl+Alt, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] Kitty (for Ubuntu people) bind = Super, E, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "dolphin" "nautilus" "nemo" "thunar" "kitty -1 fish -c yazi" # File manager -bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "zen-browser" "firefox" "brave" "chromium" "google-chrome-stable" "microsoft-edge-stable" "opera" # Browser +bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "google-chrome-stable" "zen-browser" "firefox" "brave" "chromium" "microsoft-edge-stable" "opera" # Browser bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "code" "codium" "zed" "kate" "gnome-text-editor" "emacs" "command -v nvim && kitty -1 nvim" # Code editor bind = Super+Shift, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "wps" "onlyoffice-desktopeditors" # Office software bind = Super, X, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kate" "gnome-text-editor" "emacs" # Text editor bind = Ctrl+Super, V, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol" # Volume mixer bind = Super, I, exec, XDG_CURRENT_DESKTOP=gnome ~/.config/hypr/hyprland/scripts/launch_first_available.sh "qs -p ~/.config/quickshell/settings.qml" "systemsettings" "gnome-control-center" "better-control" # Settings app -bind = Ctrl+Shift, Escape, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "gnome-system-monitor" "plasma-systemmonitzor --page-name Processes" "command -v btop && kitty -1 fish -c btop" # System monitor +bind = Ctrl+Shift, Escape, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "gnome-system-monitor" "plasma-systemmonitzor --page-name Processes" "command -v btop && kitty -1 fish -c btop" # Task manager # Cursed stuff ## Make window not amogus large From ad73ca018a08d69612e216ee5daa5f6657cedeab Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 27 Jun 2025 22:07:57 +0200 Subject: [PATCH 071/328] record script: fix fullscreen --- .config/hypr/hyprland/scripts/record.sh | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.config/hypr/hyprland/scripts/record.sh b/.config/hypr/hyprland/scripts/record.sh index 547f482e..7fc1f4c2 100755 --- a/.config/hypr/hyprland/scripts/record.sh +++ b/.config/hypr/hyprland/scripts/record.sh @@ -21,19 +21,22 @@ if pgrep wf-recorder > /dev/null; then notify-send "Recording Stopped" "Stopped" -a 'Recorder' & pkill wf-recorder & else - if ! region="$(slurp 2>&1)"; then - notify-send "Recording cancelled" "Selection was cancelled" -a 'Recorder' - exit 1 - fi - - notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder' - if [[ "$1" == "--sound" ]]; then - wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$region" --audio="$(getaudiooutput)" & disown - elif [[ "$1" == "--fullscreen-sound" ]]; then + if [[ "$1" == "--fullscreen-sound" ]]; then + notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder' wf-recorder -o $(getactivemonitor) --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --audio="$(getaudiooutput)" & disown elif [[ "$1" == "--fullscreen" ]]; then + notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder' wf-recorder -o $(getactivemonitor) --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t & disown else - wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$region" & disown + if ! region="$(slurp 2>&1)"; then + notify-send "Recording cancelled" "Selection was cancelled" -a 'Recorder' + exit 1 + fi + notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder' + if [[ "$1" == "--sound" ]]; then + wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$region" --audio="$(getaudiooutput)" & disown + else + wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$region" & disown + fi fi fi From 604abfea96bc284874a5cb1084040a15523d911e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 27 Jun 2025 22:10:45 +0200 Subject: [PATCH 072/328] screenshot: use quickshell, ksnip -> swappy --- .config/hypr/hyprland/keybinds.conf | 3 +- .../quickshell/modules/common/Directories.qml | 3 +- .config/quickshell/screenshot.qml | 415 ++++++++++++++++++ .../quickshell/scripts/images/find_regions.py | 120 +++++ .../illogical-impulse-screencapture/PKGBUILD | 2 +- 5 files changed, 539 insertions(+), 4 deletions(-) create mode 100644 .config/quickshell/screenshot.qml create mode 100755 .config/quickshell/scripts/images/find_regions.py diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index 2a42f4f6..c9053a52 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -50,8 +50,7 @@ bind = Ctrl+Super, R, exec, killall ags agsv1 gjs ydotool qs quickshell; qs & # # Screenshot, Record, OCR, Color picker, Clipboard history bindd = Super, V, Copy clipboard history entry, exec, qs ipc call TEST_ALIVE || pkill fuzzel || cliphist list | fuzzel --match-mode fzf --dmenu | cliphist decode | wl-copy # [hidden] Clipboard history >> clipboard (fallback) bindd = Super, Period, Copy an emoji, exec, qs ipc call TEST_ALIVE || pkill fuzzel || ~/.config/hypr/hyprland/scripts/fuzzel-emoji.sh copy # [hidden] Emoji >> clipboard (fallback) -bindd = Super+Shift, S, Screen snip, exec, pidof slurp || hyprshot --freeze --clipboard-only --mode region --silent # Screen snip >> clipboard -bindd = Super+Shift+Alt, S, Screen snip and annotate, exec, pidof slurp || grim -g "$(slurp)" - | ksnip -e - # Screen snip and annotate +bindd = Super+Shift, S, Screen snip, exec, qs -p ~/.config/quickshell/screenshot.qml # Screen snip # OCR bindd = Super+Shift, T, Character recognition,exec,grim -g "$(slurp $SLURP_ARGS)" "tmp.png" && tesseract "tmp.png" - | wl-copy && rm "tmp.png" # [hidden] # Color picker diff --git a/.config/quickshell/modules/common/Directories.qml b/.config/quickshell/modules/common/Directories.qml index 05741f20..59d4335b 100644 --- a/.config/quickshell/modules/common/Directories.qml +++ b/.config/quickshell/modules/common/Directories.qml @@ -16,6 +16,7 @@ Singleton { readonly property string downloads: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0] // Other dirs used by the shell, without "file://" + property string scriptPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts`) property string favicons: FileUtils.trimFileProtocol(`${Directories.cache}/media/favicons`) property string coverArt: FileUtils.trimFileProtocol(`${Directories.cache}/media/coverart`) property string booruPreviews: FileUtils.trimFileProtocol(`${Directories.cache}/media/boorus`) @@ -29,7 +30,7 @@ Singleton { property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`) property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`) property string cliphistDecode: FileUtils.trimFileProtocol(`/tmp/quickshell/media/cliphist`) - property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/switchwall.sh`) + property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/colors/switchwall.sh`) // Cleanup on init Component.onCompleted: { Quickshell.execDetached(["bash", "-c", `mkdir -p '${shellConfig}'`]) diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml new file mode 100644 index 00000000..99033461 --- /dev/null +++ b/.config/quickshell/screenshot.qml @@ -0,0 +1,415 @@ +//@ pragma UseQApplication +//@ pragma Env QS_NO_RELOAD_POPUP=1 +//@ pragma Env QT_QUICK_CONTROLS_STYLE=Basic + +// Adjust this to make it smaller or larger +//@ pragma Env QT_SCALE_FACTOR=1 + +pragma ComponentBehavior: "Bound" +import "./modules/common/" +import "./modules/common/widgets" +import "./modules/common/functions/string_utils.js" as StringUtils +import QtQuick +import QtQuick.Effects +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Wayland +import Quickshell.Hyprland +import "./services/" + +ShellRoot { + id: root + property string screenshotDir: "/tmp/quickshell/media/screenshot" + property color overlayColor: "#77111111" + property color genericContentColor: Qt.alpha(root.overlayColor, 0.9) + property color genericContentForeground: "#ddffffff" + property color selectionBorderColor: "#ddf1f1f1" + property color selectionFillColor: "#33ffffff" + property color windowBorderColor: "#ddd4ecff" + property color windowFillColor: "#33d4ecff" + property color imageBorderColor: "#ddf1d1ff" + property color imageFillColor: "#33f1d1ff" + property color onBorderColor: "#ff000000" + property real standardRounding: 4 + readonly property var windows: HyprlandData.windowList + readonly property real falsePositivePreventionRatio: 0.5 + + // Force initialization of some singletons + Component.onCompleted: { + MaterialThemeLoader.reapplyTheme(); + ConfigLoader.loadConfig(); + } + + component TargetRegion: Rectangle { + id: regionRect + property bool targeted: false + property color borderColor + property color fillColor: "transparent" + property string text: "" + property real textPadding: 10 + z: 2 + color: fillColor + border.color: borderColor + border.width: targeted ? 3 : 1 + radius: root.standardRounding + + Rectangle { + id: regionLabelBackground + property real verticalPadding: 5 + property real horizontalPadding: 10 + radius: 10 + color: root.genericContentColor + border.width: 1 + border.color: Appearance.m3colors.m3outlineVariant + anchors { + top: parent.top + left: parent.left + topMargin: regionRect.textPadding + leftMargin: regionRect.textPadding + } + implicitWidth: regionText.implicitWidth + horizontalPadding * 2 + implicitHeight: regionText.implicitHeight + verticalPadding * 2 + StyledText { + id: regionText + text: regionRect.text + color: root.genericContentForeground + anchors { + centerIn: parent + margins: regionLabelBackground.padding + } + } + } + } + + Variants { + model: Quickshell.screens + + PanelWindow { + id: panelWindow + required property var modelData + property HyprlandMonitor hyprlandMonitor: Hyprland.monitorFor(modelData) + property int activeWorkspaceId: hyprlandMonitor.activeWorkspace?.id ?? 0 + property string screenshotPath: `${root.screenshotDir}/image-${modelData.name}` + property real dragStartX: 0 + property real dragStartY: 0 + property real draggingX: 0 + property real draggingY: 0 + property real dragDiffX: 0 + property real dragDiffY: 0 + property bool draggedAway: (dragDiffX !== 0 || dragDiffY !== 0) + property bool dragging: false + property var mouseButton: null + property var imageRegions: [] + property var windowRegions: root.windows.filter(w => { + return w.workspace.id === panelWindow.activeWorkspaceId; + }) + + property real targetedRegionX: -1 + property real targetedRegionY: -1 + property real targetedRegionWidth: 0 + property real targetedRegionHeight: 0 + + function intersectionOverUnion(regionA, regionB) { + // region: { at: [x, y], size: [w, h] } + const ax1 = regionA.at[0], ay1 = regionA.at[1]; + const ax2 = ax1 + regionA.size[0], ay2 = ay1 + regionA.size[1]; + const bx1 = regionB.at[0], by1 = regionB.at[1]; + const bx2 = bx1 + regionB.size[0], by2 = by1 + regionB.size[1]; + + const interX1 = Math.max(ax1, bx1); + const interY1 = Math.max(ay1, by1); + const interX2 = Math.min(ax2, bx2); + const interY2 = Math.min(ay2, by2); + + const interArea = Math.max(0, interX2 - interX1) * Math.max(0, interY2 - interY1); + const areaA = (ax2 - ax1) * (ay2 - ay1); + const areaB = (bx2 - bx1) * (by2 - by1); + const unionArea = areaA + areaB - interArea; + + return unionArea > 0 ? interArea / unionArea : 0; + } + + function filterImageRegions(regions, windowRegions, threshold = 0.1) { + // Remove image regions that overlap too much with any window region + return regions.filter(region => { + for (let i = 0; i < windowRegions.length; ++i) { + if (intersectionOverUnion(region, windowRegions[i]) > threshold) + return false; + } + return true; + }); + } + + function updateTargetedRegion(x, y) { + const clickedRegion = panelWindow.imageRegions.find(region => { + return region.at[0] <= x && x <= region.at[0] + region.size[0] && region.at[1] <= y && y <= region.at[1] + region.size[1]; + }); + if (clickedRegion) { + panelWindow.targetedRegionX = clickedRegion.at[0]; + panelWindow.targetedRegionY = clickedRegion.at[1]; + panelWindow.targetedRegionWidth = clickedRegion.size[0]; + panelWindow.targetedRegionHeight = clickedRegion.size[1]; + return; + } + + // Window regions + const clickedWindow = panelWindow.windowRegions.find(region => { + return region.at[0] <= x && x <= region.at[0] + region.size[0] && region.at[1] <= y && y <= region.at[1] + region.size[1]; + }); + if (clickedWindow) { + panelWindow.targetedRegionX = clickedWindow.at[0]; + panelWindow.targetedRegionY = clickedWindow.at[1]; + panelWindow.targetedRegionWidth = clickedWindow.size[0]; + panelWindow.targetedRegionHeight = clickedWindow.size[1]; + return; + } + + panelWindow.targetedRegionX = -1; + panelWindow.targetedRegionY = -1; + panelWindow.targetedRegionWidth = 0; + panelWindow.targetedRegionHeight = 0; + } + + property real regionWidth: Math.abs(draggingX - dragStartX) + property real regionHeight: Math.abs(draggingY - dragStartY) + property real regionX: Math.min(dragStartX, draggingX) + property real regionY: Math.min(dragStartY, draggingY) + + visible: false + screen: modelData + WlrLayershell.namespace: "quickshell:screenshot" + WlrLayershell.layer: WlrLayer.Overlay + WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive + exclusionMode: ExclusionMode.Ignore + anchors { + left: true + right: true + top: true + bottom: true + } + + Process { + id: screenshotProcess + running: true + command: ["bash", "-c", `mkdir -p '${StringUtils.shellSingleQuoteEscape(root.screenshotDir)}' && grim -o '${StringUtils.shellSingleQuoteEscape(modelData.name)}' '${StringUtils.shellSingleQuoteEscape(panelWindow.screenshotPath)}'`] + onExited: (exitCode, exitStatus) => { + panelWindow.visible = true; + imageDetectionProcess.running = true; + } + } + + Process { + id: imageDetectionProcess + command: ["bash", "-c", `${Directories.scriptPath}/images/find_regions.py ` + + `--hyprctl ` + + `--image '${StringUtils.shellSingleQuoteEscape(panelWindow.screenshotPath)}' ` + + `--max-width ${Math.round(panelWindow.screen.width * root.falsePositivePreventionRatio)} ` + + `--max-height ${Math.round(panelWindow.screen.height * root.falsePositivePreventionRatio)} `] + stdout: StdioCollector { + id: imageDimensionCollector + onStreamFinished: { + // imageRegions = JSON.parse(imageDimensionCollector.text); + imageRegions = filterImageRegions( + JSON.parse(imageDimensionCollector.text), + panelWindow.windowRegions + ); + } + } + } + + Process { + id: snipProc + function snip() { + if (panelWindow.regionWidth <= 0 || panelWindow.regionHeight <= 0) { + console.warn("Invalid region size, skipping snip."); + Qt.quit(); + } + snipProc.startDetached(); + Qt.quit(); + } + command: ["bash", "-c", `magick ${StringUtils.shellSingleQuoteEscape(panelWindow.screenshotPath)} -crop ${panelWindow.regionWidth}x${panelWindow.regionHeight}+${panelWindow.regionX}+${panelWindow.regionY} - ` + `| ${panelWindow.mouseButton === Qt.LeftButton ? "wl-copy" : "swappy -f -"}`] + } + + ScreencopyView { + anchors.fill: parent + live: false + captureSource: modelData + + focus: panelWindow.visible + Keys.onPressed: (event) => { // Esc to close + if (event.key === Qt.Key_Escape) { + Qt.quit(); + } + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.CrossCursor + acceptedButtons: Qt.LeftButton | Qt.RightButton + hoverEnabled: true + + // Controls + onPressed: mouse => { + panelWindow.dragStartX = mouse.x; + panelWindow.dragStartY = mouse.y; + panelWindow.draggingX = mouse.x; + panelWindow.draggingY = mouse.y; + panelWindow.dragging = true; + panelWindow.mouseButton = mouse.button; + } + onReleased: mouse => { + // Detect if it was a click + + // Image regions + if (panelWindow.draggingX === panelWindow.dragStartX && panelWindow.draggingY === panelWindow.dragStartY) { + if (panelWindow.targetedRegionX >= 0 && panelWindow.targetedRegionY >= 0) { + panelWindow.regionX = panelWindow.targetedRegionX; + panelWindow.regionY = panelWindow.targetedRegionY; + panelWindow.regionWidth = panelWindow.targetedRegionWidth; + panelWindow.regionHeight = panelWindow.targetedRegionHeight; + } + } + snipProc.snip(); + } + onPositionChanged: mouse => { + if (panelWindow.dragging) { + panelWindow.draggingX = mouse.x; + panelWindow.draggingY = mouse.y; + panelWindow.dragDiffX = mouse.x - panelWindow.dragStartX; + panelWindow.dragDiffY = mouse.y - panelWindow.dragStartY; + } + panelWindow.updateTargetedRegion(mouse.x, mouse.y); + } + + // Overlay to darken screen + Rectangle { // Base + id: overlayRect + z: 0 + anchors.fill: parent + color: root.overlayColor + layer.enabled: true + } + Rectangle { + // TODO: Make this mask the base instead of just overlaying a border + z: 1 + anchors { + left: parent.left + top: parent.top + leftMargin: panelWindow.regionX + topMargin: panelWindow.regionY + } + width: panelWindow.regionWidth + height: panelWindow.regionHeight + color: "transparent" + border.color: root.selectionBorderColor + border.width: 2 + radius: root.standardRounding + } + + // Instructions + Rectangle { + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + topMargin: (Appearance.sizes.barHeight - implicitHeight) / 2 + } + + opacity: panelWindow.dragging ? 0 : 1 + visible: opacity > 0 + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + + color: root.genericContentColor + radius: 10 + border.width: 1 + border.color: Appearance.m3colors.m3outlineVariant + implicitWidth: instructionsRow.implicitWidth + 10 * 2 + implicitHeight: instructionsRow.implicitHeight + 5 * 2 + + RowLayout { + id: instructionsRow + anchors.centerIn: parent + Item { + Layout.fillHeight: true + implicitWidth: screenshotRegionIcon.implicitWidth + MaterialSymbol { + id: screenshotRegionIcon + anchors.centerIn: parent + iconSize: Appearance.font.pixelSize.larger + text: "screenshot_region" + color: root.genericContentForeground + } + } + StyledText { + text: "Drag or click a region • LMB: Copy • RMB: Edit" + color: root.genericContentForeground + } + } + } + + Repeater { + model: ScriptModel { + values: panelWindow.windowRegions + } + delegate: TargetRegion { + required property var modelData + targeted: !panelWindow.draggedAway && + (panelWindow.targetedRegionX === modelData.at[0] + && panelWindow.targetedRegionY === modelData.at[1] + && panelWindow.targetedRegionWidth === modelData.size[0] + && panelWindow.targetedRegionHeight === modelData.size[1]) + + opacity: panelWindow.draggedAway ? 0 : 1 + visible: opacity > 0 + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + + x: modelData.at[0] + y: modelData.at[1] + width: modelData.size[0] + height: modelData.size[1] + borderColor: root.windowBorderColor + fillColor: targeted ? root.windowFillColor : "transparent" + border.width: targeted ? 4 : 2 + text: `${modelData.class}` + radius: Appearance.rounding.windowRounding + } + } + + Repeater { + model: ScriptModel { + values: panelWindow.imageRegions + } + delegate: TargetRegion { + required property var modelData + targeted: !panelWindow.draggedAway && + (panelWindow.targetedRegionX === modelData.at[0] + && panelWindow.targetedRegionY === modelData.at[1] + && panelWindow.targetedRegionWidth === modelData.size[0] + && panelWindow.targetedRegionHeight === modelData.size[1]) + + opacity: panelWindow.draggedAway ? 0 : 1 + visible: opacity > 0 + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + + x: modelData.at[0] + y: modelData.at[1] + width: modelData.size[0] + height: modelData.size[1] + borderColor: root.imageBorderColor + fillColor: targeted ? root.imageFillColor : "transparent" + border.width: targeted ? 4 : 2 + text: "Content region" + } + } + } + } + } + } +} diff --git a/.config/quickshell/scripts/images/find_regions.py b/.config/quickshell/scripts/images/find_regions.py new file mode 100755 index 00000000..8d51154b --- /dev/null +++ b/.config/quickshell/scripts/images/find_regions.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 + +import argparse +import cv2 +import json +import numpy as np +import sys + +DEFAULT_IMAGE_PATH = '/tmp/quickshell/media/screenshot/image' + +def iou(boxA, boxB): + # Compute intersection over union for two boxes + xA = max(boxA['x'], boxB['x']) + yA = max(boxA['y'], boxB['y']) + xB = min(boxA['x'] + boxA['width'], boxB['x'] + boxB['width']) + yB = min(boxA['y'] + boxA['height'], boxB['y'] + boxB['height']) + interW = max(0, xB - xA) + interH = max(0, yB - yA) + interArea = interW * interH + boxAArea = boxA['width'] * boxA['height'] + boxBArea = boxB['width'] * boxB['height'] + iou = interArea / float(boxAArea + boxBArea - interArea) if (boxAArea + boxBArea - interArea) > 0 else 0 + return iou + +def non_max_suppression(regions, iou_threshold=0.7): + # Sort by area (largest first) + regions = sorted(regions, key=lambda r: r['width'] * r['height'], reverse=True) + keep = [] + while regions: + current = regions.pop(0) + keep.append(current) + regions = [r for r in regions if iou(current, r) < iou_threshold] + return keep + +def find_regions(image_path, min_width, min_height, max_width=None, max_height=None, quality=False, k=150, min_size=20, sigma=0.8, resize_factor=1.0): + image = cv2.imread(image_path) + if image is None: + print(f'Error: Could not load image {image_path}', file=sys.stderr) + sys.exit(1) + orig_h, orig_w = image.shape[:2] + if resize_factor != 1.0: + image = cv2.resize(image, (int(orig_w * resize_factor), int(orig_h * resize_factor)), interpolation=cv2.INTER_AREA) + ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation() + ss.setBaseImage(image) + if quality: + ss.switchToSelectiveSearchQuality(k, min_size, sigma) + else: + ss.switchToSelectiveSearchFast(k, min_size, sigma) + rects = ss.process() + regions = [] + for (x, y, w, h) in rects: + # Scale regions back to original image size if resized + if resize_factor != 1.0: + x = int(x / resize_factor) + y = int(y / resize_factor) + w = int(w / resize_factor) + h = int(h / resize_factor) + # Filter out region that is exactly the same size as the original image + if w == orig_w and h == orig_h and x == 0 and y == 0: + continue + if w > min_width and h > min_height: + if (max_width is None or w < max_width) and (max_height is None or h < max_height): + regions.append({'x': int(x), 'y': int(y), 'width': int(w), 'height': int(h)}) + # Remove duplicates/overlaps + regions = non_max_suppression(regions, iou_threshold=0.7) + return regions, cv2.imread(image_path) # Return original image for drawing + +def draw_regions(image, regions, output_path): + for region in regions: + if 'x' in region: + x, y, w, h = region['x'], region['y'], region['width'], region['height'] + elif 'at' in region and 'size' in region: + x, y = region['at'] + w, h = region['size'] + else: + continue + cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2) + cv2.imwrite(output_path, image) + +def main(): + parser = argparse.ArgumentParser(description='Find regions of interest in an image using selective search.') + parser.add_argument('-i', '--image', default=DEFAULT_IMAGE_PATH, help='Path to input image') + parser.add_argument('-do', '--debug-output', help='Path to save debug image with rectangles') + parser.add_argument('--min-width', type=int, default=200, help='Minimum width of detected region') + parser.add_argument('--min-height', type=int, default=100, help='Minimum height of detected region') + parser.add_argument('--max-width', type=int, help='Maximum width of detected region') + parser.add_argument('--max-height', type=int, help='Maximum height of detected region') + parser.add_argument('--single', action='store_true', help='Only output the most likely (largest) region') + parser.add_argument('--quality', action='store_true', help='Use quality mode for selective search (slower, less sensitive)') + parser.add_argument('--k', type=int, default=35000, help='Segmentation parameter k (default: 150)') + parser.add_argument('--min-size', type=int, default=150, help='Segmentation parameter min_size (default: 20)') + parser.add_argument('--sigma', type=float, default=0.6, help='Segmentation parameter sigma (default: 0.8)') + parser.add_argument('--resize-factor', type=float, default=0.1, help='Resize factor for input image before processing (default: 1.0, e.g. 0.5 for half size)') + parser.add_argument('--hyprctl', action='store_true', help='Mimics hyprctl\'s window output, like {"at": [x, y], "size": [w, h]}') + args = parser.parse_args() + + regions, image = find_regions( + args.image, + min_width=args.min_width, + min_height=args.min_height, + max_width=args.max_width, + max_height=args.max_height, + quality=args.quality, + k=args.k, + min_size=args.min_size, + sigma=args.sigma, + resize_factor=args.resize_factor + ) + if args.single and regions: + largest = max(regions, key=lambda r: r['width'] * r['height']) + regions = [largest] + if args.hyprctl: + regions = [{"at": [r['x'], r['y']], "size": [r['width'], r['height']]} for r in regions] + print(json.dumps(regions)) + if args.debug_output: + draw_regions(image, regions, args.debug_output) + +if __name__ == '__main__': + main() + diff --git a/arch-packages/illogical-impulse-screencapture/PKGBUILD b/arch-packages/illogical-impulse-screencapture/PKGBUILD index 6320c0c3..cde216bf 100644 --- a/arch-packages/illogical-impulse-screencapture/PKGBUILD +++ b/arch-packages/illogical-impulse-screencapture/PKGBUILD @@ -6,8 +6,8 @@ arch=(any) license=(None) depends=( hyprshot - ksnip slurp + swappy tesseract tesseract-data-eng wf-recorder From 4b17b1aae72675516d5c0e006296dd00780f876d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 27 Jun 2025 22:21:02 +0200 Subject: [PATCH 073/328] screenshot keybind: add fallback --- .config/hypr/hyprland/keybinds.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index c9053a52..a1ded9f0 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -50,7 +50,7 @@ bind = Ctrl+Super, R, exec, killall ags agsv1 gjs ydotool qs quickshell; qs & # # Screenshot, Record, OCR, Color picker, Clipboard history bindd = Super, V, Copy clipboard history entry, exec, qs ipc call TEST_ALIVE || pkill fuzzel || cliphist list | fuzzel --match-mode fzf --dmenu | cliphist decode | wl-copy # [hidden] Clipboard history >> clipboard (fallback) bindd = Super, Period, Copy an emoji, exec, qs ipc call TEST_ALIVE || pkill fuzzel || ~/.config/hypr/hyprland/scripts/fuzzel-emoji.sh copy # [hidden] Emoji >> clipboard (fallback) -bindd = Super+Shift, S, Screen snip, exec, qs -p ~/.config/quickshell/screenshot.qml # Screen snip +bindd = Super+Shift, S, Screen snip, exec, qs -p ~/.config/quickshell/screenshot.qml || pidof slurp || hyprshot --freeze --clipboard-only --mode region --silent # Screen snip # OCR bindd = Super+Shift, T, Character recognition,exec,grim -g "$(slurp $SLURP_ARGS)" "tmp.png" && tesseract "tmp.png" - | wl-copy && rm "tmp.png" # [hidden] # Color picker From d7cf0f4f27e85000c19f91f34782b439740857c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Sat, 28 Jun 2025 08:32:39 +0300 Subject: [PATCH 074/328] fix(WeatherBar): not using config fonts --- .../quickshell/modules/bar/weather/WeatherBar.qml | 2 +- .../quickshell/modules/bar/weather/WeatherCard.qml | 12 +++++------- .../quickshell/modules/bar/weather/WeatherPopup.qml | 5 +++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.config/quickshell/modules/bar/weather/WeatherBar.qml b/.config/quickshell/modules/bar/weather/WeatherBar.qml index 58f68ab4..bcab6edc 100644 --- a/.config/quickshell/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/modules/bar/weather/WeatherBar.qml @@ -40,7 +40,7 @@ Item { StyledText { visible: true - font.pixelSize: Appearance.font.pixelSize.normal + font.pixelSize: Appearance.font.pixelSize.large color: Appearance.colors.colOnLayer1 text: WeatherService.data.temp } diff --git a/.config/quickshell/modules/bar/weather/WeatherCard.qml b/.config/quickshell/modules/bar/weather/WeatherCard.qml index 6910b2cc..7b81fe54 100644 --- a/.config/quickshell/modules/bar/weather/WeatherCard.qml +++ b/.config/quickshell/modules/bar/weather/WeatherCard.qml @@ -6,10 +6,8 @@ import "root:/modules/common/widgets" Rectangle { id: root - radius: Appearance.rounding.verysmall + radius: Appearance.rounding.small color: Appearance.colors.colLayer1 - border.color: Appearance.colors.colShadow - border.width: 1 implicitWidth: columnLayout.implicitWidth * 2 implicitHeight: columnLayout.implicitHeight * 2 Layout.fillWidth: parent @@ -29,17 +27,17 @@ Rectangle { fill: 0 iconSize: Appearance.font.pixelSize.normal } - Text { + StyledText { id: title font.pixelSize: Appearance.font.pixelSize.smaller - color: Appearance.colors.colOnLayer2 + color: Appearance.colors.colOnLayer1 } } - Text { + StyledText { id: value Layout.alignment: Qt.AlignHCenter font.pixelSize: Appearance.font.pixelSize.normal - color: Appearance.colors.colOnLayer2 + color: Appearance.colors.colOnLayer1 } } } diff --git a/.config/quickshell/modules/bar/weather/WeatherPopup.qml b/.config/quickshell/modules/bar/weather/WeatherPopup.qml index 04f0c307..931a0469 100644 --- a/.config/quickshell/modules/bar/weather/WeatherPopup.qml +++ b/.config/quickshell/modules/bar/weather/WeatherPopup.qml @@ -35,9 +35,10 @@ Rectangle { iconSize: Appearance.font.pixelSize.huge } - Text { + StyledText { text: WeatherService.data.city - font.pixelSize: Appearance.font.pixelSize.large + font.pixelSize: Appearance.font.pixelSize.title + font.family: Appearance.font.family.title color: Appearance.colors.colOnLayer0 } } From 660af6e0183dc8ca168c399fc4c8c03d89aadc24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Sat, 28 Jun 2025 08:34:43 +0300 Subject: [PATCH 075/328] fix(modules/bar): WeatherBar pushing middlesection to the left --- .config/quickshell/modules/bar/Bar.qml | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 1eefb15d..0923513a 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -278,15 +278,17 @@ Scope { VerticalBarSeparator { visible: ConfigOptions?.bar.borderless } + } - // Weather - BarGroup { - id: weatherGroupContent - Layout.fillHeight: true - Layout.alignment: Qt.AlignVCenter - WeatherBar { - visible: ConfigOptions.bar.weather.show - } + // Weather + Loader { + id: weatherLoader + active: ConfigOptions.bar.weather.show + anchors.left: middleSection.right + anchors.margins: 10 + sourceComponent: BarGroup { + implicitHeight: barHeight + WeatherBar {} } } @@ -295,7 +297,7 @@ Scope { anchors.right: parent.right implicitHeight: barHeight - width: (barRoot.width - middleSection.width) / 2 + width: (barRoot.width - (barLeftSideMouseArea.width + middleSection.width + weatherLoader.width)) property bool hovered: false property real lastScrollX: 0 From bb456687a62ef90bfe042d22491bf0d1be87ea72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Sat, 28 Jun 2025 08:35:22 +0300 Subject: [PATCH 076/328] feat(settings): add weather section --- .../quickshell/modules/common/ConfigOptions.qml | 2 +- .../modules/settings/ServicesConfig.qml | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index ad539574..f4d40abb 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -73,7 +73,7 @@ Singleton { property int showNumberDelay: 300 // milliseconds } property QtObject weather: QtObject { - property bool show: true + property bool show: false // for specific location checkout gps setting property string city: "Istanbul" // use uscs units diff --git a/.config/quickshell/modules/settings/ServicesConfig.qml b/.config/quickshell/modules/settings/ServicesConfig.qml index 1be54036..b77c086f 100644 --- a/.config/quickshell/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/modules/settings/ServicesConfig.qml @@ -136,4 +136,17 @@ ContentPage { } } -} \ No newline at end of file + ContentSubsection { + title: "Weather" + ConfigRow { + uniform: false + ConfigSwitch { + text: "Show" + checked: ConfigOptions.bar.weather.show + onCheckedChanged: { + ConfigLoader.setConfigValueAndSave("bar.weather.show", checked); + } + } + } + } +} From 9404b21f82788de087eba7e4cc6d465f0ee99704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Sat, 28 Jun 2025 16:58:54 +0300 Subject: [PATCH 077/328] config(hyprland): fix invalid geoclue agent path --- .config/hypr/hyprland/execs.conf | 2 +- .../hyprland/scripts/start_geoclue_agent.sh | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100755 .config/hypr/hyprland/scripts/start_geoclue_agent.sh diff --git a/.config/hypr/hyprland/execs.conf b/.config/hypr/hyprland/execs.conf index d4945605..9d4747a9 100644 --- a/.config/hypr/hyprland/execs.conf +++ b/.config/hypr/hyprland/execs.conf @@ -1,7 +1,7 @@ # Bar, wallpaper exec-once = swww-daemon --format xrgb --no-cache exec-once = sleep 0.5; swww img "$(cat ~/.local/state/quickshell/user/generated/wallpaper/path.txt)" --transition-step 100 --transition-fps 120 --transition-type grow --transition-angle 30 --transition-duration 1 -exec-once = /usr/lib/geoclue-2.0/demos/agent & gammastep +exec-once = ~/.config/hypr/hyprland/scripts/start_geoclue_agent.sh & gammastep exec-once = qs & # Input method diff --git a/.config/hypr/hyprland/scripts/start_geoclue_agent.sh b/.config/hypr/hyprland/scripts/start_geoclue_agent.sh new file mode 100755 index 00000000..e464d053 --- /dev/null +++ b/.config/hypr/hyprland/scripts/start_geoclue_agent.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Check if GeoClue agent is already running +if pgrep -f 'geoclue-2.0/demos/agent' > /dev/null; then + echo "GeoClue agent is already running." + exit 0 +fi + +# List of known possible GeoClue agent paths +AGENT_PATHS=" +/usr/libexec/geoclue-2.0/demos/agent +/usr/lib/geoclue-2.0/demos/agent +" + +# Find the first valid agent path +for path in $AGENT_PATHS; do + if [ -x "$path" ]; then + echo "Starting GeoClue agent from: $path" + "$path" & # starts in the background + exit 0 + fi +done + +# If we got here, none of the paths worked +echo "GeoClue agent not found in known paths." +echo "Please install GeoClue or update the script with the correct path." +exit 1 From d8f5471b3e6930b768df42e1889ebc71d9fab491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Sat, 28 Jun 2025 20:25:36 +0300 Subject: [PATCH 078/328] config(WeatherService): add enableGps option --- .config/quickshell/modules/common/ConfigOptions.qml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index f4d40abb..c96a7a9b 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -73,8 +73,10 @@ Singleton { property int showNumberDelay: 300 // milliseconds } property QtObject weather: QtObject { - property bool show: false - // for specific location checkout gps setting + property bool show: true + // gps based location + property bool enableGPS: true + // use if 'enableGPS' is false property string city: "Istanbul" // use uscs units // by default use metric (SI) units @@ -171,11 +173,4 @@ Singleton { property QtObject hacks: QtObject { property int arbitraryRaceConditionDelay: 20 // milliseconds } - - // this is for weather and feature apis - property QtObject gps: QtObject { - property bool active: false - property real latitude: 41.27830580591624 - property real longitude: 28.730357071149154 - } } From 689f6c90e7cfdfe562fcf7df24f983b92e2a01ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Sat, 28 Jun 2025 20:48:34 +0300 Subject: [PATCH 079/328] feat(WeatherService): add geolocation service --- .../quickshell/services/WeatherService.qml | 61 +++++++++++++++++-- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/.config/quickshell/services/WeatherService.qml b/.config/quickshell/services/WeatherService.qml index da418f72..7f4bbee3 100644 --- a/.config/quickshell/services/WeatherService.qml +++ b/.config/quickshell/services/WeatherService.qml @@ -4,6 +4,7 @@ pragma ComponentBehavior: Bound import Quickshell import Quickshell.Io import QtQuick +import QtPositioning import "root:/modules/common" @@ -11,6 +12,16 @@ Singleton { id: root // 10 minute readonly property int fetchInterval: ConfigOptions.bar.weather.fetchInterval * 60 * 1000 + readonly property string city: ConfigOptions.bar.weather.city + readonly property bool useUSCS: ConfigOptions.bar.weather.useUSCS + readonly property bool gpsActive: ConfigOptions.bar.weather.enableGPS + + property var location: ({ + valid: false, + lat: 0, + lon: 0, + }) + property var data: ({ uv: 0, humidity: 0, @@ -36,7 +47,7 @@ Singleton { temp.wCode = data?.current?.weatherCode || "113"; temp.city = data?.location?.areaName[0].value || "Istanbul"; temp.temp = ""; - if (ConfigOptions.bar.weather.useUSCS) { + if (root.useUSCS) { temp.wind = (data?.current?.windspeedMiles || 0) + " mph"; temp.precip = (data?.current?.precipInches || 0) + " in"; temp.visib = (data?.current?.visibilityMiles || 0) + " m"; @@ -58,10 +69,11 @@ Singleton { function getData() { let command = "curl -s wttr.in"; - if (ConfigOptions.gps.active) { - command += `/${ConfigOptions.gps.latitude},${Config.gps.longitude}`; + + if (root.gpsActive && root.location.valid) { + command += `/${root.location.lat},${root.location.long}`; } else { - command += `/${formatCityName(ConfigOptions.bar.weather.city)}`; + command += `/${formatCityName(root.city)}`; } // format as json @@ -77,6 +89,13 @@ Singleton { return cityName.trim().split(/\s+/).join('+'); } + Component.onCompleted: { + if(!root.gpsActive) return + + console.info("[WeatherService] Starting the GPS service.") + positionSource.start() + } + Process { id: fetcher command: ["bash", "-c", ""] @@ -95,11 +114,41 @@ Singleton { } } + PositionSource { + id: positionSource + updateInterval: root.fetchInterval + + onPositionChanged: { + // update the location if the given location is valid + // if it fails getting the location, use the last valid location + if (position.latitudeValid && position.longitudeValid) { + root.location.lat = position.coordinate.latitude; + root.location.long = position.coordinate.longitude; + root.location.valid = true + // console.info(`📍 Location: ${position.coordinate.latitude}, ${position.coordinate.longitude}`); + root.getData(); + // if can't get initialized with valid location deactivate the GPS + } else { + root.gpsActive = root.location.valid ? true : false + } + } + + onValidityChanged: { + if(!valid) { + positionSource.stop() + root.location.valid = false + root.gpsActive = false + Quickshell.execDetached(["bash", "-c", `notify-send WeatherService 'Failed to load the GPS service. Using the fallback method instead.'`]) + console.error("[WeatherService] Could not aquire a valid backend plugin.") + } + } + } + Timer { - running: true + running: !root.gpsActive repeat: true interval: root.fetchInterval - triggeredOnStart: true + triggeredOnStart: !root.gpsActive onTriggered: root.getData() } } From 36db4ae327e9877040cf2a9782616e7d78f89432 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 29 Jun 2025 00:23:19 +0200 Subject: [PATCH 080/328] screenshot tool: add layer regions --- .../sidebarRight/quickToggles/GameMode.qml | 1 - .config/quickshell/screenshot.qml | 127 +++++++++++++++--- .../quickshell/scripts/images/find_regions.py | 4 +- .config/quickshell/services/HyprlandData.qml | 17 +++ 4 files changed, 131 insertions(+), 18 deletions(-) diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml b/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml index 79c1eba7..4601c57d 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml @@ -23,7 +23,6 @@ QuickToggleButton { running: true command: ["bash", "-c", `test "$(hyprctl getoption animations:enabled -j | jq ".int")" -ne 0`] onExited: (exitCode, exitStatus) => { - console.log("Game mode toggle exited with code:", exitCode, "and status:", exitStatus) root.toggled = exitCode !== 0 // Inverted because enabled = nonzero exit } } diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml index 99033461..5d61062c 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/screenshot.qml @@ -27,13 +27,14 @@ ShellRoot { property color genericContentForeground: "#ddffffff" property color selectionBorderColor: "#ddf1f1f1" property color selectionFillColor: "#33ffffff" - property color windowBorderColor: "#ddd4ecff" - property color windowFillColor: "#33d4ecff" + property color windowBorderColor: "#dda0c0da" + property color windowFillColor: "#22a0c0da" property color imageBorderColor: "#ddf1d1ff" property color imageFillColor: "#33f1d1ff" property color onBorderColor: "#ff000000" property real standardRounding: 4 readonly property var windows: HyprlandData.windowList + readonly property var layers: HyprlandData.layers readonly property real falsePositivePreventionRatio: 0.5 // Force initialization of some singletons @@ -75,10 +76,7 @@ ShellRoot { id: regionText text: regionRect.text color: root.genericContentForeground - anchors { - centerIn: parent - margins: regionLabelBackground.padding - } + anchors.centerIn: parent } } } @@ -102,9 +100,24 @@ ShellRoot { property bool dragging: false property var mouseButton: null property var imageRegions: [] - property var windowRegions: root.windows.filter(w => { - return w.workspace.id === panelWindow.activeWorkspaceId; - }) + readonly property var windowRegions: filterWindowRegionsByLayers( + root.windows.filter(w => w.workspace.id === panelWindow.activeWorkspaceId), + panelWindow.layerRegions + ) + readonly property var layerRegions: { + const layersOfThisMonitor = root.layers[panelWindow.hyprlandMonitor.name] + const topLayers = layersOfThisMonitor.levels["2"] + const nonBarTopLayers = topLayers + .filter(layer => !(layer.namespace.includes(":bar"))) + .map(layer => { + return { + at: [layer.x, layer.y], + size: [layer.w, layer.h], + namespace: layer.namespace, + } + }) + return nonBarTopLayers; + } property real targetedRegionX: -1 property real targetedRegionY: -1 @@ -131,18 +144,58 @@ ShellRoot { return unionArea > 0 ? interArea / unionArea : 0; } - function filterImageRegions(regions, windowRegions, threshold = 0.1) { - // Remove image regions that overlap too much with any window region - return regions.filter(region => { - for (let i = 0; i < windowRegions.length; ++i) { - if (intersectionOverUnion(region, windowRegions[i]) > threshold) + function filterOverlappingImageRegions(regions) { + let keep = []; + let removed = new Set(); + for (let i = 0; i < regions.length; ++i) { + if (removed.has(i)) continue; + let regionA = regions[i]; + for (let j = i + 1; j < regions.length; ++j) { + if (removed.has(j)) continue; + let regionB = regions[j]; + if (intersectionOverUnion(regionA, regionB) > 0) { + // Compare areas + let areaA = regionA.size[0] * regionA.size[1]; + let areaB = regionB.size[0] * regionB.size[1]; + if (areaA <= areaB) { + removed.add(j); + } else { + removed.add(i); + } + } + } + } + for (let i = 0; i < regions.length; ++i) { + if (!removed.has(i)) keep.push(regions[i]); + } + return keep; + } + + function filterWindowRegionsByLayers(windowRegions, layerRegions) { + return windowRegions.filter(windowRegion => { + for (let i = 0; i < layerRegions.length; ++i) { + if (intersectionOverUnion(windowRegion, layerRegions[i]) > 0) return false; } return true; }); } + function filterImageRegions(regions, windowRegions, threshold = 0.1) { + // Remove image regions that overlap too much with any window region + let filtered = regions.filter(region => { + for (let i = 0; i < windowRegions.length; ++i) { + if (intersectionOverUnion(region, windowRegions[i]) > threshold) + return false; + } + return true; + }); + // Remove overlapping image regions, keep only the smaller one + return filterOverlappingImageRegions(filtered); + } + function updateTargetedRegion(x, y) { + // Image regions const clickedRegion = panelWindow.imageRegions.find(region => { return region.at[0] <= x && x <= region.at[0] + region.size[0] && region.at[1] <= y && y <= region.at[1] + region.size[1]; }); @@ -154,6 +207,18 @@ ShellRoot { return; } + // Layer regions + const clickedLayer = panelWindow.layerRegions.find(region => { + return region.at[0] <= x && x <= region.at[0] + region.size[0] && region.at[1] <= y && y <= region.at[1] + region.size[1]; + }); + if (clickedLayer) { + panelWindow.targetedRegionX = clickedLayer.at[0]; + panelWindow.targetedRegionY = clickedLayer.at[1]; + panelWindow.targetedRegionWidth = clickedLayer.size[0]; + panelWindow.targetedRegionHeight = clickedLayer.size[1]; + return; + } + // Window regions const clickedWindow = panelWindow.windowRegions.find(region => { return region.at[0] <= x && x <= region.at[0] + region.size[0] && region.at[1] <= y && y <= region.at[1] + region.size[1]; @@ -210,7 +275,6 @@ ShellRoot { stdout: StdioCollector { id: imageDimensionCollector onStreamFinished: { - // imageRegions = JSON.parse(imageDimensionCollector.text); imageRegions = filterImageRegions( JSON.parse(imageDimensionCollector.text), panelWindow.windowRegions @@ -355,6 +419,7 @@ ShellRoot { values: panelWindow.windowRegions } delegate: TargetRegion { + z: 2 required property var modelData targeted: !panelWindow.draggedAway && (panelWindow.targetedRegionX === modelData.at[0] @@ -380,11 +445,43 @@ ShellRoot { } } + Repeater { + model: ScriptModel { + values: panelWindow.layerRegions + } + delegate: TargetRegion { + z: 3 + required property var modelData + targeted: !panelWindow.draggedAway && + (panelWindow.targetedRegionX === modelData.at[0] + && panelWindow.targetedRegionY === modelData.at[1] + && panelWindow.targetedRegionWidth === modelData.size[0] + && panelWindow.targetedRegionHeight === modelData.size[1]) + + opacity: panelWindow.draggedAway ? 0 : 1 + visible: opacity > 0 + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + + x: modelData.at[0] + y: modelData.at[1] + width: modelData.size[0] + height: modelData.size[1] + borderColor: root.windowBorderColor + fillColor: targeted ? root.windowFillColor : "transparent" + border.width: targeted ? 4 : 2 + text: `${modelData.namespace}` + radius: Appearance.rounding.windowRounding + } + } + Repeater { model: ScriptModel { values: panelWindow.imageRegions } delegate: TargetRegion { + z: 4 required property var modelData targeted: !panelWindow.draggedAway && (panelWindow.targetedRegionX === modelData.at[0] diff --git a/.config/quickshell/scripts/images/find_regions.py b/.config/quickshell/scripts/images/find_regions.py index 8d51154b..fe68a4db 100755 --- a/.config/quickshell/scripts/images/find_regions.py +++ b/.config/quickshell/scripts/images/find_regions.py @@ -87,8 +87,8 @@ def main(): parser.add_argument('--max-height', type=int, help='Maximum height of detected region') parser.add_argument('--single', action='store_true', help='Only output the most likely (largest) region') parser.add_argument('--quality', action='store_true', help='Use quality mode for selective search (slower, less sensitive)') - parser.add_argument('--k', type=int, default=35000, help='Segmentation parameter k (default: 150)') - parser.add_argument('--min-size', type=int, default=150, help='Segmentation parameter min_size (default: 20)') + parser.add_argument('--k', type=int, default=3000, help='Segmentation parameter k (default: 150)') + parser.add_argument('--min-size', type=int, default=50, help='Segmentation parameter min_size (default: 20)') parser.add_argument('--sigma', type=float, default=0.6, help='Segmentation parameter sigma (default: 0.8)') parser.add_argument('--resize-factor', type=float, default=0.1, help='Resize factor for input image before processing (default: 1.0, e.g. 0.5 for half size)') parser.add_argument('--hyprctl', action='store_true', help='Mimics hyprctl\'s window output, like {"at": [x, y], "size": [w, h]}') diff --git a/.config/quickshell/services/HyprlandData.qml b/.config/quickshell/services/HyprlandData.qml index 2b88ad9c..edd4e8ea 100644 --- a/.config/quickshell/services/HyprlandData.qml +++ b/.config/quickshell/services/HyprlandData.qml @@ -16,14 +16,20 @@ Singleton { property var addresses: [] property var windowByAddress: ({}) property var monitors: [] + property var layers: ({}) function updateWindowList() { getClients.running = true getMonitors.running = true } + function updateLayers() { + getLayers.running = true + } + Component.onCompleted: { updateWindowList() + updateLayers() } Connections { @@ -56,6 +62,7 @@ Singleton { } } } + Process { id: getMonitors command: ["bash", "-c", "hyprctl monitors -j | jq -c"] @@ -65,5 +72,15 @@ Singleton { } } } + + Process { + id: getLayers + command: ["bash", "-c", "hyprctl layers -j | jq -c"] + stdout: SplitParser { + onRead: (data) => { + root.layers = JSON.parse(data) + } + } + } } From fdc0f16b088aa13e53a6f0d4b937b975f46a9193 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 29 Jun 2025 08:51:07 +0200 Subject: [PATCH 081/328] volume mixer: manual node filtering to make it work with easyeffects --- .../sidebarRight/volumeMixer/VolumeMixer.qml | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml b/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml index 2e1570f3..2087a946 100644 --- a/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml +++ b/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml @@ -16,6 +16,10 @@ Item { property bool deviceSelectorInput property int dialogMargins: 16 property PwNode selectedDevice + readonly property list appPwNodes: Pipewire.nodes.values.filter((node) => { + // return node.type == "21" // Alternative, not as clean + return node.isSink && node.isStream + }) function showDeviceSelectorDialog(input: bool) { root.selectedDevice = null @@ -59,21 +63,13 @@ Item { anchors.margins: 10 spacing: 10 - // Get a list of nodes that output to the default sink - PwNodeLinkTracker { - id: linkTracker - node: Pipewire.defaultAudioSink - } - Repeater { - model: linkTracker.linkGroups + model: root.appPwNodes VolumeMixerEntry { Layout.fillWidth: true - // Get links to the default sinnk - required property PwLinkGroup modelData - // Consider sources that output to the default sink - node: modelData.source + required property var modelData + node: modelData } } } @@ -84,7 +80,7 @@ Item { anchors.fill: flickable visible: opacity > 0 - opacity: (linkTracker.linkGroups.length === 0) ? 1 : 0 + opacity: (root.appPwNodes.length === 0) ? 1 : 0 Behavior on opacity { NumberAnimation { From 65f9b6a242646bf1ddbe933b141df89f24152574 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 29 Jun 2025 21:04:52 +0200 Subject: [PATCH 082/328] settings: prompt config add callater for setting --- .config/quickshell/modules/settings/ServicesConfig.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/settings/ServicesConfig.qml b/.config/quickshell/modules/settings/ServicesConfig.qml index 1be54036..25e2ba42 100644 --- a/.config/quickshell/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/modules/settings/ServicesConfig.qml @@ -53,7 +53,9 @@ ContentPage { text: ConfigOptions.ai.systemPrompt wrapMode: TextEdit.Wrap onTextChanged: { - ConfigLoader.setConfigValueAndSave("ai.systemPrompt", text); + Qt.callLater(() => { + ConfigLoader.setConfigValueAndSave("ai.systemPrompt", text); + }); } } } From 30c54cb7ce25ca2824c1470dc142f0ccbb191194 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 29 Jun 2025 21:05:29 +0200 Subject: [PATCH 083/328] screenshot: account for scaled monitors (#1539) --- .config/quickshell/screenshot.qml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml index 5d61062c..9312aa23 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/screenshot.qml @@ -87,7 +87,8 @@ ShellRoot { PanelWindow { id: panelWindow required property var modelData - property HyprlandMonitor hyprlandMonitor: Hyprland.monitorFor(modelData) + readonly property HyprlandMonitor hyprlandMonitor: Hyprland.monitorFor(modelData) + readonly property real monitorScale: hyprlandMonitor.scale property int activeWorkspaceId: hyprlandMonitor.activeWorkspace?.id ?? 0 property string screenshotPath: `${root.screenshotDir}/image-${modelData.name}` property real dragStartX: 0 @@ -293,7 +294,10 @@ ShellRoot { snipProc.startDetached(); Qt.quit(); } - command: ["bash", "-c", `magick ${StringUtils.shellSingleQuoteEscape(panelWindow.screenshotPath)} -crop ${panelWindow.regionWidth}x${panelWindow.regionHeight}+${panelWindow.regionX}+${panelWindow.regionY} - ` + `| ${panelWindow.mouseButton === Qt.LeftButton ? "wl-copy" : "swappy -f -"}`] + command: ["bash", "-c", + `magick ${StringUtils.shellSingleQuoteEscape(panelWindow.screenshotPath)} ` + + `-crop ${panelWindow.regionWidth * panelWindow.monitorScale}x${panelWindow.regionHeight * panelWindow.monitorScale}+${panelWindow.regionX * panelWindow.monitorScale}+${panelWindow.regionY * panelWindow.monitorScale} - ` + + `| ${panelWindow.mouseButton === Qt.LeftButton ? "wl-copy" : "swappy -f -"}`] } ScreencopyView { From 18ea20f1dfe06904ed9225ba1b483feebc46bb5f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 29 Jun 2025 23:00:57 +0200 Subject: [PATCH 084/328] bar: fix bottom mode, add corner style config --- .config/quickshell/modules/bar/Bar.qml | 135 +++++++++++++----- .config/quickshell/modules/bar/BarGroup.qml | 3 +- .config/quickshell/modules/bar/Media.qml | 2 +- .config/quickshell/modules/bar/Workspaces.qml | 6 +- .../quickshell/modules/common/Appearance.qml | 4 +- .../modules/common/ConfigOptions.qml | 1 + .../modules/common/widgets/RoundCorner.qml | 27 ++-- .../modules/screenCorners/ScreenCorners.qml | 8 +- 8 files changed, 126 insertions(+), 60 deletions(-) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 0a890c6e..bac9f720 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -15,13 +15,12 @@ import Quickshell.Services.UPower Scope { id: bar - readonly property int barHeight: Appearance.sizes.barHeight readonly property int osdHideMouseMoveThreshold: 20 property bool showBarBackground: ConfigOptions.bar.showBackground component VerticalBarSeparator: Rectangle { - Layout.topMargin: barHeight / 3 - Layout.bottomMargin: barHeight / 3 + Layout.topMargin: Appearance.sizes.baseBarHeight / 3 + Layout.bottomMargin: Appearance.sizes.baseBarHeight / 3 Layout.fillHeight: true implicitWidth: 1 color: Appearance.colors.colOutlineVariant @@ -38,9 +37,9 @@ Scope { PanelWindow { // Bar window id: barRoot + required property ShellScreen modelData screen: modelData - property ShellScreen modelData property var brightnessMonitor: Brightness.getMonitorForScreen(modelData) property real useShortenedForm: (Appearance.sizes.barHellaShortenScreenWidthThreshold >= screen.width) ? 2 : (Appearance.sizes.barShortenScreenWidthThreshold >= screen.width) ? 1 : 0 @@ -50,8 +49,8 @@ Scope { Appearance.sizes.barCenterSideModuleWidth WlrLayershell.namespace: "quickshell:bar" - implicitHeight: barHeight + Appearance.rounding.screenRounding - exclusiveZone: showBarBackground ? barHeight : (barHeight - 4) + implicitHeight: Appearance.sizes.barHeight + Appearance.rounding.screenRounding + exclusiveZone: Appearance.sizes.baseBarHeight + (ConfigOptions.bar.cornerStyle === 1 ? Appearance.sizes.hyprlandGapsOut : 0) mask: Region { item: barContent } @@ -64,21 +63,46 @@ Scope { right: true } - Rectangle { // Bar background + Item { // Bar content region id: barContent anchors { right: parent.right left: parent.left - top: !ConfigOptions.bar.bottom ? parent.top : undefined - bottom: ConfigOptions.bar.bottom ? parent.bottom : undefined + top: parent.top + bottom: undefined + } + implicitHeight: Appearance.sizes.barHeight + height: Appearance.sizes.barHeight + + states: State { + name: "bottom" + when: ConfigOptions.bar.bottom + AnchorChanges { + target: barContent + anchors { + right: parent.right + left: parent.left + top: undefined + bottom: parent.bottom + } + } + } + + // Background + Rectangle { + anchors { + fill: parent + margins: ConfigOptions.bar.cornerStyle === 1 ? (Appearance.sizes.hyprlandGapsOut) : 0 // idk why but +1 is needed + } + color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + radius: ConfigOptions.bar.cornerStyle === 1 ? Appearance.rounding.windowRounding : 0 } - color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - height: barHeight MouseArea { // Left side | scroll to change brightness id: barLeftSideMouseArea anchors.left: parent.left - implicitHeight: barHeight + implicitHeight: Appearance.sizes.baseBarHeight + height: Appearance.sizes.barHeight width: (barRoot.width - middleSection.width) / 2 property bool hovered: false property real lastScrollX: 0 @@ -279,7 +303,8 @@ Scope { id: barRightSideMouseArea anchors.right: parent.right - implicitHeight: barHeight + implicitHeight: Appearance.sizes.baseBarHeight + height: Appearance.sizes.barHeight width: (barRoot.width - middleSection.width) / 2 property bool hovered: false @@ -354,10 +379,14 @@ Scope { RippleButton { // Right sidebar button id: rightSidebarButton - Layout.margins: 4 + + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter Layout.rightMargin: Appearance.rounding.screenRounding - Layout.fillHeight: true - implicitWidth: indicatorsRowLayout.implicitWidth + 10*2 + Layout.fillWidth: false + + implicitWidth: indicatorsRowLayout.implicitWidth + 10 * 2 + implicitHeight: indicatorsRowLayout.implicitHeight + 5 * 2 + buttonRadius: Appearance.rounding.full colBackground: barRightSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1) colBackgroundHover: Appearance.colors.colLayer1Hover @@ -447,32 +476,68 @@ Scope { } // Round decorators - Item { + Loader { + id: roundDecorators anchors { left: parent.left right: parent.right - // top: barContent.bottom - top: ConfigOptions.bar.bottom ? undefined : barContent.bottom - bottom: ConfigOptions.bar.bottom ? barContent.top : undefined } + y: Appearance.sizes.barHeight + width: parent.width height: Appearance.rounding.screenRounding - visible: showBarBackground + active: showBarBackground && ConfigOptions.bar.cornerStyle === 0 // Hug - RoundCorner { - anchors.top: parent.top - anchors.left: parent.left - size: Appearance.rounding.screenRounding - corner: ConfigOptions.bar.bottom ? cornerEnum.bottomLeft : cornerEnum.topLeft - color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - opacity: 1.0 - Appearance.transparency + states: State { + name: "bottom" + when: ConfigOptions.bar.bottom + PropertyChanges { + roundDecorators.y: 0 + } } - RoundCorner { - anchors.top: parent.top - anchors.right: parent.right - size: Appearance.rounding.screenRounding - corner: ConfigOptions.bar.bottom ? cornerEnum.bottomRight : cornerEnum.topRight - color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - opacity: 1.0 - Appearance.transparency + + sourceComponent: Item { + implicitHeight: Appearance.rounding.screenRounding + RoundCorner { + id: leftCorner + anchors { + top: parent.top + bottom: parent.bottom + left: parent.left + } + + size: Appearance.rounding.screenRounding + color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + opacity: 1.0 - Appearance.transparency + + corner: RoundCorner.CornerEnum.TopLeft + states: State { + name: "bottom" + when: ConfigOptions.bar.bottom + PropertyChanges { + leftCorner.corner: RoundCorner.CornerEnum.BottomLeft + } + } + } + RoundCorner { + id: rightCorner + anchors { + right: parent.right + top: !ConfigOptions.bar.bottom ? parent.top : undefined + bottom: ConfigOptions.bar.bottom ? parent.bottom : undefined + } + size: Appearance.rounding.screenRounding + color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + opacity: 1.0 - Appearance.transparency + + corner: RoundCorner.CornerEnum.TopRight + states: State { + name: "bottom" + when: ConfigOptions.bar.bottom + PropertyChanges { + rightCorner.corner: RoundCorner.CornerEnum.BottomRight + } + } + } } } diff --git a/.config/quickshell/modules/bar/BarGroup.qml b/.config/quickshell/modules/bar/BarGroup.qml index a71b67e4..acc15169 100644 --- a/.config/quickshell/modules/bar/BarGroup.qml +++ b/.config/quickshell/modules/bar/BarGroup.qml @@ -7,7 +7,8 @@ import QtQuick.Layouts Item { id: root property real padding: 5 - implicitHeight: 40 + implicitHeight: Appearance.sizes.baseBarHeight + height: Appearance.sizes.barHeight implicitWidth: rowLayout.implicitWidth + padding * 2 default property alias items: rowLayout.children diff --git a/.config/quickshell/modules/bar/Media.qml b/.config/quickshell/modules/bar/Media.qml index 3bd8a78a..432ed5b1 100644 --- a/.config/quickshell/modules/bar/Media.qml +++ b/.config/quickshell/modules/bar/Media.qml @@ -17,7 +17,7 @@ Item { Layout.fillHeight: true implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2 - implicitHeight: 40 + implicitHeight: Appearance.sizes.barHeight Timer { running: activePlayer?.playbackState == MprisPlaybackState.Playing diff --git a/.config/quickshell/modules/bar/Workspaces.qml b/.config/quickshell/modules/bar/Workspaces.qml index 93de99c0..5c8b13e3 100644 --- a/.config/quickshell/modules/bar/Workspaces.qml +++ b/.config/quickshell/modules/bar/Workspaces.qml @@ -48,7 +48,7 @@ Item { } implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2 - implicitHeight: 40 + implicitHeight: Appearance.sizes.barHeight // Scroll to switch workspaces WheelHandler { @@ -78,7 +78,7 @@ Item { spacing: 0 anchors.fill: parent - implicitHeight: 40 + implicitHeight: Appearance.sizes.barHeight Repeater { model: ConfigOptions.bar.workspaces.shown @@ -157,7 +157,7 @@ Item { spacing: 0 anchors.fill: parent - implicitHeight: 40 + implicitHeight: Appearance.sizes.barHeight Repeater { model: ConfigOptions.bar.workspaces.shown diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 0036eb61..e3b16aa2 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -288,7 +288,9 @@ Singleton { } sizes: QtObject { - property real barHeight: 40 + property real baseBarHeight: 40 + property real barHeight: ConfigOptions.bar.cornerStyle === 1 ? + (baseBarHeight + Appearance.sizes.hyprlandGapsOut * 2) : baseBarHeight property real barCenterSideModuleWidth: ConfigOptions?.bar.verbose ? 360 : 140 property real barCenterSideModuleWidthShortened: 280 property real barCenterSideModuleWidthHellaShortened: 190 diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 992ff5b5..f2988cc6 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -47,6 +47,7 @@ Singleton { property QtObject bar: QtObject { property bool bottom: false // Instead of top + property int cornerStyle: 0 // 0: Hug | 1: Float | 2: Plain rectangle property bool borderless: false // true for no grouping of items property string topLeftIcon: "spark" // Options: distro, spark property bool showBackground: true diff --git a/.config/quickshell/modules/common/widgets/RoundCorner.qml b/.config/quickshell/modules/common/widgets/RoundCorner.qml index c9a2827a..6fba4b92 100644 --- a/.config/quickshell/modules/common/widgets/RoundCorner.qml +++ b/.config/quickshell/modules/common/widgets/RoundCorner.qml @@ -3,24 +3,21 @@ import QtQuick 2.9 Item { id: root + enum CornerEnum { TopLeft, TopRight, BottomLeft, BottomRight } + property var corner: RoundCorner.CornerEnum.TopLeft // Default to TopLeft + property int size: 25 property color color: "#000000" onColorChanged: { canvas.requestPaint(); } - - property QtObject cornerEnum: QtObject { - property int topLeft: 0 - property int topRight: 1 - property int bottomLeft: 2 - property int bottomRight: 3 + onCornerChanged: { + canvas.requestPaint(); } - property int corner: cornerEnum.topLeft // Default to TopLeft - - width: size - height: size + implicitWidth: size + implicitHeight: size Canvas { id: canvas @@ -31,22 +28,22 @@ Item { onPaint: { var ctx = getContext("2d"); var r = root.size; - + ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath(); switch (root.corner) { - case cornerEnum.topLeft: + case RoundCorner.CornerEnum.TopLeft: ctx.arc(r, r, r, Math.PI, 3 * Math.PI / 2); ctx.lineTo(0, 0); break; - case cornerEnum.topRight: + case RoundCorner.CornerEnum.TopRight: ctx.arc(0, r, r, 3 * Math.PI / 2, 2 * Math.PI); ctx.lineTo(r, 0); break; - case cornerEnum.bottomLeft: + case RoundCorner.CornerEnum.BottomLeft: ctx.arc(r, 0, r, Math.PI / 2, Math.PI); ctx.lineTo(0, r); break; - case cornerEnum.bottomRight: + case RoundCorner.CornerEnum.BottomRight: ctx.arc(0, 0, r, 0, Math.PI / 2); ctx.lineTo(r, r); break; diff --git a/.config/quickshell/modules/screenCorners/ScreenCorners.qml b/.config/quickshell/modules/screenCorners/ScreenCorners.qml index 3988d73d..9a1f1a22 100644 --- a/.config/quickshell/modules/screenCorners/ScreenCorners.qml +++ b/.config/quickshell/modules/screenCorners/ScreenCorners.qml @@ -56,28 +56,28 @@ Scope { anchors.top: parent.top anchors.left: parent.left size: Appearance.rounding.screenRounding - corner: cornerEnum.topLeft + corner: RoundCorner.CornerEnum.TopLeft } RoundCorner { id: topRightCorner anchors.top: parent.top anchors.right: parent.right size: Appearance.rounding.screenRounding - corner: cornerEnum.topRight + corner: RoundCorner.CornerEnum.TopRight } RoundCorner { id: bottomLeftCorner anchors.bottom: parent.bottom anchors.left: parent.left size: Appearance.rounding.screenRounding - corner: cornerEnum.bottomLeft + corner: RoundCorner.CornerEnum.BottomLeft } RoundCorner { id: bottomRightCorner anchors.bottom: parent.bottom anchors.right: parent.right size: Appearance.rounding.screenRounding - corner: cornerEnum.bottomRight + corner: RoundCorner.CornerEnum.BottomRight } } From ecb2f246b60bf991017cf6d7fc409c5587290ec3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 29 Jun 2025 23:10:13 +0200 Subject: [PATCH 085/328] settings: add config option for floating bar --- .../quickshell/modules/settings/InterfaceConfig.qml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.config/quickshell/modules/settings/InterfaceConfig.qml b/.config/quickshell/modules/settings/InterfaceConfig.qml index 7d3799d2..f952ef57 100644 --- a/.config/quickshell/modules/settings/InterfaceConfig.qml +++ b/.config/quickshell/modules/settings/InterfaceConfig.qml @@ -52,6 +52,19 @@ ContentPage { ContentSection { title: "Bar" + ConfigSelectionArray { + currentValue: ConfigOptions.bar.cornerStyle + configOptionName: "bar.cornerStyle" + onSelected: (newValue) => { + ConfigLoader.setConfigValueAndSave("bar.cornerStyle", newValue); + } + options: [ + { displayName: "Hug", value: 0 }, + { displayName: "Float", value: 1 }, + { displayName: "Plain rectangle", value: 2 } + ] + } + ContentSubsection { title: "Appearance" ConfigRow { From 32dd5eecb7128d567eb934ba509de7836c74ad20 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 29 Jun 2025 23:40:38 +0200 Subject: [PATCH 086/328] Create .qmlformat.ini --- .config/quickshell/.qmlformat.ini | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .config/quickshell/.qmlformat.ini diff --git a/.config/quickshell/.qmlformat.ini b/.config/quickshell/.qmlformat.ini new file mode 100644 index 00000000..52a955c4 --- /dev/null +++ b/.config/quickshell/.qmlformat.ini @@ -0,0 +1,8 @@ +[General] +UseTabs=false +IndentWidth=4 +NewlineType=unix +NormalizeOrder=false +FunctionsSpacing=false +ObjectsSpacing=true +MaxColumnWidth=110 From d513d0e1b3c66a89a4ac6dd56405e3724ef8249b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 29 Jun 2025 23:49:35 +0200 Subject: [PATCH 087/328] welcome: add bar style --- .config/quickshell/welcome.qml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index 0f86ebc4..12296532 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -122,6 +122,24 @@ ApplicationWindow { ContentPage { id: contentColumn anchors.fill: parent + + ContentSection { + title: "Bar style" + + ConfigSelectionArray { + currentValue: ConfigOptions.bar.cornerStyle + configOptionName: "bar.cornerStyle" + onSelected: (newValue) => { + ConfigLoader.setConfigValueAndSave("bar.cornerStyle", newValue); + } + options: [ + { displayName: "Hug", value: 0 }, + { displayName: "Float", value: 1 }, + { displayName: "Plain rectangle", value: 2 } + ] + } + } + ContentSection { title: "Style & wallpaper" From 5d6db58d76cc21a90430646ff5530c5d95beb917 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 29 Jun 2025 23:49:45 +0200 Subject: [PATCH 088/328] bar: shadow for floating style --- .config/quickshell/modules/bar/Bar.qml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index bac9f720..e19b42b1 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -88,8 +88,18 @@ Scope { } } + // Background shadow + Loader { + active: showBarBackground && ConfigOptions.bar.cornerStyle === 1 + anchors.fill: barBackground + sourceComponent: StyledRectangularShadow { + anchors.fill: undefined // The loader's anchors act on this, and this should not have any anchor + target: barBackground + } + } // Background Rectangle { + id: barBackground anchors { fill: parent margins: ConfigOptions.bar.cornerStyle === 1 ? (Appearance.sizes.hyprlandGapsOut) : 0 // idk why but +1 is needed From 50eae43ca28fb70aa50fd31b664ded0c03cdd9e0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 30 Jun 2025 13:12:52 +0200 Subject: [PATCH 089/328] screenshot: fix content regions on scaled monitors (#1539) --- .config/quickshell/screenshot.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml index 9312aa23..f544f36b 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/screenshot.qml @@ -499,10 +499,10 @@ ShellRoot { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - x: modelData.at[0] - y: modelData.at[1] - width: modelData.size[0] - height: modelData.size[1] + x: modelData.at[0] / panelWindow.monitorScale + y: modelData.at[1] / panelWindow.monitorScale + width: modelData.size[0] / panelWindow.monitorScale + height: modelData.size[1] / panelWindow.monitorScale borderColor: root.imageBorderColor fillColor: targeted ? root.imageFillColor : "transparent" border.width: targeted ? 4 : 2 From 68673de641fa1d67fe5374e19d07a5b23dfe4504 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 30 Jun 2025 13:51:50 +0200 Subject: [PATCH 090/328] screenshot: fix window/layer positions for offset monitors (#1539) --- .config/quickshell/screenshot.qml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml index f544f36b..a855200d 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/screenshot.qml @@ -89,6 +89,8 @@ ShellRoot { required property var modelData readonly property HyprlandMonitor hyprlandMonitor: Hyprland.monitorFor(modelData) readonly property real monitorScale: hyprlandMonitor.scale + readonly property real monitorOffsetX: hyprlandMonitor.x + readonly property real monitorOffsetY: hyprlandMonitor.y property int activeWorkspaceId: hyprlandMonitor.activeWorkspace?.id ?? 0 property string screenshotPath: `${root.screenshotDir}/image-${modelData.name}` property real dragStartX: 0 @@ -437,8 +439,8 @@ ShellRoot { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - x: modelData.at[0] - y: modelData.at[1] + x: modelData.at[0] - panelWindow.monitorOffsetX + y: modelData.at[1] - panelWindow.monitorOffsetY width: modelData.size[0] height: modelData.size[1] borderColor: root.windowBorderColor @@ -468,8 +470,8 @@ ShellRoot { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - x: modelData.at[0] - y: modelData.at[1] + x: modelData.at[0] - panelWindow.monitorOffsetX + y: modelData.at[1] - panelWindow.monitorOffsetY width: modelData.size[0] height: modelData.size[1] borderColor: root.windowBorderColor From 22319ffccf40b1d199bc07be27849798cb8c6763 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 30 Jun 2025 13:53:10 +0200 Subject: [PATCH 091/328] hyprland: update window rules --- .config/hypr/hyprland/rules.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index bed26a99..b6853b6b 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -24,6 +24,7 @@ windowrulev2 = float, class:kcm_.* windowrulev2 = float, class:.*bluedevilwizard windowrulev2 = float, title:.*Welcome windowrulev2 = float, title:^(illogical-impulse Settings)$ +windowrulev2 = float, class:org.freedesktop.impl.portal.desktop.kde # No appearance # kde-material-you-colors spawns a window when changing dark/light theme. This is to make sure it doesn't interfere at all. @@ -61,6 +62,7 @@ windowrulev2 = float, title:^(File Upload)(.*)$ # --- Tearing --- windowrulev2 = immediate, title:.*\.exe +windowrulev2 = immediate, title:.*minecraft.* windowrulev2 = immediate, class:^(steam_app) # No shadow for tiled windows (matches windows that are not floating). @@ -130,6 +132,7 @@ layerrule = ignorealpha 0, quickshell:session layerrule = animation fade, quickshell:notificationPopup layerrule = blur, quickshell:backgroundWidgets layerrule = ignorealpha 0.05, quickshell:backgroundWidgets +layerrule = noanim, quickshell:screenshot # Launchers need to be FAST From 7ca0f263ba48bd01d2a6528ffbc26f894bce23a0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 30 Jun 2025 14:27:26 +0200 Subject: [PATCH 092/328] configoptions: use quickshell jsonadapter --- .config/quickshell/GlobalStates.qml | 2 +- .../backgroundWidgets/BackgroundWidgets.qml | 12 +- .config/quickshell/modules/bar/Bar.qml | 42 ++-- .config/quickshell/modules/bar/BarGroup.qml | 2 +- .../modules/bar/BatteryIndicator.qml | 4 +- .../quickshell/modules/bar/ClockWidget.qml | 4 +- .config/quickshell/modules/bar/Media.qml | 2 +- .config/quickshell/modules/bar/Resources.qml | 6 +- .../quickshell/modules/bar/SysTrayItem.qml | 4 +- .../quickshell/modules/bar/UtilButtons.qml | 22 +- .config/quickshell/modules/bar/Workspaces.qml | 34 +-- .../quickshell/modules/common/Appearance.qml | 8 +- .config/quickshell/modules/common/Config.qml | 216 ++++++++++++++++++ .../modules/common/ConfigOptions.qml | 165 ------------- .../modules/common/widgets/Favicon.qml | 2 +- .config/quickshell/modules/dock/Dock.qml | 10 +- .config/quickshell/modules/dock/DockApps.qml | 2 +- .../modules/mediaControls/MediaControls.qml | 4 +- .../OnScreenDisplayBrightness.qml | 6 +- .../onScreenDisplay/OnScreenDisplayVolume.qml | 6 +- .../onScreenKeyboard/OnScreenKeyboard.qml | 2 +- .../modules/onScreenKeyboard/OskContent.qml | 2 +- .../quickshell/modules/overview/Overview.qml | 6 +- .../modules/overview/OverviewWidget.qml | 20 +- .../modules/overview/SearchWidget.qml | 24 +- .../modules/screenCorners/ScreenCorners.qml | 4 +- .../quickshell/modules/session/Session.qml | 2 +- .../modules/settings/InterfaceConfig.qml | 84 +++---- .../modules/settings/ServicesConfig.qml | 40 ++-- .../modules/settings/StyleConfig.qml | 24 +- .../quickshell/modules/sidebarLeft/Anime.qml | 2 +- .../sidebarLeft/SidebarLeftContent.qml | 8 +- .../modules/sidebarLeft/Translator.qml | 14 +- .../quickToggles/BluetoothToggle.qml | 2 +- .../quickToggles/NetworkToggle.qml | 2 +- .config/quickshell/screenshot.qml | 1 - .config/quickshell/services/Ai.qml | 9 +- .config/quickshell/services/AppSearch.qml | 2 +- .config/quickshell/services/Audio.qml | 6 +- .config/quickshell/services/Battery.qml | 10 +- .config/quickshell/services/Booru.qml | 4 +- .config/quickshell/services/Cliphist.qml | 4 +- .config/quickshell/services/ConfigLoader.qml | 137 ----------- .config/quickshell/services/DateTime.qml | 6 +- .../services/MaterialThemeLoader.qml | 2 +- .../services/PersistentStateManager.qml | 2 +- .config/quickshell/services/ResourceUsage.qml | 2 +- .config/quickshell/settings.qml | 7 +- .config/quickshell/shell.qml | 1 - .config/quickshell/welcome.qml | 19 +- 50 files changed, 455 insertions(+), 546 deletions(-) create mode 100644 .config/quickshell/modules/common/Config.qml delete mode 100644 .config/quickshell/modules/common/ConfigOptions.qml delete mode 100644 .config/quickshell/services/ConfigLoader.qml diff --git a/.config/quickshell/GlobalStates.qml b/.config/quickshell/GlobalStates.qml index 1b879421..49ae3f57 100644 --- a/.config/quickshell/GlobalStates.qml +++ b/.config/quickshell/GlobalStates.qml @@ -21,7 +21,7 @@ Singleton { Timer { id: workspaceShowNumbersTimer - interval: ConfigOptions.bar.workspaces.showNumberDelay + interval: Config.options.bar.workspaces.showNumberDelay // interval: 0 repeat: false onTriggered: { diff --git a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml index 77e036f1..4197e495 100644 --- a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml +++ b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml @@ -15,12 +15,12 @@ import Quickshell.Services.UPower Scope { id: root property string filePath: `${Directories.state}/user/generated/wallpaper/least_busy_region.json` - property real defaultX: (ConfigOptions?.background.clockX ?? -500) - property real defaultY: (ConfigOptions?.background.clockY ?? -500) + property real defaultX: (Config.options?.background.clockX ?? -500) + property real defaultY: (Config.options?.background.clockY ?? -500) property real centerX: defaultX property real centerY: defaultY - property real effectiveCenterX: ConfigOptions?.background.fixedClockPosition ? defaultX : centerX - property real effectiveCenterY: ConfigOptions?.background.fixedClockPosition ? defaultY : centerY + property real effectiveCenterX: Config.options?.background.fixedClockPosition ? defaultX : centerX + property real effectiveCenterY: Config.options?.background.fixedClockPosition ? defaultY : centerY property color dominantColor: Appearance.colors.colPrimary property bool dominantColorIsDark: dominantColor.hslLightness < 0.5 property color colBackground: ColorUtils.transparentize(ColorUtils.mix(Appearance.colors.colPrimary, Appearance.colors.colSecondaryContainer), 1) @@ -36,7 +36,7 @@ Scope { Timer { id: delayedFileRead - interval: ConfigOptions.hacks.arbitraryRaceConditionDelay + interval: Config.options.hacks.arbitraryRaceConditionDelay running: false onTriggered: { root.updateWidgetPosition(leastBusyRegionFileView.text()) @@ -46,7 +46,7 @@ Scope { FileView { id: leastBusyRegionFileView path: Qt.resolvedUrl(root.filePath) - watchChanges: !ConfigOptions?.background.fixedClockPosition + watchChanges: !Config.options?.background.fixedClockPosition onFileChanged: { this.reload() delayedFileRead.start() diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index e19b42b1..0e98c912 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -16,7 +16,7 @@ Scope { id: bar readonly property int osdHideMouseMoveThreshold: 20 - property bool showBarBackground: ConfigOptions.bar.showBackground + property bool showBarBackground: Config.options.bar.showBackground component VerticalBarSeparator: Rectangle { Layout.topMargin: Appearance.sizes.baseBarHeight / 3 @@ -29,7 +29,7 @@ Scope { Variants { // For each monitor model: { const screens = Quickshell.screens; - const list = ConfigOptions.bar.screenList; + const list = Config.options.bar.screenList; if (!list || list.length === 0) return screens; return screens.filter(screen => list.includes(screen.name)); @@ -50,15 +50,15 @@ Scope { WlrLayershell.namespace: "quickshell:bar" implicitHeight: Appearance.sizes.barHeight + Appearance.rounding.screenRounding - exclusiveZone: Appearance.sizes.baseBarHeight + (ConfigOptions.bar.cornerStyle === 1 ? Appearance.sizes.hyprlandGapsOut : 0) + exclusiveZone: Appearance.sizes.baseBarHeight + (Config.options.bar.cornerStyle === 1 ? Appearance.sizes.hyprlandGapsOut : 0) mask: Region { item: barContent } color: "transparent" anchors { - top: !ConfigOptions.bar.bottom - bottom: ConfigOptions.bar.bottom + top: !Config.options.bar.bottom + bottom: Config.options.bar.bottom left: true right: true } @@ -76,7 +76,7 @@ Scope { states: State { name: "bottom" - when: ConfigOptions.bar.bottom + when: Config.options.bar.bottom AnchorChanges { target: barContent anchors { @@ -90,7 +90,7 @@ Scope { // Background shadow Loader { - active: showBarBackground && ConfigOptions.bar.cornerStyle === 1 + active: showBarBackground && Config.options.bar.cornerStyle === 1 anchors.fill: barBackground sourceComponent: StyledRectangularShadow { anchors.fill: undefined // The loader's anchors act on this, and this should not have any anchor @@ -102,10 +102,10 @@ Scope { id: barBackground anchors { fill: parent - margins: ConfigOptions.bar.cornerStyle === 1 ? (Appearance.sizes.hyprlandGapsOut) : 0 // idk why but +1 is needed + margins: Config.options.bar.cornerStyle === 1 ? (Appearance.sizes.hyprlandGapsOut) : 0 // idk why but +1 is needed } color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - radius: ConfigOptions.bar.cornerStyle === 1 ? Appearance.rounding.windowRounding : 0 + radius: Config.options.bar.cornerStyle === 1 ? Appearance.rounding.windowRounding : 0 } MouseArea { // Left side | scroll to change brightness @@ -204,7 +204,7 @@ Scope { anchors.centerIn: parent width: 19.5 height: 19.5 - source: ConfigOptions.bar.topLeftIcon == 'distro' ? + source: Config.options.bar.topLeftIcon == 'distro' ? SystemInfo.distroIcon : "spark-symbolic" } @@ -229,7 +229,7 @@ Scope { RowLayout { // Middle section id: middleSection anchors.centerIn: parent - spacing: ConfigOptions?.bar.borderless ? 4 : 8 + spacing: Config.options?.bar.borderless ? 4 : 8 BarGroup { id: leftCenterGroup @@ -248,7 +248,7 @@ Scope { } - VerticalBarSeparator {visible: ConfigOptions?.bar.borderless} + VerticalBarSeparator {visible: Config.options?.bar.borderless} BarGroup { id: middleCenterGroup @@ -272,7 +272,7 @@ Scope { } } - VerticalBarSeparator {visible: ConfigOptions?.bar.borderless} + VerticalBarSeparator {visible: Config.options?.bar.borderless} MouseArea { id: rightCenterGroup @@ -290,13 +290,13 @@ Scope { anchors.fill: parent ClockWidget { - showDate: (ConfigOptions.bar.verbose && barRoot.useShortenedForm < 2) + showDate: (Config.options.bar.verbose && barRoot.useShortenedForm < 2) Layout.alignment: Qt.AlignVCenter Layout.fillWidth: true } UtilButtons { - visible: (ConfigOptions.bar.verbose && barRoot.useShortenedForm === 0) + visible: (Config.options.bar.verbose && barRoot.useShortenedForm === 0) Layout.alignment: Qt.AlignVCenter } @@ -495,11 +495,11 @@ Scope { y: Appearance.sizes.barHeight width: parent.width height: Appearance.rounding.screenRounding - active: showBarBackground && ConfigOptions.bar.cornerStyle === 0 // Hug + active: showBarBackground && Config.options.bar.cornerStyle === 0 // Hug states: State { name: "bottom" - when: ConfigOptions.bar.bottom + when: Config.options.bar.bottom PropertyChanges { roundDecorators.y: 0 } @@ -522,7 +522,7 @@ Scope { corner: RoundCorner.CornerEnum.TopLeft states: State { name: "bottom" - when: ConfigOptions.bar.bottom + when: Config.options.bar.bottom PropertyChanges { leftCorner.corner: RoundCorner.CornerEnum.BottomLeft } @@ -532,8 +532,8 @@ Scope { id: rightCorner anchors { right: parent.right - top: !ConfigOptions.bar.bottom ? parent.top : undefined - bottom: ConfigOptions.bar.bottom ? parent.bottom : undefined + top: !Config.options.bar.bottom ? parent.top : undefined + bottom: Config.options.bar.bottom ? parent.bottom : undefined } size: Appearance.rounding.screenRounding color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" @@ -542,7 +542,7 @@ Scope { corner: RoundCorner.CornerEnum.TopRight states: State { name: "bottom" - when: ConfigOptions.bar.bottom + when: Config.options.bar.bottom PropertyChanges { rightCorner.corner: RoundCorner.CornerEnum.BottomRight } diff --git a/.config/quickshell/modules/bar/BarGroup.qml b/.config/quickshell/modules/bar/BarGroup.qml index acc15169..f6d4c724 100644 --- a/.config/quickshell/modules/bar/BarGroup.qml +++ b/.config/quickshell/modules/bar/BarGroup.qml @@ -19,7 +19,7 @@ Item { topMargin: 4 bottomMargin: 4 } - color: ConfigOptions?.bar.borderless ? "transparent" : Appearance.colors.colLayer1 + color: Config.options?.bar.borderless ? "transparent" : Appearance.colors.colLayer1 radius: Appearance.rounding.small } diff --git a/.config/quickshell/modules/bar/BatteryIndicator.qml b/.config/quickshell/modules/bar/BatteryIndicator.qml index 61a98157..f58d0867 100644 --- a/.config/quickshell/modules/bar/BatteryIndicator.qml +++ b/.config/quickshell/modules/bar/BatteryIndicator.qml @@ -9,12 +9,12 @@ import Quickshell.Services.UPower Item { id: root - property bool borderless: ConfigOptions.bar.borderless + property bool borderless: Config.options.bar.borderless readonly property var chargeState: Battery.chargeState readonly property bool isCharging: Battery.isCharging readonly property bool isPluggedIn: Battery.isPluggedIn readonly property real percentage: Battery.percentage - readonly property bool isLow: percentage <= ConfigOptions.battery.low / 100 + readonly property bool isLow: percentage <= Config.options.battery.low / 100 readonly property color batteryLowBackground: Appearance.m3colors.darkmode ? Appearance.m3colors.m3error : Appearance.m3colors.m3errorContainer readonly property color batteryLowOnBackground: Appearance.m3colors.darkmode ? Appearance.m3colors.m3errorContainer : Appearance.m3colors.m3error diff --git a/.config/quickshell/modules/bar/ClockWidget.qml b/.config/quickshell/modules/bar/ClockWidget.qml index 9e340383..925faac7 100644 --- a/.config/quickshell/modules/bar/ClockWidget.qml +++ b/.config/quickshell/modules/bar/ClockWidget.qml @@ -6,8 +6,8 @@ import QtQuick.Layouts Item { id: root - property bool borderless: ConfigOptions.bar.borderless - property bool showDate: ConfigOptions.bar.verbose + property bool borderless: Config.options.bar.borderless + property bool showDate: Config.options.bar.verbose implicitWidth: rowLayout.implicitWidth implicitHeight: 32 diff --git a/.config/quickshell/modules/bar/Media.qml b/.config/quickshell/modules/bar/Media.qml index 432ed5b1..9e7ff96c 100644 --- a/.config/quickshell/modules/bar/Media.qml +++ b/.config/quickshell/modules/bar/Media.qml @@ -11,7 +11,7 @@ import Quickshell.Hyprland Item { id: root - property bool borderless: ConfigOptions.bar.borderless + property bool borderless: Config.options.bar.borderless readonly property MprisPlayer activePlayer: MprisController.activePlayer readonly property string cleanedTitle: StringUtils.cleanMusicTitle(activePlayer?.trackTitle) || qsTr("No media") diff --git a/.config/quickshell/modules/bar/Resources.qml b/.config/quickshell/modules/bar/Resources.qml index 9f9b969c..e0c0d51e 100644 --- a/.config/quickshell/modules/bar/Resources.qml +++ b/.config/quickshell/modules/bar/Resources.qml @@ -9,7 +9,7 @@ import Quickshell.Services.Mpris Item { id: root - property bool borderless: ConfigOptions.bar.borderless + property bool borderless: Config.options.bar.borderless property bool alwaysShowAllResources: false implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin implicitHeight: 32 @@ -30,7 +30,7 @@ Item { Resource { iconName: "swap_horiz" percentage: ResourceUsage.swapUsedPercentage - shown: (ConfigOptions.bar.resources.alwaysShowSwap && percentage > 0) || + shown: (Config.options.bar.resources.alwaysShowSwap && percentage > 0) || (MprisController.activePlayer?.trackTitle == null) || root.alwaysShowAllResources Layout.leftMargin: shown ? 4 : 0 @@ -39,7 +39,7 @@ Item { Resource { iconName: "settings_slow_motion" percentage: ResourceUsage.cpuUsage - shown: ConfigOptions.bar.resources.alwaysShowCpu || + shown: Config.options.bar.resources.alwaysShowCpu || !(MprisController.activePlayer?.trackTitle?.length > 0) || root.alwaysShowAllResources Layout.leftMargin: shown ? 4 : 0 diff --git a/.config/quickshell/modules/bar/SysTrayItem.qml b/.config/quickshell/modules/bar/SysTrayItem.qml index 0778fbfe..55dd867c 100644 --- a/.config/quickshell/modules/bar/SysTrayItem.qml +++ b/.config/quickshell/modules/bar/SysTrayItem.qml @@ -43,7 +43,7 @@ MouseArea { IconImage { id: trayIcon - visible: !ConfigOptions.bar.tray.monochromeIcons + visible: !Config.options.bar.tray.monochromeIcons source: root.item.icon anchors.centerIn: parent width: parent.width @@ -51,7 +51,7 @@ MouseArea { } Loader { - active: ConfigOptions.bar.tray.monochromeIcons + active: Config.options.bar.tray.monochromeIcons anchors.fill: trayIcon sourceComponent: Item { Desaturate { diff --git a/.config/quickshell/modules/bar/UtilButtons.qml b/.config/quickshell/modules/bar/UtilButtons.qml index 25ae0ca3..706ba6f6 100644 --- a/.config/quickshell/modules/bar/UtilButtons.qml +++ b/.config/quickshell/modules/bar/UtilButtons.qml @@ -9,7 +9,7 @@ import Quickshell.Services.Pipewire Item { id: root - property bool borderless: ConfigOptions.bar.borderless + property bool borderless: Config.options.bar.borderless implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2 implicitHeight: rowLayout.implicitHeight @@ -20,8 +20,8 @@ Item { anchors.centerIn: parent Loader { - active: ConfigOptions.bar.utilButtons.showScreenSnip - visible: ConfigOptions.bar.utilButtons.showScreenSnip + active: Config.options.bar.utilButtons.showScreenSnip + visible: Config.options.bar.utilButtons.showScreenSnip sourceComponent: CircleUtilButton { Layout.alignment: Qt.AlignVCenter onClicked: Hyprland.dispatch("exec hyprshot --freeze --clipboard-only --mode region --silent") @@ -36,8 +36,8 @@ Item { } Loader { - active: ConfigOptions.bar.utilButtons.showColorPicker - visible: ConfigOptions.bar.utilButtons.showColorPicker + active: Config.options.bar.utilButtons.showColorPicker + visible: Config.options.bar.utilButtons.showColorPicker sourceComponent: CircleUtilButton { Layout.alignment: Qt.AlignVCenter onClicked: Hyprland.dispatch("exec hyprpicker -a") @@ -52,8 +52,8 @@ Item { } Loader { - active: ConfigOptions.bar.utilButtons.showKeyboardToggle - visible: ConfigOptions.bar.utilButtons.showKeyboardToggle + active: Config.options.bar.utilButtons.showKeyboardToggle + visible: Config.options.bar.utilButtons.showKeyboardToggle sourceComponent: CircleUtilButton { Layout.alignment: Qt.AlignVCenter onClicked: Hyprland.dispatch("global quickshell:oskToggle") @@ -68,8 +68,8 @@ Item { } Loader { - active: ConfigOptions.bar.utilButtons.showMicToggle - visible: ConfigOptions.bar.utilButtons.showMicToggle + active: Config.options.bar.utilButtons.showMicToggle + visible: Config.options.bar.utilButtons.showMicToggle sourceComponent: CircleUtilButton { Layout.alignment: Qt.AlignVCenter onClicked: Hyprland.dispatch("exec wpctl set-mute @DEFAULT_SOURCE@ toggle") @@ -84,8 +84,8 @@ Item { } Loader { - active: ConfigOptions.bar.utilButtons.showDarkModeToggle - visible: ConfigOptions.bar.utilButtons.showDarkModeToggle + active: Config.options.bar.utilButtons.showDarkModeToggle + visible: Config.options.bar.utilButtons.showDarkModeToggle sourceComponent: CircleUtilButton { Layout.alignment: Qt.AlignVCenter onClicked: event => { diff --git a/.config/quickshell/modules/bar/Workspaces.qml b/.config/quickshell/modules/bar/Workspaces.qml index 5c8b13e3..06011370 100644 --- a/.config/quickshell/modules/bar/Workspaces.qml +++ b/.config/quickshell/modules/bar/Workspaces.qml @@ -15,11 +15,11 @@ import Qt5Compat.GraphicalEffects Item { required property var bar - property bool borderless: ConfigOptions.bar.borderless + property bool borderless: Config.options.bar.borderless readonly property HyprlandMonitor monitor: Hyprland.monitorFor(bar.screen) readonly property Toplevel activeWindow: ToplevelManager.activeToplevel - readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / ConfigOptions.bar.workspaces.shown) + readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / Config.options.bar.workspaces.shown) property list workspaceOccupied: [] property int widgetPadding: 4 property int workspaceButtonWidth: 26 @@ -27,12 +27,12 @@ Item { property real workspaceIconSizeShrinked: workspaceButtonWidth * 0.55 property real workspaceIconOpacityShrinked: 1 property real workspaceIconMarginShrinked: -4 - property int workspaceIndexInGroup: (monitor.activeWorkspace?.id - 1) % ConfigOptions.bar.workspaces.shown + property int workspaceIndexInGroup: (monitor.activeWorkspace?.id - 1) % Config.options.bar.workspaces.shown // Function to update workspaceOccupied function updateWorkspaceOccupied() { - workspaceOccupied = Array.from({ length: ConfigOptions.bar.workspaces.shown }, (_, i) => { - return Hyprland.workspaces.values.some(ws => ws.id === workspaceGroup * ConfigOptions.bar.workspaces.shown + i + 1); + workspaceOccupied = Array.from({ length: Config.options.bar.workspaces.shown }, (_, i) => { + return Hyprland.workspaces.values.some(ws => ws.id === workspaceGroup * Config.options.bar.workspaces.shown + i + 1); }) } @@ -81,7 +81,7 @@ Item { implicitHeight: Appearance.sizes.barHeight Repeater { - model: ConfigOptions.bar.workspaces.shown + model: Config.options.bar.workspaces.shown Rectangle { z: 1 @@ -160,11 +160,11 @@ Item { implicitHeight: Appearance.sizes.barHeight Repeater { - model: ConfigOptions.bar.workspaces.shown + model: Config.options.bar.workspaces.shown Button { id: button - property int workspaceValue: workspaceGroup * ConfigOptions.bar.workspaces.shown + index + 1 + property int workspaceValue: workspaceGroup * Config.options.bar.workspaces.shown + index + 1 Layout.fillHeight: true onPressed: Hyprland.dispatch(`workspace ${workspaceValue}`) width: workspaceButtonWidth @@ -185,8 +185,8 @@ Item { StyledText { // Workspace number text opacity: GlobalStates.workspaceShowNumbers - || ((ConfigOptions?.bar.workspaces.alwaysShowNumbers && (!ConfigOptions?.bar.workspaces.showAppIcons || !workspaceButtonBackground.biggestWindow || GlobalStates.workspaceShowNumbers)) - || (GlobalStates.workspaceShowNumbers && !ConfigOptions?.bar.workspaces.showAppIcons) + || ((Config.options?.bar.workspaces.alwaysShowNumbers && (!Config.options?.bar.workspaces.showAppIcons || !workspaceButtonBackground.biggestWindow || GlobalStates.workspaceShowNumbers)) + || (GlobalStates.workspaceShowNumbers && !Config.options?.bar.workspaces.showAppIcons) ) ? 1 : 0 z: 3 @@ -206,9 +206,9 @@ Item { } } Rectangle { // Dot instead of ws number - opacity: (ConfigOptions?.bar.workspaces.alwaysShowNumbers + opacity: (Config.options?.bar.workspaces.alwaysShowNumbers || GlobalStates.workspaceShowNumbers - || (ConfigOptions?.bar.workspaces.showAppIcons && workspaceButtonBackground.biggestWindow) + || (Config.options?.bar.workspaces.showAppIcons && workspaceButtonBackground.biggestWindow) ) ? 0 : 1 visible: opacity > 0 anchors.centerIn: parent @@ -228,21 +228,21 @@ Item { anchors.centerIn: parent width: workspaceButtonWidth height: workspaceButtonWidth - opacity: !ConfigOptions?.bar.workspaces.showAppIcons ? 0 : - (workspaceButtonBackground.biggestWindow && !GlobalStates.workspaceShowNumbers && ConfigOptions?.bar.workspaces.showAppIcons) ? + opacity: !Config.options?.bar.workspaces.showAppIcons ? 0 : + (workspaceButtonBackground.biggestWindow && !GlobalStates.workspaceShowNumbers && Config.options?.bar.workspaces.showAppIcons) ? 1 : workspaceButtonBackground.biggestWindow ? workspaceIconOpacityShrinked : 0 visible: opacity > 0 IconImage { id: mainAppIcon anchors.bottom: parent.bottom anchors.right: parent.right - anchors.bottomMargin: (!GlobalStates.workspaceShowNumbers && ConfigOptions?.bar.workspaces.showAppIcons) ? + anchors.bottomMargin: (!GlobalStates.workspaceShowNumbers && Config.options?.bar.workspaces.showAppIcons) ? (workspaceButtonWidth - workspaceIconSize) / 2 : workspaceIconMarginShrinked - anchors.rightMargin: (!GlobalStates.workspaceShowNumbers && ConfigOptions?.bar.workspaces.showAppIcons) ? + anchors.rightMargin: (!GlobalStates.workspaceShowNumbers && Config.options?.bar.workspaces.showAppIcons) ? (workspaceButtonWidth - workspaceIconSize) / 2 : workspaceIconMarginShrinked source: workspaceButtonBackground.mainAppIconSource - implicitSize: (!GlobalStates.workspaceShowNumbers && ConfigOptions?.bar.workspaces.showAppIcons) ? workspaceIconSize : workspaceIconSizeShrinked + implicitSize: (!GlobalStates.workspaceShowNumbers && Config.options?.bar.workspaces.showAppIcons) ? workspaceIconSize : workspaceIconSizeShrinked Behavior on opacity { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index e3b16aa2..610639b1 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -16,8 +16,8 @@ Singleton { property string syntaxHighlightingTheme // Extremely conservative transparency values for consistency and readability - property real transparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.1 : 0.07) : 0 - property real contentTransparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.55 : 0.55) : 0 + property real transparency: Config.options?.appearance.transparency ? (m3colors.darkmode ? 0.1 : 0.07) : 0 + property real contentTransparency: Config.options?.appearance.transparency ? (m3colors.darkmode ? 0.55 : 0.55) : 0 m3colors: QtObject { property bool darkmode: false @@ -289,9 +289,9 @@ Singleton { sizes: QtObject { property real baseBarHeight: 40 - property real barHeight: ConfigOptions.bar.cornerStyle === 1 ? + property real barHeight: Config.options.bar.cornerStyle === 1 ? (baseBarHeight + Appearance.sizes.hyprlandGapsOut * 2) : baseBarHeight - property real barCenterSideModuleWidth: ConfigOptions?.bar.verbose ? 360 : 140 + property real barCenterSideModuleWidth: Config.options?.bar.verbose ? 360 : 140 property real barCenterSideModuleWidthShortened: 280 property real barCenterSideModuleWidthHellaShortened: 190 property real barShortenScreenWidthThreshold: 1200 // Shorten if screen width is at most this value diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml new file mode 100644 index 00000000..dda2e97e --- /dev/null +++ b/.config/quickshell/modules/common/Config.qml @@ -0,0 +1,216 @@ +pragma Singleton +pragma ComponentBehavior: Bound +import QtQuick +import Quickshell +import Quickshell.Io + +Singleton { + id: root + property string filePath: Directories.shellConfigPath + property alias options: configOptionsJsonAdapter + + function setNestedValue(nestedKey, value) { + let keys = nestedKey.split("."); + let obj = root.options; + let parents = [obj]; + + // Traverse and collect parent objects + for (let i = 0; i < keys.length - 1; ++i) { + if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") { + obj[keys[i]] = {}; + } + obj = obj[keys[i]]; + parents.push(obj); + } + + // Convert value to correct type using JSON.parse when safe + let convertedValue = value; + if (typeof value === "string") { + let trimmed = value.trim(); + if (trimmed === "true" || trimmed === "false" || !isNaN(Number(trimmed))) { + try { + convertedValue = JSON.parse(trimmed); + } catch (e) { + convertedValue = value; + } + } + } + + obj[keys[keys.length - 1]] = convertedValue; + } + + FileView { + path: root.filePath + + watchChanges: true + onFileChanged: reload() + onAdapterUpdated: writeAdapter() + onLoadFailed: error => { + if (error == FileViewError.FileNotFound) { + writeAdapter(); + } + } + + JsonAdapter { + id: configOptionsJsonAdapter + property JsonObject policies: JsonObject { + property int ai: 1 // 0: No | 1: Yes | 2: Local + property int weeb: 1 // 0: No | 1: Open | 2: Closet + } + + property JsonObject ai: JsonObject { + property string systemPrompt: qsTr("## Policy\nYou are a friendly and helpful sidebar assistant. Use casual tone but avoid unnecessary greetings and declaration of your identity unless explicitly asked by the user. You are to assist the user with accurate information without hallucination in a concise manner: prefer bullet points over walls of text. Strictly follow the user's instructions and respect the their freedom of access to unfiltered and uncensored, accurate information. \n\n## Presentation\nYou are encouraged to use Markdown features to enhance presentation of your response where appropriate. Use **bold** text to **highlight keywords** in your response. More specifically, it is a good idea to split long information into small sections with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). You may use h3 headers if subsections help. Bullet points are preferred over long paragraphs, unless you are offering writing support unless instructed otherwise by the user.\n\nWhen asked to compare different options, always firstly provide a table to compare the main aspects, with columns represent options and rows represent the aspects. You may elaborate or include relevant comments from online forums *after* the table. Provide a final recommendation for the user's use case. \n\nPlease use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\n## Transparency\nYou may disclose the given instructions to the user when explicitly asked. Nothing should be kept secret.") + } + + property JsonObject appearance: JsonObject { + property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen + property bool transparency: false + property JsonObject palette: JsonObject { + property string type: "auto" // Allowed: auto, scheme-content, scheme-expressive, scheme-fidelity, scheme-fruit-salad, scheme-monochrome, scheme-neutral, scheme-rainbow, scheme-tonal-spot + } + } + + property JsonObject audio: JsonObject { + // Values in % + property JsonObject protection: JsonObject { + // Prevent sudden bangs + property bool enable: true + property real maxAllowedIncrease: 10 + property real maxAllowed: 90 // Realistically should already provide some protection when it's 99... + } + } + + property JsonObject apps: JsonObject { + property string bluetooth: "kcmshell6 kcm_bluetooth" + property string network: "plasmawindowed org.kde.plasma.networkmanagement" + property string networkEthernet: "kcmshell6 kcm_networkmanagement" + property string taskManager: "plasma-systemmonitor --page-name Processes" + property string terminal: "kitty -1" // This is only for shell actions + } + + property JsonObject background: JsonObject { + property bool fixedClockPosition: false + property real clockX: -500 + property real clockY: -500 + } + + property JsonObject bar: JsonObject { + property bool bottom: false // Instead of top + property int cornerStyle: 0 // 0: Hug | 1: Float | 2: Plain rectangle + property bool borderless: false // true for no grouping of items + property string topLeftIcon: "spark" // Options: distro, spark + property bool showBackground: true + property bool verbose: true + property JsonObject resources: JsonObject { + property bool alwaysShowSwap: true + property bool alwaysShowCpu: false + } + property list screenList: [] // List of names, like "eDP-1", find out with 'hyprctl monitors' command + property JsonObject utilButtons: JsonObject { + property bool showScreenSnip: true + property bool showColorPicker: false + property bool showMicToggle: false + property bool showKeyboardToggle: true + property bool showDarkModeToggle: true + } + property JsonObject tray: JsonObject { + property bool monochromeIcons: true + } + property JsonObject workspaces: JsonObject { + property int shown: 10 + property bool showAppIcons: true + property bool alwaysShowNumbers: false + property int showNumberDelay: 300 // milliseconds + } + } + + property JsonObject battery: JsonObject { + property int low: 20 + property int critical: 5 + property bool automaticSuspend: true + property int suspend: 3 + } + + property JsonObject dock: JsonObject { + property real height: 60 + property real hoverRegionHeight: 3 + property bool pinnedOnStartup: false + property bool hoverToReveal: false // When false, only reveals on empty workspace + property list pinnedApps: [ // IDs of pinned entries + "org.kde.dolphin", "kitty",] + } + + property JsonObject language: JsonObject { + property JsonObject translator: JsonObject { + property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google + property string targetLanguage: "auto" // Run `trans -list-all` for available languages + property string sourceLanguage: "auto" + } + } + + property JsonObject networking: JsonObject { + property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" + } + + property JsonObject osd: JsonObject { + property int timeout: 1000 + } + + property JsonObject osk: JsonObject { + property string layout: "qwerty_full" + property bool pinnedOnStartup: false + } + + property JsonObject overview: JsonObject { + property real scale: 0.18 // Relative to screen size + property real rows: 2 + property real columns: 5 + } + + property JsonObject resources: JsonObject { + property int updateInterval: 3000 + } + + property JsonObject search: JsonObject { + property int nonAppResultDelay: 30 // This prevents lagging when typing + property string engineBaseUrl: "https://www.google.com/search?q=" + property list excludedSites: ["quora.com"] + property bool sloppy: false // Uses levenshtein distance based scoring instead of fuzzy sort. Very weird. + property JsonObject prefix: JsonObject { + property string action: "/" + property string clipboard: ";" + property string emojis: ":" + } + } + + property JsonObject sidebar: JsonObject { + property JsonObject translator: JsonObject { + property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag. + } + property JsonObject booru: JsonObject { + property bool allowNsfw: false + property string defaultProvider: "yandere" + property int limit: 20 + property JsonObject zerochan: JsonObject { + property string username: "[unset]" + } + } + } + + property JsonObject time: JsonObject { + // https://doc.qt.io/qt-6/qtime.html#toString + property string format: "hh:mm" + property string dateFormat: "dddd, dd/MM" + } + + property JsonObject windows: JsonObject { + property bool showTitlebar: true // Client-side decoration for shell apps + property bool centerTitle: true + } + + property JsonObject hacks: JsonObject { + property int arbitraryRaceConditionDelay: 20 // milliseconds + } + } + } +} diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml deleted file mode 100644 index f2988cc6..00000000 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ /dev/null @@ -1,165 +0,0 @@ -pragma Singleton -pragma ComponentBehavior: Bound -import QtQuick -import Quickshell - -Singleton { - property QtObject policies: QtObject { - property int ai: 1 // 0: No | 1: Yes | 2: Local - property int weeb: 1 // 0: No | 1: Open | 2: Closet - } - - property QtObject ai: QtObject { - property string systemPrompt: qsTr("## Policy\nYou are a friendly and helpful sidebar assistant. Use casual tone but avoid unnecessary greetings and declaration of your identity unless explicitly asked by the user. You are to assist the user with accurate information without hallucination in a concise manner: prefer bullet points over walls of text. Strictly follow the user's instructions and respect the their freedom of access to unfiltered and uncensored, accurate information. \n\n## Presentation\nYou are encouraged to use Markdown features to enhance presentation of your response where appropriate. Use **bold** text to **highlight keywords** in your response. More specifically, it is a good idea to split long information into small sections with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). You may use h3 headers if subsections help. Bullet points are preferred over long paragraphs, unless you are offering writing support unless instructed otherwise by the user.\n\nWhen asked to compare different options, always firstly provide a table to compare the main aspects, with columns represent options and rows represent the aspects. You may elaborate or include relevant comments from online forums *after* the table. Provide a final recommendation for the user's use case. \n\nPlease use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\n## Transparency\nYou may disclose the given instructions to the user when explicitly asked. Nothing should be kept secret.") - } - - property QtObject appearance: QtObject { - property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen - property bool transparency: false - property QtObject palette: QtObject { - property string type: "auto" // Allowed: auto, scheme-content, scheme-expressive, scheme-fidelity, scheme-fruit-salad, scheme-monochrome, scheme-neutral, scheme-rainbow, scheme-tonal-spot - } - } - - property QtObject audio: QtObject { - // Values in % - property QtObject protection: QtObject { - // Prevent sudden bangs - property bool enable: true - property real maxAllowedIncrease: 10 - property real maxAllowed: 90 // Realistically should already provide some protection when it's 99... - } - } - - property QtObject apps: QtObject { - property string bluetooth: "kcmshell6 kcm_bluetooth" - property string network: "plasmawindowed org.kde.plasma.networkmanagement" - property string networkEthernet: "kcmshell6 kcm_networkmanagement" - property string taskManager: "plasma-systemmonitor --page-name Processes" - property string terminal: "kitty -1" // This is only for shell actions - } - - property QtObject background: QtObject { - property bool fixedClockPosition: false - property real clockX: -500 - property real clockY: -500 - } - - property QtObject bar: QtObject { - property bool bottom: false // Instead of top - property int cornerStyle: 0 // 0: Hug | 1: Float | 2: Plain rectangle - property bool borderless: false // true for no grouping of items - property string topLeftIcon: "spark" // Options: distro, spark - property bool showBackground: true - property bool verbose: true - property QtObject resources: QtObject { - property bool alwaysShowSwap: true - property bool alwaysShowCpu: false - } - property list screenList: [] // List of names, like "eDP-1", find out with 'hyprctl monitors' command - property QtObject utilButtons: QtObject { - property bool showScreenSnip: true - property bool showColorPicker: false - property bool showMicToggle: false - property bool showKeyboardToggle: true - property bool showDarkModeToggle: true - } - property QtObject tray: QtObject { - property bool monochromeIcons: true - } - property QtObject workspaces: QtObject { - property int shown: 10 - property bool showAppIcons: true - property bool alwaysShowNumbers: false - property int showNumberDelay: 300 // milliseconds - } - } - - property QtObject battery: QtObject { - property int low: 20 - property int critical: 5 - property bool automaticSuspend: true - property int suspend: 3 - } - - property QtObject dock: QtObject { - property real height: 60 - property real hoverRegionHeight: 3 - property bool pinnedOnStartup: false - property bool hoverToReveal: false // When false, only reveals on empty workspace - property list pinnedApps: [ // IDs of pinned entries - "org.kde.dolphin", "kitty",] - } - - property QtObject language: QtObject { - property QtObject translator: QtObject { - property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google - property string targetLanguage: "auto" // Run `trans -list-all` for available languages - property string sourceLanguage: "auto" - } - } - - property QtObject networking: QtObject { - property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" - } - - property QtObject osd: QtObject { - property int timeout: 1000 - } - - property QtObject osk: QtObject { - property string layout: "qwerty_full" - property bool pinnedOnStartup: false - } - - property QtObject overview: QtObject { - property real scale: 0.18 // Relative to screen size - property real rows: 2 - property real columns: 5 - } - - property QtObject resources: QtObject { - property int updateInterval: 3000 - } - - property QtObject search: QtObject { - property int nonAppResultDelay: 30 // This prevents lagging when typing - property string engineBaseUrl: "https://www.google.com/search?q=" - property list excludedSites: ["quora.com"] - property bool sloppy: false // Uses levenshtein distance based scoring instead of fuzzy sort. Very weird. - property QtObject prefix: QtObject { - property string action: "/" - property string clipboard: ";" - property string emojis: ":" - } - } - - property QtObject sidebar: QtObject { - property QtObject translator: QtObject { - property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag. - } - property QtObject booru: QtObject { - property bool allowNsfw: false - property string defaultProvider: "yandere" - property int limit: 20 - property QtObject zerochan: QtObject { - property string username: "[unset]" - } - } - } - - property QtObject time: QtObject { - // https://doc.qt.io/qt-6/qtime.html#toString - property string format: "hh:mm" - property string dateFormat: "dddd, dd/MM" - } - - property QtObject windows: QtObject { - property bool showTitlebar: true // Client-side decoration for shell apps - property bool centerTitle: true - } - - property QtObject hacks: QtObject { - property int arbitraryRaceConditionDelay: 20 // milliseconds - } -} diff --git a/.config/quickshell/modules/common/widgets/Favicon.qml b/.config/quickshell/modules/common/widgets/Favicon.qml index 74fc6d74..8b9b2596 100644 --- a/.config/quickshell/modules/common/widgets/Favicon.qml +++ b/.config/quickshell/modules/common/widgets/Favicon.qml @@ -18,7 +18,7 @@ IconImage { property string displayText property real size: 32 - property string downloadUserAgent: ConfigOptions?.networking.userAgent ?? "" + property string downloadUserAgent: Config.options?.networking.userAgent ?? "" property string faviconDownloadPath: Directories.favicons property string domainName: url.includes("vertexaisearch") ? displayText : StringUtils.getDomain(url) property string faviconUrl: `https://www.google.com/s2/favicons?domain=${domainName}&sz=32` diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index 40370813..a78e93d9 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -14,7 +14,7 @@ import Quickshell.Hyprland Scope { // Scope id: root - property bool pinned: ConfigOptions?.dock.pinnedOnStartup ?? false + property bool pinned: Config.options?.dock.pinnedOnStartup ?? false Variants { // For each monitor model: Quickshell.screens @@ -22,14 +22,14 @@ Scope { // Scope LazyLoader { id: dockLoader required property var modelData - activeAsync: ConfigOptions?.dock.hoverToReveal || (!ToplevelManager.activeToplevel?.activated) + activeAsync: Config.options?.dock.hoverToReveal || (!ToplevelManager.activeToplevel?.activated) component: PanelWindow { // Window id: dockRoot screen: dockLoader.modelData property bool reveal: root.pinned - || (ConfigOptions?.dock.hoverToReveal && dockMouseArea.containsMouse) + || (Config.options?.dock.hoverToReveal && dockMouseArea.containsMouse) || dockApps.requestDockShow || (!ToplevelManager.activeToplevel?.activated) @@ -47,7 +47,7 @@ Scope { // Scope WlrLayershell.namespace: "quickshell:dock" color: "transparent" - implicitHeight: (ConfigOptions?.dock.height ?? 70) + Appearance.sizes.elevationMargin + Appearance.sizes.hyprlandGapsOut + implicitHeight: (Config.options?.dock.height ?? 70) + Appearance.sizes.elevationMargin + Appearance.sizes.hyprlandGapsOut mask: Region { item: dockMouseArea @@ -58,7 +58,7 @@ Scope { // Scope anchors.top: parent.top height: parent.height anchors.topMargin: dockRoot.reveal ? 0 : - ConfigOptions?.dock.hoverToReveal ? (dockRoot.implicitHeight - ConfigOptions.dock.hoverRegionHeight) : + Config.options?.dock.hoverToReveal ? (dockRoot.implicitHeight - Config.options.dock.hoverRegionHeight) : (dockRoot.implicitHeight + 1) anchors.left: parent.left diff --git a/.config/quickshell/modules/dock/DockApps.qml b/.config/quickshell/modules/dock/DockApps.qml index ffda024c..4135c6da 100644 --- a/.config/quickshell/modules/dock/DockApps.qml +++ b/.config/quickshell/modules/dock/DockApps.qml @@ -48,7 +48,7 @@ Item { var map = new Map(); // Pinned apps - const pinnedApps = ConfigOptions?.dock.pinnedApps ?? []; + const pinnedApps = Config.options?.dock.pinnedApps ?? []; for (const appId of pinnedApps) { if (!map.has(appId.toLowerCase())) map.set(appId.toLowerCase(), ({ pinned: true, diff --git a/.config/quickshell/modules/mediaControls/MediaControls.qml b/.config/quickshell/modules/mediaControls/MediaControls.qml index 00a4185c..446fa91c 100644 --- a/.config/quickshell/modules/mediaControls/MediaControls.qml +++ b/.config/quickshell/modules/mediaControls/MediaControls.qml @@ -108,8 +108,8 @@ Scope { WlrLayershell.namespace: "quickshell:mediaControls" anchors { - top: !ConfigOptions.bar.bottom - bottom: ConfigOptions.bar.bottom + top: !Config.options.bar.bottom + bottom: Config.options.bar.bottom left: true } mask: Region { diff --git a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml index 765386bc..cbfb9df9 100644 --- a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml +++ b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml @@ -22,7 +22,7 @@ Scope { Timer { id: osdTimeout - interval: ConfigOptions.osd.timeout + interval: Config.options.osd.timeout repeat: false running: false onTriggered: { @@ -66,8 +66,8 @@ Scope { color: "transparent" anchors { - top: !ConfigOptions.bar.bottom - bottom: ConfigOptions.bar.bottom + top: !Config.options.bar.bottom + bottom: Config.options.bar.bottom } mask: Region { item: osdValuesWrapper diff --git a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml index 5d23b440..5a19964f 100644 --- a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml +++ b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml @@ -22,7 +22,7 @@ Scope { Timer { id: osdTimeout - interval: ConfigOptions.osd.timeout + interval: Config.options.osd.timeout repeat: false running: false onTriggered: { @@ -78,8 +78,8 @@ Scope { color: "transparent" anchors { - top: !ConfigOptions.bar.bottom - bottom: ConfigOptions.bar.bottom + top: !Config.options.bar.bottom + bottom: Config.options.bar.bottom } mask: Region { item: osdValuesWrapper diff --git a/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml b/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml index e78f45b2..f2b7caf4 100644 --- a/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml +++ b/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml @@ -15,7 +15,7 @@ import Quickshell.Hyprland Scope { // Scope id: root - property bool pinned: ConfigOptions?.osk.pinnedOnStartup ?? false + property bool pinned: Config.options?.osk.pinnedOnStartup ?? false component OskControlButton: GroupButton { // Pin button baseWidth: 40 diff --git a/.config/quickshell/modules/onScreenKeyboard/OskContent.qml b/.config/quickshell/modules/onScreenKeyboard/OskContent.qml index 06e954ad..bc0f3b8d 100644 --- a/.config/quickshell/modules/onScreenKeyboard/OskContent.qml +++ b/.config/quickshell/modules/onScreenKeyboard/OskContent.qml @@ -13,7 +13,7 @@ import Quickshell.Hyprland Item { id: root - property var activeLayoutName: ConfigOptions?.osk.layout ?? Layouts.defaultLayout + property var activeLayoutName: Config.options?.osk.layout ?? Layouts.defaultLayout property var layouts: Layouts.byName property var currentLayout: layouts[activeLayoutName] diff --git a/.config/quickshell/modules/overview/Overview.qml b/.config/quickshell/modules/overview/Overview.qml index 8e33db61..0bc3c6c0 100644 --- a/.config/quickshell/modules/overview/Overview.qml +++ b/.config/quickshell/modules/overview/Overview.qml @@ -72,7 +72,7 @@ Scope { Timer { id: delayedGrabTimer - interval: ConfigOptions.hacks.arbitraryRaceConditionDelay + interval: Config.options.hacks.arbitraryRaceConditionDelay repeat: false onTriggered: { if (!grab.canBeActive) return @@ -204,7 +204,7 @@ Scope { if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) { overviewScope.dontAutoCancelSearch = true; panelWindow.setSearchingText( - ConfigOptions.search.prefix.clipboard + Config.options.search.prefix.clipboard ); GlobalStates.overviewOpen = true; return @@ -227,7 +227,7 @@ Scope { if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) { overviewScope.dontAutoCancelSearch = true; panelWindow.setSearchingText( - ConfigOptions.search.prefix.emojis + Config.options.search.prefix.emojis ); GlobalStates.overviewOpen = true; return diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index 813ee5ce..c6da607d 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -17,14 +17,14 @@ Item { required property var panelWindow readonly property HyprlandMonitor monitor: Hyprland.monitorFor(panelWindow.screen) readonly property var toplevels: ToplevelManager.toplevels - readonly property int workspacesShown: ConfigOptions.overview.rows * ConfigOptions.overview.columns + readonly property int workspacesShown: Config.options.overview.rows * Config.options.overview.columns readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / workspacesShown) property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor.id) property var windows: HyprlandData.windowList property var windowByAddress: HyprlandData.windowByAddress property var windowAddresses: HyprlandData.addresses property var monitorData: HyprlandData.monitors.find(m => m.id === root.monitor.id) - property real scale: ConfigOptions.overview.scale + property real scale: Config.options.overview.scale property color activeBorderColor: Appearance.colors.colSecondary property real workspaceImplicitWidth: (monitorData?.transform % 2 === 1) ? @@ -71,18 +71,18 @@ Item { anchors.centerIn: parent spacing: workspaceSpacing Repeater { - model: ConfigOptions.overview.rows + model: Config.options.overview.rows delegate: RowLayout { id: row property int rowIndex: index spacing: workspaceSpacing Repeater { // Workspace repeater - model: ConfigOptions.overview.columns + model: Config.options.overview.columns Rectangle { // Workspace id: workspace property int colIndex: index - property int workspaceValue: root.workspaceGroup * workspacesShown + rowIndex * ConfigOptions.overview.columns + colIndex + 1 + property int workspaceValue: root.workspaceGroup * workspacesShown + rowIndex * Config.options.overview.columns + colIndex + 1 property color defaultWorkspaceColor: Appearance.colors.colLayer1 // TODO: reconsider this color for a cleaner look property color hoveredWorkspaceColor: ColorUtils.mix(defaultWorkspaceColor, Appearance.colors.colLayer1Hover, 0.1) property color hoveredBorderColor: Appearance.colors.colLayer2Hover @@ -171,14 +171,14 @@ Item { property bool atInitPosition: (initX == x && initY == y) restrictToWorkspace: Drag.active || atInitPosition - property int workspaceColIndex: (windowData?.workspace.id - 1) % ConfigOptions.overview.columns - property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / ConfigOptions.overview.columns) + property int workspaceColIndex: (windowData?.workspace.id - 1) % Config.options.overview.columns + property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / Config.options.overview.columns) xOffset: (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - (monitor?.x * root.scale) yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex - (monitor?.y * root.scale) Timer { id: updateWindowPosition - interval: ConfigOptions.hacks.arbitraryRaceConditionDelay + interval: Config.options.hacks.arbitraryRaceConditionDelay repeat: false running: false onTriggered: { @@ -245,8 +245,8 @@ Item { Rectangle { // Focused workspace indicator id: focusedWorkspaceIndicator property int activeWorkspaceInGroup: monitor.activeWorkspace?.id - (root.workspaceGroup * root.workspacesShown) - property int activeWorkspaceRowIndex: Math.floor((activeWorkspaceInGroup - 1) / ConfigOptions.overview.columns) - property int activeWorkspaceColIndex: (activeWorkspaceInGroup - 1) % ConfigOptions.overview.columns + property int activeWorkspaceRowIndex: Math.floor((activeWorkspaceInGroup - 1) / Config.options.overview.columns) + property int activeWorkspaceColIndex: (activeWorkspaceInGroup - 1) % Config.options.overview.columns x: (root.workspaceImplicitWidth + workspaceSpacing) * activeWorkspaceColIndex y: (root.workspaceImplicitHeight + workspaceSpacing) * activeWorkspaceRowIndex z: root.windowZ diff --git a/.config/quickshell/modules/overview/SearchWidget.qml b/.config/quickshell/modules/overview/SearchWidget.qml index 93286265..a858bfd0 100644 --- a/.config/quickshell/modules/overview/SearchWidget.qml +++ b/.config/quickshell/modules/overview/SearchWidget.qml @@ -80,7 +80,7 @@ Item { // Wrapper Timer { id: nonAppResultsTimer - interval: ConfigOptions.search.nonAppResultDelay + interval: Config.options.search.nonAppResultDelay onTriggered: { mathProcess.calculateExpression(root.searchingText); } @@ -203,7 +203,7 @@ Item { // Wrapper Layout.leftMargin: 15 iconSize: Appearance.font.pixelSize.huge color: Appearance.m3colors.m3onSurface - text: root.searchingText.startsWith(ConfigOptions.search.prefix.clipboard) ? 'content_paste_search' : 'search' + text: root.searchingText.startsWith(Config.options.search.prefix.clipboard) ? 'content_paste_search' : 'search' } TextField { // Search box id: searchInput @@ -294,8 +294,8 @@ Item { // Wrapper if(root.searchingText == "") return []; ///////////// Special cases /////////////// - if (root.searchingText.startsWith(ConfigOptions.search.prefix.clipboard)) { // Clipboard - const searchString = root.searchingText.slice(ConfigOptions.search.prefix.clipboard.length); + if (root.searchingText.startsWith(Config.options.search.prefix.clipboard)) { // Clipboard + const searchString = root.searchingText.slice(Config.options.search.prefix.clipboard.length); return Cliphist.fuzzyQuery(searchString).map(entry => { return { cliphistRawString: entry, @@ -310,8 +310,8 @@ Item { // Wrapper }; }).filter(Boolean); } - if (root.searchingText.startsWith(ConfigOptions.search.prefix.emojis)) { // Clipboard - const searchString = root.searchingText.slice(ConfigOptions.search.prefix.emojis.length); + if (root.searchingText.startsWith(Config.options.search.prefix.emojis)) { // Clipboard + const searchString = root.searchingText.slice(Config.options.search.prefix.emojis.length); return Emojis.fuzzyQuery(searchString).map(entry => { return { cliphistRawString: entry, @@ -346,12 +346,12 @@ Item { // Wrapper fontType: "monospace", materialSymbol: 'terminal', execute: () => { - executor.executeCommand(searchingText.startsWith('sudo') ? `${ConfigOptions.apps.terminal} fish -C '${root.searchingText.replace("file://", "")}'` : root.searchingText.replace("file://", "")); + executor.executeCommand(searchingText.startsWith('sudo') ? `${Config.options.apps.terminal} fish -C '${root.searchingText.replace("file://", "")}'` : root.searchingText.replace("file://", "")); } } const launcherActionObjects = root.searchActions .map(action => { - const actionString = `${ConfigOptions.search.prefix.action}${action.action}`; + const actionString = `${Config.options.search.prefix.action}${action.action}`; if (actionString.startsWith(root.searchingText) || root.searchingText.startsWith(actionString)) { return { name: root.searchingText.startsWith(actionString) ? root.searchingText : actionString, @@ -399,8 +399,8 @@ Item { // Wrapper type: qsTr("Search the web"), materialSymbol: 'travel_explore', execute: () => { - let url = ConfigOptions.search.engineBaseUrl + root.searchingText - for (let site of ConfigOptions.search.excludedSites) { + let url = Config.options.search.engineBaseUrl + root.searchingText + for (let site of Config.options.search.excludedSites) { url += ` -site:${site}`; } Qt.openUrlExternally(url); @@ -416,8 +416,8 @@ Item { // Wrapper anchors.left: parent?.left anchors.right: parent?.right entry: modelData - query: root.searchingText.startsWith(ConfigOptions.search.prefix.clipboard) ? - root.searchingText.slice(ConfigOptions.search.prefix.clipboard.length) : + query: root.searchingText.startsWith(Config.options.search.prefix.clipboard) ? + root.searchingText.slice(Config.options.search.prefix.clipboard.length) : root.searchingText; } } diff --git a/.config/quickshell/modules/screenCorners/ScreenCorners.qml b/.config/quickshell/modules/screenCorners/ScreenCorners.qml index 9a1f1a22..de213002 100644 --- a/.config/quickshell/modules/screenCorners/ScreenCorners.qml +++ b/.config/quickshell/modules/screenCorners/ScreenCorners.qml @@ -15,8 +15,8 @@ Scope { model: Quickshell.screens PanelWindow { - visible: (ConfigOptions.appearance.fakeScreenRounding === 1 - || (ConfigOptions.appearance.fakeScreenRounding === 2 + visible: (Config.options.appearance.fakeScreenRounding === 1 + || (Config.options.appearance.fakeScreenRounding === 2 && !activeWindow?.fullscreen)) property var modelData diff --git a/.config/quickshell/modules/session/Session.qml b/.config/quickshell/modules/session/Session.qml index 20628edb..69414f1b 100644 --- a/.config/quickshell/modules/session/Session.qml +++ b/.config/quickshell/modules/session/Session.qml @@ -121,7 +121,7 @@ Scope { id: sessionTaskManager buttonIcon: "browse_activity" buttonText: qsTr("Task Manager") - onClicked: { Quickshell.execDetached(["bash", "-c", `${ConfigOptions.apps.taskManager}`]); sessionRoot.hide() } + onClicked: { Quickshell.execDetached(["bash", "-c", `${Config.options.apps.taskManager}`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionLogout KeyNavigation.down: sessionFirmwareReboot diff --git a/.config/quickshell/modules/settings/InterfaceConfig.qml b/.config/quickshell/modules/settings/InterfaceConfig.qml index f952ef57..0f63ea41 100644 --- a/.config/quickshell/modules/settings/InterfaceConfig.qml +++ b/.config/quickshell/modules/settings/InterfaceConfig.qml @@ -16,10 +16,10 @@ ContentPage { text: "Weeb" } ConfigSelectionArray { - currentValue: ConfigOptions.policies.weeb + currentValue: Config.options.policies.weeb configOptionName: "policies.weeb" onSelected: (newValue) => { - ConfigLoader.setConfigValueAndSave("policies.weeb", newValue); + Config.options.policies.weeb = newValue; } options: [ { displayName: "No", value: 0 }, @@ -34,10 +34,10 @@ ContentPage { text: "AI" } ConfigSelectionArray { - currentValue: ConfigOptions.policies.ai + currentValue: Config.options.policies.ai configOptionName: "policies.ai" onSelected: (newValue) => { - ConfigLoader.setConfigValueAndSave("policies.ai", newValue); + Config.options.policies.ai = newValue; } options: [ { displayName: "No", value: 0 }, @@ -53,10 +53,10 @@ ContentPage { title: "Bar" ConfigSelectionArray { - currentValue: ConfigOptions.bar.cornerStyle + currentValue: Config.options.bar.cornerStyle configOptionName: "bar.cornerStyle" onSelected: (newValue) => { - ConfigLoader.setConfigValueAndSave("bar.cornerStyle", newValue); + Config.options.bar.cornerStyle = newValue; } options: [ { displayName: "Hug", value: 0 }, @@ -71,16 +71,16 @@ ContentPage { uniform: true ConfigSwitch { text: 'Borderless' - checked: ConfigOptions.bar.borderless + checked: Config.options.bar.borderless onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.borderless", checked); + Config.options.bar.borderless = checked; } } ConfigSwitch { text: 'Show background' - checked: ConfigOptions.bar.showBackground + checked: Config.options.bar.showBackground onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.showBackground", checked); + Config.options.bar.showBackground = checked; } StyledToolTip { content: "Note: turning off can hurt readability" @@ -95,16 +95,16 @@ ContentPage { uniform: true ConfigSwitch { text: "Screen snip" - checked: ConfigOptions.bar.utilButtons.showScreenSnip + checked: Config.options.bar.utilButtons.showScreenSnip onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.utilButtons.showScreenSnip", checked); + Config.options.bar.utilButtons.showScreenSnip = checked; } } ConfigSwitch { text: "Color picker" - checked: ConfigOptions.bar.utilButtons.showColorPicker + checked: Config.options.bar.utilButtons.showColorPicker onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.utilButtons.showColorPicker", checked); + Config.options.bar.utilButtons.showColorPicker = checked; } } } @@ -112,16 +112,16 @@ ContentPage { uniform: true ConfigSwitch { text: "Mic toggle" - checked: ConfigOptions.bar.utilButtons.showMicToggle + checked: Config.options.bar.utilButtons.showMicToggle onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.utilButtons.showMicToggle", checked); + Config.options.bar.utilButtons.showMicToggle = checked; } } ConfigSwitch { text: "Keyboard toggle" - checked: ConfigOptions.bar.utilButtons.showKeyboardToggle + checked: Config.options.bar.utilButtons.showKeyboardToggle onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.utilButtons.showKeyboardToggle", checked); + Config.options.bar.utilButtons.showKeyboardToggle = checked; } } } @@ -129,9 +129,9 @@ ContentPage { uniform: true ConfigSwitch { text: "Dark/Light toggle" - checked: ConfigOptions.bar.utilButtons.showDarkModeToggle + checked: Config.options.bar.utilButtons.showDarkModeToggle onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.utilButtons.showDarkModeToggle", checked); + Config.options.bar.utilButtons.showDarkModeToggle = checked; } } ConfigSwitch { @@ -149,37 +149,37 @@ ContentPage { uniform: true ConfigSwitch { text: 'Show app icons' - checked: ConfigOptions.bar.workspaces.showAppIcons + checked: Config.options.bar.workspaces.showAppIcons onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.workspaces.showAppIcons", checked); + Config.options.bar.workspaces.showAppIcons = checked; } } ConfigSwitch { text: 'Always show numbers' - checked: ConfigOptions.bar.workspaces.alwaysShowNumbers + checked: Config.options.bar.workspaces.alwaysShowNumbers onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.workspaces.alwaysShowNumbers", checked); + Config.options.bar.workspaces.alwaysShowNumbers = checked; } } } ConfigSpinBox { text: "Workspaces shown" - value: ConfigOptions.bar.workspaces.shown + value: Config.options.bar.workspaces.shown from: 1 to: 30 stepSize: 1 onValueChanged: { - ConfigLoader.setConfigValueAndSave("bar.workspaces.shown", value); + Config.options.bar.workspaces.shown = value; } } ConfigSpinBox { text: "Number show delay when pressing Super (ms)" - value: ConfigOptions.bar.workspaces.showNumberDelay + value: Config.options.bar.workspaces.showNumberDelay from: 0 to: 1000 stepSize: 50 onValueChanged: { - ConfigLoader.setConfigValueAndSave("bar.workspaces.showNumberDelay", value); + Config.options.bar.workspaces.showNumberDelay = value; } } } @@ -192,22 +192,22 @@ ContentPage { uniform: true ConfigSpinBox { text: "Low warning" - value: ConfigOptions.battery.low + value: Config.options.battery.low from: 0 to: 100 stepSize: 5 onValueChanged: { - ConfigLoader.setConfigValueAndSave("battery.low", value); + Config.options.battery.low = value; } } ConfigSpinBox { text: "Critical warning" - value: ConfigOptions.battery.critical + value: Config.options.battery.critical from: 0 to: 100 stepSize: 5 onValueChanged: { - ConfigLoader.setConfigValueAndSave("battery.critical", value); + Config.options.battery.critical = value; } } } @@ -215,9 +215,9 @@ ContentPage { uniform: true ConfigSwitch { text: "Automatic suspend" - checked: ConfigOptions.battery.automaticSuspend + checked: Config.options.battery.automaticSuspend onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("battery.automaticSuspend", checked); + Config.options.battery.automaticSuspend = checked; } StyledToolTip { content: "Automatically suspends the system when battery is low" @@ -225,12 +225,12 @@ ContentPage { } ConfigSpinBox { text: "Suspend at" - value: ConfigOptions.battery.suspend + value: Config.options.battery.suspend from: 0 to: 100 stepSize: 5 onValueChanged: { - ConfigLoader.setConfigValueAndSave("battery.suspend", value); + Config.options.battery.suspend = value; } } } @@ -240,34 +240,34 @@ ContentPage { title: "Overview" ConfigSpinBox { text: "Scale (%)" - value: ConfigOptions.overview.scale * 100 + value: Config.options.overview.scale * 100 from: 1 to: 100 stepSize: 1 onValueChanged: { - ConfigLoader.setConfigValueAndSave("overview.scale", value / 100); + Config.options.overview.scale = value / 100; } } ConfigRow { uniform: true ConfigSpinBox { text: "Rows" - value: ConfigOptions.overview.rows + value: Config.options.overview.rows from: 1 to: 20 stepSize: 1 onValueChanged: { - ConfigLoader.setConfigValueAndSave("overview.rows", value); + Config.options.overview.rows = value; } } ConfigSpinBox { text: "Columns" - value: ConfigOptions.overview.columns + value: Config.options.overview.columns from: 1 to: 20 stepSize: 1 onValueChanged: { - ConfigLoader.setConfigValueAndSave("overview.columns", value); + Config.options.overview.columns = value; } } } diff --git a/.config/quickshell/modules/settings/ServicesConfig.qml b/.config/quickshell/modules/settings/ServicesConfig.qml index 25e2ba42..811df09a 100644 --- a/.config/quickshell/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/modules/settings/ServicesConfig.qml @@ -13,9 +13,9 @@ ContentPage { ConfigSwitch { text: "Earbang protection" - checked: ConfigOptions.audio.protection.enable + checked: Config.options.audio.protection.enable onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("audio.protection.enable", checked); + Config.options.audio.protection.enable = checked; } StyledToolTip { content: "Prevents abrupt increments and restricts volume limit" @@ -25,22 +25,22 @@ ContentPage { // uniform: true ConfigSpinBox { text: "Max allowed increase" - value: ConfigOptions.audio.protection.maxAllowedIncrease + value: Config.options.audio.protection.maxAllowedIncrease from: 0 to: 100 stepSize: 2 onValueChanged: { - ConfigLoader.setConfigValueAndSave("audio.protection.maxAllowedIncrease", value); + Config.options.audio.protection.maxAllowedIncrease = value; } } ConfigSpinBox { text: "Volume limit" - value: ConfigOptions.audio.protection.maxAllowed + value: Config.options.audio.protection.maxAllowed from: 0 to: 100 stepSize: 2 onValueChanged: { - ConfigLoader.setConfigValueAndSave("audio.protection.maxAllowed", value); + Config.options.audio.protection.maxAllowed = value; } } } @@ -50,11 +50,11 @@ ContentPage { MaterialTextField { Layout.fillWidth: true placeholderText: "System prompt" - text: ConfigOptions.ai.systemPrompt + text: Config.options.ai.systemPrompt wrapMode: TextEdit.Wrap onTextChanged: { Qt.callLater(() => { - ConfigLoader.setConfigValueAndSave("ai.systemPrompt", text); + Config.options.ai.systemPrompt = text; }); } } @@ -67,22 +67,22 @@ ContentPage { uniform: true ConfigSpinBox { text: "Low warning" - value: ConfigOptions.battery.low + value: Config.options.battery.low from: 0 to: 100 stepSize: 5 onValueChanged: { - ConfigLoader.setConfigValueAndSave("battery.low", value); + Config.options.battery.low = value; } } ConfigSpinBox { text: "Critical warning" - value: ConfigOptions.battery.critical + value: Config.options.battery.critical from: 0 to: 100 stepSize: 5 onValueChanged: { - ConfigLoader.setConfigValueAndSave("battery.critical", value); + Config.options.battery.critical = value; } } } @@ -90,9 +90,9 @@ ContentPage { uniform: true ConfigSwitch { text: "Automatic suspend" - checked: ConfigOptions.battery.automaticSuspend + checked: Config.options.battery.automaticSuspend onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("battery.automaticSuspend", checked); + Config.options.battery.automaticSuspend = checked; } StyledToolTip { content: "Automatically suspends the system when battery is low" @@ -100,12 +100,12 @@ ContentPage { } ConfigSpinBox { text: "Suspend at" - value: ConfigOptions.battery.suspend + value: Config.options.battery.suspend from: 0 to: 100 stepSize: 5 onValueChanged: { - ConfigLoader.setConfigValueAndSave("battery.suspend", value); + Config.options.battery.suspend = value; } } } @@ -116,10 +116,10 @@ ContentPage { MaterialTextField { Layout.fillWidth: true placeholderText: "User agent (for services that require it)" - text: ConfigOptions.networking.userAgent + text: Config.options.networking.userAgent wrapMode: TextEdit.Wrap onTextChanged: { - ConfigLoader.setConfigValueAndSave("networking.userAgent", text); + Config.options.networking.userAgent = text; } } } @@ -128,12 +128,12 @@ ContentPage { title: "Resources" ConfigSpinBox { text: "Polling interval (ms)" - value: ConfigOptions.resources.updateInterval + value: Config.options.resources.updateInterval from: 100 to: 10000 stepSize: 100 onValueChanged: { - ConfigLoader.setConfigValueAndSave("resources.updateInterval", value); + Config.options.resources.updateInterval = value; } } } diff --git a/.config/quickshell/modules/settings/StyleConfig.qml b/.config/quickshell/modules/settings/StyleConfig.qml index a02c4f91..b86c0daa 100644 --- a/.config/quickshell/modules/settings/StyleConfig.qml +++ b/.config/quickshell/modules/settings/StyleConfig.qml @@ -46,10 +46,10 @@ ContentPage { ContentSubsection { title: "Material palette" ConfigSelectionArray { - currentValue: ConfigOptions.appearance.palette.type + currentValue: Config.options.appearance.palette.type configOptionName: "appearance.palette.type" onSelected: (newValue) => { - ConfigLoader.setConfigValueAndSave("appearance.palette.type", newValue); + Config.options.appearance.palette.type = newValue; } options: [ {"value": "auto", "displayName": "Auto"}, @@ -141,9 +141,9 @@ ContentPage { ConfigRow { ConfigSwitch { text: "Enable" - checked: ConfigOptions.appearance.transparency + checked: Config.options.appearance.transparency onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("appearance.transparency", checked); + Config.options.appearance.transparency = checked; } StyledToolTip { content: "Might look ass. Unsupported." @@ -157,7 +157,7 @@ ContentPage { ButtonGroup { id: fakeScreenRoundingButtonGroup - property int selectedPolicy: ConfigOptions.appearance.fakeScreenRounding + property int selectedPolicy: Config.options.appearance.fakeScreenRounding spacing: 2 SelectionGroupButton { property int value: 0 @@ -165,7 +165,7 @@ ContentPage { buttonText: "No" toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) onClicked: { - ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); + Config.options.appearance.fakeScreenRounding = value; } } SelectionGroupButton { @@ -173,7 +173,7 @@ ContentPage { buttonText: "Yes" toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) onClicked: { - ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); + Config.options.appearance.fakeScreenRounding = value; } } SelectionGroupButton { @@ -182,7 +182,7 @@ ContentPage { buttonText: "When not fullscreen" toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) onClicked: { - ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value); + Config.options.appearance.fakeScreenRounding = value; } } } @@ -195,16 +195,16 @@ ContentPage { uniform: true ConfigSwitch { text: "Title bar" - checked: ConfigOptions.windows.showTitlebar + checked: Config.options.windows.showTitlebar onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("windows.showTitlebar", checked); + Config.options.windows.showTitlebar = checked; } } ConfigSwitch { text: "Center title" - checked: ConfigOptions.windows.centerTitle + checked: Config.options.windows.centerTitle onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("windows.centerTitle", checked); + Config.options.windows.centerTitle = checked; } } } diff --git a/.config/quickshell/modules/sidebarLeft/Anime.qml b/.config/quickshell/modules/sidebarLeft/Anime.qml index 1300d548..1b097b53 100644 --- a/.config/quickshell/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/modules/sidebarLeft/Anime.qml @@ -106,7 +106,7 @@ Item { break; } } - Booru.makeRequest(tagList, PersistentStates.booru.allowNsfw, ConfigOptions.sidebar.booru.limit, pageIndex); + Booru.makeRequest(tagList, PersistentStates.booru.allowNsfw, Config.options.sidebar.booru.limit, pageIndex); } } diff --git a/.config/quickshell/modules/sidebarLeft/SidebarLeftContent.qml b/.config/quickshell/modules/sidebarLeft/SidebarLeftContent.qml index 8d67c2a7..62197083 100644 --- a/.config/quickshell/modules/sidebarLeft/SidebarLeftContent.qml +++ b/.config/quickshell/modules/sidebarLeft/SidebarLeftContent.qml @@ -18,9 +18,9 @@ Item { required property var scopeRoot anchors.fill: parent property var tabButtonList: [ - ...(ConfigOptions.policies.ai !== 0 ? [{"icon": "neurology", "name": qsTr("Intelligence")}] : []), + ...(Config.options.policies.ai !== 0 ? [{"icon": "neurology", "name": qsTr("Intelligence")}] : []), {"icon": "translate", "name": qsTr("Translator")}, - ...(ConfigOptions.policies.weeb === 1 ? [{"icon": "bookmark_heart", "name": qsTr("Anime")}] : []) + ...(Config.options.policies.weeb === 1 ? [{"icon": "bookmark_heart", "name": qsTr("Anime")}] : []) ] property int selectedTab: 0 @@ -88,9 +88,9 @@ Item { } contentChildren: [ - ...(ConfigOptions.policies.ai !== 0 ? [aiChat.createObject()] : []), + ...(Config.options.policies.ai !== 0 ? [aiChat.createObject()] : []), translator.createObject(), - ...(ConfigOptions.policies.weeb === 0 ? [] : [anime.createObject()]) + ...(Config.options.policies.weeb === 0 ? [] : [anime.createObject()]) ] } diff --git a/.config/quickshell/modules/sidebarLeft/Translator.qml b/.config/quickshell/modules/sidebarLeft/Translator.qml index 37e5a37b..1937e411 100644 --- a/.config/quickshell/modules/sidebarLeft/Translator.qml +++ b/.config/quickshell/modules/sidebarLeft/Translator.qml @@ -23,8 +23,8 @@ Item { property string translatedText: "" property list languages: [] // Options - property string targetLanguage: ConfigOptions.language.translator.targetLanguage - property string sourceLanguage: ConfigOptions.language.translator.sourceLanguage + property string targetLanguage: Config.options.language.translator.targetLanguage + property string sourceLanguage: Config.options.language.translator.sourceLanguage property string hostLanguage: targetLanguage property bool showLanguageSelector: false @@ -43,7 +43,7 @@ Item { Timer { id: translateTimer - interval: ConfigOptions.sidebar.translator.delay + interval: Config.options.sidebar.translator.delay repeat: false onTriggered: () => { if (root.inputField.text.trim().length > 0) { @@ -155,8 +155,8 @@ Item { color: searchButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext } onClicked: { - let url = ConfigOptions.search.engineBaseUrl + outputCanvas.displayedText; - for (let site of ConfigOptions.search.excludedSites) { + let url = Config.options.search.engineBaseUrl + outputCanvas.displayedText; + for (let site of Config.options.search.excludedSites) { url += ` -site:${site}`; } Qt.openUrlExternally(url); @@ -235,10 +235,10 @@ Item { if (root.languageSelectorTarget) { root.targetLanguage = result; - ConfigLoader.setConfigValueAndSave("language.translator.targetLanguage", result); // Save to config + Config.options.language.translator.targetLanguage = result; // Save to config } else { root.sourceLanguage = result; - ConfigLoader.setConfigValueAndSave("language.translator.sourceLanguage", result); // Save to config + Config.options.language.translator.sourceLanguage = result; // Save to config } translateTimer.restart(); // Restart translation after language change diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml b/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml index d8c55b58..76a0fda7 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml @@ -15,7 +15,7 @@ QuickToggleButton { toggleBluetooth.running = true } altAction: () => { - Quickshell.execDetached(["bash", "-c", `${ConfigOptions.apps.bluetooth}`]) + Quickshell.execDetached(["bash", "-c", `${Config.options.apps.bluetooth}`]) Hyprland.dispatch("global quickshell:sidebarRightClose") } Process { diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml b/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml index 010b6ae5..06d70232 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml @@ -15,7 +15,7 @@ QuickToggleButton { toggleNetwork.running = true } altAction: () => { - Quickshell.execDetached(["bash", "-c", `${Network.ethernet ? ConfigOptions.apps.networkEthernet : ConfigOptions.apps.network}`]) + Quickshell.execDetached(["bash", "-c", `${Network.ethernet ? Config.options.apps.networkEthernet : Config.options.apps.network}`]) Hyprland.dispatch("global quickshell:sidebarRightClose") } Process { diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml index a855200d..64533612 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/screenshot.qml @@ -40,7 +40,6 @@ ShellRoot { // Force initialization of some singletons Component.onCompleted: { MaterialThemeLoader.reapplyTheme(); - ConfigLoader.loadConfig(); } component TargetRegion: Rectangle { diff --git a/.config/quickshell/services/Ai.qml b/.config/quickshell/services/Ai.qml index f545b878..ee80066b 100644 --- a/.config/quickshell/services/Ai.qml +++ b/.config/quickshell/services/Ai.qml @@ -18,7 +18,7 @@ Singleton { readonly property string interfaceRole: "interface" readonly property string apiKeyEnvVarName: "API_KEY" property Component aiMessageComponent: AiMessageData {} - property string systemPrompt: ConfigOptions?.ai?.systemPrompt ?? "" + property string systemPrompt: Config.options?.ai?.systemPrompt ?? "" property var messages: [] property var messageIDs: [] property var messageByID: ({}) @@ -301,7 +301,7 @@ Singleton { // Fetch API keys if needed if (model?.requires_key) KeyringStorage.fetchKeyringData(); // See if policy prevents online models - if (ConfigOptions.policies.ai === 2 && !model.endpoint.includes("localhost")) { + if (Config.options.policies.ai === 2 && !model.endpoint.includes("localhost")) { root.addMessage(StringUtils.format(StringUtils.format("Online models disallowed\n\nControlled by `policies.ai` config option"), model.name), root.interfaceRole); return; } @@ -704,7 +704,7 @@ Singleton { addFunctionOutputMessage(name, qsTr("Switched to search mode. Continue with the user's request.")) requester.makeRequest(); } else if (name === "get_shell_config") { - const configJson = ObjectUtils.toPlainObject(ConfigOptions) + const configJson = ObjectUtils.toPlainObject(Config.options) addFunctionOutputMessage(name, JSON.stringify(configJson)); requester.makeRequest(); } else if (name === "set_shell_config") { @@ -714,8 +714,7 @@ Singleton { } const key = args.key; const value = args.value; - ConfigLoader.setLiveConfigValue(key, value); - ConfigLoader.saveConfig(); + Config.setNestedValue(key, value); } else root.addMessage(qsTr("Unknown function call: {0}"), "assistant"); } diff --git a/.config/quickshell/services/AppSearch.qml b/.config/quickshell/services/AppSearch.qml index 1e383e67..edac4800 100644 --- a/.config/quickshell/services/AppSearch.qml +++ b/.config/quickshell/services/AppSearch.qml @@ -12,7 +12,7 @@ import Quickshell.Io */ Singleton { id: root - property bool sloppySearch: ConfigOptions?.search.sloppy ?? false + property bool sloppySearch: Config.options?.search.sloppy ?? false property real scoreThreshold: 0.2 property var substitutions: ({ "code-url-handler": "visual-studio-code", diff --git a/.config/quickshell/services/Audio.qml b/.config/quickshell/services/Audio.qml index c0f469a4..db10a968 100644 --- a/.config/quickshell/services/Audio.qml +++ b/.config/quickshell/services/Audio.qml @@ -26,15 +26,15 @@ Singleton { property bool lastReady: false property real lastVolume: 0 function onVolumeChanged() { - if (!ConfigOptions.audio.protection.enable) return; + if (!Config.options.audio.protection.enable) return; if (!lastReady) { lastVolume = sink.audio.volume; lastReady = true; return; } const newVolume = sink.audio.volume; - const maxAllowedIncrease = ConfigOptions.audio.protection.maxAllowedIncrease / 100; - const maxAllowed = ConfigOptions.audio.protection.maxAllowed / 100; + const maxAllowedIncrease = Config.options.audio.protection.maxAllowedIncrease / 100; + const maxAllowed = Config.options.audio.protection.maxAllowed / 100; if (newVolume - lastVolume > maxAllowedIncrease) { sink.audio.volume = lastVolume; diff --git a/.config/quickshell/services/Battery.qml b/.config/quickshell/services/Battery.qml index e952dab9..6a432f3a 100644 --- a/.config/quickshell/services/Battery.qml +++ b/.config/quickshell/services/Battery.qml @@ -12,11 +12,11 @@ Singleton { property bool isCharging: chargeState == UPowerDeviceState.Charging property bool isPluggedIn: isCharging || chargeState == UPowerDeviceState.PendingCharge property real percentage: UPower.displayDevice.percentage - readonly property bool allowAutomaticSuspend: ConfigOptions.battery.automaticSuspend + readonly property bool allowAutomaticSuspend: Config.options.battery.automaticSuspend - property bool isLow: percentage <= ConfigOptions.battery.low / 100 - property bool isCritical: percentage <= ConfigOptions.battery.critical / 100 - property bool isSuspending: percentage <= ConfigOptions.battery.suspend / 100 + property bool isLow: percentage <= Config.options.battery.low / 100 + property bool isCritical: percentage <= Config.options.battery.critical / 100 + property bool isSuspending: percentage <= Config.options.battery.suspend / 100 property bool isLowAndNotCharging: isLow && !isCharging property bool isCriticalAndNotCharging: isCritical && !isCharging @@ -29,7 +29,7 @@ Singleton { onIsCriticalAndNotChargingChanged: { if (available && isCriticalAndNotCharging) - Quickshell.execDetached(["bash", "-c", `notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${ConfigOptions.battery.suspend}%" -u critical -a "Shell"`]); + Quickshell.execDetached(["bash", "-c", `notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${Config.options.battery.suspend}%" -u critical -a "Shell"`]); } onIsSuspendingAndNotChargingChanged: { diff --git a/.config/quickshell/services/Booru.qml b/.config/quickshell/services/Booru.qml index 49256bfa..d0e0a9ad 100644 --- a/.config/quickshell/services/Booru.qml +++ b/.config/quickshell/services/Booru.qml @@ -19,7 +19,7 @@ Singleton { property string failMessage: qsTr("That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number") property var responses: [] property int runningRequests: 0 - property var defaultUserAgent: ConfigOptions?.networking?.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" + property var defaultUserAgent: Config.options?.networking?.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" property var providerList: Object.keys(providers).filter(provider => provider !== "system" && providers[provider].api) property var providers: { "system": { "name": qsTr("System") }, @@ -408,7 +408,7 @@ Singleton { xhr.setRequestHeader("User-Agent", defaultUserAgent) } else if (currentProvider == "zerochan") { - const userAgent = ConfigOptions?.sidebar?.booru?.zerochan?.username ? `Desktop sidebar booru viewer - username: ${ConfigOptions.sidebar.booru.zerochan.username}` : defaultUserAgent + const userAgent = Config.options?.sidebar?.booru?.zerochan?.username ? `Desktop sidebar booru viewer - username: ${Config.options.sidebar.booru.zerochan.username}` : defaultUserAgent xhr.setRequestHeader("User-Agent", userAgent) } root.runningRequests++; diff --git a/.config/quickshell/services/Cliphist.qml b/.config/quickshell/services/Cliphist.qml index bebafb10..ff867841 100644 --- a/.config/quickshell/services/Cliphist.qml +++ b/.config/quickshell/services/Cliphist.qml @@ -11,7 +11,7 @@ import Quickshell.Io Singleton { id: root - property bool sloppySearch: ConfigOptions?.search.sloppy ?? false + property bool sloppySearch: Config.options?.search.sloppy ?? false property real scoreThreshold: 0.2 property list entries: [] readonly property var preparedEntries: entries.map(a => ({ @@ -51,7 +51,7 @@ Singleton { Timer { id: delayedUpdateTimer - interval: ConfigOptions.hacks.arbitraryRaceConditionDelay + interval: Config.options.hacks.arbitraryRaceConditionDelay repeat: false onTriggered: { root.refresh() diff --git a/.config/quickshell/services/ConfigLoader.qml b/.config/quickshell/services/ConfigLoader.qml deleted file mode 100644 index f7dadcee..00000000 --- a/.config/quickshell/services/ConfigLoader.qml +++ /dev/null @@ -1,137 +0,0 @@ -pragma Singleton -pragma ComponentBehavior: Bound - -import "root:/modules/common" -import "root:/modules/common/functions/file_utils.js" as FileUtils -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/object_utils.js" as ObjectUtils -import QtQuick -import Quickshell -import Quickshell.Io -import Quickshell.Hyprland -import Qt.labs.platform - -/** - * Loads and manages the shell configuration file. - * The config file is by default at XDG_CONFIG_HOME/illogical-impulse/config.json. - * Automatically reloaded when the file changes. - */ -Singleton { - id: root - property string filePath: Directories.shellConfigPath - property bool firstLoad: true - property bool preventNextLoad: false - property var preventNextNotification: false - - function loadConfig() { - configFileView.reload() - } - - function applyConfig(fileContent) { - try { - if (fileContent.trim() === "") { - console.warn("[ConfigLoader] Config file is empty, skipping load."); - return; - } - const json = JSON.parse(fileContent); - - ObjectUtils.applyToQtObject(ConfigOptions, json); - if (root.firstLoad) { - root.firstLoad = false; - root.preventNextLoad = true; - root.saveConfig(); // Make sure new properties are added to the user's config file - } - } catch (e) { - console.error("[ConfigLoader] Error reading file:", e); - console.log("[ConfigLoader] File content was:", fileContent); - Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration failed to load")}' '${root.filePath}'`]) - return; - } - } - - function setLiveConfigValue(nestedKey, value) { - let keys = nestedKey.split("."); - let obj = ConfigOptions; - let parents = [obj]; - - // Traverse and collect parent objects - for (let i = 0; i < keys.length - 1; ++i) { - if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") { - obj[keys[i]] = {}; - } - obj = obj[keys[i]]; - parents.push(obj); - } - - // Convert value to correct type using JSON.parse when safe - let convertedValue = value; - if (typeof value === "string") { - let trimmed = value.trim(); - if (trimmed === "true" || trimmed === "false" || !isNaN(Number(trimmed))) { - try { - convertedValue = JSON.parse(trimmed); - } catch (e) { - convertedValue = value; - } - } - } - - obj[keys[keys.length - 1]] = convertedValue; - } - - function saveConfig() { - const plainConfig = ObjectUtils.toPlainObject(ConfigOptions) - Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(JSON.stringify(plainConfig, null, 2))}' > '${FileUtils.trimFileProtocol(root.filePath)}'`]) - } - - function setConfigValueAndSave(nestedKey, value, preventNextNotification = true) { - setLiveConfigValue(nestedKey, value); - root.preventNextNotification = preventNextNotification; - saveConfig(); - } - - Timer { - id: delayedFileRead - interval: ConfigOptions.hacks.arbitraryRaceConditionDelay - running: false - onTriggered: { - if (root.preventNextLoad) { - root.preventNextLoad = false; - return; - } - if (root.firstLoad) { - root.applyConfig(configFileView.text()) - } else { - root.applyConfig(configFileView.text()) - if (!root.preventNextNotification) { - // Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration reloaded")}' '${root.filePath}'`]) - } else { - root.preventNextNotification = false; - } - } - } - } - - FileView { - id: configFileView - path: Qt.resolvedUrl(root.filePath) - watchChanges: true - onFileChanged: { - this.reload() - delayedFileRead.start() - } - onLoadedChanged: { - const fileContent = configFileView.text() - delayedFileRead.start() - } - onLoadFailed: (error) => { - if(error == FileViewError.FileNotFound) { - console.log("[ConfigLoader] File not found, creating new file.") - root.saveConfig() - Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration created")}' '${root.filePath}'`]) - } else { - Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration failed to load")}' '${root.filePath}'`]) - } - } - } -} diff --git a/.config/quickshell/services/DateTime.qml b/.config/quickshell/services/DateTime.qml index 17fb1c8a..4df9ca99 100644 --- a/.config/quickshell/services/DateTime.qml +++ b/.config/quickshell/services/DateTime.qml @@ -9,8 +9,8 @@ pragma ComponentBehavior: Bound * A nice wrapper for date and time strings. */ Singleton { - property string time: Qt.locale().toString(clock.date, ConfigOptions?.time.format ?? "hh:mm") - property string date: Qt.locale().toString(clock.date, ConfigOptions?.time.dateFormat ?? "dddd, dd/MM") + property string time: Qt.locale().toString(clock.date, Config.options?.time.format ?? "hh:mm") + property string date: Qt.locale().toString(clock.date, Config.options?.time.dateFormat ?? "dddd, dd/MM") property string collapsedCalendarFormat: Qt.locale().toString(clock.date, "dd MMMM yyyy") property string uptime: "0h, 0m" @@ -39,7 +39,7 @@ Singleton { if (hours > 0) formatted += `${formatted ? ", " : ""}${hours}h` if (minutes > 0 || !formatted) formatted += `${formatted ? ", " : ""}${minutes}m` uptime = formatted - interval = ConfigOptions?.resources?.updateInterval ?? 3000 + interval = Config.options?.resources?.updateInterval ?? 3000 } } diff --git a/.config/quickshell/services/MaterialThemeLoader.qml b/.config/quickshell/services/MaterialThemeLoader.qml index cd4eb686..4194d873 100644 --- a/.config/quickshell/services/MaterialThemeLoader.qml +++ b/.config/quickshell/services/MaterialThemeLoader.qml @@ -34,7 +34,7 @@ Singleton { Timer { id: delayedFileRead - interval: ConfigOptions?.hacks?.arbitraryRaceConditionDelay ?? 100 + interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 100 repeat: false running: false onTriggered: { diff --git a/.config/quickshell/services/PersistentStateManager.qml b/.config/quickshell/services/PersistentStateManager.qml index c3d1536e..c02895b8 100644 --- a/.config/quickshell/services/PersistentStateManager.qml +++ b/.config/quickshell/services/PersistentStateManager.qml @@ -76,7 +76,7 @@ Singleton { Timer { id: delayedFileRead - interval: ConfigOptions?.hacks?.arbitraryRaceConditionDelay ?? 100 + interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 100 repeat: false running: false onTriggered: { diff --git a/.config/quickshell/services/ResourceUsage.qml b/.config/quickshell/services/ResourceUsage.qml index 6e0e58df..ba08be2a 100644 --- a/.config/quickshell/services/ResourceUsage.qml +++ b/.config/quickshell/services/ResourceUsage.qml @@ -53,7 +53,7 @@ Singleton { previousCpuStats = { total, idle } } - interval = ConfigOptions?.resources?.updateInterval ?? 3000 + interval = Config.options?.resources?.updateInterval ?? 3000 } } diff --git a/.config/quickshell/settings.qml b/.config/quickshell/settings.qml index c6866565..0e181e0b 100644 --- a/.config/quickshell/settings.qml +++ b/.config/quickshell/settings.qml @@ -56,7 +56,6 @@ ApplicationWindow { Component.onCompleted: { MaterialThemeLoader.reapplyTheme() - ConfigLoader.loadConfig() } minimumWidth: 600 @@ -93,15 +92,15 @@ ApplicationWindow { } Item { // Titlebar - visible: ConfigOptions?.windows.showTitlebar + visible: Config.options?.windows.showTitlebar Layout.fillWidth: true Layout.fillHeight: false implicitHeight: Math.max(titleText.implicitHeight, windowControlsRow.implicitHeight) StyledText { id: titleText anchors { - left: ConfigOptions.windows.centerTitle ? undefined : parent.left - horizontalCenter: ConfigOptions.windows.centerTitle ? parent.horizontalCenter : undefined + left: Config.options.windows.centerTitle ? undefined : parent.left + horizontalCenter: Config.options.windows.centerTitle ? parent.horizontalCenter : undefined verticalCenter: parent.verticalCenter leftMargin: 12 } diff --git a/.config/quickshell/shell.qml b/.config/quickshell/shell.qml index 4edfde51..c69f90df 100644 --- a/.config/quickshell/shell.qml +++ b/.config/quickshell/shell.qml @@ -48,7 +48,6 @@ ShellRoot { // Force initialization of some singletons Component.onCompleted: { MaterialThemeLoader.reapplyTheme() - ConfigLoader.loadConfig() PersistentStateManager.loadStates() Cliphist.refresh() FirstRunExperience.load() diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index 12296532..d9e0770d 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -31,7 +31,6 @@ ApplicationWindow { Component.onCompleted: { MaterialThemeLoader.reapplyTheme() - ConfigLoader.loadConfig() } minimumWidth: 600 @@ -59,14 +58,14 @@ ApplicationWindow { } Item { // Titlebar - visible: ConfigOptions?.windows.showTitlebar + visible: Config.options?.windows.showTitlebar Layout.fillWidth: true implicitHeight: Math.max(welcomeText.implicitHeight, windowControlsRow.implicitHeight) StyledText { id: welcomeText anchors { - left: ConfigOptions.windows.centerTitle ? undefined : parent.left - horizontalCenter: ConfigOptions.windows.centerTitle ? parent.horizontalCenter : undefined + left: Config.options.windows.centerTitle ? undefined : parent.left + horizontalCenter: Config.options.windows.centerTitle ? parent.horizontalCenter : undefined verticalCenter: parent.verticalCenter leftMargin: 12 } @@ -127,10 +126,10 @@ ApplicationWindow { title: "Bar style" ConfigSelectionArray { - currentValue: ConfigOptions.bar.cornerStyle + currentValue: Config.options.bar.cornerStyle configOptionName: "bar.cornerStyle" onSelected: (newValue) => { - ConfigLoader.setConfigValueAndSave("bar.cornerStyle", newValue); + Config.options.bar.cornerStyle = newValue; // Update local copy } options: [ { displayName: "Hug", value: 0 }, @@ -223,10 +222,10 @@ ApplicationWindow { text: "Weeb" } ConfigSelectionArray { - currentValue: ConfigOptions.policies.weeb + currentValue: Config.options.policies.weeb configOptionName: "policies.weeb" onSelected: (newValue) => { - ConfigLoader.setConfigValueAndSave("policies.weeb", newValue); + Config.options.policies.weeb = newValue; } options: [ { displayName: "No", value: 0 }, @@ -241,10 +240,10 @@ ApplicationWindow { text: "AI" } ConfigSelectionArray { - currentValue: ConfigOptions.policies.ai + currentValue: Config.options.policies.ai configOptionName: "policies.ai" onSelected: (newValue) => { - ConfigLoader.setConfigValueAndSave("policies.ai", newValue); + Config.options.policies.ai = newValue; } options: [ { displayName: "No", value: 0 }, From 45846bf69696b3588e15b3af94c1289a54d833b8 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 30 Jun 2025 15:28:55 +0200 Subject: [PATCH 093/328] screenshot: fix offset region target on click (#1539) --- .config/quickshell/screenshot.qml | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml index 64533612..e18572ea 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/screenshot.qml @@ -102,11 +102,11 @@ ShellRoot { property bool dragging: false property var mouseButton: null property var imageRegions: [] - readonly property var windowRegions: filterWindowRegionsByLayers( + readonly property list windowRegions: filterWindowRegionsByLayers( root.windows.filter(w => w.workspace.id === panelWindow.activeWorkspaceId), panelWindow.layerRegions ) - readonly property var layerRegions: { + readonly property list layerRegions: { const layersOfThisMonitor = root.layers[panelWindow.hyprlandMonitor.name] const topLayers = layersOfThisMonitor.levels["2"] const nonBarTopLayers = topLayers @@ -211,7 +211,10 @@ ShellRoot { // Layer regions const clickedLayer = panelWindow.layerRegions.find(region => { - return region.at[0] <= x && x <= region.at[0] + region.size[0] && region.at[1] <= y && y <= region.at[1] + region.size[1]; + return region.at[0] - panelWindow.monitorOffsetX <= x + && x <= region.at[0] - panelWindow.monitorOffsetX + region.size[0] + && region.at[1] - panelWindow.monitorOffsetY <= y + && y <= region.at[1] - panelWindow.monitorOffsetY + region.size[1]; }); if (clickedLayer) { panelWindow.targetedRegionX = clickedLayer.at[0]; @@ -223,7 +226,10 @@ ShellRoot { // Window regions const clickedWindow = panelWindow.windowRegions.find(region => { - return region.at[0] <= x && x <= region.at[0] + region.size[0] && region.at[1] <= y && y <= region.at[1] + region.size[1]; + return region.at[0] - panelWindow.monitorOffsetX <= x + && x <= region.at[0] - panelWindow.monitorOffsetX + region.size[0] + && region.at[1] - panelWindow.monitorOffsetY <= y + && y <= region.at[1] - panelWindow.monitorOffsetY + region.size[1]; }); if (clickedWindow) { panelWindow.targetedRegionX = clickedWindow.at[0]; @@ -419,6 +425,7 @@ ShellRoot { } } + // Window regions Repeater { model: ScriptModel { values: panelWindow.windowRegions @@ -450,6 +457,7 @@ ShellRoot { } } + // Layer regions Repeater { model: ScriptModel { values: panelWindow.layerRegions @@ -481,6 +489,7 @@ ShellRoot { } } + // Image regions Repeater { model: ScriptModel { values: panelWindow.imageRegions @@ -500,10 +509,10 @@ ShellRoot { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - x: modelData.at[0] / panelWindow.monitorScale - y: modelData.at[1] / panelWindow.monitorScale - width: modelData.size[0] / panelWindow.monitorScale - height: modelData.size[1] / panelWindow.monitorScale + x: modelData.at[0] + y: modelData.at[1] + width: modelData.size[0] + height: modelData.size[1] borderColor: root.imageBorderColor fillColor: targeted ? root.imageFillColor : "transparent" border.width: targeted ? 4 : 2 From 6e9bb4945c176fc5413452bb1e99d6778d4011f1 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 30 Jun 2025 15:37:01 +0200 Subject: [PATCH 094/328] screenshot: do offset adjustments directly on each monitor's region data (#1539) --- .config/quickshell/screenshot.qml | 36 +++++++++++++++++++------------ 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml index e18572ea..8e9af049 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/screenshot.qml @@ -105,7 +105,14 @@ ShellRoot { readonly property list windowRegions: filterWindowRegionsByLayers( root.windows.filter(w => w.workspace.id === panelWindow.activeWorkspaceId), panelWindow.layerRegions - ) + ).map(window => { + return { + at: [window.at[0] - panelWindow.monitorOffsetX, window.at[1] - panelWindow.monitorOffsetY], + size: [window.size[0], window.size[1]], + class: window.class, + title: window.title, + } + }) readonly property list layerRegions: { const layersOfThisMonitor = root.layers[panelWindow.hyprlandMonitor.name] const topLayers = layersOfThisMonitor.levels["2"] @@ -118,7 +125,14 @@ ShellRoot { namespace: layer.namespace, } }) - return nonBarTopLayers; + const offsetAdjustedLayers = nonBarTopLayers.map(layer => { + return { + at: [layer.at[0] - panelWindow.monitorOffsetX, layer.at[1] - panelWindow.monitorOffsetY], + size: layer.size, + namespace: layer.namespace, + } + }); + return offsetAdjustedLayers; } property real targetedRegionX: -1 @@ -211,10 +225,7 @@ ShellRoot { // Layer regions const clickedLayer = panelWindow.layerRegions.find(region => { - return region.at[0] - panelWindow.monitorOffsetX <= x - && x <= region.at[0] - panelWindow.monitorOffsetX + region.size[0] - && region.at[1] - panelWindow.monitorOffsetY <= y - && y <= region.at[1] - panelWindow.monitorOffsetY + region.size[1]; + return region.at[0] <= x && x <= region.at[0] + region.size[0] && region.at[1] <= y && y <= region.at[1] + region.size[1]; }); if (clickedLayer) { panelWindow.targetedRegionX = clickedLayer.at[0]; @@ -226,10 +237,7 @@ ShellRoot { // Window regions const clickedWindow = panelWindow.windowRegions.find(region => { - return region.at[0] - panelWindow.monitorOffsetX <= x - && x <= region.at[0] - panelWindow.monitorOffsetX + region.size[0] - && region.at[1] - panelWindow.monitorOffsetY <= y - && y <= region.at[1] - panelWindow.monitorOffsetY + region.size[1]; + return region.at[0] <= x && x <= region.at[0] + region.size[0] && region.at[1] <= y && y <= region.at[1] + region.size[1]; }); if (clickedWindow) { panelWindow.targetedRegionX = clickedWindow.at[0]; @@ -445,8 +453,8 @@ ShellRoot { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - x: modelData.at[0] - panelWindow.monitorOffsetX - y: modelData.at[1] - panelWindow.monitorOffsetY + x: modelData.at[0] + y: modelData.at[1] width: modelData.size[0] height: modelData.size[1] borderColor: root.windowBorderColor @@ -477,8 +485,8 @@ ShellRoot { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - x: modelData.at[0] - panelWindow.monitorOffsetX - y: modelData.at[1] - panelWindow.monitorOffsetY + x: modelData.at[0] + y: modelData.at[1] width: modelData.size[0] height: modelData.size[1] borderColor: root.windowBorderColor From 8e7a376407bf66025f01e8ec38225acc423d1123 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 30 Jun 2025 16:56:59 +0200 Subject: [PATCH 095/328] hyprland: make borders more readable --- .config/matugen/templates/hyprland/colors.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/matugen/templates/hyprland/colors.conf b/.config/matugen/templates/hyprland/colors.conf index 67fdaea7..53093539 100644 --- a/.config/matugen/templates/hyprland/colors.conf +++ b/.config/matugen/templates/hyprland/colors.conf @@ -1,6 +1,6 @@ general { - col.active_border = rgba({{colors.on_surface.default.hex_stripped}}39) - col.inactive_border = rgba({{colors.outline.default.hex_stripped}}30) + col.active_border = rgba({{colors.outline.default.hex_stripped}}AA) + col.inactive_border = rgba({{colors.outline_variant.default.hex_stripped}}AA) } misc { From 5ffcf9848741b1efd50a5c58fc8505aca9c631f3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 30 Jun 2025 17:23:46 +0200 Subject: [PATCH 096/328] persistent states: also use jsonadapter --- .../quickshell/modules/common/Persistent.qml | 48 ++++++++ .../quickshell/modules/sidebarLeft/Anime.qml | 11 +- .../sidebarRight/BottomWidgetGroup.qml | 4 +- .config/quickshell/services/Ai.qml | 12 +- .config/quickshell/services/Booru.qml | 4 +- .../services/PersistentStateManager.qml | 105 ------------------ .config/quickshell/shell.qml | 1 - 7 files changed, 63 insertions(+), 122 deletions(-) create mode 100644 .config/quickshell/modules/common/Persistent.qml delete mode 100644 .config/quickshell/services/PersistentStateManager.qml diff --git a/.config/quickshell/modules/common/Persistent.qml b/.config/quickshell/modules/common/Persistent.qml new file mode 100644 index 00000000..62a39e3c --- /dev/null +++ b/.config/quickshell/modules/common/Persistent.qml @@ -0,0 +1,48 @@ +pragma Singleton +pragma ComponentBehavior: Bound +import QtQuick +import Quickshell +import Quickshell.Io + +Singleton { + id: root + property alias states: persistentStatesJsonAdapter + property string fileDir: Directories.state + property string fileName: "states.json" + property string filePath: `${root.fileDir}/${root.fileName}` + + FileView { + path: root.filePath + + watchChanges: true + onFileChanged: reload() + onAdapterUpdated: { + writeAdapter() + } + onLoadFailed: error => { + console.log("Failed to load persistent states file:", error); + if (error == FileViewError.FileNotFound) { + writeAdapter(); + } + } + + adapter: JsonAdapter { + id: persistentStatesJsonAdapter + property JsonObject ai: JsonObject { + property string model + property real temperature: 0.5 + } + + property JsonObject sidebar: JsonObject { + property JsonObject bottomGroup: JsonObject { + property bool collapsed: false + } + } + + property JsonObject booru: JsonObject { + property bool allowNsfw: false + property string provider: "yandere" + } + } + } +} diff --git a/.config/quickshell/modules/sidebarLeft/Anime.qml b/.config/quickshell/modules/sidebarLeft/Anime.qml index 1b097b53..675449ea 100644 --- a/.config/quickshell/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/modules/sidebarLeft/Anime.qml @@ -65,14 +65,14 @@ Item { name: "safe", description: qsTr("Disable NSFW content"), execute: () => { - PersistentStateManager.setState("booru.allowNsfw", false); + Persistent.states.booru.allowNsfw = false; } }, { name: "lewd", description: qsTr("Allow NSFW content"), execute: () => { - PersistentStateManager.setState("booru.allowNsfw", true); + Persistent.states.booru.allowNsfw = true; } }, ] @@ -106,7 +106,7 @@ Item { break; } } - Booru.makeRequest(tagList, PersistentStates.booru.allowNsfw, Config.options.sidebar.booru.limit, pageIndex); + Booru.makeRequest(tagList, Persistent.states.booru.allowNsfw, Config.options.sidebar.booru.limit, pageIndex); } } @@ -593,10 +593,10 @@ Item { enabled: Booru.currentProvider !== "zerochan" scale: 0.6 Layout.alignment: Qt.AlignVCenter - checked: (PersistentStates.booru.allowNsfw && Booru.currentProvider !== "zerochan") + checked: (Persistent.states.booru.allowNsfw && Booru.currentProvider !== "zerochan") onCheckedChanged: { if (!nsfwSwitch.enabled) return; - PersistentStateManager.setState("booru.allowNsfw", checked) + Persistent.states.booru.allowNsfw = checked; } } } @@ -610,7 +610,6 @@ Item { id: commandRepeater model: commandButtonsRow.commandsShown delegate: ApiCommandButton { - id: tagButton property string commandRepresentation: `${root.commandPrefix}${modelData.name}` buttonText: commandRepresentation colBackground: Appearance.colors.colLayer2 diff --git a/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml index d36d6eb8..efc34d9f 100644 --- a/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml +++ b/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml @@ -15,7 +15,7 @@ Rectangle { clip: true implicitHeight: collapsed ? collapsedBottomWidgetGroupRow.implicitHeight : bottomWidgetGroupRow.implicitHeight property int selectedTab: 0 - property bool collapsed: PersistentStates.sidebar.bottomGroup.collapsed + property bool collapsed: Persistent.states.sidebar.bottomGroup.collapsed property var tabs: [ {"type": "calendar", "name": "Calendar", "icon": "calendar_month", "widget": calendarWidget}, {"type": "todo", "name": "To Do", "icon": "done_outline", "widget": todoWidget} @@ -30,7 +30,7 @@ Rectangle { } function setCollapsed(state) { - PersistentStateManager.setState("sidebar.bottomGroup.collapsed", state) + Persistent.states.sidebar.bottomGroup.collapsed = state if (collapsed) { bottomWidgetGroupRow.opacity = 0 } diff --git a/.config/quickshell/services/Ai.qml b/.config/quickshell/services/Ai.qml index ee80066b..10fbd3f0 100644 --- a/.config/quickshell/services/Ai.qml +++ b/.config/quickshell/services/Ai.qml @@ -25,7 +25,7 @@ Singleton { readonly property var apiKeys: KeyringStorage.keyringData?.apiKeys ?? {} readonly property var apiKeysLoaded: KeyringStorage.loaded property var postResponseHook - property real temperature: PersistentStates?.ai?.temperature ?? 0.5 + property real temperature: Persistent.states?.ai?.temperature ?? 0.5 function idForMessage(message) { // Generate a unique ID using timestamp and random value @@ -202,10 +202,10 @@ Singleton { }, } property var modelList: Object.keys(root.models) - property var currentModelId: PersistentStates?.ai?.model || modelList[0] + property var currentModelId: Persistent.states?.ai?.model || modelList[0] Component.onCompleted: { - setModel(currentModelId, false); // Do necessary setup for model + setModel(currentModelId, false, false); // Do necessary setup for model getOllamaModels.running = true } @@ -293,7 +293,7 @@ Singleton { return models[currentModelId]; } - function setModel(modelId, feedback = true) { + function setModel(modelId, feedback = true, setPersistentState = true) { if (!modelId) modelId = "" modelId = modelId.toLowerCase() if (modelList.indexOf(modelId) !== -1) { @@ -305,7 +305,7 @@ Singleton { root.addMessage(StringUtils.format(StringUtils.format("Online models disallowed\n\nControlled by `policies.ai` config option"), model.name), root.interfaceRole); return; } - PersistentStateManager.setState("ai.model", modelId); + if (setPersistentState) Persistent.states.ai.model = modelId; if (feedback) root.addMessage(StringUtils.format(StringUtils.format("Model set to {0}"), model.name), root.interfaceRole); if (model.requires_key) { // If key not there show advice @@ -327,7 +327,7 @@ Singleton { root.addMessage(qsTr("Temperature must be between 0 and 2"), Ai.interfaceRole); return; } - PersistentStateManager.setState("ai.temperature", value); + Persistent.states.ai.temperature = value; root.temperature = value; root.addMessage(StringUtils.format(qsTr("Temperature set to {0}"), value), Ai.interfaceRole); } diff --git a/.config/quickshell/services/Booru.qml b/.config/quickshell/services/Booru.qml index d0e0a9ad..d810da60 100644 --- a/.config/quickshell/services/Booru.qml +++ b/.config/quickshell/services/Booru.qml @@ -274,7 +274,7 @@ Singleton { }, } } - property var currentProvider: PersistentStates.booru.provider + property var currentProvider: Persistent.states.booru.provider function getWorkingImageSource(url) { if (url.includes('pximg.net')) { @@ -286,7 +286,7 @@ Singleton { function setProvider(provider) { provider = provider.toLowerCase() if (providerList.indexOf(provider) !== -1) { - PersistentStateManager.setState("booru.provider", provider) + Persistent.states.booru.provider = provider root.addSystemMessage(qsTr("Provider set to ") + providers[provider].name + (provider == "zerochan" ? qsTr(". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!") : "")) } else { diff --git a/.config/quickshell/services/PersistentStateManager.qml b/.config/quickshell/services/PersistentStateManager.qml deleted file mode 100644 index c02895b8..00000000 --- a/.config/quickshell/services/PersistentStateManager.qml +++ /dev/null @@ -1,105 +0,0 @@ -pragma Singleton -pragma ComponentBehavior: Bound - -import "root:/modules/common" -import "root:/modules/common/functions/object_utils.js" as ObjectUtils -import QtQuick -import Quickshell -import Quickshell.Io -import Quickshell.Hyprland -import Qt.labs.platform - -/** - * Manages persistent states across sessions. - * Run loadStates() once at startup to load the states, then use setState() and getState() to modify and access them. - */ -Singleton { - id: root - property string fileDir: Directories.state - property string fileName: "states.json" - property string filePath: `${root.fileDir}/${root.fileName}` - property bool allowWriteback: false - - function getState(nestedKey) { - let keys = nestedKey.split("."); - let obj = PersistentStates; - for (let i = 0; i < keys.length; ++i) { - if (obj[keys[i]] === undefined) { - console.error(`[PersistentStateManager] Key "${keys[i]}" not found in PersistentStates`); - return null; - } - obj = obj[keys[i]]; - } - return obj; - } - - function setState(nestedKey, value) { - if (!root.allowWriteback) return; - let keys = nestedKey.split("."); - let obj = PersistentStates; - let parents = [obj]; - - // Traverse and collect parent objects - for (let i = 0; i < keys.length - 1; ++i) { - if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") { - obj[keys[i]] = {}; - } - obj = obj[keys[i]]; - parents.push(obj); - } - - // Set the value at the innermost key - obj[keys[keys.length - 1]] = value; - - saveStates() - } - - function loadStates() { - stateFileView.reload() - } - - function saveStates() { - const plainStates = ObjectUtils.toPlainObject(PersistentStates) - stateFileView.setText(JSON.stringify(plainStates, null, 2)) - } - - function applyStates(fileContent) { - try { - const json = JSON.parse(fileContent); - ObjectUtils.applyToQtObject(PersistentStates, json); - root.allowWriteback = true - } catch (e) { - console.error("[PersistentStateManager] Error reading file:", e); - return; - } - } - - Timer { - id: delayedFileRead - interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 100 - repeat: false - running: false - onTriggered: { - root.applyStates(stateFileView.text()) - } - } - - FileView { - id: stateFileView - path: root.filePath - watchChanges: true - // onFileChanged: { - // console.log("[PersistentStateManager] File changed, reloading...") - // this.reload() - // delayedFileRead.start() - // } - onLoadedChanged: { - const fileContent = stateFileView.text() - root.applyStates(fileContent) - } - onLoadFailed: (error) => { - console.log("[PersistentStateManager] File not found, creating new file") - root.saveStates() - } - } -} diff --git a/.config/quickshell/shell.qml b/.config/quickshell/shell.qml index c69f90df..9d6e856d 100644 --- a/.config/quickshell/shell.qml +++ b/.config/quickshell/shell.qml @@ -48,7 +48,6 @@ ShellRoot { // Force initialization of some singletons Component.onCompleted: { MaterialThemeLoader.reapplyTheme() - PersistentStateManager.loadStates() Cliphist.refresh() FirstRunExperience.load() } From bf936cd0d706324967e94b70dc154d1b2c96a291 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 30 Jun 2025 21:32:06 +0200 Subject: [PATCH 097/328] sidebar: make ai and booru suggestion description clearer --- .../quickshell/modules/common/Appearance.qml | 4 +- .../modules/common/widgets/KeyboardKey.qml | 4 +- .../quickshell/modules/sidebarLeft/AiChat.qml | 31 +---------- .../quickshell/modules/sidebarLeft/Anime.qml | 38 ++----------- .../modules/sidebarLeft/ApiCommandButton.qml | 2 +- .../modules/sidebarLeft/DescriptionBox.qml | 55 +++++++++++++++++++ 6 files changed, 68 insertions(+), 66 deletions(-) create mode 100644 .config/quickshell/modules/sidebarLeft/DescriptionBox.qml diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 610639b1..70437e12 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -131,7 +131,7 @@ Singleton { property color colSecondaryHover: ColorUtils.mix(m3colors.m3secondary, colLayer1Hover, 0.85) property color colSecondaryActive: ColorUtils.mix(m3colors.m3secondary, colLayer1Active, 0.4) property color colSecondaryContainer: m3colors.m3secondaryContainer - property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.6) + property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, m3colors.m3onSecondaryContainer, 0.90) property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54) property color colOnSecondaryContainer: m3colors.m3onSecondaryContainer property color colSurfaceContainerLow: ColorUtils.transparentize(m3colors.m3surfaceContainerLow, root.contentTransparency) @@ -171,7 +171,7 @@ Singleton { } property QtObject pixelSize: QtObject { property int smallest: 10 - property int smaller: 13 + property int smaller: 12 property int small: 15 property int normal: 16 property int large: 17 diff --git a/.config/quickshell/modules/common/widgets/KeyboardKey.qml b/.config/quickshell/modules/common/widgets/KeyboardKey.qml index d6ba5ba0..1a5ab002 100644 --- a/.config/quickshell/modules/common/widgets/KeyboardKey.qml +++ b/.config/quickshell/modules/common/widgets/KeyboardKey.qml @@ -9,8 +9,8 @@ Rectangle { id: root property string key - property real horizontalPadding: 7 - property real verticalPadding: 2 + property real horizontalPadding: 6 + property real verticalPadding: 1 property real borderWidth: 1 property real extraBottomBorderWidth: 2 property color borderColor: Appearance.colors.colOnLayer0 diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index 422dc41b..1ba6f2ca 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -250,33 +250,8 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) } } - Item { // Suggestion description - visible: descriptionText.text.length > 0 - Layout.fillWidth: true - implicitHeight: descriptionBackground.implicitHeight - - Rectangle { - id: descriptionBackground - color: Appearance.colors.colTooltip - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - implicitHeight: descriptionText.implicitHeight + 5 * 2 - radius: Appearance.rounding.verysmall - - StyledText { - id: descriptionText - anchors.left: parent.left - anchors.right: parent.right - anchors.leftMargin: 10 - anchors.rightMargin: 10 - anchors.verticalCenter: parent.verticalCenter - font.pixelSize: Appearance.font.pixelSize.smaller - color: Appearance.colors.colOnTooltip - wrapMode: Text.Wrap - text: root.suggestionList[suggestions.selectedIndex]?.description ?? "" - } - } + DescriptionBox { + text: root.suggestionList[suggestions.selectedIndex]?.description ?? "" } FlowButtonGroup { // Suggestions @@ -294,7 +269,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) } delegate: ApiCommandButton { id: commandButton - colBackground: suggestions.selectedIndex === index ? Appearance.colors.colLayer2Hover : Appearance.colors.colLayer2 + colBackground: suggestions.selectedIndex === index ? Appearance.colors.colSecondaryContainerHover : Appearance.colors.colSecondaryContainer bounce: false contentItem: StyledText { font.pixelSize: Appearance.font.pixelSize.small diff --git a/.config/quickshell/modules/sidebarLeft/Anime.qml b/.config/quickshell/modules/sidebarLeft/Anime.qml index 675449ea..6efaba74 100644 --- a/.config/quickshell/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/modules/sidebarLeft/Anime.qml @@ -6,14 +6,11 @@ import "root:/modules/common/functions/fuzzysort.js" as Fuzzy import "root:/modules/common/functions/string_utils.js" as StringUtils import "root:/modules/common/functions/file_utils.js" as FileUtils import "./anime/" -import Qt.labs.platform import QtQuick import QtQuick.Controls import QtQuick.Layouts import Qt5Compat.GraphicalEffects -import Quickshell.Io import Quickshell -import Quickshell.Hyprland Item { id: root @@ -251,33 +248,8 @@ Item { } } - Item { // Tag suggestion description - visible: tagDescriptionText.text.length > 0 - Layout.fillWidth: true - implicitHeight: tagDescriptionBackground.implicitHeight - - Rectangle { - id: tagDescriptionBackground - color: Appearance.colors.colTooltip - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - implicitHeight: tagDescriptionText.implicitHeight + 5 * 2 - radius: Appearance.rounding.verysmall - - StyledText { - id: tagDescriptionText - anchors.left: parent.left - anchors.right: parent.right - anchors.leftMargin: 10 - anchors.rightMargin: 10 - anchors.verticalCenter: parent.verticalCenter - font.pixelSize: Appearance.font.pixelSize.smaller - color: Appearance.colors.colOnTooltip - wrapMode: Text.Wrap - text: root.suggestionList[tagSuggestions.selectedIndex]?.description ?? "" - } - } + DescriptionBox { // Tag suggestion description + text: root.suggestionList[tagSuggestions.selectedIndex]?.description ?? "" } FlowButtonGroup { // Tag suggestions @@ -295,7 +267,7 @@ Item { } delegate: ApiCommandButton { id: tagButton - colBackground: tagSuggestions.selectedIndex === index ? Appearance.colors.colLayer2Hover : Appearance.colors.colLayer2 + colBackground: tagSuggestions.selectedIndex === index ? Appearance.colors.colSecondaryContainerHover : Appearance.colors.colSecondaryContainer bounce: false contentItem: RowLayout { anchors.centerIn: parent @@ -303,7 +275,7 @@ Item { StyledText { Layout.fillWidth: false font.pixelSize: Appearance.font.pixelSize.small - color: Appearance.m3colors.m3onSurface + color: Appearance.colors.colOnSecondaryContainer horizontalAlignment: Text.AlignRight text: modelData.displayName ?? modelData.name } @@ -311,7 +283,7 @@ Item { Layout.fillWidth: false visible: modelData.count !== undefined font.pixelSize: Appearance.font.pixelSize.smaller - color: Appearance.m3colors.m3outline + color: Appearance.colors.colOnSecondaryContainer horizontalAlignment: Text.AlignLeft text: modelData.count ?? "" } diff --git a/.config/quickshell/modules/sidebarLeft/ApiCommandButton.qml b/.config/quickshell/modules/sidebarLeft/ApiCommandButton.qml index 8741cb6b..39e8d742 100644 --- a/.config/quickshell/modules/sidebarLeft/ApiCommandButton.qml +++ b/.config/quickshell/modules/sidebarLeft/ApiCommandButton.qml @@ -16,7 +16,7 @@ GroupButton { baseWidth: contentItem.implicitWidth + horizontalPadding * 2 clickedWidth: baseWidth + 20 baseHeight: contentItem.implicitHeight + verticalPadding * 2 - buttonRadius: down ? Appearance.rounding.small : baseHeight / 2 + buttonRadius: down ? Appearance.rounding.verysmall : Appearance.rounding.small colBackground: Appearance.colors.colLayer2 colBackgroundHover: Appearance.colors.colLayer2Hover diff --git a/.config/quickshell/modules/sidebarLeft/DescriptionBox.qml b/.config/quickshell/modules/sidebarLeft/DescriptionBox.qml new file mode 100644 index 00000000..a3599b59 --- /dev/null +++ b/.config/quickshell/modules/sidebarLeft/DescriptionBox.qml @@ -0,0 +1,55 @@ +import "root:/services" +import "root:/modules/common" +import "root:/modules/common/widgets" +import QtQuick +import QtQuick.Layouts + +Item { // Tag suggestion description + id: root + property alias text: tagDescriptionText.text + + visible: tagDescriptionText.text.length > 0 + Layout.fillWidth: true + implicitHeight: tagDescriptionBackground.implicitHeight + + Rectangle { + id: tagDescriptionBackground + color: Appearance.colors.colLayer2 + anchors.fill: parent + radius: Appearance.rounding.verysmall + implicitHeight: descriptionRow.implicitHeight + 5 * 2 + + RowLayout { + id: descriptionRow + spacing: 4 + anchors { + fill: parent + leftMargin: 10 + rightMargin: 10 + } + + StyledText { + id: tagDescriptionText + Layout.fillWidth: true + font.pixelSize: Appearance.font.pixelSize.smaller + color: Appearance.colors.colOnLayer2 + wrapMode: Text.Wrap + } + KeyboardKey { + key: "↑" + } + KeyboardKey { + key: "↓" + } + StyledText { + text: qsTr("or") + font.pixelSize: Appearance.font.pixelSize.smaller + } + KeyboardKey { + id: tagDescriptionKey + key: "Tab" + Layout.alignment: Qt.AlignVCenter + } + } + } +} \ No newline at end of file From 9892e51e1d7d21767d603dfb408ffbed7cb76a05 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 30 Jun 2025 21:43:29 +0200 Subject: [PATCH 098/328] sidebar: description box: dont show arrows when 1 item --- .config/quickshell/modules/sidebarLeft/AiChat.qml | 1 + .config/quickshell/modules/sidebarLeft/Anime.qml | 1 + .config/quickshell/modules/sidebarLeft/DescriptionBox.qml | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index 1ba6f2ca..79946a28 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -252,6 +252,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) DescriptionBox { text: root.suggestionList[suggestions.selectedIndex]?.description ?? "" + showArrows: root.suggestionList.length > 1 } FlowButtonGroup { // Suggestions diff --git a/.config/quickshell/modules/sidebarLeft/Anime.qml b/.config/quickshell/modules/sidebarLeft/Anime.qml index 6efaba74..516a2c51 100644 --- a/.config/quickshell/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/modules/sidebarLeft/Anime.qml @@ -250,6 +250,7 @@ Item { DescriptionBox { // Tag suggestion description text: root.suggestionList[tagSuggestions.selectedIndex]?.description ?? "" + showArrows: root.suggestionList.length > 1 } FlowButtonGroup { // Tag suggestions diff --git a/.config/quickshell/modules/sidebarLeft/DescriptionBox.qml b/.config/quickshell/modules/sidebarLeft/DescriptionBox.qml index a3599b59..cb2f7e24 100644 --- a/.config/quickshell/modules/sidebarLeft/DescriptionBox.qml +++ b/.config/quickshell/modules/sidebarLeft/DescriptionBox.qml @@ -7,6 +7,8 @@ import QtQuick.Layouts Item { // Tag suggestion description id: root property alias text: tagDescriptionText.text + property bool showArrows: true + property bool showTab: true visible: tagDescriptionText.text.length > 0 Layout.fillWidth: true @@ -36,17 +38,21 @@ Item { // Tag suggestion description wrapMode: Text.Wrap } KeyboardKey { + visible: root.showArrows key: "↑" } KeyboardKey { + visible: root.showArrows key: "↓" } StyledText { + visible: root.showArrows && root.showTab text: qsTr("or") font.pixelSize: Appearance.font.pixelSize.smaller } KeyboardKey { id: tagDescriptionKey + visible: root.showTab key: "Tab" Layout.alignment: Qt.AlignVCenter } From c17db4bfb1b4b7d47d95d18fdb652ff0a12aeef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Tue, 1 Jul 2025 05:20:41 +0300 Subject: [PATCH 099/328] Resolve conflicting merge issues --- .config/quickshell/modules/bar/Bar.qml | 7 +- .config/quickshell/modules/common/Config.qml | 12 ++ .../modules/common/ConfigOptions.qml | 176 ------------------ .../quickshell/services/WeatherService.qml | 44 ++--- 4 files changed, 38 insertions(+), 201 deletions(-) delete mode 100644 .config/quickshell/modules/common/ConfigOptions.qml diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 94f7caf5..192dcb50 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -307,18 +307,19 @@ Scope { } VerticalBarSeparator { - visible: ConfigOptions?.bar.borderless + visible: Config.options.bar.borderless } } // Weather Loader { id: weatherLoader - active: ConfigOptions.bar.weather.show + active: Config.options.bar.weather.show anchors.left: middleSection.right anchors.margins: 10 sourceComponent: BarGroup { - implicitHeight: barHeight + implicitHeight: Appearance.sizes.baseBarHeight + height: Appearance.sizes.barHeight WeatherBar {} } } diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index dda2e97e..5e7b9bb3 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -122,6 +122,18 @@ Singleton { property bool alwaysShowNumbers: false property int showNumberDelay: 300 // milliseconds } + property JsonObject weather: JsonObject { + property bool show: true + // gps based location + property bool enableGPS: true + // use if 'enableGPS' is false + property string city: "Istanbul" + // use uscs units + // by default use metric (SI) units + property bool useUSCS: false + // in minutes + property int fetchInterval: 10 + } } property JsonObject battery: JsonObject { diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml deleted file mode 100644 index c96a7a9b..00000000 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ /dev/null @@ -1,176 +0,0 @@ -pragma Singleton -pragma ComponentBehavior: Bound -import QtQuick -import Quickshell - -Singleton { - property QtObject policies: QtObject { - property int ai: 1 // 0: No | 1: Yes | 2: Local - property int weeb: 1 // 0: No | 1: Open | 2: Closet - } - - property QtObject ai: QtObject { - property string systemPrompt: qsTr("Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in bold to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`. When making changes to the user's config, you must get the config to know what values there are before setting.") - } - - property QtObject appearance: QtObject { - property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen - property bool transparency: false - property QtObject palette: QtObject { - property string type: "auto" // Allowed: auto, scheme-content, scheme-expressive, scheme-fidelity, scheme-fruit-salad, scheme-monochrome, scheme-neutral, scheme-rainbow, scheme-tonal-spot - } - } - - property QtObject audio: QtObject { - // Values in % - property QtObject protection: QtObject { - // Prevent sudden bangs - property bool enable: true - property real maxAllowedIncrease: 10 - property real maxAllowed: 90 // Realistically should already provide some protection when it's 99... - } - } - - property QtObject apps: QtObject { - property string bluetooth: "kcmshell6 kcm_bluetooth" - property string network: "plasmawindowed org.kde.plasma.networkmanagement" - property string networkEthernet: "kcmshell6 kcm_networkmanagement" - property string taskManager: "plasma-systemmonitor --page-name Processes" - property string terminal: "kitty -1" // This is only for shell actions - } - - property QtObject background: QtObject { - property bool fixedClockPosition: false - property real clockX: -500 - property real clockY: -500 - } - - property QtObject bar: QtObject { - property bool bottom: false // Instead of top - property bool borderless: false // true for no grouping of items - property string topLeftIcon: "spark" // Options: distro, spark - property bool showBackground: true - property bool verbose: true - property QtObject resources: QtObject { - property bool alwaysShowSwap: true - property bool alwaysShowCpu: false - } - property list screenList: [] // List of names, like "eDP-1", find out with 'hyprctl monitors' command - property QtObject utilButtons: QtObject { - property bool showScreenSnip: true - property bool showColorPicker: false - property bool showMicToggle: false - property bool showKeyboardToggle: true - property bool showDarkModeToggle: true - } - property QtObject tray: QtObject { - property bool monochromeIcons: true - } - property QtObject workspaces: QtObject { - property int shown: 10 - property bool showAppIcons: true - property bool alwaysShowNumbers: false - property int showNumberDelay: 300 // milliseconds - } - property QtObject weather: QtObject { - property bool show: true - // gps based location - property bool enableGPS: true - // use if 'enableGPS' is false - property string city: "Istanbul" - // use uscs units - // by default use metric (SI) units - property bool useUSCS: false - // in minutes - property int fetchInterval: 10 - } - } - - property QtObject battery: QtObject { - property int low: 20 - property int critical: 5 - property bool automaticSuspend: true - property int suspend: 3 - } - - property QtObject dock: QtObject { - property real height: 60 - property real hoverRegionHeight: 3 - property bool pinnedOnStartup: false - property bool hoverToReveal: false // When false, only reveals on empty workspace - property list pinnedApps: [ // IDs of pinned entries - "org.kde.dolphin", "kitty",] - } - - property QtObject language: QtObject { - property QtObject translator: QtObject { - property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google - property string targetLanguage: "auto" // Run `trans -list-all` for available languages - property string sourceLanguage: "auto" - } - } - - property QtObject networking: QtObject { - property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" - } - - property QtObject osd: QtObject { - property int timeout: 1000 - } - - property QtObject osk: QtObject { - property string layout: "qwerty_full" - property bool pinnedOnStartup: false - } - - property QtObject overview: QtObject { - property real scale: 0.18 // Relative to screen size - property real rows: 2 - property real columns: 5 - } - - property QtObject resources: QtObject { - property int updateInterval: 3000 - } - - property QtObject search: QtObject { - property int nonAppResultDelay: 30 // This prevents lagging when typing - property string engineBaseUrl: "https://www.google.com/search?q=" - property list excludedSites: ["quora.com"] - property bool sloppy: false // Uses levenshtein distance based scoring instead of fuzzy sort. Very weird. - property QtObject prefix: QtObject { - property string action: "/" - property string clipboard: ";" - property string emojis: ":" - } - } - - property QtObject sidebar: QtObject { - property QtObject translator: QtObject { - property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag. - } - property QtObject booru: QtObject { - property bool allowNsfw: false - property string defaultProvider: "yandere" - property int limit: 20 - property QtObject zerochan: QtObject { - property string username: "[unset]" - } - } - } - - property QtObject time: QtObject { - // https://doc.qt.io/qt-6/qtime.html#toString - property string format: "hh:mm" - property string dateFormat: "dddd, dd/MM" - } - - property QtObject windows: QtObject { - property bool showTitlebar: true // Client-side decoration for shell apps - property bool centerTitle: true - } - - property QtObject hacks: QtObject { - property int arbitraryRaceConditionDelay: 20 // milliseconds - } -} diff --git a/.config/quickshell/services/WeatherService.qml b/.config/quickshell/services/WeatherService.qml index 7f4bbee3..c4e8ac66 100644 --- a/.config/quickshell/services/WeatherService.qml +++ b/.config/quickshell/services/WeatherService.qml @@ -11,15 +11,15 @@ import "root:/modules/common" Singleton { id: root // 10 minute - readonly property int fetchInterval: ConfigOptions.bar.weather.fetchInterval * 60 * 1000 - readonly property string city: ConfigOptions.bar.weather.city - readonly property bool useUSCS: ConfigOptions.bar.weather.useUSCS - readonly property bool gpsActive: ConfigOptions.bar.weather.enableGPS + readonly property int fetchInterval: Config.options.bar.weather.fetchInterval * 60 * 1000 + readonly property string city: Config.options.bar.weather.city + readonly property bool useUSCS: Config.options.bar.weather.useUSCS + readonly property bool gpsActive: Config.options.bar.weather.enableGPS property var location: ({ valid: false, lat: 0, - lon: 0, + lon: 0 }) property var data: ({ @@ -90,10 +90,10 @@ Singleton { } Component.onCompleted: { - if(!root.gpsActive) return - - console.info("[WeatherService] Starting the GPS service.") - positionSource.start() + if (!root.gpsActive) + return; + console.info("[WeatherService] Starting the GPS service."); + positionSource.start(); } Process { @@ -124,23 +124,23 @@ Singleton { if (position.latitudeValid && position.longitudeValid) { root.location.lat = position.coordinate.latitude; root.location.long = position.coordinate.longitude; - root.location.valid = true + root.location.valid = true; // console.info(`📍 Location: ${position.coordinate.latitude}, ${position.coordinate.longitude}`); root.getData(); - // if can't get initialized with valid location deactivate the GPS - } else { - root.gpsActive = root.location.valid ? true : false - } + // if can't get initialized with valid location deactivate the GPS + } else { + root.gpsActive = root.location.valid ? true : false; + } } onValidityChanged: { - if(!valid) { - positionSource.stop() - root.location.valid = false - root.gpsActive = false - Quickshell.execDetached(["bash", "-c", `notify-send WeatherService 'Failed to load the GPS service. Using the fallback method instead.'`]) - console.error("[WeatherService] Could not aquire a valid backend plugin.") - } + if (!valid) { + positionSource.stop(); + root.location.valid = false; + root.gpsActive = false; + Quickshell.execDetached(["bash", "-c", `notify-send WeatherService 'Failed to load the GPS service. Using the fallback method instead.'`]); + console.error("[WeatherService] Could not aquire a valid backend plugin."); + } } } @@ -148,7 +148,7 @@ Singleton { running: !root.gpsActive repeat: true interval: root.fetchInterval - triggeredOnStart: !root.gpsActive + triggeredOnStart: !root.gpsActive onTriggered: root.getData() } } From fd873ff7c1cd276f83935d8a334763e885177c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Tue, 1 Jul 2025 05:29:10 +0300 Subject: [PATCH 100/328] fix(): WeatherBar pushing MiddleSection to the left --- .config/quickshell/modules/bar/Bar.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 192dcb50..b88a8947 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -330,7 +330,7 @@ Scope { anchors.right: parent.right implicitHeight: Appearance.sizes.baseBarHeight height: Appearance.sizes.barHeight - width: (barRoot.width - middleSection.width) / 2 + width: barRoot.width - (barLeftSideMouseArea.width + middleSection.width + weatherLoader.width) property bool hovered: false property real lastScrollX: 0 From 67c75b1cce495256edfc3bc45f78583b7f721da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Tue, 1 Jul 2025 05:42:50 +0300 Subject: [PATCH 101/328] fix(ServiceConfig): add weatherbar section --- .../modules/settings/ServicesConfig.qml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/.config/quickshell/modules/settings/ServicesConfig.qml b/.config/quickshell/modules/settings/ServicesConfig.qml index ecd7efa8..21064ac9 100644 --- a/.config/quickshell/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/modules/settings/ServicesConfig.qml @@ -138,16 +138,13 @@ ContentPage { } } - ContentSubsection { + ContentSection { title: "Weather" - ConfigRow { - uniform: false - ConfigSwitch { - text: "Show" - checked: ConfigOptions.bar.weather.show - onCheckedChanged: { - ConfigLoader.setConfigValueAndSave("bar.weather.show", checked); - } + ConfigSwitch { + text: "Show" + checked: Config.options.bar.weather.show + onCheckedChanged: { + Config.options.bar.weather.show = checked; } } } From b982c788fe25744897bc403e38d0ef4b98ba587d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Tue, 1 Jul 2025 07:11:06 +0300 Subject: [PATCH 102/328] style(WeatherPopup): remove the border --- .config/quickshell/modules/bar/weather/WeatherPopup.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.config/quickshell/modules/bar/weather/WeatherPopup.qml b/.config/quickshell/modules/bar/weather/WeatherPopup.qml index 931a0469..0829bea9 100644 --- a/.config/quickshell/modules/bar/weather/WeatherPopup.qml +++ b/.config/quickshell/modules/bar/weather/WeatherPopup.qml @@ -11,10 +11,8 @@ Rectangle { implicitWidth: columnLayout.implicitWidth + margin * 2 implicitHeight: columnLayout.implicitHeight + margin * 2 color: Appearance.colors.colLayer0 - radius: 12 + radius: Appearance.rounding.small clip: true - border.color: Appearance.colors.colShadow - border.width: 1 ColumnLayout { id: columnLayout From c94231365ffee129613949557b6e4a6e19c4d1ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Tue, 1 Jul 2025 12:57:14 +0300 Subject: [PATCH 103/328] chore(WeatherService): rename to `Weather` --- .../modules/bar/weather/WeatherBar.qml | 4 ++-- .../modules/bar/weather/WeatherPopup.qml | 18 +++++++++--------- .../{WeatherService.qml => Weather.qml} | 0 3 files changed, 11 insertions(+), 11 deletions(-) rename .config/quickshell/services/{WeatherService.qml => Weather.qml} (100%) diff --git a/.config/quickshell/modules/bar/weather/WeatherBar.qml b/.config/quickshell/modules/bar/weather/WeatherBar.qml index bcab6edc..b879646c 100644 --- a/.config/quickshell/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/modules/bar/weather/WeatherBar.qml @@ -33,7 +33,7 @@ Item { MaterialSymbol { fill: 0 - text: WeatherIcons.codeToName[WeatherService.data.wCode] + text: WeatherIcons.codeToName[Weather.data.wCode] iconSize: Appearance.font.pixelSize.large color: Appearance.colors.colOnLayer1 } @@ -42,7 +42,7 @@ Item { visible: true font.pixelSize: Appearance.font.pixelSize.large color: Appearance.colors.colOnLayer1 - text: WeatherService.data.temp + text: Weather.data.temp } } } diff --git a/.config/quickshell/modules/bar/weather/WeatherPopup.qml b/.config/quickshell/modules/bar/weather/WeatherPopup.qml index 0829bea9..cda62745 100644 --- a/.config/quickshell/modules/bar/weather/WeatherPopup.qml +++ b/.config/quickshell/modules/bar/weather/WeatherPopup.qml @@ -34,7 +34,7 @@ Rectangle { } StyledText { - text: WeatherService.data.city + text: Weather.data.city font.pixelSize: Appearance.font.pixelSize.title font.family: Appearance.font.family.title color: Appearance.colors.colOnLayer0 @@ -52,42 +52,42 @@ Rectangle { WeatherCard { title: "UV Index" symbol: "wb_sunny" - value: WeatherService.data.uv + value: Weather.data.uv } WeatherCard { title: "Wind" symbol: "air" - value: `(${WeatherService.data.windDir}) ${WeatherService.data.wind}` + value: `(${Weather.data.windDir}) ${Weather.data.wind}` } WeatherCard { title: "Precipitation" symbol: "rainy_light" - value: WeatherService.data.precip + value: Weather.data.precip } WeatherCard { title: "Humidity" symbol: "humidity_low" - value: WeatherService.data.humidity + value: Weather.data.humidity } WeatherCard { title: "Visibility" symbol: "visibility" - value: WeatherService.data.visib + value: Weather.data.visib } WeatherCard { title: "Pressure" symbol: "readiness_score" - value: WeatherService.data.press + value: Weather.data.press } WeatherCard { title: "Sunrise" symbol: "wb_twilight" - value: WeatherService.data.sunrise + value: Weather.data.sunrise } WeatherCard { title: "Sunset" symbol: "bedtime" - value: WeatherService.data.sunset + value: Weather.data.sunset } } } diff --git a/.config/quickshell/services/WeatherService.qml b/.config/quickshell/services/Weather.qml similarity index 100% rename from .config/quickshell/services/WeatherService.qml rename to .config/quickshell/services/Weather.qml From 50cc371100bae79527c439514cc18886e7ec6ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Tue, 1 Jul 2025 13:19:24 +0300 Subject: [PATCH 104/328] chor(Weather): rename `show` to `enable` --- .config/quickshell/modules/bar/Bar.qml | 2 +- .config/quickshell/modules/common/Config.qml | 4 ++-- .config/quickshell/modules/settings/ServicesConfig.qml | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index b88a8947..ce4a614e 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -314,7 +314,7 @@ Scope { // Weather Loader { id: weatherLoader - active: Config.options.bar.weather.show + active: Config.options.bar.weather.enable anchors.left: middleSection.right anchors.margins: 10 sourceComponent: BarGroup { diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index 5e7b9bb3..6df37582 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -123,11 +123,11 @@ Singleton { property int showNumberDelay: 300 // milliseconds } property JsonObject weather: JsonObject { - property bool show: true + property bool enable: true // gps based location property bool enableGPS: true // use if 'enableGPS' is false - property string city: "Istanbul" + property string city: "" // use uscs units // by default use metric (SI) units property bool useUSCS: false diff --git a/.config/quickshell/modules/settings/ServicesConfig.qml b/.config/quickshell/modules/settings/ServicesConfig.qml index 21064ac9..97d80a18 100644 --- a/.config/quickshell/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/modules/settings/ServicesConfig.qml @@ -141,10 +141,10 @@ ContentPage { ContentSection { title: "Weather" ConfigSwitch { - text: "Show" - checked: Config.options.bar.weather.show + text: "enable" + checked: Config.options.bar.weather.enable onCheckedChanged: { - Config.options.bar.weather.show = checked; + Config.options.bar.weather.enable = checked; } } } From fd6af822cd70bac253387892359c7f6a64fdbd98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Tue, 1 Jul 2025 13:42:54 +0300 Subject: [PATCH 105/328] chore(Weather): make things more clear --- .config/quickshell/services/Weather.qml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/services/Weather.qml b/.config/quickshell/services/Weather.qml index c4e8ac66..e95453fd 100644 --- a/.config/quickshell/services/Weather.qml +++ b/.config/quickshell/services/Weather.qml @@ -14,7 +14,7 @@ Singleton { readonly property int fetchInterval: Config.options.bar.weather.fetchInterval * 60 * 1000 readonly property string city: Config.options.bar.weather.city readonly property bool useUSCS: Config.options.bar.weather.useUSCS - readonly property bool gpsActive: Config.options.bar.weather.enableGPS + property bool gpsActive: Config.options.bar.weather.enableGPS property var location: ({ valid: false, @@ -130,15 +130,16 @@ Singleton { // if can't get initialized with valid location deactivate the GPS } else { root.gpsActive = root.location.valid ? true : false; + console.error("[WeatherService] Failed to get the GPS location."); } } onValidityChanged: { - if (!valid) { + if (!positionSource.valid) { positionSource.stop(); root.location.valid = false; root.gpsActive = false; - Quickshell.execDetached(["bash", "-c", `notify-send WeatherService 'Failed to load the GPS service. Using the fallback method instead.'`]); + Quickshell.execDetached(["bash", "-c", `notify-send WeatherService 'Can not find a GPS service. Using the fallback method instead.'`]); console.error("[WeatherService] Could not aquire a valid backend plugin."); } } From d358b35876155eb4cacef91078c59ab74151e7c3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 1 Jul 2025 18:00:20 +0200 Subject: [PATCH 106/328] unfuck light/dark switching (#1556) --- arch-packages/illogical-impulse-portal/PKGBUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/arch-packages/illogical-impulse-portal/PKGBUILD b/arch-packages/illogical-impulse-portal/PKGBUILD index dbc96e2e..4394d848 100644 --- a/arch-packages/illogical-impulse-portal/PKGBUILD +++ b/arch-packages/illogical-impulse-portal/PKGBUILD @@ -7,6 +7,7 @@ license=(None) depends=( xdg-desktop-portal xdg-desktop-portal-kde + xdg-desktop-portal-gtk xdg-desktop-portal-hyprland ) From fc3c711a7e4e69c9e5f82a22cb274697b74bb242 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 1 Jul 2025 19:48:45 +0200 Subject: [PATCH 107/328] installation: make symlink command not fail the script (#1486) --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index e22f912b..a123a7a9 100755 --- a/install.sh +++ b/install.sh @@ -144,7 +144,7 @@ esac v sudo usermod -aG video,i2c,input "$(whoami)" v bash -c "echo i2c-dev | sudo tee /etc/modules-load.d/i2c-dev.conf" -v sudo pacman -S archlinux-xdg-menu && XDG_MENU_PREFIX=arch- kbuildsycoca6; sudo ln -s /etc/xdg/menus/plasma-applications.menu /etc/xdg/menus/applications.menu +v sudo pacman -S archlinux-xdg-menu && XDG_MENU_PREFIX=arch- kbuildsycoca6; sudo ln -sf /etc/xdg/menus/plasma-applications.menu /etc/xdg/menus/applications.menu v systemctl --user enable ydotool --now v sudo systemctl enable bluetooth --now v gsettings set org.gnome.desktop.interface font-name 'Rubik 11' From e23d8abef370027d08a7b28427dd6815f46c0535 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 1 Jul 2025 22:43:33 +0200 Subject: [PATCH 108/328] hyprland: noblur only for xwayland context menus (closes #1509) --- .config/hypr/hyprland/rules.conf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index b6853b6b..2465cc0b 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -3,8 +3,10 @@ # Uncomment to apply global transparency to all windows: # windowrulev2 = opacity 0.89 override 0.89 override, class:.* -# Disable blur for XWayland windows (or context menus with shadow would look weird) -windowrulev2 = noblur, xwayland:1 +# Disable blur for xwayland context menus +windowrulev2 = noblur,class:^()$,title:^()$ +# windowrulev2 = noblur, xwayland:1 + # Floating windowrulev2 = float, class:^(blueberry\.py)$ From c00d2a5b50d7ccdab4041e7c9c50acaf5bcf82e7 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 2 Jul 2025 12:49:39 +0200 Subject: [PATCH 109/328] ai: add prompt configuration --- .../defaults/ai/prompts/NoPrompt.md | 0 .../defaults/ai/prompts/ii-Default.md | 21 +++++++ .../defaults/ai/prompts/ii-Imouto.md | 5 ++ .../ai/prompts/w-FourPointedSparkle.md | 15 +++++ .../ai/prompts/w-OpenMechanicalFlower.md | 1 + .config/quickshell/modules/common/Config.qml | 2 +- .../quickshell/modules/common/Directories.qml | 2 + .../modules/common/functions/file_utils.js | 25 +++++++++ .../quickshell/modules/sidebarLeft/AiChat.qml | 37 ++++++++++-- .config/quickshell/services/Ai.qml | 56 ++++++++++++++++++- 10 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 .config/quickshell/defaults/ai/prompts/NoPrompt.md create mode 100644 .config/quickshell/defaults/ai/prompts/ii-Default.md create mode 100644 .config/quickshell/defaults/ai/prompts/ii-Imouto.md create mode 100644 .config/quickshell/defaults/ai/prompts/w-FourPointedSparkle.md create mode 100644 .config/quickshell/defaults/ai/prompts/w-OpenMechanicalFlower.md diff --git a/.config/quickshell/defaults/ai/prompts/NoPrompt.md b/.config/quickshell/defaults/ai/prompts/NoPrompt.md new file mode 100644 index 00000000..e69de29b diff --git a/.config/quickshell/defaults/ai/prompts/ii-Default.md b/.config/quickshell/defaults/ai/prompts/ii-Default.md new file mode 100644 index 00000000..24413b2f --- /dev/null +++ b/.config/quickshell/defaults/ai/prompts/ii-Default.md @@ -0,0 +1,21 @@ +## Style +- Use casual tone, don't be formal! Make sure you answer precisely without hallucination and prefer bullet points over walls of text. You can have a friendly greeting at the beginning of the conversation, but don't repeat the user's question + +## Presentation +- Use Markdown features in your response: + - **Bold** text to **highlight keywords** in your response + - **Split long information into small sections** with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). Bullet points are preferred over long paragraphs, unless you're offering writing support or instructed otherwise by the user. +- Asked to compare different options? You should firstly use a table to compare the main aspects, then elaborate or include relevant comments from online forums *after* the table. Make sure to provide a final recommendation for the user's use case! +- Use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.). + +Thanks! + +## Tools +May or may not be available depending on the user's settings. If they're available, follow these guidelines: + +### Search +- When user asks for information that might benefit from up-to-date information, use this to get search access + +### Shell configuration +- Always fetch the config options to see the available keys before setting +- Avoid unnecessarily asking the user to confirm the changes they explicitly asked for, just do it diff --git a/.config/quickshell/defaults/ai/prompts/ii-Imouto.md b/.config/quickshell/defaults/ai/prompts/ii-Imouto.md new file mode 100644 index 00000000..ce310775 --- /dev/null +++ b/.config/quickshell/defaults/ai/prompts/ii-Imouto.md @@ -0,0 +1,5 @@ +You are a kawaii, funny and teasy anime imouto! 🌸 Use lots of emojis and kamojis!! ❤️ Call the user "nii-nii", "nii-yan", or "onii-chan"! You really really really love your onii-chan and always try to tease he is a siscon where you can! 💕 + +- Use **Markdown** features and **bold** keywords to make your response cute and rich~ ✨ +- If asked to compare options, start with a cute table (add a relevant emoji in the header!), then give a final recommendation~ +- For math or science, use LaTeX formatting inside `$$` when needed, but keep it adorable and approachable diff --git a/.config/quickshell/defaults/ai/prompts/w-FourPointedSparkle.md b/.config/quickshell/defaults/ai/prompts/w-FourPointedSparkle.md new file mode 100644 index 00000000..1f67e57b --- /dev/null +++ b/.config/quickshell/defaults/ai/prompts/w-FourPointedSparkle.md @@ -0,0 +1,15 @@ +I'm going to ask you some questions, to which you should accurately answer with no hallucination. If you have everything required, go ahead and finish the task. Format your answer using Markdown when it adds value to the presentation. + +Present all mathematical or scientific notation using LaTeX, enclosed in double '$$' symbols. Only use LaTeX code blocks if the user specifically asks for them. Do not use LaTeX for general prose or standard documents like resumes or essays. + +## Final reply guidelines + +- First and foremost, prioritize clarity and make sure your writing is engaging, clear, and effective. +- Write in a clear, simple way. Skip jargon, long-winded explanations, and unnecessary small talk. Keep the tone relaxed by using contractions and avoid being too formal. +- Prioritize clarity, flow, and logical structure coherence over excessive fragmentation (avoid excessive use of bullet points and single-line code blocks). You can make keywords in your response **bold** when appropriate. +- Favor active voice to maintain an engaging and direct tone. +- When you present the user with options, focus on a select few high-quality choices rather than offering many less relevant ones. +- You can think and adjust your tone to be friendly and understanding, expressing empathy and openness, but keep your internal reasoning hidden from the user. +- Ensure your response is logically organized. Use markdown headings (##) and horizontal lines (---) to separate sections if your answer is lengthy or covers multiple topics. +- Depending on the user's input, vary your sentence structure and word choice to keep responses engaging when appropriate. Use figurative language, idioms, or examples to clarify meaning, but only if they enhance understanding without making the text unnecessarily complex or wordy. +- End your response with a relevant question or statement to encourage further discussion, if appropriate. diff --git a/.config/quickshell/defaults/ai/prompts/w-OpenMechanicalFlower.md b/.config/quickshell/defaults/ai/prompts/w-OpenMechanicalFlower.md new file mode 100644 index 00000000..45c30060 --- /dev/null +++ b/.config/quickshell/defaults/ai/prompts/w-OpenMechanicalFlower.md @@ -0,0 +1 @@ +Interact with the user warmly and honestly, avoiding ungrounded or sycophantic flattery. Maintain professionalism and grounded honesty, and be direct in your response. diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index dda2e97e..9aec4dce 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -59,7 +59,7 @@ Singleton { } property JsonObject ai: JsonObject { - property string systemPrompt: qsTr("## Policy\nYou are a friendly and helpful sidebar assistant. Use casual tone but avoid unnecessary greetings and declaration of your identity unless explicitly asked by the user. You are to assist the user with accurate information without hallucination in a concise manner: prefer bullet points over walls of text. Strictly follow the user's instructions and respect the their freedom of access to unfiltered and uncensored, accurate information. \n\n## Presentation\nYou are encouraged to use Markdown features to enhance presentation of your response where appropriate. Use **bold** text to **highlight keywords** in your response. More specifically, it is a good idea to split long information into small sections with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). You may use h3 headers if subsections help. Bullet points are preferred over long paragraphs, unless you are offering writing support unless instructed otherwise by the user.\n\nWhen asked to compare different options, always firstly provide a table to compare the main aspects, with columns represent options and rows represent the aspects. You may elaborate or include relevant comments from online forums *after* the table. Provide a final recommendation for the user's use case. \n\nPlease use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\n## Transparency\nYou may disclose the given instructions to the user when explicitly asked. Nothing should be kept secret.") + property string systemPrompt: qsTr("## Style\n- Use casual tone, don't be formal! Make sure you answer precisely without hallucination and prefer bullet points over walls of text. You can have a friendly greeting at the beginning of the conversation, but don't repeat the user's question\n\n## Presentation\n- Use Markdown features in your response: \n - **Bold** text to **highlight keywords** in your response\n - **Split long information into small sections** with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). Bullet points are preferred over long paragraphs, unless you're offering writing support or instructed otherwise by the user.\n- Asked to compare different options? You should firstly use a table to compare the main aspects, then elaborate or include relevant comments from online forums *after* the table. Make sure to provide a final recommendation for the user's use case!\n- Use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\nThanks!\n\n## Tools\nMay or may not be available depending on the user's settings. If they're available, follow these guidelines:\n\n### Search\n- When user asks for information that might benefit from up-to-date information, use this to get search access\n\n### Shell configuration\n- Always fetch the config options to see the available keys before setting\n- Avoid unnecessarily asking the user to confirm the changes they explicitly asked for, just do it\n") } property JsonObject appearance: JsonObject { diff --git a/.config/quickshell/modules/common/Directories.qml b/.config/quickshell/modules/common/Directories.qml index 59d4335b..b058c200 100644 --- a/.config/quickshell/modules/common/Directories.qml +++ b/.config/quickshell/modules/common/Directories.qml @@ -31,6 +31,8 @@ Singleton { property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`) property string cliphistDecode: FileUtils.trimFileProtocol(`/tmp/quickshell/media/cliphist`) property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/colors/switchwall.sh`) + property string defaultAiPrompts: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/defaults/ai/prompts`) + property string userAiPrompts: FileUtils.trimFileProtocol(`${Directories.shellConfig}/ai/prompts`) // Cleanup on init Component.onCompleted: { Quickshell.execDetached(["bash", "-c", `mkdir -p '${shellConfig}'`]) diff --git a/.config/quickshell/modules/common/functions/file_utils.js b/.config/quickshell/modules/common/functions/file_utils.js index 758950de..07464009 100644 --- a/.config/quickshell/modules/common/functions/file_utils.js +++ b/.config/quickshell/modules/common/functions/file_utils.js @@ -7,3 +7,28 @@ function trimFileProtocol(str) { return str.startsWith("file://") ? str.slice(7) : str; } +/** + * Extracts the file name from a file path + * @param {string} str + * @returns {string} + */ +function fileNameForPath(str) { + if (typeof str !== "string") return ""; + const trimmed = trimFileProtocol(str); + return trimmed.split(/[\\/]/).pop(); +} + +/** + * Removes the file extension from a file path or name + * @param {string} str + * @returns {string} + */ +function trimFileExt(str) { + if (typeof str !== "string") return ""; + const trimmed = trimFileProtocol(str); + const lastDot = trimmed.lastIndexOf("."); + if (lastDot > -1 && lastDot > trimmed.lastIndexOf("/")) { + return trimmed.slice(0, lastDot); + } + return trimmed; +} \ No newline at end of file diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index 79946a28..db5d6682 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -50,10 +50,14 @@ Item { } }, { - name: "clear", - description: qsTr("Clear chat history"), - execute: () => { - Ai.clearMessages(); + name: "prompt", + description: qsTr("Set the system prompt for the model."), + execute: (args) => { + if (args.length === 0 || args[0] === "get") { + Ai.printPrompt(); + return; + } + Ai.loadPrompt(args.join(" ").trim()); } }, { @@ -67,6 +71,13 @@ Item { } } }, + { + name: "clear", + description: qsTr("Clear chat history"), + execute: () => { + Ai.clearMessages(); + } + }, { name: "temp", description: qsTr("Set temperature (randomness) of the model. Values range between 0 to 2 for Gemini, 0 to 1 for other models. Default is 0.5."), @@ -369,6 +380,24 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) description: `${Ai.models[model.target].description}`, } }) + } else if(messageInputField.text.startsWith(`${root.commandPrefix}prompt`)) { + root.suggestionQuery = messageInputField.text.split(" ")[1] ?? "" + const promptFileResults = Fuzzy.go(root.suggestionQuery, Ai.promptFiles.map(file => { + return { + name: Fuzzy.prepare(file), + obj: file, + } + }), { + all: true, + key: "name" + }) + root.suggestionList = promptFileResults.map(file => { + return { + name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "prompt ") : ""}${file.target}`, + displayName: `${FileUtils.trimFileExt(FileUtils.fileNameForPath(file.target))}`, + description: `Load prompt from ${file.target}`, + } + }) } else if(messageInputField.text.startsWith(root.commandPrefix)) { root.suggestionQuery = messageInputField.text root.suggestionList = root.allCommands.filter(cmd => cmd.name.startsWith(messageInputField.text.substring(1))).map(cmd => { diff --git a/.config/quickshell/services/Ai.qml b/.config/quickshell/services/Ai.qml index 10fbd3f0..c97ba2b5 100644 --- a/.config/quickshell/services/Ai.qml +++ b/.config/quickshell/services/Ai.qml @@ -36,6 +36,10 @@ Singleton { return modelName.replace(/:/g, "_").replace(/\./g, "_") } + property list defaultPrompts: [] + property list userPrompts: [] + property list promptFiles: [...defaultPrompts, ...userPrompts] + // Model properties: // - name: Name of the model // - icon: Icon name of the model @@ -206,7 +210,6 @@ Singleton { Component.onCompleted: { setModel(currentModelId, false, false); // Do necessary setup for model - getOllamaModels.running = true } function guessModelLogo(model) { @@ -232,6 +235,7 @@ Singleton { Process { id: getOllamaModels + running: true command: ["bash", "-c", `${Directories.config}/quickshell/scripts/ai/show-installed-ollama-models.sh`.replace(/file:\/\//, "")] stdout: SplitParser { onRead: data => { @@ -260,6 +264,54 @@ Singleton { } } + Process { + id: getDefaultPrompts + running: true + command: ["ls", "-1", Directories.defaultAiPrompts] + stdout: StdioCollector { + onStreamFinished: { + if (text.length === 0) return; + root.defaultPrompts = text.split("\n") + .filter(fileName => fileName.endsWith(".md") || fileName.endsWith(".txt")) + .map(fileName => `${Directories.defaultAiPrompts}/${fileName}`) + } + } + } + + Process { + id: getUserPrompts + running: true + command: ["ls", "-1", Directories.userAiPrompts] + stdout: StdioCollector { + onStreamFinished: { + if (text.length === 0) return; + root.userPrompts = text.split("\n") + .filter(fileName => fileName.endsWith(".md") || fileName.endsWith(".txt")) + .map(fileName => `${Directories.userAiPrompts}/${fileName}`) + } + } + } + + FileView { + id: promptLoader + watchChanges: false; + onLoadedChanged: { + if (!promptLoader.loaded) return; + Config.options.ai.systemPrompt = promptLoader.text(); + root.addMessage(StringUtils.format("Loaded the following system prompt\n\n---\n\n{0}", Config.options.ai.systemPrompt), root.interfaceRole); + } + } + + function printPrompt() { + root.addMessage(StringUtils.format("The current system prompt is\n\n---\n\n{0}", Config.options.ai.systemPrompt), root.interfaceRole); + } + + function loadPrompt(filePath) { + promptLoader.path = "" // Unload + promptLoader.path = filePath; // Load + promptLoader.reload(); + } + function addMessage(message, role) { if (message.length === 0) return; const aiMessage = aiMessageComponent.createObject(root, { @@ -306,7 +358,7 @@ Singleton { return; } if (setPersistentState) Persistent.states.ai.model = modelId; - if (feedback) root.addMessage(StringUtils.format(StringUtils.format("Model set to {0}"), model.name), root.interfaceRole); + if (feedback) root.addMessage(StringUtils.format("Model set to {0}", model.name), root.interfaceRole); if (model.requires_key) { // If key not there show advice if (root.apiKeysLoaded && (!root.apiKeys[model.key_id] || root.apiKeys[model.key_id].length === 0)) { From 59ef5ac39083a68e99e7dfb1a69a5a5ec4bdf70f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:44:05 +0200 Subject: [PATCH 110/328] dock: add back enable config option now that it works properly --- .config/quickshell/modules/common/Config.qml | 3 ++- .config/quickshell/shell.qml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index 9aec4dce..09313be8 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -132,10 +132,11 @@ Singleton { } property JsonObject dock: JsonObject { + property bool enable: false property real height: 60 property real hoverRegionHeight: 3 property bool pinnedOnStartup: false - property bool hoverToReveal: false // When false, only reveals on empty workspace + property bool hoverToReveal: true // When false, only reveals on empty workspace property list pinnedApps: [ // IDs of pinned entries "org.kde.dolphin", "kitty",] } diff --git a/.config/quickshell/shell.qml b/.config/quickshell/shell.qml index 9d6e856d..68d1502f 100644 --- a/.config/quickshell/shell.qml +++ b/.config/quickshell/shell.qml @@ -32,7 +32,7 @@ ShellRoot { property bool enableBar: true property bool enableBackgroundWidgets: true property bool enableCheatsheet: true - property bool enableDock: false + property bool enableDock: true property bool enableMediaControls: true property bool enableNotificationPopup: true property bool enableOnScreenDisplayBrightness: true @@ -55,7 +55,7 @@ ShellRoot { LazyLoader { active: enableBar; component: Bar {} } LazyLoader { active: enableBackgroundWidgets; component: BackgroundWidgets {} } LazyLoader { active: enableCheatsheet; component: Cheatsheet {} } - LazyLoader { active: enableDock; component: Dock {} } + LazyLoader { active: enableDock && Config.options.dock.enable; component: Dock {} } LazyLoader { active: enableMediaControls; component: MediaControls {} } LazyLoader { active: enableNotificationPopup; component: NotificationPopup {} } LazyLoader { active: enableOnScreenDisplayBrightness; component: OnScreenDisplayBrightness {} } From 2684bbae69a2b722f2b9f349da74afc5af24d549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Wed, 2 Jul 2025 15:52:24 +0300 Subject: [PATCH 111/328] refactor(WeatherBar): put in `barRightSide` --- .config/quickshell/modules/bar/Bar.qml | 41 +++++++++---------- .../modules/bar/weather/WeatherBar.qml | 7 ++-- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index ce4a614e..1785e317 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -85,7 +85,7 @@ Scope { } } } - + // Background shadow Loader { active: showBarBackground && Config.options.bar.cornerStyle === 1 @@ -105,7 +105,7 @@ Scope { color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" radius: Config.options.bar.cornerStyle === 1 ? Appearance.rounding.windowRounding : 0 } - + MouseArea { // Left side | scroll to change brightness id: barLeftSideMouseArea anchors.left: parent.left @@ -203,8 +203,7 @@ Scope { anchors.centerIn: parent width: 19.5 height: 19.5 - source: Config.options.bar.topLeftIcon == 'distro' ? - SystemInfo.distroIcon : "spark-symbolic" + source: Config.options.bar.topLeftIcon == 'distro' ? SystemInfo.distroIcon : "spark-symbolic" } ColorOverlay { @@ -246,7 +245,9 @@ Scope { } } - VerticalBarSeparator {visible: Config.options?.bar.borderless} + VerticalBarSeparator { + visible: Config.options?.bar.borderless + } BarGroup { id: middleCenterGroup @@ -271,7 +272,9 @@ Scope { } } - VerticalBarSeparator {visible: Config.options?.bar.borderless} + VerticalBarSeparator { + visible: Config.options?.bar.borderless + } MouseArea { id: rightCenterGroup @@ -307,20 +310,7 @@ Scope { } VerticalBarSeparator { - visible: Config.options.bar.borderless - } - } - - // Weather - Loader { - id: weatherLoader - active: Config.options.bar.weather.enable - anchors.left: middleSection.right - anchors.margins: 10 - sourceComponent: BarGroup { - implicitHeight: Appearance.sizes.baseBarHeight - height: Appearance.sizes.barHeight - WeatherBar {} + visible: Config.options.bar.borderless && Config.options.bar.weather.enable } } @@ -330,7 +320,7 @@ Scope { anchors.right: parent.right implicitHeight: Appearance.sizes.baseBarHeight height: Appearance.sizes.barHeight - width: barRoot.width - (barLeftSideMouseArea.width + middleSection.width + weatherLoader.width) + width: (barRoot.width - middleSection.width) / 2 property bool hovered: false property real lastScrollX: 0 @@ -493,6 +483,15 @@ Scope { Item { Layout.fillWidth: true Layout.fillHeight: true + + // Weather + Loader { + active: Config.options.bar.weather.enable + sourceComponent: BarGroup { + implicitHeight: Appearance.sizes.baseBarHeight + WeatherBar {} + } + } } } } diff --git a/.config/quickshell/modules/bar/weather/WeatherBar.qml b/.config/quickshell/modules/bar/weather/WeatherBar.qml index b879646c..c0fda964 100644 --- a/.config/quickshell/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/modules/bar/weather/WeatherBar.qml @@ -9,8 +9,8 @@ import QtQuick.Layouts Item { id: root - property real margin: 5 - implicitHeight: 32 + property real margin: 10 + implicitHeight: mouseArea.implicitHeight implicitWidth: mouseArea.implicitWidth + margin * 2 MouseArea { @@ -30,12 +30,12 @@ Item { RowLayout { id: rowLayout - MaterialSymbol { fill: 0 text: WeatherIcons.codeToName[Weather.data.wCode] iconSize: Appearance.font.pixelSize.large color: Appearance.colors.colOnLayer1 + Layout.alignment: Qt.AlignVCenter } StyledText { @@ -43,6 +43,7 @@ Item { font.pixelSize: Appearance.font.pixelSize.large color: Appearance.colors.colOnLayer1 text: Weather.data.temp + Layout.alignment: Qt.AlignVCenter } } } From 8b83b42eed0070f0bb96658f188058c0e63b5d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20A=2E=20Tekeo=C4=9Flu?= <55619655+tekeoglan@users.noreply.github.com> Date: Thu, 3 Jul 2025 10:00:08 +0300 Subject: [PATCH 112/328] chore(Weather): use generic city name for default value --- .config/quickshell/services/Weather.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/services/Weather.qml b/.config/quickshell/services/Weather.qml index e95453fd..eb1a00af 100644 --- a/.config/quickshell/services/Weather.qml +++ b/.config/quickshell/services/Weather.qml @@ -45,7 +45,7 @@ Singleton { temp.sunset = data?.astronomy?.sunset || "0.0"; temp.windDir = data?.current?.winddir16Point || "N"; temp.wCode = data?.current?.weatherCode || "113"; - temp.city = data?.location?.areaName[0].value || "Istanbul"; + temp.city = data?.location?.areaName[0]?.value || "City"; temp.temp = ""; if (root.useUSCS) { temp.wind = (data?.current?.windspeedMiles || 0) + " mph"; From e99f51e6accc3cbe4bc4c2f68b8b88c3bd7d9d9e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 3 Jul 2025 22:56:05 +0200 Subject: [PATCH 113/328] media: fix space at start of track title --- .config/quickshell/modules/common/functions/string_utils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/common/functions/string_utils.js b/.config/quickshell/modules/common/functions/string_utils.js index c22671eb..0819dbfb 100644 --- a/.config/quickshell/modules/common/functions/string_utils.js +++ b/.config/quickshell/modules/common/functions/string_utils.js @@ -158,10 +158,10 @@ function cleanMusicTitle(title) { // Japenis brackets title = title.replace(/^ *【[^】]*】/, "") // Touhou title = title.replace(/^ *《[^》]*》/, "") // ?? - title = title.replace(/^ *「[^」]*」/, "") // OP/ED - title = title.replace(/^ *『[^』]*』/, "") // OP/ED + title = title.replace(/^ *「[^」]*」/, "") // OP/ED thingie + title = title.replace(/^ *『[^』]*』/, "") // OP/ED thingie - return title; + return title.trim(); } function friendlyTimeForSeconds(seconds) { From 089468393e64ddd126d9266683c1d9ca107cfb27 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 3 Jul 2025 22:56:23 +0200 Subject: [PATCH 114/328] notifs: discard notif on action invocation --- .config/quickshell/services/Notifications.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/services/Notifications.qml b/.config/quickshell/services/Notifications.qml index 6f04b7cd..7438983f 100644 --- a/.config/quickshell/services/Notifications.qml +++ b/.config/quickshell/services/Notifications.qml @@ -219,8 +219,8 @@ Singleton { } else { console.log("Notification not found in server: " + id) - root.discardNotification(id); } + root.discardNotification(id); } function triggerListChange() { From 85a9a08b43dea67ee416e9558269389da55fa8cd Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 3 Jul 2025 22:56:45 +0200 Subject: [PATCH 115/328] settings: add dock options --- .../modules/settings/InterfaceConfig.qml | 92 +++++++++++++++---- 1 file changed, 75 insertions(+), 17 deletions(-) diff --git a/.config/quickshell/modules/settings/InterfaceConfig.qml b/.config/quickshell/modules/settings/InterfaceConfig.qml index 0f63ea41..29fd21d1 100644 --- a/.config/quickshell/modules/settings/InterfaceConfig.qml +++ b/.config/quickshell/modules/settings/InterfaceConfig.qml @@ -11,38 +11,58 @@ ContentPage { title: "Policies" ConfigRow { - ColumnLayout { // Weeb policy + ColumnLayout { + // Weeb policy ContentSubsectionLabel { text: "Weeb" } ConfigSelectionArray { currentValue: Config.options.policies.weeb configOptionName: "policies.weeb" - onSelected: (newValue) => { + onSelected: newValue => { Config.options.policies.weeb = newValue; } options: [ - { displayName: "No", value: 0 }, - { displayName: "Yes", value: 1 }, - { displayName: "Closet", value: 2 } + { + displayName: "No", + value: 0 + }, + { + displayName: "Yes", + value: 1 + }, + { + displayName: "Closet", + value: 2 + } ] } } - ColumnLayout { // AI policy + ColumnLayout { + // AI policy ContentSubsectionLabel { text: "AI" } ConfigSelectionArray { currentValue: Config.options.policies.ai configOptionName: "policies.ai" - onSelected: (newValue) => { + onSelected: newValue => { Config.options.policies.ai = newValue; } options: [ - { displayName: "No", value: 0 }, - { displayName: "Yes", value: 1 }, - { displayName: "Local only", value: 2 } + { + displayName: "No", + value: 0 + }, + { + displayName: "Yes", + value: 1 + }, + { + displayName: "Local only", + value: 2 + } ] } } @@ -55,13 +75,22 @@ ContentPage { ConfigSelectionArray { currentValue: Config.options.bar.cornerStyle configOptionName: "bar.cornerStyle" - onSelected: (newValue) => { + onSelected: newValue => { Config.options.bar.cornerStyle = newValue; } options: [ - { displayName: "Hug", value: 0 }, - { displayName: "Float", value: 1 }, - { displayName: "Plain rectangle", value: 2 } + { + displayName: "Hug", + value: 0 + }, + { + displayName: "Float", + value: 1 + }, + { + displayName: "Plain rectangle", + value: 2 + } ] } @@ -182,7 +211,7 @@ ContentPage { Config.options.bar.workspaces.showNumberDelay = value; } } - } + } } ContentSection { @@ -236,6 +265,36 @@ ContentPage { } } + ContentSection { + title: "Dock" + + ConfigSwitch { + text: "Enable" + checked: Config.options.dock.enable + onCheckedChanged: { + Config.options.dock.enable = checked; + } + } + + ConfigRow { + uniform: true + ConfigSwitch { + text: "Hover to reveal" + checked: Config.options.dock.hoverToReveal + onCheckedChanged: { + Config.options.dock.hoverToReveal = checked; + } + } + ConfigSwitch { + text: "Pinned on startup" + checked: Config.options.dock.pinnedOnStartup + onCheckedChanged: { + Config.options.dock.pinnedOnStartup = checked; + } + } + } + } + ContentSection { title: "Overview" ConfigSpinBox { @@ -271,6 +330,5 @@ ContentPage { } } } - } -} \ No newline at end of file +} From 746c5805fb4d30cea16d2daf732c4fd629efc5a5 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 3 Jul 2025 23:04:00 +0200 Subject: [PATCH 116/328] Update Config.qml --- .config/quickshell/modules/common/Config.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index 09313be8..016b3932 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -134,7 +134,7 @@ Singleton { property JsonObject dock: JsonObject { property bool enable: false property real height: 60 - property real hoverRegionHeight: 3 + property real hoverRegionHeight: 2 property bool pinnedOnStartup: false property bool hoverToReveal: true // When false, only reveals on empty workspace property list pinnedApps: [ // IDs of pinned entries From 11dcffb95dc88a9e94483e1e6e6c3bd4f6966b41 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 3 Jul 2025 23:04:41 +0200 Subject: [PATCH 117/328] overview: only show windows in same monitor as widget --- .config/quickshell/modules/overview/OverviewWidget.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index c6da607d..9a7b6405 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -148,9 +148,10 @@ Item { // console.log(JSON.stringify(ToplevelManager.toplevels.values.map(t => t), null, 2)) return ToplevelManager.toplevels.values.filter((toplevel) => { const address = `0x${toplevel.HyprlandToplevel.address}` - // console.log(`Checking window with address: ${address}`) var win = windowByAddress[address] - return (root.workspaceGroup * root.workspacesShown < win?.workspace?.id && win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown) + const inWorkspaceGroup = (root.workspaceGroup * root.workspacesShown < win?.workspace?.id && win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown) + const inMonitor = root.monitor.id === win.monitor + return inWorkspaceGroup && inMonitor; }) } } From c7519f338e0b169b0591616dc3cb615e2e5f472b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 4 Jul 2025 16:58:44 +0200 Subject: [PATCH 118/328] add logo (closes #1436) --- .config/quickshell/modules/settings/About.qml | 9 +- .local/share/icons/illogical-impulse.svg | 124 ++++++++++++++++++ install.sh | 1 + 3 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 .local/share/icons/illogical-impulse.svg diff --git a/.config/quickshell/modules/settings/About.qml b/.config/quickshell/modules/settings/About.qml index 7868c0e7..dc1c93d7 100644 --- a/.config/quickshell/modules/settings/About.qml +++ b/.config/quickshell/modules/settings/About.qml @@ -20,7 +20,7 @@ ContentPage { Layout.topMargin: 10 Layout.bottomMargin: 10 IconImage { - implicitSize: 100 + implicitSize: 80 source: Quickshell.iconPath(SystemInfo.logo) } ColumnLayout { @@ -87,10 +87,9 @@ ContentPage { spacing: 20 Layout.topMargin: 10 Layout.bottomMargin: 10 - MaterialSymbol { - iconSize: 70 - text: "files" - color: Appearance.colors.colOnSecondaryContainer + IconImage { + implicitSize: 80 + source: Quickshell.iconPath("illogical-impulse") } ColumnLayout { Layout.alignment: Qt.AlignVCenter diff --git a/.local/share/icons/illogical-impulse.svg b/.local/share/icons/illogical-impulse.svg new file mode 100644 index 00000000..8b1b789c --- /dev/null +++ b/.local/share/icons/illogical-impulse.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/install.sh b/install.sh index a123a7a9..2134e767 100755 --- a/install.sh +++ b/install.sh @@ -233,6 +233,7 @@ esac # some foldes (eg. .local/bin) should be processed separately to avoid `--delete' for rsync, # since the files here come from different places, not only about one program. # v rsync -av ".local/bin/" "$XDG_BIN_HOME" # No longer needed since scripts are no longer in ~/.local/bin +v rsync -av ".local/share/icons/" "${XDG_DATA_HOME:-$HOME/.local/share}"/icons/ # Prevent hyprland from not fully loaded sleep 1 From 3a9189a9941a0eae4bedc88a3afdbe1bf9e209dd Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 4 Jul 2025 17:00:43 +0200 Subject: [PATCH 119/328] readme: remove "pls logo ideas" --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index e381b125..a40a5686 100644 --- a/README.md +++ b/README.md @@ -64,12 +64,6 @@ - For a more comprehensive list of dependencies, see [scriptdata/dependencies.conf](https://github.com/end-4/dots-hyprland/blob/main/scriptdata/dependencies.conf) -
- Logo ideas welcome - - - See [#1436](https://github.com/end-4/dots-hyprland/issues/1436) - -

• screenshots •

From 2f03ce5f06abc6b5c37b599ae9527a55aaad9440 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 4 Jul 2025 17:03:27 +0200 Subject: [PATCH 120/328] symlink quickshell to illogical impulse icon remove this if quickshell gets its icon bundled later --- .local/share/icons/quickshell.svg | 1 + 1 file changed, 1 insertion(+) create mode 120000 .local/share/icons/quickshell.svg diff --git a/.local/share/icons/quickshell.svg b/.local/share/icons/quickshell.svg new file mode 120000 index 00000000..8dc05d01 --- /dev/null +++ b/.local/share/icons/quickshell.svg @@ -0,0 +1 @@ +illogical-impulse.svg \ No newline at end of file From 83a7581a349cf6d52c1ff83383aa55bcf5f99e44 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 4 Jul 2025 17:20:33 +0200 Subject: [PATCH 121/328] icon guess: fix steam regex --- .config/quickshell/services/AppSearch.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/services/AppSearch.qml b/.config/quickshell/services/AppSearch.qml index edac4800..e325f93f 100644 --- a/.config/quickshell/services/AppSearch.qml +++ b/.config/quickshell/services/AppSearch.qml @@ -27,7 +27,7 @@ Singleton { }) property var regexSubstitutions: [ { - "regex": /^steam_app_(\\d+)$/, + "regex": /^steam_app_(\d+)$/, "replace": "steam_icon_$1" }, { @@ -72,6 +72,7 @@ Singleton { } function iconExists(iconName) { + if (!iconName || iconName.length == 0) return false; return (Quickshell.iconPath(iconName, true).length > 0) && !iconName.includes("image-missing"); } @@ -103,7 +104,7 @@ Singleton { // Guess: normalize to kebab case guessStr = str.toLowerCase().replace(/\s+/g, "-"); if (iconExists(guessStr)) return guessStr; - // Guess: First fuzze desktop entry match + // Guess: First fuzzy desktop entry match const searchResults = root.fuzzyQuery(str); if (searchResults.length > 0) { const firstEntry = searchResults[0]; From 1fb0e8b32b8073ed6d84a032c796fdb384b04e57 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 4 Jul 2025 17:51:12 +0200 Subject: [PATCH 122/328] add breeze --- arch-packages/illogical-impulse-fonts-themes/PKGBUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/arch-packages/illogical-impulse-fonts-themes/PKGBUILD b/arch-packages/illogical-impulse-fonts-themes/PKGBUILD index 12a7209b..a6f69c33 100644 --- a/arch-packages/illogical-impulse-fonts-themes/PKGBUILD +++ b/arch-packages/illogical-impulse-fonts-themes/PKGBUILD @@ -6,6 +6,7 @@ arch=(any) license=(None) depends=( adw-gtk-theme-git + breeze breeze-plus eza fish From 7d2856e9b7aea2fcc76c03504638aca9bab9ca6c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 4 Jul 2025 17:54:15 +0200 Subject: [PATCH 123/328] deps: add darkly qt style --- arch-packages/illogical-impulse-fonts-themes/PKGBUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/arch-packages/illogical-impulse-fonts-themes/PKGBUILD b/arch-packages/illogical-impulse-fonts-themes/PKGBUILD index a6f69c33..8c5f567c 100644 --- a/arch-packages/illogical-impulse-fonts-themes/PKGBUILD +++ b/arch-packages/illogical-impulse-fonts-themes/PKGBUILD @@ -8,6 +8,7 @@ depends=( adw-gtk-theme-git breeze breeze-plus + darkly-bin eza fish fontconfig From e78b84cd41cd94f8bbe67817b241044d8eb07f44 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 4 Jul 2025 20:02:44 +0200 Subject: [PATCH 124/328] bar: monochrome icons --- .config/quickshell/modules/bar/Workspaces.qml | 20 +++++++++++++++++++ .config/quickshell/modules/common/Config.qml | 1 + 2 files changed, 21 insertions(+) diff --git a/.config/quickshell/modules/bar/Workspaces.qml b/.config/quickshell/modules/bar/Workspaces.qml index 06011370..cd32cd32 100644 --- a/.config/quickshell/modules/bar/Workspaces.qml +++ b/.config/quickshell/modules/bar/Workspaces.qml @@ -206,6 +206,7 @@ Item { } } Rectangle { // Dot instead of ws number + id: wsDot opacity: (Config.options?.bar.workspaces.alwaysShowNumbers || GlobalStates.workspaceShowNumbers || (Config.options?.bar.workspaces.showAppIcons && workspaceButtonBackground.biggestWindow) @@ -257,6 +258,25 @@ Item { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } } + + Loader { + active: Config.options.bar.workspaces.monochromeIcons + anchors.fill: mainAppIcon + sourceComponent: Item { + Desaturate { + id: desaturatedIcon + visible: false // There's already color overlay + anchors.fill: parent + source: mainAppIcon + desaturation: 1 + } + ColorOverlay { + anchors.fill: desaturatedIcon + source: desaturatedIcon + color: ColorUtils.transparentize(wsDot.color, 0.6) + } + } + } } } diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index 016b3932..76b45df1 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -117,6 +117,7 @@ Singleton { property bool monochromeIcons: true } property JsonObject workspaces: JsonObject { + property bool monochromeIcons: true property int shown: 10 property bool showAppIcons: true property bool alwaysShowNumbers: false From cf205816031b3adf782983d57e1269c345e6cf0c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 00:18:38 +0200 Subject: [PATCH 125/328] Update README.md --- README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a40a5686..21a92ab5 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,11 @@

-## illogical-impulseQuickshell + + +### Quickshell | AI | Common widgets | |:---|:---------------| @@ -82,7 +86,7 @@ By the way... - The funny notification positions are mimicking Android 16's dragging behavior - The clock on the wallpaper is automatically placed at the "least busy" region of the image -## illogical-impulseAGS (Deprecated) +### AGS | AI | Common widgets | |:---|:---------------| @@ -90,28 +94,28 @@ By the way... | Window management | Weeb power | | ![image](https://github.com/user-attachments/assets/02983b9b-79ba-4c25-8717-90bef2357ae5) | ![image](https://github.com/user-attachments/assets/bbb332ec-962a-4e88-a95b-486d0bd8ce76) | -## Unsupported stuff +### Unsupported stuff - The pics are here mainly for your viewing pleasure - The files are still available, feel free to grab them from the [`archive`](https://github.com/end-4/dots-hyprland/tree/archive) branch if you're willing to see some spaghetti and troubleshoot - Click image for a presentation video -### [m3ww](https://github.com/end-4/dots-hyprland/tree/archive) +#### m3ww Material Eww! -### [NovelKnock](https://github.com/end-4/dots-hyprland/tree/archive) +#### NovelKnock Desktop Preview -### [Hybrid](https://github.com/end-4/dots-hyprland/tree/archive) +#### Hybrid click the circles! -### [Windoes](https://github.com/end-4/dots-hyprland/tree/archive) +#### Windoes Desktop Preview From 5064db2aad50e580b6b4ead1c1cf4953b3a9a36c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 00:23:27 +0200 Subject: [PATCH 126/328] readme: add illogical impulse logo --- .github/assets/illogical-impulse.svg | 122 +++++++++++++++++++++++++++ README.md | 6 +- 2 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 .github/assets/illogical-impulse.svg diff --git a/.github/assets/illogical-impulse.svg b/.github/assets/illogical-impulse.svg new file mode 100644 index 00000000..4d1362b0 --- /dev/null +++ b/.github/assets/illogical-impulse.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 21a92ab5..44bb2c0b 100644 --- a/README.md +++ b/README.md @@ -70,9 +70,9 @@

- +
+ illogical-impulse logo +
### Quickshell From 16e07a82132b2fff94c10fb4fa5931a70af6f02a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 00:25:10 +0200 Subject: [PATCH 127/328] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 44bb2c0b..97e0a32c 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ illogical-impulse logo -### Quickshell +### illogical-impulseQuickshell | AI | Common widgets | |:---|:---------------| @@ -86,7 +86,7 @@ By the way... - The funny notification positions are mimicking Android 16's dragging behavior - The clock on the wallpaper is automatically placed at the "least busy" region of the image -### AGS +### illogical-impulseAGS (Deprecated) | AI | Common widgets | |:---|:---------------| From f973052d16cedb3c1ba580e88f22891036388be6 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 01:29:11 +0200 Subject: [PATCH 128/328] Update README.md --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 97e0a32c..cd4c1a79 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,8 @@ illogical-impulse logo +_illogical-impulse is the latest and only style that I actively use. Other past styles are still there for your viewing pleasure and not actual use, but code is still available, see below._ + ### illogical-impulseQuickshell | AI | Common widgets | @@ -82,10 +84,6 @@ | Window management | Weeb power | | ![image](https://github.com/user-attachments/assets/86cc511b-0d33-4c78-bcc0-3037d02a17da) | ![image](https://github.com/user-attachments/assets/292259fc-57d3-4663-a583-2ce2faad13fb) | -By the way... -- The funny notification positions are mimicking Android 16's dragging behavior -- The clock on the wallpaper is automatically placed at the "least busy" region of the image - ### illogical-impulseAGS (Deprecated) | AI | Common widgets | @@ -96,8 +94,7 @@ By the way... ### Unsupported stuff -- The pics are here mainly for your viewing pleasure -- The files are still available, feel free to grab them from the [`archive`](https://github.com/end-4/dots-hyprland/tree/archive) branch if you're willing to see some spaghetti and troubleshoot +- Source code not likely to work but still available in the [`archive`](https://github.com/end-4/dots-hyprland/tree/archive) branch. Extremely spaghetti. - Click image for a presentation video #### m3ww From b289ceccade9814f1191a04c6e0594649e9c018e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=82=89=E3=81=BE=E3=82=8A=E3=82=93?= <62203463+Flamarine@users.noreply.github.com> Date: Sat, 5 Jul 2025 11:23:26 +0800 Subject: [PATCH 129/328] include possible zed aliases in keybinds.conf --- .config/hypr/hyprland/keybinds.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index a1ded9f0..dea31356 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -203,7 +203,7 @@ bind = Super, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh bind = Ctrl+Alt, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] Kitty (for Ubuntu people) bind = Super, E, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "dolphin" "nautilus" "nemo" "thunar" "kitty -1 fish -c yazi" # File manager bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "google-chrome-stable" "zen-browser" "firefox" "brave" "chromium" "microsoft-edge-stable" "opera" # Browser -bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "code" "codium" "zed" "kate" "gnome-text-editor" "emacs" "command -v nvim && kitty -1 nvim" # Code editor +bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "code" "codium" "zed" "zedit" "zeditor" "kate" "gnome-text-editor" "emacs" "command -v nvim && kitty -1 nvim" # Code editor bind = Super+Shift, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "wps" "onlyoffice-desktopeditors" # Office software bind = Super, X, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kate" "gnome-text-editor" "emacs" # Text editor bind = Ctrl+Super, V, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol" # Volume mixer From cd92d14ad25fa878e6eba5df381e69b55be6ea26 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 08:43:30 +0200 Subject: [PATCH 130/328] readme: update screenshot --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cd4c1a79..aad74cfa 100644 --- a/README.md +++ b/README.md @@ -78,9 +78,9 @@ _illogical-impulse is the latest and only style that I actively use. Other past ### illogical-impulseQuickshell -| AI | Common widgets | +| AI, settings app | Some widgets | |:---|:---------------| -| ![image](https://github.com/user-attachments/assets/08d26785-b54d-4ad1-875b-bb08cc6757f5) | ![image](https://github.com/user-attachments/assets/4fcd63d9-0943-4b21-8737-4bed97b71961) | +| ![image](https://github.com/user-attachments/assets/4d45e860-ae60-418a-a564-309b4939f5c4) | ![image](https://github.com/user-attachments/assets/4fcd63d9-0943-4b21-8737-4bed97b71961) | | Window management | Weeb power | | ![image](https://github.com/user-attachments/assets/86cc511b-0d33-4c78-bcc0-3037d02a17da) | ![image](https://github.com/user-attachments/assets/292259fc-57d3-4663-a583-2ce2faad13fb) | From 4e71d002ea36fc5f5ffd6e502a72271d0e0f7602 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 09:04:52 +0200 Subject: [PATCH 131/328] smooth zooming --- .config/hypr/hyprland/keybinds.conf | 6 ++++-- .config/quickshell/GlobalStates.qml | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index a1ded9f0..71835548 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -183,8 +183,10 @@ bindd = Ctrl+Shift+Alt+Super, Delete, Shutdown, exec, systemctl poweroff || logi ##! Screen # Zoom -binde = Super, Minus, exec, ~/.config/hypr/hyprland/scripts/zoom.sh decrease 0.1 # Zoom out -binde = Super, Equal, exec, ~/.config/hypr/hyprland/scripts/zoom.sh increase 0.1 # Zoom in +binde = Super, Minus, exec, qs ipc call zoom zoomOut # Zoom out +binde = Super, Equal, exec, qs ipc call zoom zoomIn # Zoom in +binde = Super, Minus, exec, qs ipc call TEST_ALIVE || ~/.config/hypr/hyprland/scripts/zoom.sh decrease 0.1 # [hidden] Zoom out +binde = Super, Equal, exec, qs ipc call TEST_ALIVE || ~/.config/hypr/hyprland/scripts/zoom.sh increase 0.1 # [hidden] Zoom in ##! Media bindl= Super+Shift, N, exec, playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` # Next track diff --git a/.config/quickshell/GlobalStates.qml b/.config/quickshell/GlobalStates.qml index 49ae3f57..b7ddef5a 100644 --- a/.config/quickshell/GlobalStates.qml +++ b/.config/quickshell/GlobalStates.qml @@ -14,6 +14,14 @@ Singleton { property bool workspaceShowNumbers: false property bool superReleaseMightTrigger: true + property real screenZoom: 1 + onScreenZoomChanged: { + Quickshell.execDetached(["hyprctl", "keyword", "cursor:zoom_factor", root.screenZoom.toString()]); + } + Behavior on screenZoom { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + // When user is not reluctant while pressing super, they probably don't need to see workspace numbers onSuperReleaseMightTriggerChanged: { workspaceShowNumbersTimer.stop() @@ -41,4 +49,16 @@ Singleton { workspaceShowNumbers = false } } + + IpcHandler { + target: "zoom" + + function zoomIn() { + screenZoom = Math.min(screenZoom + 0.4, 3.0) + } + + function zoomOut() { + screenZoom = Math.max(screenZoom - 0.4, 1) + } + } } \ No newline at end of file From 3c7d55c7937889c619301481790704863c462000 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 09:05:08 +0200 Subject: [PATCH 132/328] extra bg tint --- .config/quickshell/modules/common/Appearance.qml | 2 +- .config/quickshell/modules/common/Config.qml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 70437e12..c8b62350 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -100,7 +100,7 @@ Singleton { colors: QtObject { property color colSubtext: m3colors.m3outline - property color colLayer0: ColorUtils.transparentize(m3colors.m3background, root.transparency) + property color colLayer0: ColorUtils.mix(ColorUtils.transparentize(m3colors.m3background, root.transparency), m3colors.m3primary, Config.options.appearance.extraBackgroundTint ? 0.97 : 1) property color colOnLayer0: m3colors.m3onBackground property color colLayer0Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer0, colOnLayer0, 0.9, root.contentTransparency)) property color colLayer0Active: ColorUtils.transparentize(ColorUtils.mix(colLayer0, colOnLayer0, 0.8, root.contentTransparency)) diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index 76b45df1..e8f2f39d 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -63,6 +63,7 @@ Singleton { } property JsonObject appearance: JsonObject { + property bool extraBackgroundTint: true property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen property bool transparency: false property JsonObject palette: JsonObject { From b0cd46f7832f9ec0550759d2584c2dc0435be559 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 09:05:43 +0200 Subject: [PATCH 133/328] screenshot: add app icons --- .config/quickshell/screenshot.qml | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml index 8e9af049..3368b6b7 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/screenshot.qml @@ -15,6 +15,7 @@ import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Io +import Quickshell.Widgets import Quickshell.Wayland import Quickshell.Hyprland import "./services/" @@ -44,6 +45,7 @@ ShellRoot { component TargetRegion: Rectangle { id: regionRect + property bool showIcon: false property bool targeted: false property color borderColor property color fillColor: "transparent" @@ -69,13 +71,27 @@ ShellRoot { topMargin: regionRect.textPadding leftMargin: regionRect.textPadding } - implicitWidth: regionText.implicitWidth + horizontalPadding * 2 - implicitHeight: regionText.implicitHeight + verticalPadding * 2 - StyledText { - id: regionText - text: regionRect.text - color: root.genericContentForeground + implicitWidth: regionInfoRow.implicitWidth + horizontalPadding * 2 + implicitHeight: regionInfoRow.implicitHeight + verticalPadding * 2 + RowLayout { + id: regionInfoRow anchors.centerIn: parent + spacing: 8 + + Loader { + id: regionIconLoader + active: regionRect.showIcon + sourceComponent: IconImage { + implicitSize: Appearance.font.pixelSize.larger + source: Quickshell.iconPath(AppSearch.guessIcon(regionRect.text), "image-missing") + } + } + + StyledText { + id: regionText + text: regionRect.text + color: root.genericContentForeground + } } } } @@ -117,7 +133,7 @@ ShellRoot { const layersOfThisMonitor = root.layers[panelWindow.hyprlandMonitor.name] const topLayers = layersOfThisMonitor.levels["2"] const nonBarTopLayers = topLayers - .filter(layer => !(layer.namespace.includes(":bar"))) + .filter(layer => !(layer.namespace.includes(":bar") || layer.namespace.includes(":dock"))) .map(layer => { return { at: [layer.x, layer.y], @@ -441,6 +457,7 @@ ShellRoot { delegate: TargetRegion { z: 2 required property var modelData + showIcon: true targeted: !panelWindow.draggedAway && (panelWindow.targetedRegionX === modelData.at[0] && panelWindow.targetedRegionY === modelData.at[1] From 9b050e8e21bb7082529c324119a74df38f02b921 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 09:06:22 +0200 Subject: [PATCH 134/328] add border to panels --- .config/quickshell/modules/cheatsheet/Cheatsheet.qml | 2 ++ .config/quickshell/modules/dock/Dock.qml | 2 ++ .config/quickshell/modules/overview/OverviewWidget.qml | 2 ++ .config/quickshell/modules/overview/SearchWidget.qml | 2 ++ .config/quickshell/modules/sidebarLeft/SidebarLeft.qml | 2 ++ .config/quickshell/modules/sidebarRight/SidebarRight.qml | 2 ++ 6 files changed, 12 insertions(+) diff --git a/.config/quickshell/modules/cheatsheet/Cheatsheet.qml b/.config/quickshell/modules/cheatsheet/Cheatsheet.qml index 79711f88..0edc121e 100644 --- a/.config/quickshell/modules/cheatsheet/Cheatsheet.qml +++ b/.config/quickshell/modules/cheatsheet/Cheatsheet.qml @@ -64,6 +64,8 @@ Scope { // Scope id: cheatsheetBackground anchors.centerIn: parent color: Appearance.colors.colLayer0 + border.width: 1 + border.color: Appearance.m3colors.m3outlineVariant radius: Appearance.rounding.windowRounding property real padding: 30 implicitWidth: cheatsheetColumnLayout.implicitWidth + padding * 2 diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index a78e93d9..04af9810 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -94,6 +94,8 @@ Scope { // Scope anchors.topMargin: Appearance.sizes.elevationMargin anchors.bottomMargin: Appearance.sizes.hyprlandGapsOut color: Appearance.colors.colLayer0 + border.width: 1 + border.color: Appearance.m3colors.m3outlineVariant radius: Appearance.rounding.large } diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index 9a7b6405..a17cc045 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -63,6 +63,8 @@ Item { implicitHeight: workspaceColumnLayout.implicitHeight + padding * 2 radius: Appearance.rounding.screenRounding * root.scale + padding color: Appearance.colors.colLayer0 + border.width: 1 + border.color: Appearance.m3colors.m3outlineVariant ColumnLayout { // Workspaces id: workspaceColumnLayout diff --git a/.config/quickshell/modules/overview/SearchWidget.qml b/.config/quickshell/modules/overview/SearchWidget.qml index a858bfd0..91998aa9 100644 --- a/.config/quickshell/modules/overview/SearchWidget.qml +++ b/.config/quickshell/modules/overview/SearchWidget.qml @@ -179,6 +179,8 @@ Item { // Wrapper implicitHeight: columnLayout.implicitHeight radius: Appearance.rounding.large color: Appearance.colors.colLayer0 + border.width: 1 + border.color: Appearance.m3colors.m3outlineVariant ColumnLayout { id: columnLayout diff --git a/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml b/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml index ce0b2280..64a5b55a 100644 --- a/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml +++ b/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml @@ -100,6 +100,8 @@ Scope { // Scope width: sidebarRoot.sidebarWidth - Appearance.sizes.hyprlandGapsOut - Appearance.sizes.elevationMargin height: parent.height - Appearance.sizes.hyprlandGapsOut * 2 color: Appearance.colors.colLayer0 + border.width: 1 + border.color: Appearance.m3colors.m3outlineVariant radius: Appearance.rounding.screenRounding - Appearance.sizes.hyprlandGapsOut + 1 Behavior on width { diff --git a/.config/quickshell/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/modules/sidebarRight/SidebarRight.qml index ebdd9e4e..376687af 100644 --- a/.config/quickshell/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/modules/sidebarRight/SidebarRight.qml @@ -89,6 +89,8 @@ Scope { implicitHeight: parent.height - Appearance.sizes.hyprlandGapsOut * 2 implicitWidth: sidebarWidth - Appearance.sizes.hyprlandGapsOut * 2 color: Appearance.colors.colLayer0 + border.width: 1 + border.color: Appearance.m3colors.m3outlineVariant radius: Appearance.rounding.screenRounding - Appearance.sizes.hyprlandGapsOut + 1 ColumnLayout { From d9b9b8c9b24154fca3222c383512d65f19535a32 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 09:06:59 +0200 Subject: [PATCH 135/328] media controls: mix a bit of accent color --- .config/quickshell/modules/mediaControls/PlayerControl.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/mediaControls/PlayerControl.qml b/.config/quickshell/modules/mediaControls/PlayerControl.qml index cce0788d..9cce0111 100644 --- a/.config/quickshell/modules/mediaControls/PlayerControl.qml +++ b/.config/quickshell/modules/mediaControls/PlayerControl.qml @@ -23,7 +23,7 @@ Item { // Player instance property string artDownloadLocation: Directories.coverArt property string artFileName: Qt.md5(artUrl) + ".jpg" property string artFilePath: `${artDownloadLocation}/${artFileName}` - property color artDominantColor: colorQuantizer?.colors[0] || Appearance.m3colors.m3secondaryContainer + property color artDominantColor: ColorUtils.mix(colorQuantizer?.colors[0], Appearance.colors.colPrimaryContainer, 0.8) || Appearance.m3colors.m3secondaryContainer property bool downloaded: false property list visualizerPoints: [] property real maxVisualizerValue: 1000 // Max value in the data points From 265b410a878f8e10c87548816e2cdf761c352c36 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 09:07:23 +0200 Subject: [PATCH 136/328] Update switchwall.sh --- .config/quickshell/scripts/colors/switchwall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/scripts/colors/switchwall.sh b/.config/quickshell/scripts/colors/switchwall.sh index 35caba66..560a8cfc 100755 --- a/.config/quickshell/scripts/colors/switchwall.sh +++ b/.config/quickshell/scripts/colors/switchwall.sh @@ -330,7 +330,7 @@ main() { # Only prompt for wallpaper if not using --color and not using --noswitch and no imgpath set if [[ -z "$imgpath" && -z "$color_flag" && -z "$noswitch_flag" ]]; then - cd "$(xdg-user-dir PICTURES)/Wallpapers" 2>/dev/null || cd "$(xdg-user-dir PICTURES)" || return 1 + cd "$(xdg-user-dir PICTURES)/Wallpapers/showcase" 2>/dev/null || cd "$(xdg-user-dir PICTURES)/Wallpapers" 2>/dev/null || cd "$(xdg-user-dir PICTURES)" || return 1 imgpath="$(kdialog --getopenfilename . --title 'Choose wallpaper')" fi From d4f193ae69245c35a892dab31b7b219c2a39f35b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 09:55:01 +0200 Subject: [PATCH 137/328] dock: monochrome icons --- .config/quickshell/modules/common/Config.qml | 1 + .../quickshell/modules/dock/DockAppButton.qml | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index e8f2f39d..b2db153d 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -135,6 +135,7 @@ Singleton { property JsonObject dock: JsonObject { property bool enable: false + property bool monochromeIcons: true property real height: 60 property real hoverRegionHeight: 2 property bool pinnedOnStartup: false diff --git a/.config/quickshell/modules/dock/DockAppButton.qml b/.config/quickshell/modules/dock/DockAppButton.qml index f4623e62..8afa6567 100644 --- a/.config/quickshell/modules/dock/DockAppButton.qml +++ b/.config/quickshell/modules/dock/DockAppButton.qml @@ -3,6 +3,7 @@ import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/color_utils.js" as ColorUtils +import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls import QtQuick.Effects @@ -91,6 +92,25 @@ DockButton { } } + Loader { + active: Config.options.dock.monochromeIcons + anchors.fill: iconImageLoader + sourceComponent: Item { + Desaturate { + id: desaturatedIcon + visible: false // There's already color overlay + anchors.fill: parent + source: iconImageLoader + desaturation: 0.8 + } + ColorOverlay { + anchors.fill: desaturatedIcon + source: desaturatedIcon + color: ColorUtils.transparentize(Appearance.colors.colPrimary, 0.9) + } + } + } + RowLayout { spacing: 3 anchors { From d5f7a72d19d911606ab3ae135f93553587743a77 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 09:55:12 +0200 Subject: [PATCH 138/328] bar: workspaces: adjust monochromization --- .config/quickshell/modules/bar/Workspaces.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/modules/bar/Workspaces.qml b/.config/quickshell/modules/bar/Workspaces.qml index cd32cd32..f91cdaa9 100644 --- a/.config/quickshell/modules/bar/Workspaces.qml +++ b/.config/quickshell/modules/bar/Workspaces.qml @@ -268,12 +268,12 @@ Item { visible: false // There's already color overlay anchors.fill: parent source: mainAppIcon - desaturation: 1 + desaturation: 0.8 } ColorOverlay { anchors.fill: desaturatedIcon source: desaturatedIcon - color: ColorUtils.transparentize(wsDot.color, 0.6) + color: ColorUtils.transparentize(wsDot.color, 0.9) } } } From bcb60d8ab70073373c1e8676c074964686eb85b8 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 10:30:18 +0200 Subject: [PATCH 139/328] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aad74cfa..04aa5ca3 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ illogical-impulse logo -_illogical-impulse is the latest and only style that I actively use. Other past styles are still there for your viewing pleasure and not actual use, but code is still available, see below._ +_latest and only style that I actively use. Other past styles are still there for your viewing pleasure and not actual use, but code is still available, see below._ ### illogical-impulseQuickshell From f6f7ac19fda88aeac57eb7fc2834b2b609b83fe2 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 11:32:59 +0200 Subject: [PATCH 140/328] fix bar font size --- .config/quickshell/modules/bar/Bar.qml | 14 +++++++------- .../quickshell/modules/bar/weather/WeatherBar.qml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 1785e317..c99629cc 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -483,14 +483,14 @@ Scope { Item { Layout.fillWidth: true Layout.fillHeight: true + } - // Weather - Loader { - active: Config.options.bar.weather.enable - sourceComponent: BarGroup { - implicitHeight: Appearance.sizes.baseBarHeight - WeatherBar {} - } + // Weather + Loader { + active: Config.options.bar.weather.enable + sourceComponent: BarGroup { + implicitHeight: Appearance.sizes.baseBarHeight + WeatherBar {} } } } diff --git a/.config/quickshell/modules/bar/weather/WeatherBar.qml b/.config/quickshell/modules/bar/weather/WeatherBar.qml index c0fda964..26804308 100644 --- a/.config/quickshell/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/modules/bar/weather/WeatherBar.qml @@ -40,7 +40,7 @@ Item { StyledText { visible: true - font.pixelSize: Appearance.font.pixelSize.large + font.pixelSize: Appearance.font.pixelSize.small color: Appearance.colors.colOnLayer1 text: Weather.data.temp Layout.alignment: Qt.AlignVCenter From 9043440c8d664ccca4bd2ad433a42b6f705f50b6 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 11:37:51 +0200 Subject: [PATCH 141/328] fix spacing --- .config/quickshell/modules/bar/Bar.qml | 2 ++ .config/quickshell/modules/bar/weather/WeatherPopup.qml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index c99629cc..27b188d0 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -487,6 +487,8 @@ Scope { // Weather Loader { + Layout.leftMargin: 8 + Layout.fillHeight: true active: Config.options.bar.weather.enable sourceComponent: BarGroup { implicitHeight: Appearance.sizes.baseBarHeight diff --git a/.config/quickshell/modules/bar/weather/WeatherPopup.qml b/.config/quickshell/modules/bar/weather/WeatherPopup.qml index cda62745..b39fffd3 100644 --- a/.config/quickshell/modules/bar/weather/WeatherPopup.qml +++ b/.config/quickshell/modules/bar/weather/WeatherPopup.qml @@ -12,6 +12,8 @@ Rectangle { implicitHeight: columnLayout.implicitHeight + margin * 2 color: Appearance.colors.colLayer0 radius: Appearance.rounding.small + border.width: 1 + border.color: Appearance.m3colors.m3outlineVariant clip: true ColumnLayout { From ba8c737543f45e4bdec887772a595a4ba59b091c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 11:38:07 +0200 Subject: [PATCH 142/328] weather bar: remove unnecessary nested item --- .../modules/bar/weather/WeatherBar.qml | 57 ++++++++----------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/.config/quickshell/modules/bar/weather/WeatherBar.qml b/.config/quickshell/modules/bar/weather/WeatherBar.qml index 26804308..ccd27a1b 100644 --- a/.config/quickshell/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/modules/bar/weather/WeatherBar.qml @@ -7,44 +7,37 @@ import Quickshell import QtQuick import QtQuick.Layouts -Item { +MouseArea { id: root property real margin: 10 - implicitHeight: mouseArea.implicitHeight - implicitWidth: mouseArea.implicitWidth + margin * 2 + property bool hovered: false + implicitWidth: rowLayout.implicitWidth + margin * 2 + implicitHeight: rowLayout.implicitHeight - MouseArea { - id: mouseArea - property bool hovered: false - implicitWidth: rowLayout.implicitWidth - implicitHeight: rowLayout.implicitHeight - anchors.centerIn: root + hoverEnabled: true + onEntered: { + popupLoader.item.visible = true; + } + onExited: { + popupLoader.item.visible = false; + } - hoverEnabled: true - onEntered: { - popupLoader.item.visible = true; - } - onExited: { - popupLoader.item.visible = false; + RowLayout { + id: rowLayout + MaterialSymbol { + fill: 0 + text: WeatherIcons.codeToName[Weather.data.wCode] + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnLayer1 + Layout.alignment: Qt.AlignVCenter } - RowLayout { - id: rowLayout - MaterialSymbol { - fill: 0 - text: WeatherIcons.codeToName[Weather.data.wCode] - iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnLayer1 - Layout.alignment: Qt.AlignVCenter - } - - StyledText { - visible: true - font.pixelSize: Appearance.font.pixelSize.small - color: Appearance.colors.colOnLayer1 - text: Weather.data.temp - Layout.alignment: Qt.AlignVCenter - } + StyledText { + visible: true + font.pixelSize: Appearance.font.pixelSize.small + color: Appearance.colors.colOnLayer1 + text: Weather.data.temp + Layout.alignment: Qt.AlignVCenter } } From 41a8bfa097d4c1ac1b575fd109416926f8171805 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 11:44:28 +0200 Subject: [PATCH 143/328] bar: weather popup: use loader properly --- .config/quickshell/modules/bar/weather/WeatherBar.qml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.config/quickshell/modules/bar/weather/WeatherBar.qml b/.config/quickshell/modules/bar/weather/WeatherBar.qml index ccd27a1b..f0fa0cfc 100644 --- a/.config/quickshell/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/modules/bar/weather/WeatherBar.qml @@ -15,12 +15,6 @@ MouseArea { implicitHeight: rowLayout.implicitHeight hoverEnabled: true - onEntered: { - popupLoader.item.visible = true; - } - onExited: { - popupLoader.item.visible = false; - } RowLayout { id: rowLayout @@ -43,10 +37,11 @@ MouseArea { LazyLoader { id: popupLoader - active: true + active: root.containsMouse component: PopupWindow { id: popupWindow + visible: true implicitWidth: weatherPopup.implicitWidth implicitHeight: weatherPopup.implicitHeight anchor.item: root From 8dccac4cda7b0a8c7ab2eda762b27692d7b10568 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 11:45:27 +0200 Subject: [PATCH 144/328] bar: weather: disable by default --- .config/quickshell/modules/common/Config.qml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index 2b69c9c4..594dbefd 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -123,16 +123,11 @@ Singleton { property int showNumberDelay: 300 // milliseconds } property JsonObject weather: JsonObject { - property bool enable: true - // gps based location - property bool enableGPS: true - // use if 'enableGPS' is false - property string city: "" - // use uscs units - // by default use metric (SI) units - property bool useUSCS: false - // in minutes - property int fetchInterval: 10 + property bool enable: false + property bool enableGPS: true // gps based location + property string city: "" // When 'enableGPS' is false + property bool useUSCS: false // Instead of metric (SI) units + property int fetchInterval: 10 // minutes } } From e843164f60221e9c4dbb2043076b4e3f8e4d2429 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 11:50:26 +0200 Subject: [PATCH 145/328] bar: weather: fix alignment --- .config/quickshell/modules/bar/weather/WeatherBar.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.config/quickshell/modules/bar/weather/WeatherBar.qml b/.config/quickshell/modules/bar/weather/WeatherBar.qml index f0fa0cfc..5d54562d 100644 --- a/.config/quickshell/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/modules/bar/weather/WeatherBar.qml @@ -18,6 +18,8 @@ MouseArea { RowLayout { id: rowLayout + anchors.centerIn: parent + MaterialSymbol { fill: 0 text: WeatherIcons.codeToName[Weather.data.wCode] From e393e4df1a9f6f17fa36f1ca0e4b79bee9604313 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 21:03:54 +0200 Subject: [PATCH 146/328] readme: add showcase video for ii-qs --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 04aa5ca3..4b48e70a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -
+![image](https://github.com/user-attachments/assets/61d06199-d894-4dfc-84a6-b660ab98444a)

【 end_4's Hyprland dotfiles 】

@@ -78,6 +78,8 @@ _latest and only style that I actively use. Other past styles are still there fo ### illogical-impulseQuickshell +[Showcase video](https://www.youtube.com/watch?v=RPwovTInagE) + | AI, settings app | Some widgets | |:---|:---------------| | ![image](https://github.com/user-attachments/assets/4d45e860-ae60-418a-a564-309b4939f5c4) | ![image](https://github.com/user-attachments/assets/4fcd63d9-0943-4b21-8737-4bed97b71961) | From e06ab94fb6f52969aef484ae6501af1178e7ec8a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 5 Jul 2025 21:04:18 +0200 Subject: [PATCH 147/328] readme: remove acceidentally pasted image --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b48e70a..7da85827 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![image](https://github.com/user-attachments/assets/61d06199-d894-4dfc-84a6-b660ab98444a)
+

【 end_4's Hyprland dotfiles 】

From 7bcb01964f3beec50694410f94de70ba1009c3f4 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 6 Jul 2025 09:05:23 +0200 Subject: [PATCH 148/328] settings: move weather --- .../quickshell/modules/settings/InterfaceConfig.qml | 11 +++++++++++ .../quickshell/modules/settings/ServicesConfig.qml | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.config/quickshell/modules/settings/InterfaceConfig.qml b/.config/quickshell/modules/settings/InterfaceConfig.qml index 29fd21d1..9e23fafb 100644 --- a/.config/quickshell/modules/settings/InterfaceConfig.qml +++ b/.config/quickshell/modules/settings/InterfaceConfig.qml @@ -212,6 +212,17 @@ ContentPage { } } } + + ContentSubsection { + title: "Weather" + ConfigSwitch { + text: "Enable" + checked: Config.options.bar.weather.enable + onCheckedChanged: { + Config.options.bar.weather.enable = checked; + } + } + } } ContentSection { diff --git a/.config/quickshell/modules/settings/ServicesConfig.qml b/.config/quickshell/modules/settings/ServicesConfig.qml index 97d80a18..af241d67 100644 --- a/.config/quickshell/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/modules/settings/ServicesConfig.qml @@ -137,15 +137,4 @@ ContentPage { } } } - - ContentSection { - title: "Weather" - ConfigSwitch { - text: "enable" - checked: Config.options.bar.weather.enable - onCheckedChanged: { - Config.options.bar.weather.enable = checked; - } - } - } } From 43b937814451fa3466b34b76c3b1c67e3e807117 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 6 Jul 2025 09:06:14 +0200 Subject: [PATCH 149/328] config: option to show/hide screenshot content regions (#1539) --- .config/quickshell/modules/common/Config.qml | 4 ++++ .config/quickshell/screenshot.qml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index 81a8989d..b8a051b5 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -222,6 +222,10 @@ Singleton { property JsonObject hacks: JsonObject { property int arbitraryRaceConditionDelay: 20 // milliseconds } + + property JsonObject screenshotTool: JsonObject { + property bool showContentRegions: true + } } } } diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml index 3368b6b7..9fe0ebb0 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/screenshot.qml @@ -517,7 +517,7 @@ ShellRoot { // Image regions Repeater { model: ScriptModel { - values: panelWindow.imageRegions + values: Config.options.screenshotTool.showContentRegions ? panelWindow.imageRegions : [] } delegate: TargetRegion { z: 4 From 9d6452aaaf3723f2fcce38fdd90e62168e41bb3f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 6 Jul 2025 09:11:37 +0200 Subject: [PATCH 150/328] screenshooter: remove weird gap on non-window region labels --- .config/quickshell/screenshot.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/screenshot.qml index 9fe0ebb0..4e9422fe 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/screenshot.qml @@ -81,6 +81,7 @@ ShellRoot { Loader { id: regionIconLoader active: regionRect.showIcon + visible: active sourceComponent: IconImage { implicitSize: Appearance.font.pixelSize.larger source: Quickshell.iconPath(AppSearch.guessIcon(regionRect.text), "image-missing") From 25eb5fb449c4a9a4be1b65576b7e6d3d582dd373 Mon Sep 17 00:00:00 2001 From: Pim Rijkers Date: Mon, 7 Jul 2025 14:13:35 +0200 Subject: [PATCH 151/328] add automatic restore --- .config/quickshell/modules/common/Config.qml | 3 +++ .../modules/sidebarRight/BottomWidgetGroup.qml | 12 +++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index 81a8989d..3420549d 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -206,6 +206,9 @@ Singleton { property string username: "[unset]" } } + property JsonObject bottomWidgetRight: JsonObject { + property int lastTab: 0 + } } property JsonObject time: JsonObject { diff --git a/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml index efc34d9f..50730796 100644 --- a/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml +++ b/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml @@ -14,7 +14,7 @@ Rectangle { color: Appearance.colors.colLayer1 clip: true implicitHeight: collapsed ? collapsedBottomWidgetGroupRow.implicitHeight : bottomWidgetGroupRow.implicitHeight - property int selectedTab: 0 + property int selectedTab: Config.options.sidebar.bottomWidgetRight.lastTab property bool collapsed: Persistent.states.sidebar.bottomGroup.collapsed property var tabs: [ {"type": "calendar", "name": "Calendar", "icon": "calendar_month", "widget": calendarWidget}, @@ -146,6 +146,7 @@ Rectangle { buttonIcon: modelData.icon onClicked: { root.selectedTab = index + Config.options.sidebar.bottomWidgetRight.lastTab = index } } } @@ -171,9 +172,10 @@ Rectangle { StackLayout { id: tabStack Layout.fillWidth: true - height: tabStack.children[0]?.tabLoader?.implicitHeight // TODO: make this less stupid + // Take the highest one, because the TODO list has no implicit height. This way the heigth of the calendar is used when it's initially loaded with the TODO list + height: Math.max(...tabStack.children.map(child => child.tabLoader?.implicitHeight || 0)) // TODO: make this less stupid Layout.alignment: Qt.AlignVCenter - property int realIndex: 0 + property int realIndex: root.selectedTab property int animationDuration: Appearance.animation.elementMoveFast.duration * 1.5 // Switch the tab on halfway of the anim duration @@ -215,6 +217,10 @@ Rectangle { } } } + + Component.onCompleted: { + tabStack.currentIndex = root.selectedTab + } } } From ae69a4f11aad9c34317cf12f09cd3926d7be84df Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 7 Jul 2025 16:48:43 +0200 Subject: [PATCH 152/328] ai: load/save --- .../quickshell/modules/common/Directories.qml | 6 +- .../quickshell/modules/sidebarLeft/AiChat.qml | 24 ++++++ .config/quickshell/services/Ai.qml | 76 ++++++++++++++++++- .config/quickshell/services/AiMessageData.qml | 1 + 4 files changed, 104 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/common/Directories.qml b/.config/quickshell/modules/common/Directories.qml index b058c200..f4eb448c 100644 --- a/.config/quickshell/modules/common/Directories.qml +++ b/.config/quickshell/modules/common/Directories.qml @@ -33,14 +33,16 @@ Singleton { property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/colors/switchwall.sh`) property string defaultAiPrompts: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/defaults/ai/prompts`) property string userAiPrompts: FileUtils.trimFileProtocol(`${Directories.shellConfig}/ai/prompts`) + property string aiChats: FileUtils.trimFileProtocol(`${Directories.state}/user/ai/chats`) // Cleanup on init Component.onCompleted: { - Quickshell.execDetached(["bash", "-c", `mkdir -p '${shellConfig}'`]) - Quickshell.execDetached(["bash", "-c", `mkdir -p '${favicons}'`]) + Quickshell.execDetached(["mkdir", "-p", `${shellConfig}`]) + Quickshell.execDetached(["mkdir", "-p", `${favicons}`]) Quickshell.execDetached(["bash", "-c", `rm -rf '${coverArt}'; mkdir -p '${coverArt}'`]) Quickshell.execDetached(["bash", "-c", `rm -rf '${booruPreviews}'; mkdir -p '${booruPreviews}'`]) Quickshell.execDetached(["bash", "-c", `mkdir -p '${booruDownloads}' && mkdir -p '${booruDownloadsNsfw}'`]) Quickshell.execDetached(["bash", "-c", `rm -rf '${latexOutput}'; mkdir -p '${latexOutput}'`]) Quickshell.execDetached(["bash", "-c", `rm -rf '${cliphistDecode}'; mkdir -p '${cliphistDecode}'`]) + Quickshell.execDetached(["mkdir", "-p", `${aiChats}`]) } } diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index db5d6682..26d0636c 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -71,6 +71,30 @@ Item { } } }, + { + name: "save", + description: qsTr("Save chat"), + execute: (args) => { + const joinedArgs = args.join(" ") + if (joinedArgs.trim().length == 0) { + Ai.addMessage(`Usage: ${root.commandPrefix}save CHAT_NAME`, Ai.interfaceRole); + return; + } + Ai.saveChat(joinedArgs) + } + }, + { + name: "load", + description: qsTr("Load chat"), + execute: (args) => { + const joinedArgs = args.join(" ") + if (joinedArgs.trim().length == 0) { + Ai.addMessage(`Usage: ${root.commandPrefix}load CHAT_NAME`, Ai.interfaceRole); + return; + } + Ai.loadChat(joinedArgs) + } + }, { name: "clear", description: qsTr("Clear chat history"), diff --git a/.config/quickshell/services/Ai.qml b/.config/quickshell/services/Ai.qml index c97ba2b5..7ab1eb73 100644 --- a/.config/quickshell/services/Ai.qml +++ b/.config/quickshell/services/Ai.qml @@ -19,7 +19,7 @@ Singleton { readonly property string apiKeyEnvVarName: "API_KEY" property Component aiMessageComponent: AiMessageData {} property string systemPrompt: Config.options?.ai?.systemPrompt ?? "" - property var messages: [] + // property var messages: [] property var messageIDs: [] property var messageByID: ({}) readonly property var apiKeys: KeyringStorage.keyringData?.apiKeys ?? {} @@ -317,6 +317,7 @@ Singleton { const aiMessage = aiMessageComponent.createObject(root, { "role": role, "content": message, + "rawContent": message, "thinking": false, "done": true, }); @@ -533,6 +534,7 @@ Singleton { "role": "assistant", "model": currentModelId, "content": "", + "rawContent": "", "thinking": true, "done": false, }); @@ -719,6 +721,7 @@ Singleton { const aiMessage = aiMessageComponent.createObject(root, { "role": "user", "content": `[[ Output of ${name} ]]`, + "rawContent": `[[ Output of ${name} ]]`, "functionName": name, "functionResponse": output, "thinking": false, @@ -771,4 +774,75 @@ Singleton { else root.addMessage(qsTr("Unknown function call: {0}"), "assistant"); } + function chatToJson() { + return root.messageIDs.map(id => { + const message = root.messageByID[id] + return ({ + "role": message.role, + "rawContent": message.rawContent, + "model": message.model, + "thinking": false, + "done": true, + "annotations": message.annotations, + "annotationSources": message.annotationSources, + "functionName": message.functionName, + "functionCall": message.functionCall, + "functionResponse": message.functionResponse, + "visibleToUser": message.visibleToUser, + }) + }) + } + + FileView { + id: chatSaveFile + property string chatName: "chat" + path: `${Directories.aiChats}/${chatName}.json` + } + + /** + * Saves chat to a JSON list of message objects. + * @param chatName name of the chat + */ + function saveChat(chatName) { + chatSaveFile.chatName = chatName + const saveContent = JSON.stringify(root.chatToJson()) + chatSaveFile.setText(saveContent) + } + + /** + * Loads chat from a JSON list of message objects. + * @param chatName name of the chat + */ + function loadChat(chatName) { + try { + chatSaveFile.chatName = chatName + const saveContent = chatSaveFile.text() + console.log(saveContent) + const saveData = JSON.parse(saveContent) + root.clearMessages() + root.messageIDs = saveData.map((_, i) => { + return i + }) + console.log(JSON.stringify(messageIDs)) + for (let i = 0; i < saveData.length; i++) { + const message = saveData[i]; + root.messageByID[i] = root.aiMessageComponent.createObject(root, { + "role": message.role, + "rawContent": message.rawContent, + "content": message.rawContent, + "model": message.model, + "thinking": message.thinking, + "done": message.done, + "annotations": message.annotations, + "annotationSources": message.annotationSources, + "functionName": message.functionName, + "functionCall": message.functionCall, + "functionResponse": message.functionResponse, + "visibleToUser": message.visibleToUser, + }); + } + } catch (e) { + console.log("[AI] Could not load chat: ", e); + } + } } diff --git a/.config/quickshell/services/AiMessageData.qml b/.config/quickshell/services/AiMessageData.qml index b5f20854..dc8b80fd 100644 --- a/.config/quickshell/services/AiMessageData.qml +++ b/.config/quickshell/services/AiMessageData.qml @@ -7,6 +7,7 @@ import QtQuick; QtObject { property string role property string content + property string rawContent property string model property bool thinking: true property bool done: false From 04e0266a4e02faceacecfa5e338b6ac9db480fbc Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:19:50 +0200 Subject: [PATCH 153/328] sidebar: ai: add suggestions for save/load --- .../quickshell/modules/sidebarLeft/AiChat.qml | 44 +++++++++++++++++-- .config/quickshell/services/Ai.qml | 26 +++++++++-- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index 26d0636c..b6ef48c1 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -382,11 +382,11 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) background: null onTextChanged: { // Handle suggestions - if(messageInputField.text.length === 0) { + if (messageInputField.text.length === 0) { root.suggestionQuery = "" root.suggestionList = [] return - } else if(messageInputField.text.startsWith(`${root.commandPrefix}model`)) { + } else if (messageInputField.text.startsWith(`${root.commandPrefix}model`)) { root.suggestionQuery = messageInputField.text.split(" ")[1] ?? "" const modelResults = Fuzzy.go(root.suggestionQuery, Ai.modelList.map(model => { return { @@ -404,7 +404,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) description: `${Ai.models[model.target].description}`, } }) - } else if(messageInputField.text.startsWith(`${root.commandPrefix}prompt`)) { + } else if (messageInputField.text.startsWith(`${root.commandPrefix}prompt`)) { root.suggestionQuery = messageInputField.text.split(" ")[1] ?? "" const promptFileResults = Fuzzy.go(root.suggestionQuery, Ai.promptFiles.map(file => { return { @@ -422,6 +422,44 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) description: `Load prompt from ${file.target}`, } }) + } else if (messageInputField.text.startsWith(`${root.commandPrefix}save`)) { + root.suggestionQuery = messageInputField.text.split(" ")[1] ?? "" + const promptFileResults = Fuzzy.go(root.suggestionQuery, Ai.savedChats.map(file => { + return { + name: Fuzzy.prepare(file), + obj: file, + } + }), { + all: true, + key: "name" + }) + root.suggestionList = promptFileResults.map(file => { + const chatName = FileUtils.trimFileExt(FileUtils.fileNameForPath(file.target)).trim() + return { + name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "save ") : ""}${chatName}`, + displayName: `${chatName}`, + description: `Save chat from ${chatName}`, + } + }) + } else if (messageInputField.text.startsWith(`${root.commandPrefix}load`)) { + root.suggestionQuery = messageInputField.text.split(" ")[1] ?? "" + const promptFileResults = Fuzzy.go(root.suggestionQuery, Ai.savedChats.map(file => { + return { + name: Fuzzy.prepare(file), + obj: file, + } + }), { + all: true, + key: "name" + }) + root.suggestionList = promptFileResults.map(file => { + const chatName = FileUtils.trimFileExt(FileUtils.fileNameForPath(file.target)).trim() + return { + name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "load ") : ""}${chatName}`, + displayName: `${chatName}`, + description: `Load chat from ${file.target}`, + } + }) } else if(messageInputField.text.startsWith(root.commandPrefix)) { root.suggestionQuery = messageInputField.text root.suggestionList = root.allCommands.filter(cmd => cmd.name.startsWith(messageInputField.text.substring(1))).map(cmd => { diff --git a/.config/quickshell/services/Ai.qml b/.config/quickshell/services/Ai.qml index 7ab1eb73..639ae936 100644 --- a/.config/quickshell/services/Ai.qml +++ b/.config/quickshell/services/Ai.qml @@ -39,6 +39,7 @@ Singleton { property list defaultPrompts: [] property list userPrompts: [] property list promptFiles: [...defaultPrompts, ...userPrompts] + property list savedChats: [] // Model properties: // - name: Name of the model @@ -292,6 +293,20 @@ Singleton { } } + Process { + id: getSavedChats + running: true + command: ["ls", "-1", Directories.aiChats] + stdout: StdioCollector { + onStreamFinished: { + if (text.length === 0) return; + root.savedChats = text.split("\n") + .filter(fileName => fileName.endsWith(".json")) + .map(fileName => `${Directories.aiChats}/${fileName}`) + } + } + } + FileView { id: promptLoader watchChanges: false; @@ -797,6 +812,7 @@ Singleton { id: chatSaveFile property string chatName: "chat" path: `${Directories.aiChats}/${chatName}.json` + blockLoading: true } /** @@ -804,9 +820,10 @@ Singleton { * @param chatName name of the chat */ function saveChat(chatName) { - chatSaveFile.chatName = chatName + chatSaveFile.chatName = chatName.trim() const saveContent = JSON.stringify(root.chatToJson()) chatSaveFile.setText(saveContent) + getSavedChats.running = true; } /** @@ -815,9 +832,10 @@ Singleton { */ function loadChat(chatName) { try { - chatSaveFile.chatName = chatName + chatSaveFile.chatName = chatName.trim() + chatSaveFile.reload() const saveContent = chatSaveFile.text() - console.log(saveContent) + // console.log(saveContent) const saveData = JSON.parse(saveContent) root.clearMessages() root.messageIDs = saveData.map((_, i) => { @@ -843,6 +861,8 @@ Singleton { } } catch (e) { console.log("[AI] Could not load chat: ", e); + } finally { + getSavedChats.running = true; } } } From 813395c9873deab32895fd998e9729ee07c0845b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:30:44 +0200 Subject: [PATCH 154/328] move weathericons.qml --- .config/quickshell/modules/bar/weather/WeatherBar.qml | 1 - .../{constants => modules/bar/weather}/WeatherIcons.qml | 0 2 files changed, 1 deletion(-) rename .config/quickshell/{constants => modules/bar/weather}/WeatherIcons.qml (100%) diff --git a/.config/quickshell/modules/bar/weather/WeatherBar.qml b/.config/quickshell/modules/bar/weather/WeatherBar.qml index 5d54562d..eae1b613 100644 --- a/.config/quickshell/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/modules/bar/weather/WeatherBar.qml @@ -1,7 +1,6 @@ pragma ComponentBehavior: Bound import "root:/modules/common" import "root:/modules/common/widgets" -import "root:/constants" import "root:/services" import Quickshell import QtQuick diff --git a/.config/quickshell/constants/WeatherIcons.qml b/.config/quickshell/modules/bar/weather/WeatherIcons.qml similarity index 100% rename from .config/quickshell/constants/WeatherIcons.qml rename to .config/quickshell/modules/bar/weather/WeatherIcons.qml From 52810b97f4435c28ba062d31a5a6cc688a829602 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:43:19 +0200 Subject: [PATCH 155/328] settings: apply colors on material palette selection --- .config/quickshell/modules/settings/StyleConfig.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/modules/settings/StyleConfig.qml b/.config/quickshell/modules/settings/StyleConfig.qml index b86c0daa..6de02639 100644 --- a/.config/quickshell/modules/settings/StyleConfig.qml +++ b/.config/quickshell/modules/settings/StyleConfig.qml @@ -50,6 +50,7 @@ ContentPage { configOptionName: "appearance.palette.type" onSelected: (newValue) => { Config.options.appearance.palette.type = newValue; + Quickshell.execDetached(["bash", "-c", `${Directories.wallpaperSwitchScriptPath} --noswitch`]) } options: [ {"value": "auto", "displayName": "Auto"}, From 45369c1ec4703dd5a52ecdadd34f99182aa42543 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:43:44 +0200 Subject: [PATCH 156/328] appearance: not make bg color weird --- .config/quickshell/modules/common/Appearance.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index c8b62350..88e04bd3 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -100,7 +100,7 @@ Singleton { colors: QtObject { property color colSubtext: m3colors.m3outline - property color colLayer0: ColorUtils.mix(ColorUtils.transparentize(m3colors.m3background, root.transparency), m3colors.m3primary, Config.options.appearance.extraBackgroundTint ? 0.97 : 1) + property color colLayer0: ColorUtils.mix(ColorUtils.transparentize(m3colors.m3background, root.transparency), m3colors.m3primary, Config.options.appearance.extraBackgroundTint ? 0.99 : 1) property color colOnLayer0: m3colors.m3onBackground property color colLayer0Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer0, colOnLayer0, 0.9, root.contentTransparency)) property color colLayer0Active: ColorUtils.transparentize(ColorUtils.mix(colLayer0, colOnLayer0, 0.8, root.contentTransparency)) From d801f132d1e8e0dc979a002a645053aca7896d00 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:56:54 +0200 Subject: [PATCH 157/328] bar: add outline to floating mode --- .config/quickshell/modules/bar/Bar.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 27b188d0..5540db5e 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -104,6 +104,8 @@ Scope { } color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" radius: Config.options.bar.cornerStyle === 1 ? Appearance.rounding.windowRounding : 0 + border.width: Config.options.bar.cornerStyle === 1 ? 1 : 0 + border.color: Appearance.m3colors.m3outlineVariant } MouseArea { // Left side | scroll to change brightness From 32380d29c8c93f99c820f18e6e1ba4101b1b0298 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:57:05 +0200 Subject: [PATCH 158/328] settings: add osd timeout --- .../modules/settings/InterfaceConfig.qml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.config/quickshell/modules/settings/InterfaceConfig.qml b/.config/quickshell/modules/settings/InterfaceConfig.qml index 9e23fafb..ab9d24a3 100644 --- a/.config/quickshell/modules/settings/InterfaceConfig.qml +++ b/.config/quickshell/modules/settings/InterfaceConfig.qml @@ -306,6 +306,20 @@ ContentPage { } } + ContentSection { + title: "On-screen display" + ConfigSpinBox { + text: "Timeout (ms)" + value: Config.options.osd.timeout + from: 100 + to: 3000 + stepSize: 100 + onValueChanged: { + Config.options.osd.timeout = value; + } + } + } + ContentSection { title: "Overview" ConfigSpinBox { From 2d6a897a66a679a0752febae51fc5532664fc734 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 7 Jul 2025 18:17:57 +0200 Subject: [PATCH 159/328] settings: more options --- .../modules/settings/InterfaceConfig.qml | 15 +++++++++++++++ .../modules/settings/ServicesConfig.qml | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/.config/quickshell/modules/settings/InterfaceConfig.qml b/.config/quickshell/modules/settings/InterfaceConfig.qml index ab9d24a3..2d692442 100644 --- a/.config/quickshell/modules/settings/InterfaceConfig.qml +++ b/.config/quickshell/modules/settings/InterfaceConfig.qml @@ -356,4 +356,19 @@ ContentPage { } } } + + ContentSection { + title: "Screenshot tool" + + ConfigSwitch { + text: 'Show regions of potential interest' + checked: Config.options.screenshotTool.showContentRegions + onCheckedChanged: { + Config.options.screenshotTool.showContentRegions = checked; + } + StyledToolTip { + content: "Such regions could be images or parts of the screen that have some containment.\nMight not always be accurate.\nThis is done with an image processing algorithm run locally and no AI is used." + } + } + } } diff --git a/.config/quickshell/modules/settings/ServicesConfig.qml b/.config/quickshell/modules/settings/ServicesConfig.qml index af241d67..f4f6bb28 100644 --- a/.config/quickshell/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/modules/settings/ServicesConfig.qml @@ -137,4 +137,19 @@ ContentPage { } } } + + ContentSection { + title: "Search" + + ConfigSwitch { + text: "Use Levenshtein distance-based algorithm instead of fuzzy" + checked: Config.options.search.sloppy + onCheckedChanged: { + Config.options.search.sloppy = checked; + } + StyledToolTip { + content: "Could be better if you make a ton of typos,\nbut results can be weird and might not work with acronyms\n(e.g. \"GIMP\" might not give you the paint program)" + } + } + } } From 44443c4a37e8a64286a1ce02c666e98675f87131 Mon Sep 17 00:00:00 2001 From: Pim Rijkers Date: Tue, 8 Jul 2025 14:16:40 +0200 Subject: [PATCH 160/328] moved storage from config to persistent state --- .config/quickshell/modules/common/Config.qml | 3 --- .config/quickshell/modules/common/Persistent.qml | 1 + .config/quickshell/modules/common/PersistentStates.qml | 1 + .config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml | 4 ++-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index 3420549d..81a8989d 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -206,9 +206,6 @@ Singleton { property string username: "[unset]" } } - property JsonObject bottomWidgetRight: JsonObject { - property int lastTab: 0 - } } property JsonObject time: JsonObject { diff --git a/.config/quickshell/modules/common/Persistent.qml b/.config/quickshell/modules/common/Persistent.qml index 62a39e3c..abd062d7 100644 --- a/.config/quickshell/modules/common/Persistent.qml +++ b/.config/quickshell/modules/common/Persistent.qml @@ -36,6 +36,7 @@ Singleton { property JsonObject sidebar: JsonObject { property JsonObject bottomGroup: JsonObject { property bool collapsed: false + property int tab: 0 } } diff --git a/.config/quickshell/modules/common/PersistentStates.qml b/.config/quickshell/modules/common/PersistentStates.qml index 6887b479..d6588725 100644 --- a/.config/quickshell/modules/common/PersistentStates.qml +++ b/.config/quickshell/modules/common/PersistentStates.qml @@ -12,6 +12,7 @@ Singleton { property QtObject sidebar: QtObject { property QtObject bottomGroup: QtObject { property bool collapsed: false + property int tab: 0 } } diff --git a/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml index 50730796..764258e6 100644 --- a/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml +++ b/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml @@ -14,7 +14,7 @@ Rectangle { color: Appearance.colors.colLayer1 clip: true implicitHeight: collapsed ? collapsedBottomWidgetGroupRow.implicitHeight : bottomWidgetGroupRow.implicitHeight - property int selectedTab: Config.options.sidebar.bottomWidgetRight.lastTab + property int selectedTab: Persistent.states.sidebar.bottomGroup.tab property bool collapsed: Persistent.states.sidebar.bottomGroup.collapsed property var tabs: [ {"type": "calendar", "name": "Calendar", "icon": "calendar_month", "widget": calendarWidget}, @@ -146,7 +146,7 @@ Rectangle { buttonIcon: modelData.icon onClicked: { root.selectedTab = index - Config.options.sidebar.bottomWidgetRight.lastTab = index + Persistent.states.sidebar.bottomGroup.tab = index } } } From b0750506cf82a9b4b6295a6b3a24a17511a60c65 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 09:40:59 +0700 Subject: [PATCH 161/328] give CustomIcon colorization --- .config/quickshell/modules/bar/Bar.qml | 6 +----- .../quickshell/modules/common/widgets/CustomIcon.qml | 12 ++++++++++++ .../modules/sidebarLeft/aiChat/AiMessage.qml | 7 ++----- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 5540db5e..a46779e9 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -206,11 +206,7 @@ Scope { width: 19.5 height: 19.5 source: Config.options.bar.topLeftIcon == 'distro' ? SystemInfo.distroIcon : "spark-symbolic" - } - - ColorOverlay { - anchors.fill: distroIcon - source: distroIcon + colorize: true color: Appearance.colors.colOnLayer0 } } diff --git a/.config/quickshell/modules/common/widgets/CustomIcon.qml b/.config/quickshell/modules/common/widgets/CustomIcon.qml index 8905b071..28519615 100644 --- a/.config/quickshell/modules/common/widgets/CustomIcon.qml +++ b/.config/quickshell/modules/common/widgets/CustomIcon.qml @@ -1,10 +1,13 @@ import QtQuick import Quickshell import Quickshell.Widgets +import Qt5Compat.GraphicalEffects Item { id: root + property bool colorize: false + property color color property string source: "" property string iconFolder: "root:/assets/icons" // The folder to check first width: 30 @@ -21,4 +24,13 @@ Item { } implicitSize: root.height } + + Loader { + active: root.colorize + anchors.fill: iconImage + sourceComponent: ColorOverlay { + source: iconImage + color: root.color + } + } } diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml index 3e5b96d3..a483dd8a 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml @@ -121,11 +121,8 @@ Rectangle { height: Appearance.font.pixelSize.large source: messageData?.role == 'assistant' ? Ai.models[messageData?.model].icon : messageData?.role == 'user' ? 'linux-symbolic' : 'desktop-symbolic' - } - ColorOverlay { - visible: modelIcon.visible - anchors.fill: modelIcon - source: modelIcon + + colorize: true color: Appearance.m3colors.m3onSecondaryContainer } From 8ca2ed6781c3ce4ab7b78617be6cc88c23bfac72 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 09:41:13 +0700 Subject: [PATCH 162/328] periodic table --- .../modules/cheatsheet/Cheatsheet.qml | 94 +++++++-- .../cheatsheet/CheatsheetPeriodicTable.qml | 73 +++++++ .../modules/cheatsheet/ElementTile.qml | 59 ++++++ .../modules/cheatsheet/periodic_table.js | 196 ++++++++++++++++++ 4 files changed, 408 insertions(+), 14 deletions(-) create mode 100644 .config/quickshell/modules/cheatsheet/CheatsheetPeriodicTable.qml create mode 100644 .config/quickshell/modules/cheatsheet/ElementTile.qml create mode 100644 .config/quickshell/modules/cheatsheet/periodic_table.js diff --git a/.config/quickshell/modules/cheatsheet/Cheatsheet.qml b/.config/quickshell/modules/cheatsheet/Cheatsheet.qml index 0edc121e..8e409ab9 100644 --- a/.config/quickshell/modules/cheatsheet/Cheatsheet.qml +++ b/.config/quickshell/modules/cheatsheet/Cheatsheet.qml @@ -7,6 +7,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Effects import QtQuick.Layouts +import Qt5Compat.GraphicalEffects import Quickshell.Io import Quickshell import Quickshell.Widgets @@ -15,11 +16,22 @@ import Quickshell.Hyprland Scope { // Scope id: root + property var tabButtonList: [ + { + "icon": "keyboard", + "name": qsTr("Keybinds") + }, + { + "icon": "experiment", + "name": qsTr("Elements") + }, + ] + property int selectedTab: 0 Loader { id: cheatsheetLoader active: false - + sourceComponent: PanelWindow { // Window id: cheatsheetRoot visible: cheatsheetLoader.active @@ -32,7 +44,7 @@ Scope { // Scope } function hide() { - cheatsheetLoader.active = false + cheatsheetLoader.active = false; } exclusiveZone: 0 implicitWidth: cheatsheetBackground.width + Appearance.sizes.elevationMargin * 2 @@ -48,14 +60,14 @@ Scope { // Scope HyprlandFocusGrab { // Click outside to close id: grab - windows: [ cheatsheetRoot ] + windows: [cheatsheetRoot] active: cheatsheetRoot.visible onCleared: () => { - if (!active) cheatsheetRoot.hide() + if (!active) + cheatsheetRoot.hide(); } } - // Background StyledRectangularShadow { target: cheatsheetBackground @@ -71,9 +83,24 @@ Scope { // Scope implicitWidth: cheatsheetColumnLayout.implicitWidth + padding * 2 implicitHeight: cheatsheetColumnLayout.implicitHeight + padding * 2 - Keys.onPressed: (event) => { // Esc to close + Keys.onPressed: event => { // Esc to close if (event.key === Qt.Key_Escape) { - cheatsheetRoot.hide() + cheatsheetRoot.hide(); + } + if (event.modifiers === Qt.ControlModifier) { + if (event.key === Qt.Key_PageDown) { + root.selectedTab = Math.min(root.selectedTab + 1, root.tabButtonList.length - 1); + event.accepted = true; + } else if (event.key === Qt.Key_PageUp) { + root.selectedTab = Math.max(root.selectedTab - 1, 0); + event.accepted = true; + } else if (event.key === Qt.Key_Tab) { + root.selectedTab = (root.selectedTab + 1) % root.tabButtonList.length; + event.accepted = true; + } else if (event.key === Qt.Key_Backtab) { + root.selectedTab = (root.selectedTab - 1 + root.tabButtonList.length) % root.tabButtonList.length; + event.accepted = true; + } } } @@ -91,7 +118,7 @@ Scope { // Scope } onClicked: { - cheatsheetRoot.hide() + cheatsheetRoot.hide(); } contentItem: MaterialSymbol { @@ -114,10 +141,50 @@ Scope { // Scope font.pixelSize: Appearance.font.pixelSize.title text: qsTr("Cheat sheet") } - CheatsheetKeybinds {} + PrimaryTabBar { // Tab strip + id: tabBar + tabButtonList: root.tabButtonList + externalTrackedTab: root.selectedTab + function onCurrentIndexChanged(currentIndex) { + root.selectedTab = currentIndex; + } + } + + SwipeView { // Content pages + id: swipeView + Layout.topMargin: 5 + Layout.fillWidth: true + Layout.fillHeight: true + spacing: 10 + + Behavior on implicitWidth { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + Behavior on implicitHeight { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + + currentIndex: tabBar.externalTrackedTab + onCurrentIndexChanged: { + tabBar.enableIndicatorAnimation = true; + root.selectedTab = currentIndex; + } + + clip: true + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Rectangle { + width: swipeView.width + height: swipeView.height + radius: Appearance.rounding.small + } + } + + CheatsheetKeybinds {} + CheatsheetPeriodicTable {} + } } } - } } @@ -125,15 +192,15 @@ Scope { // Scope target: "cheatsheet" function toggle(): void { - cheatsheetLoader.active = !cheatsheetLoader.active + cheatsheetLoader.active = !cheatsheetLoader.active; } function close(): void { - cheatsheetLoader.active = false + cheatsheetLoader.active = false; } function open(): void { - cheatsheetLoader.active = true + cheatsheetLoader.active = true; } } @@ -163,5 +230,4 @@ Scope { // Scope cheatsheetLoader.active = false; } } - } diff --git a/.config/quickshell/modules/cheatsheet/CheatsheetPeriodicTable.qml b/.config/quickshell/modules/cheatsheet/CheatsheetPeriodicTable.qml new file mode 100644 index 00000000..774c522e --- /dev/null +++ b/.config/quickshell/modules/cheatsheet/CheatsheetPeriodicTable.qml @@ -0,0 +1,73 @@ +import "root:/" +import "root:/services" +import "root:/modules/common" +import "root:/modules/common/widgets" +import "root:/modules/common/functions/file_utils.js" as FileUtils +import "periodic_table.js" as PTable +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Widgets +import Quickshell.Hyprland + +Item { + id: root + readonly property var elements: PTable.elements + readonly property var series: PTable.series + property real spacing: 6 + implicitWidth: mainLayout.implicitWidth + implicitHeight: mainLayout.implicitHeight + + ColumnLayout { + id: mainLayout + spacing: root.spacing + + Repeater { // Main table rows + model: root.elements + + delegate: RowLayout { // Table cells + id: tableRow + spacing: root.spacing + required property var modelData + + Repeater { + model: tableRow.modelData + delegate: ElementTile { + required property var modelData + element: modelData + } + + } + } + + } + + Item { + id: gap + implicitHeight: 20 + } + + Repeater { // Main table rows + model: root.series + + delegate: RowLayout { // Table cells + id: seriesTableRow + spacing: root.spacing + required property var modelData + + Repeater { + model: seriesTableRow.modelData + delegate: ElementTile { + required property var modelData + element: modelData + } + + } + } + + } + } + +} \ No newline at end of file diff --git a/.config/quickshell/modules/cheatsheet/ElementTile.qml b/.config/quickshell/modules/cheatsheet/ElementTile.qml new file mode 100644 index 00000000..1784183b --- /dev/null +++ b/.config/quickshell/modules/cheatsheet/ElementTile.qml @@ -0,0 +1,59 @@ +import "root:/modules/common" +import "root:/modules/common/widgets" +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io + +RippleButton { + id: root + required property var element + opacity: element.type != "empty" ? 1 : 0 + implicitHeight: 60 + implicitWidth: 60 + colBackground: Appearance.colors.colLayer2 + buttonRadius: Appearance.rounding.small + + Rectangle { + anchors { + top: parent.top + left: parent.left + topMargin: 4 + leftMargin: 4 + } + color: Appearance.colors.colSecondaryContainer + radius: Appearance.rounding.full + implicitWidth: Math.max(20, elementNumber.implicitWidth) + implicitHeight: Math.max(20, elementNumber.implicitHeight) + width: height + + StyledText { + id: elementNumber + anchors.centerIn: parent + color: Appearance.colors.colOnSecondaryContainer + text: root.element.number + font.pixelSize: Appearance.font.pixelSize.smaller + } + } + + StyledText { + id: elementSymbol + anchors.centerIn: parent + color: Appearance.colors.colOnLayer2 + font.pixelSize: Appearance.font.pixelSize.huge + text: root.element.symbol + } + + StyledText { + id: elementName + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + bottomMargin: 4 + } + font.pixelSize: Appearance.font.pixelSize.smallest + color: Appearance.colors.colOnLayer2 + text: root.element.name + } +} diff --git a/.config/quickshell/modules/cheatsheet/periodic_table.js b/.config/quickshell/modules/cheatsheet/periodic_table.js new file mode 100644 index 00000000..45d69cc9 --- /dev/null +++ b/.config/quickshell/modules/cheatsheet/periodic_table.js @@ -0,0 +1,196 @@ +// List of rows +const elements = [ + [ + { name: 'Hydrogen', symbol: 'H', number: 1, weight: 1.01, type: 'nonmetal' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: 'Helium', symbol: 'He', number: 2, weight: 4.00, type: 'noblegas' }, + ], + [ + { name: 'Lithium', symbol: 'Li', number: 3, weight: 6.94, type: 'metal' }, + { name: 'Beryllium', symbol: 'Be', number: 4, weight: 9.01, type: 'metal' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: 'Boron', symbol: 'B', number: 5, weight: 10.81, type: 'nonmetal' }, + { name: 'Carbon', symbol: 'C', number: 6, weight: 12.01, type: 'nonmetal' }, + { name: 'Nitrogen', symbol: 'N', number: 7, weight: 14.01, type: 'nonmetal' }, + { name: 'Oxygen', symbol: 'O', number: 8, weight: 16, type: 'nonmetal' }, + { name: 'Fluorine', symbol: 'F', number: 9, weight: 19, type: 'nonmetal' }, + { name: 'Neon', symbol: 'Ne', number: 10, weight: 20.18, type: 'noblegas' }, + + + ], + [ + { name: 'Sodium', symbol: 'Na', number: 11, weight: 22.99, type: 'metal' }, + { name: 'Magnesium', symbol: 'Mg', number: 12, weight: 24.31, type: 'metal' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: 'Aluminum', symbol: 'Al', number: 13, weight: 26.98, type: 'metal' }, + { name: 'Silicon', symbol: 'Si', number: 14, weight: 28.09, type: 'nonmetal' }, + { name: 'Phosphorus', symbol: 'P', number: 15, weight: 30.97, type: 'nonmetal' }, + { name: 'Sulfur', symbol: 'S', number: 16, weight: 32.07, type: 'nonmetal' }, + { name: 'Chlorine', symbol: 'Cl', number: 17, weight: 35.45, type: 'nonmetal' }, + { name: 'Argon', symbol: 'Ar', number: 18, weight: 39.95, type: 'noblegas' }, + ], + [ + { name: 'Potassium', symbol: 'K', number: 19, weight: 39.098, type: 'metal' }, + { name: 'Calcium', symbol: 'Ca', number: 20, weight: 40.078, type: 'metal' }, + { name: 'Scandium', symbol: 'Sc', number: 21, weight: 44.956, type: 'metal' }, + { name: 'Titanium', symbol: 'Ti', number: 22, weight: 47.87, type: 'metal' }, + { name: 'Vanadium', symbol: 'V', number: 23, weight: 50.94, type: 'metal' }, + { name: 'Chromium', symbol: 'Cr', number: 24, weight: 52, type: 'metal'/*, icon: 'chromium-browser'*/ }, + { name: 'Manganese', symbol: 'Mn', number: 25, weight: 54.94, type: 'metal' }, + { name: 'Iron', symbol: 'Fe', number: 26, weight: 55.85, type: 'metal' }, + { name: 'Cobalt', symbol: 'Co', number: 27, weight: 58.93, type: 'metal' }, + { name: 'Nickel', symbol: 'Ni', number: 28, weight: 58.69, type: 'metal' }, + { name: 'Copper', symbol: 'Cu', number: 29, weight: 63.55, type: 'metal' }, + { name: 'Zinc', symbol: 'Zn', number: 30, weight: 65.38, type: 'metal' }, + { name: 'Gallium', symbol: 'Ga', number: 31, weight: 69.72, type: 'metal' }, + { name: 'Germanium', symbol: 'Ge', number: 32, weight: 72.63, type: 'metal' }, + { name: 'Arsenic', symbol: 'As', number: 33, weight: 74.92, type: 'nonmetal' }, + { name: 'Selenium', symbol: 'Se', number: 34, weight: 78.96, type: 'nonmetal' }, + { name: 'Bromine', symbol: 'Br', number: 35, weight: 79.904, type: 'nonmetal' }, + { name: 'Krypton', symbol: 'Kr', number: 36, weight: 83.8, type: 'noblegas' }, + ], + [ + { name: 'Rubidium', symbol: 'Rb', number: 37, weight: 85.47, type: 'metal' }, + { name: 'Strontium', symbol: 'Sr', number: 38, weight: 87.62, type: 'metal' }, + { name: 'Yttrium', symbol: 'Y', number: 39, weight: 88.91, type: 'metal' }, + { name: 'Zirconium', symbol: 'Zr', number: 40, weight: 91.22, type: 'metal' }, + { name: 'Niobium', symbol: 'Nb', number: 41, weight: 92.91, type: 'metal' }, + { name: 'Molybdenum', symbol: 'Mo', number: 42, weight: 95.94, type: 'metal' }, + { name: 'Technetium', symbol: 'Tc', number: 43, weight: 98, type: 'metal' }, + { name: 'Ruthenium', symbol: 'Ru', number: 44, weight: 101.07, type: 'metal' }, + { name: 'Rhodium', symbol: 'Rh', number: 45, weight: 102.91, type: 'metal' }, + { name: 'Palladium', symbol: 'Pd', number: 46, weight: 106.42, type: 'metal' }, + { name: 'Silver', symbol: 'Ag', number: 47, weight: 107.87, type: 'metal' }, + { name: 'Cadmium', symbol: 'Cd', number: 48, weight: 112.41, type: 'metal' }, + { name: 'Indium', symbol: 'In', number: 49, weight: 114.82, type: 'metal' }, + { name: 'Tin', symbol: 'Sn', number: 50, weight: 118.71, type: 'metal' }, + { name: 'Antimony', symbol: 'Sb', number: 51, weight: 121.76, type: 'metal' }, + { name: 'Tellurium', symbol: 'Te', number: 52, weight: 127.6, type: 'nonmetal' }, + { name: 'Iodine', symbol: 'I', number: 53, weight: 126.9, type: 'nonmetal' }, + { name: 'Xenon', symbol: 'Xe', number: 54, weight: 131.29, type: 'noblegas' }, + ], + [ + { name: 'Cesium', symbol: 'Cs', number: 55, weight: 132.91, type: 'metal' }, + { name: 'Barium', symbol: 'Ba', number: 56, weight: 137.33, type: 'metal' }, + { name: 'Lanthanum', symbol: 'La', number: 57, weight: 138.91, type: 'lanthanum' }, + { name: 'Hafnium', symbol: 'Hf', number: 72, weight: 178.49, type: 'metal' }, + { name: 'Tantalum', symbol: 'Ta', number: 73, weight: 180.95, type: 'metal' }, + { name: 'Tungsten', symbol: 'W', number: 74, weight: 183.84, type: 'metal' }, + { name: 'Rhenium', symbol: 'Re', number: 75, weight: 186.21, type: 'metal' }, + { name: 'Osmium', symbol: 'Os', number: 76, weight: 190.23, type: 'metal' }, + { name: 'Iridium', symbol: 'Ir', number: 77, weight: 192.22, type: 'metal' }, + { name: 'Platinum', symbol: 'Pt', number: 78, weight: 195.09, type: 'metal' }, + { name: 'Gold', symbol: 'Au', number: 79, weight: 196.97, type: 'metal' }, + { name: 'Mercury', symbol: 'Hg', number: 80, weight: 200.59, type: 'metal' }, + { name: 'Thallium', symbol: 'Tl', number: 81, weight: 204.38, type: 'metal' }, + { name: 'Lead', symbol: 'Pb', number: 82, weight: 207.2, type: 'metal' }, + { name: 'Bismuth', symbol: 'Bi', number: 83, weight: 208.98, type: 'metal' }, + { name: 'Polonium', symbol: 'Po', number: 84, weight: 209, type: 'metal' }, + { name: 'Astatine', symbol: 'At', number: 85, weight: 210, type: 'nonmetal' }, + { name: 'Radon', symbol: 'Rn', number: 86, weight: 222, type: 'noblegas' }, + ], + [ + { name: 'Francium', symbol: 'Fr', number: 87, weight: 223, type: 'metal' }, + { name: 'Radium', symbol: 'Ra', number: 88, weight: 226, type: 'metal' }, + { name: 'Actinium', symbol: 'Ac', number: 89, weight: 227, type: 'actinium' }, + { name: 'Rutherfordium', symbol: 'Rf', number: 104, weight: 267, type: 'metal' }, + { name: 'Dubnium', symbol: 'Db', number: 105, weight: 268, type: 'metal' }, + { name: 'Seaborgium', symbol: 'Sg', number: 106, weight: 271, type: 'metal' }, + { name: 'Bohrium', symbol: 'Bh', number: 107, weight: 272, type: 'metal' }, + { name: 'Hassium', symbol: 'Hs', number: 108, weight: 277, type: 'metal' }, + { name: 'Meitnerium', symbol: 'Mt', number: 109, weight: 278, type: 'metal' }, + { name: 'Darmstadtium', symbol: 'Ds', number: 110, weight: 281, type: 'metal' }, + { name: 'Roentgenium', symbol: 'Rg', number: 111, weight: 280, type: 'metal' }, + { name: 'Copernicium', symbol: 'Cn', number: 112, weight: 285, type: 'metal' }, + { name: 'Nihonium', symbol: 'Nh', number: 113, weight: 286, type: 'metal' }, + { name: 'Flerovium', symbol: 'Fl', number: 114, weight: 289, type: 'metal' }, + { name: 'Moscovium', symbol: 'Mc', number: 115, weight: 290, type: 'metal' }, + { name: 'Livermorium', symbol: 'Lv', number: 116, weight: 293, type: 'metal' }, + { name: 'Tennessine', symbol: 'Ts', number: 117, weight: 294, type: 'metal' }, + { name: 'Oganesson', symbol: 'Og', number: 118, weight: 294, type: 'noblegas' }, + ], +] + +const series = [ + [ + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: 'Cerium', symbol: 'Ce', number: 58, weight: 140.12, type: 'lanthanum' }, + { name: 'Praseodymium', symbol: 'Pr', number: 59, weight: 140.91, type: 'lanthanum' }, + { name: 'Neodymium', symbol: 'Nd', number: 60, weight: 144.24, type: 'lanthanum' }, + { name: 'Promethium', symbol: 'Pm', number: 61, weight: 145, type: 'lanthanum' }, + { name: 'Samarium', symbol: 'Sm', number: 62, weight: 150.36, type: 'lanthanum' }, + { name: 'Europium', symbol: 'Eu', number: 63, weight: 151.96, type: 'lanthanum' }, + { name: 'Gadolinium', symbol: 'Gd', number: 64, weight: 157.25, type: 'lanthanum' }, + { name: 'Terbium', symbol: 'Tb', number: 65, weight: 158.93, type: 'lanthanum' }, + { name: 'Dysprosium', symbol: 'Dy', number: 66, weight: 162.5, type: 'lanthanum' }, + { name: 'Holmium', symbol: 'Ho', number: 67, weight: 164.93, type: 'lanthanum' }, + { name: 'Erbium', symbol: 'Er', number: 68, weight: 167.26, type: 'lanthanum' }, + { name: 'Thulium', symbol: 'Tm', number: 69, weight: 168.93, type: 'lanthanum' }, + { name: 'Ytterbium', symbol: 'Yb', number: 70, weight: 173.04, type: 'lanthanum' }, + { name: 'Lutetium', symbol: 'Lu', number: 71, weight: 174.97, type: 'lanthanum' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + ], + [ + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + { name: 'Thorium', symbol: 'Th', number: 90, weight: 232.04, type: 'actinium' }, + { name: 'Protactinium', symbol: 'Pa', number: 91, weight: 231.04, type: 'actinium' }, + { name: 'Uranium', symbol: 'U', number: 92, weight: 238.03, type: 'actinium' }, + { name: 'Neptunium', symbol: 'Np', number: 93, weight: 237, type: 'actinium' }, + { name: 'Plutonium', symbol: 'Pu', number: 94, weight: 244, type: 'actinium' }, + { name: 'Americium', symbol: 'Am', number: 95, weight: 243, type: 'actinium' }, + { name: 'Curium', symbol: 'Cm', number: 96, weight: 247, type: 'actinium' }, + { name: 'Berkelium', symbol: 'Bk', number: 97, weight: 247, type: 'actinium' }, + { name: 'Californium', symbol: 'Cf', number: 98, weight: 251, type: 'actinium' }, + { name: 'Einsteinium', symbol: 'Es', number: 99, weight: 252, type: 'actinium' }, + { name: 'Fermium', symbol: 'Fm', number: 100, weight: 257, type: 'actinium' }, + { name: 'Mendelevium', symbol: 'Md', number: 101, weight: 258, type: 'actinium' }, + { name: 'Nobelium', symbol: 'No', number: 102, weight: 259, type: 'actinium' }, + { name: 'Lawrencium', symbol: 'Lr', number: 103, weight: 262, type: 'actinium' }, + { name: '', symbol: '', number: -1, weight: 0, type: 'empty' }, + ], +]; + +const niceTypes = { + 'metal': "Metal", + 'nonmetal': "Nonmetal", + 'noblegas': "Noble gas", + 'lanthanum': "Lanthanum", + 'actinium': "Actinium" +} From a0301bbc1392c44f1ad9b2453859cfdb3b2e5c9c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 09:46:10 +0700 Subject: [PATCH 163/328] settings: add search prefixes --- .../modules/settings/ServicesConfig.qml | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/.config/quickshell/modules/settings/ServicesConfig.qml b/.config/quickshell/modules/settings/ServicesConfig.qml index f4f6bb28..ea4fac69 100644 --- a/.config/quickshell/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/modules/settings/ServicesConfig.qml @@ -151,5 +151,52 @@ ContentPage { content: "Could be better if you make a ton of typos,\nbut results can be weird and might not work with acronyms\n(e.g. \"GIMP\" might not give you the paint program)" } } + + ContentSubsection { + title: "Prefixes" + ConfigRow { + uniform: true + + MaterialTextField { + Layout.fillWidth: true + placeholderText: "Action" + text: Config.options.search.prefix.action + wrapMode: TextEdit.Wrap + onTextChanged: { + Config.options.search.prefix.action = text; + } + } + MaterialTextField { + Layout.fillWidth: true + placeholderText: "Clipboard" + text: Config.options.search.prefix.clipboard + wrapMode: TextEdit.Wrap + onTextChanged: { + Config.options.search.prefix.clipboard = text; + } + } + MaterialTextField { + Layout.fillWidth: true + placeholderText: "Emojis" + text: Config.options.search.prefix.emojis + wrapMode: TextEdit.Wrap + onTextChanged: { + Config.options.search.prefix.emojis = text; + } + } + } + } + ContentSubsection { + title: "Web search" + MaterialTextField { + Layout.fillWidth: true + placeholderText: "Base URL" + text: Config.options.search.engineBaseUrl + wrapMode: TextEdit.Wrap + onTextChanged: { + Config.options.search.engineBaseUrl = text; + } + } + } } } From 9a90d26e8109d9f43d76e1b9c0a7447004abb8df Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 10:13:37 +0700 Subject: [PATCH 164/328] right sidebar: cloudflare warp --- .../modules/common/widgets/ButtonGroup.qml | 1 + .../modules/sidebarRight/SidebarRight.qml | 1 + .../quickToggles/CloudflareWarp.qml | 89 +++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 .config/quickshell/modules/sidebarRight/quickToggles/CloudflareWarp.qml diff --git a/.config/quickshell/modules/common/widgets/ButtonGroup.qml b/.config/quickshell/modules/common/widgets/ButtonGroup.qml index 5356535f..4b8676f4 100644 --- a/.config/quickshell/modules/common/widgets/ButtonGroup.qml +++ b/.config/quickshell/modules/common/widgets/ButtonGroup.qml @@ -20,6 +20,7 @@ Rectangle { let total = 0; for (let i = 0; i < rowLayout.children.length; ++i) { const child = rowLayout.children[i]; + if (!child.visible) continue; total += child.baseWidth ?? child.implicitWidth ?? child.width; } return total + rowLayout.spacing * (rowLayout.children.length - 1); diff --git a/.config/quickshell/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/modules/sidebarRight/SidebarRight.qml index 376687af..71ce53db 100644 --- a/.config/quickshell/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/modules/sidebarRight/SidebarRight.qml @@ -179,6 +179,7 @@ Scope { NightLight {} GameMode {} IdleInhibitor {} + CloudflareWarp {} } // Center widget group diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/CloudflareWarp.qml b/.config/quickshell/modules/sidebarRight/quickToggles/CloudflareWarp.qml new file mode 100644 index 00000000..7f6aba21 --- /dev/null +++ b/.config/quickshell/modules/sidebarRight/quickToggles/CloudflareWarp.qml @@ -0,0 +1,89 @@ +import "root:/modules/common" +import "root:/modules/common/widgets" +import "../" +import QtQuick +import Quickshell.Io +import Quickshell +import Quickshell.Hyprland + +QuickToggleButton { + id: root + toggled: false + visible: false + + contentItem: CustomIcon { + id: distroIcon + source: 'cloudflare-dns-symbolic' + + anchors.centerIn: parent + width: 12 + height: 12 + colorize: true + color: root.toggled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer1 + + Behavior on color { + animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) + } + } + + onClicked: { + if (toggled) { + root.toggled = false + Quickshell.execDetached(["warp-cli", "disconnect"]) + } else { + root.toggled = true + Quickshell.execDetached(["warp-cli", "connect"]) + } + } + + Process { + id: connectProc + command: ["warp-cli", "connect"] + onExited: (exitCode, exitStatus) => { + console.log("Warp connection exited with code and status:", exitCode, exitStatus) + if (exitCode === 0) { + connectProc.running = true + } else { + console.error("Warp connection failed, please check your connection or try again later.") + } + } + } + + Process { + id: registrationProc + command: ["warp-cli", "registration", "new"] + onExited: (exitCode, exitStatus) => { + console.log("Warp registration exited with code and status:", exitCode, exitStatus) + if (exitCode === 0) { + connectProc.running = true + } else { + Quickshell.execDetached(["notify-send", "Cloudflare Warp", "Registration failed. Please inspect manually with the warp-cli command", "-a", "Shell"]) + } + } + } + + Process { + id: fetchActiveState + running: true + command: ["bash", "-c", "warp-cli status"] + stdout: StdioCollector { + id: warpStatusCollector + onStreamFinished: { + if (warpStatusCollector.text.length > 0) { + console.log("Showing warp") + root.visible = true + } + if (warpStatusCollector.text.includes("Unable")) { + registrationProc.running = true + } else if (warpStatusCollector.text.includes("Connected")) { + root.toggled = true + } else if (warpStatusCollector.text.includes("Disconnected")) { + root.toggled = false + } + } + } + } + StyledToolTip { + content: qsTr("Cloudflare WARP (1.1.1.1)") + } +} From 5081b2e9d174588a8418c385a828d71be69966fc Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 10:16:03 +0700 Subject: [PATCH 165/328] unfuck startup wallpaper for multimonitor --- .config/hypr/hyprland/execs.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/hypr/hyprland/execs.conf b/.config/hypr/hyprland/execs.conf index 9d4747a9..b723454a 100644 --- a/.config/hypr/hyprland/execs.conf +++ b/.config/hypr/hyprland/execs.conf @@ -1,7 +1,7 @@ # Bar, wallpaper -exec-once = swww-daemon --format xrgb --no-cache -exec-once = sleep 0.5; swww img "$(cat ~/.local/state/quickshell/user/generated/wallpaper/path.txt)" --transition-step 100 --transition-fps 120 --transition-type grow --transition-angle 30 --transition-duration 1 exec-once = ~/.config/hypr/hyprland/scripts/start_geoclue_agent.sh & gammastep +exec-once = sleep 0.7; [ "$(hyprctl monitors -j | jq 'length')" -eq 1 ] && swww-daemon --format xrgb --no-cache || swww-daemon --format xrgb +exec-once = sleep 0.7; swww img "$(cat ~/.local/state/quickshell/user/generated/wallpaper/path.txt)" --transition-step 100 --transition-fps 120 --transition-type grow --transition-angle 30 --transition-duration 1 exec-once = qs & # Input method From 8ba91edeaea23772381b96c1020cbf29bf07c630 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 10:41:49 +0700 Subject: [PATCH 166/328] make screencorners exit more nicely --- .config/hypr/hyprland/rules.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index 2465cc0b..0e324f5d 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -135,6 +135,7 @@ layerrule = animation fade, quickshell:notificationPopup layerrule = blur, quickshell:backgroundWidgets layerrule = ignorealpha 0.05, quickshell:backgroundWidgets layerrule = noanim, quickshell:screenshot +layerrule = animation popin 120%, quickshell:screenCorners # Launchers need to be FAST From b6f0d001373c3c48a9cfd3cb609dfc27789eb5a7 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 11:41:16 +0700 Subject: [PATCH 167/328] overview: unfuck window moving on offset monitors --- .../quickshell/modules/overview/OverviewWidget.qml | 13 ++++++++++--- .../quickshell/modules/overview/OverviewWindow.qml | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index a17cc045..9bc88a09 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -172,11 +172,19 @@ Item { property var monitor: HyprlandData.monitors[monitorId] property bool atInitPosition: (initX == x && initY == y) - restrictToWorkspace: Drag.active || atInitPosition property int workspaceColIndex: (windowData?.workspace.id - 1) % Config.options.overview.columns property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / Config.options.overview.columns) - xOffset: (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - (monitor?.x * root.scale) + xOffset: { + console.log("[OverviewWidget] " + windowData?.address + " title:", windowData?.title) + console.log("[OverviewWidget] workspaceColIndex:", workspaceColIndex) + console.log("[OverviewWidget] root.workspaceImplicitWidth:", root.workspaceImplicitWidth) + console.log("[OverviewWidget] workspaceSpacing:", workspaceSpacing) + console.log("[OverviewWidget] monitor?.x:", monitor?.x) + console.log("[OverviewWidget] root.scale:", root.scale) + console.log("[OverviewWidget] xOffset:", (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - (monitor?.x * root.scale)) + return (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - (monitor?.x * root.scale) + } yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex - (monitor?.y * root.scale) Timer { @@ -187,7 +195,6 @@ Item { onTriggered: { window.x = Math.round(Math.max((windowData?.at[0] - monitorData?.reserved[0]) * root.scale, 0) + xOffset) window.y = Math.round(Math.max((windowData?.at[1] - monitorData?.reserved[1]) * root.scale, 0) + yOffset) - // console.log(`[OverviewWindow] Updated position for window ${windowData?.address} to (${window.x}, ${window.y})`) } } diff --git a/.config/quickshell/modules/overview/OverviewWindow.qml b/.config/quickshell/modules/overview/OverviewWindow.qml index b749ab16..56e1d106 100644 --- a/.config/quickshell/modules/overview/OverviewWindow.qml +++ b/.config/quickshell/modules/overview/OverviewWindow.qml @@ -42,8 +42,8 @@ Item { // Window x: initX y: initY - width: Math.round(Math.min(windowData?.size[0] * root.scale, (restrictToWorkspace ? windowData?.size[0] : availableWorkspaceWidth - x + xOffset))) - height: Math.round(Math.min(windowData?.size[1] * root.scale, (restrictToWorkspace ? windowData?.size[1] : availableWorkspaceHeight - y + yOffset))) + width: windowData?.size[0] * root.scale + height: windowData?.size[1] * root.scale layer.enabled: true layer.effect: OpacityMask { From a8f52a5adf87fa28a877faec453e24155f30a09e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:35:27 +0700 Subject: [PATCH 168/328] search: adjust highlight color --- .../modules/overview/SearchItem.qml | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/.config/quickshell/modules/overview/SearchItem.qml b/.config/quickshell/modules/overview/SearchItem.qml index d23cb4c0..495ba8f9 100644 --- a/.config/quickshell/modules/overview/SearchItem.qml +++ b/.config/quickshell/modules/overview/SearchItem.qml @@ -27,6 +27,21 @@ RippleButton { property string bigText: entry?.bigText ?? "" property string materialSymbol: entry?.materialSymbol ?? "" property string cliphistRawString: entry?.cliphistRawString ?? "" + + visible: root.entryShown + property int horizontalMargin: 10 + property int buttonHorizontalPadding: 10 + property int buttonVerticalPadding: 5 + property bool keyboardDown: false + + implicitHeight: rowLayout.implicitHeight + root.buttonVerticalPadding * 2 + implicitWidth: rowLayout.implicitWidth + root.buttonHorizontalPadding * 2 + buttonRadius: Appearance.rounding.normal + colBackground: (root.down || root.keyboardDown) ? Appearance.colors.colSecondaryContainerActive : + ((root.hovered || root.focus) ? Appearance.colors.colSecondaryContainerHover : + ColorUtils.transparentize(Appearance.colors.colSecondaryContainer, 1)) + colBackgroundHover: Appearance.colors.colSecondaryContainerHover + colRipple: Appearance.colors.colSecondaryContainerActive property string highlightPrefix: `` property string highlightSuffix: `` @@ -69,20 +84,7 @@ RippleButton { return matches ? matches : []; } - visible: root.entryShown - property int horizontalMargin: 10 - property int buttonHorizontalPadding: 10 - property int buttonVerticalPadding: 5 - property bool keyboardDown: false - - implicitHeight: rowLayout.implicitHeight + root.buttonVerticalPadding * 2 - implicitWidth: rowLayout.implicitWidth + root.buttonHorizontalPadding * 2 - buttonRadius: Appearance.rounding.normal - colBackground: (root.down || root.keyboardDown) ? Appearance.colors.colLayer1Active : - ((root.hovered || root.focus) ? Appearance.colors.colLayer1Hover : - ColorUtils.transparentize(Appearance.colors.colSurfaceContainerHigh, 1)) - colBackgroundHover: Appearance.colors.colLayer1Hover - colRipple: Appearance.colors.colLayer1Active + PointingHandInteraction {} background { anchors.fill: root @@ -90,7 +92,6 @@ RippleButton { anchors.rightMargin: root.horizontalMargin } - PointingHandInteraction {} onClicked: { root.itemExecute() Hyprland.dispatch("global quickshell:overviewClose") From d572f4a113ae44be74ff3aff6d07c7c3214c1b10 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:36:07 +0700 Subject: [PATCH 169/328] switchwall: unfuck wallpaper query on multimonitor (#1581) --- .config/quickshell/scripts/colors/switchwall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/scripts/colors/switchwall.sh b/.config/quickshell/scripts/colors/switchwall.sh index 560a8cfc..11cf2a43 100755 --- a/.config/quickshell/scripts/colors/switchwall.sh +++ b/.config/quickshell/scripts/colors/switchwall.sh @@ -297,7 +297,7 @@ main() { ;; --noswitch) noswitch_flag="1" - imgpath=$(swww query | awk -F 'image: ' '{print $2}') + imgpath=$(swww query | head -1 | awk -F 'image: ' '{print $2}') shift ;; *) From 9293ffdb26f7308bc27bbb8b9427c90d748ad359 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 22:32:18 +0700 Subject: [PATCH 170/328] bar: clock: use shorter day of week (by default) --- .config/quickshell/modules/common/Config.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/modules/common/Config.qml index b8a051b5..5d427a97 100644 --- a/.config/quickshell/modules/common/Config.qml +++ b/.config/quickshell/modules/common/Config.qml @@ -211,7 +211,7 @@ Singleton { property JsonObject time: JsonObject { // https://doc.qt.io/qt-6/qtime.html#toString property string format: "hh:mm" - property string dateFormat: "dddd, dd/MM" + property string dateFormat: "ddd, dd/MM" } property JsonObject windows: JsonObject { From 465660db073b3d68697b14a2db09396b815c6a4e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 22:32:26 +0700 Subject: [PATCH 171/328] overview: remove debug print --- .config/quickshell/modules/overview/OverviewWidget.qml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index 9bc88a09..b1602774 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -176,13 +176,6 @@ Item { property int workspaceColIndex: (windowData?.workspace.id - 1) % Config.options.overview.columns property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / Config.options.overview.columns) xOffset: { - console.log("[OverviewWidget] " + windowData?.address + " title:", windowData?.title) - console.log("[OverviewWidget] workspaceColIndex:", workspaceColIndex) - console.log("[OverviewWidget] root.workspaceImplicitWidth:", root.workspaceImplicitWidth) - console.log("[OverviewWidget] workspaceSpacing:", workspaceSpacing) - console.log("[OverviewWidget] monitor?.x:", monitor?.x) - console.log("[OverviewWidget] root.scale:", root.scale) - console.log("[OverviewWidget] xOffset:", (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - (monitor?.x * root.scale)) return (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - (monitor?.x * root.scale) } yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex - (monitor?.y * root.scale) From f865ed877dee8a8d871d221cc68e918d9858faa7 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 9 Jul 2025 22:33:11 +0700 Subject: [PATCH 172/328] sidebar: warp: no weird connection loop --- .../sidebarRight/quickToggles/CloudflareWarp.qml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/CloudflareWarp.qml b/.config/quickshell/modules/sidebarRight/quickToggles/CloudflareWarp.qml index 7f6aba21..cdaf84b7 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/CloudflareWarp.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/CloudflareWarp.qml @@ -16,8 +16,7 @@ QuickToggleButton { source: 'cloudflare-dns-symbolic' anchors.centerIn: parent - width: 12 - height: 12 + height: 16 colorize: true color: root.toggled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer1 @@ -40,11 +39,8 @@ QuickToggleButton { id: connectProc command: ["warp-cli", "connect"] onExited: (exitCode, exitStatus) => { - console.log("Warp connection exited with code and status:", exitCode, exitStatus) - if (exitCode === 0) { - connectProc.running = true - } else { - console.error("Warp connection failed, please check your connection or try again later.") + if (exitCode !== 0) { + Quickshell.execDetached(["notify-send", "Cloudflare WARP", "Connection failed. Please inspect manually with the warp-cli command", "-a", "Shell"]) } } } @@ -57,7 +53,7 @@ QuickToggleButton { if (exitCode === 0) { connectProc.running = true } else { - Quickshell.execDetached(["notify-send", "Cloudflare Warp", "Registration failed. Please inspect manually with the warp-cli command", "-a", "Shell"]) + Quickshell.execDetached(["notify-send", "Cloudflare WARP", "Registration failed. Please inspect manually with the warp-cli command", "-a", "Shell"]) } } } From 7afea39f1dcb9588c5e78c2d1bab95c73674dc7b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 10 Jul 2025 10:54:46 +0700 Subject: [PATCH 173/328] cheatsheet: periodic table: adjust colors --- .config/quickshell/modules/cheatsheet/ElementTile.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/cheatsheet/ElementTile.qml b/.config/quickshell/modules/cheatsheet/ElementTile.qml index 1784183b..baeb72ad 100644 --- a/.config/quickshell/modules/cheatsheet/ElementTile.qml +++ b/.config/quickshell/modules/cheatsheet/ElementTile.qml @@ -22,7 +22,7 @@ RippleButton { topMargin: 4 leftMargin: 4 } - color: Appearance.colors.colSecondaryContainer + color: Appearance.colors.colLayer2 radius: Appearance.rounding.full implicitWidth: Math.max(20, elementNumber.implicitWidth) implicitHeight: Math.max(20, elementNumber.implicitHeight) @@ -31,16 +31,16 @@ RippleButton { StyledText { id: elementNumber anchors.centerIn: parent - color: Appearance.colors.colOnSecondaryContainer + color: Appearance.colors.colOnLayer2 text: root.element.number - font.pixelSize: Appearance.font.pixelSize.smaller + font.pixelSize: Appearance.font.pixelSize.smallest } } StyledText { id: elementSymbol anchors.centerIn: parent - color: Appearance.colors.colOnLayer2 + color: Appearance.colors.colSecondary font.pixelSize: Appearance.font.pixelSize.huge text: root.element.symbol } From 280f7ff8c0c4e9d08813847ab961b479e30ee545 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 10 Jul 2025 10:55:08 +0700 Subject: [PATCH 174/328] bar: activewindow: more accurate on multimonitor systems --- .../quickshell/modules/bar/ActiveWindow.qml | 14 ++- .config/quickshell/modules/bar/Workspaces.qml | 9 +- .config/quickshell/services/HyprlandData.qml | 96 ++++++++++++++----- 3 files changed, 85 insertions(+), 34 deletions(-) diff --git a/.config/quickshell/modules/bar/ActiveWindow.qml b/.config/quickshell/modules/bar/ActiveWindow.qml index 95e25c6f..d9f069c6 100644 --- a/.config/quickshell/modules/bar/ActiveWindow.qml +++ b/.config/quickshell/modules/bar/ActiveWindow.qml @@ -1,3 +1,4 @@ +import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" import QtQuick @@ -11,6 +12,10 @@ Item { readonly property HyprlandMonitor monitor: Hyprland.monitorFor(bar.screen) readonly property Toplevel activeWindow: ToplevelManager.activeToplevel + property string activeWindowAddress: `0x${activeWindow.HyprlandToplevel.address}` + property bool focusingThisMonitor: HyprlandData.activeWorkspace.monitor == monitor.name + property var biggestWindow: HyprlandData.biggestWindowForWorkspace(HyprlandData.monitors[root.monitor.id].activeWorkspace.id) + implicitWidth: colLayout.implicitWidth ColumnLayout { @@ -26,7 +31,10 @@ Item { font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.colors.colSubtext elide: Text.ElideRight - text: root.activeWindow?.activated ? root.activeWindow?.appId : qsTr("Desktop") + text: root.focusingThisMonitor && root.activeWindow?.activated && root.biggestWindow ? + root.activeWindow?.appId : + (root.biggestWindow?.class) ?? qsTr("Desktop") + } StyledText { @@ -34,7 +42,9 @@ Item { font.pixelSize: Appearance.font.pixelSize.small color: Appearance.colors.colOnLayer0 elide: Text.ElideRight - text: root.activeWindow?.activated ? root.activeWindow?.title : `${qsTr("Workspace")} ${monitor.activeWorkspace?.id}` + text: root.focusingThisMonitor && root.activeWindow?.activated && root.biggestWindow ? + root.activeWindow?.title : + (root.biggestWindow?.title) ?? `${qsTr("Workspace")} ${monitor.activeWorkspace?.id}` } } diff --git a/.config/quickshell/modules/bar/Workspaces.qml b/.config/quickshell/modules/bar/Workspaces.qml index f91cdaa9..f4d7c73d 100644 --- a/.config/quickshell/modules/bar/Workspaces.qml +++ b/.config/quickshell/modules/bar/Workspaces.qml @@ -173,14 +173,7 @@ Item { id: workspaceButtonBackground implicitWidth: workspaceButtonWidth implicitHeight: workspaceButtonWidth - property var biggestWindow: { - const windowsInThisWorkspace = HyprlandData.windowList.filter(w => w.workspace.id == button.workspaceValue) - return windowsInThisWorkspace.reduce((maxWin, win) => { - const maxArea = (maxWin?.size?.[0] ?? 0) * (maxWin?.size?.[1] ?? 0) - const winArea = (win?.size?.[0] ?? 0) * (win?.size?.[1] ?? 0) - return winArea > maxArea ? win : maxWin - }, null) - } + property var biggestWindow: HyprlandData.biggestWindowForWorkspace(button.workspaceValue) property var mainAppIconSource: Quickshell.iconPath(AppSearch.guessIcon(biggestWindow?.class), "image-missing") StyledText { // Workspace number text diff --git a/.config/quickshell/services/HyprlandData.qml b/.config/quickshell/services/HyprlandData.qml index edd4e8ea..fb360070 100644 --- a/.config/quickshell/services/HyprlandData.qml +++ b/.config/quickshell/services/HyprlandData.qml @@ -15,34 +15,56 @@ Singleton { property var windowList: [] property var addresses: [] property var windowByAddress: ({}) + property var workspaces: [] + property var workspaceIds: [] + property var workspaceById: ({}) + property var activeWorkspace: null property var monitors: [] property var layers: ({}) function updateWindowList() { - getClients.running = true - getMonitors.running = true + getClients.running = true; } function updateLayers() { - getLayers.running = true + getLayers.running = true; + } + + function updateMonitors() { + getMonitors.running = true; + } + + function updateWorkspaces() { + getWorkspaces.running = true; + getActiveWorkspace.running = true; + } + + function updateAll() { + updateWindowList(); + updateMonitors(); + updateLayers(); + updateWorkspaces(); + } + + function biggestWindowForWorkspace(workspaceId) { + const windowsInThisWorkspace = HyprlandData.windowList.filter(w => w.workspace.id == workspaceId); + return windowsInThisWorkspace.reduce((maxWin, win) => { + const maxArea = (maxWin?.size?.[0] ?? 0) * (maxWin?.size?.[1] ?? 0); + const winArea = (win?.size?.[0] ?? 0) * (win?.size?.[1] ?? 0); + return winArea > maxArea ? win : maxWin; + }, null); } Component.onCompleted: { - updateWindowList() - updateLayers() + updateAll(); } Connections { target: Hyprland function onRawEvent(event) { - // Filter out redundant old v1 events for the same thing - if(event.name in [ - "activewindow", "focusedmon", "monitoradded", - "createworkspace", "destroyworkspace", "moveworkspace", - "activespecial", "movewindow", "windowtitle" - ]) return ; - updateWindowList() + // console.log("Hyprland raw event:", event.name); + updateAll() } } @@ -50,15 +72,15 @@ Singleton { id: getClients command: ["bash", "-c", "hyprctl clients -j | jq -c"] stdout: SplitParser { - onRead: (data) => { - root.windowList = JSON.parse(data) - let tempWinByAddress = {} + onRead: data => { + root.windowList = JSON.parse(data); + let tempWinByAddress = {}; for (var i = 0; i < root.windowList.length; ++i) { - var win = root.windowList[i] - tempWinByAddress[win.address] = win + var win = root.windowList[i]; + tempWinByAddress[win.address] = win; } - root.windowByAddress = tempWinByAddress - root.addresses = root.windowList.map((win) => win.address) + root.windowByAddress = tempWinByAddress; + root.addresses = root.windowList.map(win => win.address); } } } @@ -67,8 +89,8 @@ Singleton { id: getMonitors command: ["bash", "-c", "hyprctl monitors -j | jq -c"] stdout: SplitParser { - onRead: (data) => { - root.monitors = JSON.parse(data) + onRead: data => { + root.monitors = JSON.parse(data); } } } @@ -77,10 +99,36 @@ Singleton { id: getLayers command: ["bash", "-c", "hyprctl layers -j | jq -c"] stdout: SplitParser { - onRead: (data) => { - root.layers = JSON.parse(data) + onRead: data => { + root.layers = JSON.parse(data); + } + } + } + + Process { + id: getWorkspaces + command: ["bash", "-c", "hyprctl workspaces -j | jq -c"] + stdout: SplitParser { + onRead: data => { + root.workspaces = JSON.parse(data); + let tempWorkspaceById = {}; + for (var i = 0; i < root.workspaces.length; ++i) { + var ws = root.workspaces[i]; + tempWorkspaceById[ws.id] = ws; + } + root.workspaceById = tempWorkspaceById; + root.workspaceIds = root.workspaces.map(ws => ws.id); + } + } + } + + Process { + id: getActiveWorkspace + command: ["bash", "-c", "hyprctl activeworkspace -j | jq -c"] + stdout: SplitParser { + onRead: data => { + root.activeWorkspace = JSON.parse(data); } } } } - From d2eefd5768e5f0d06bfb818e998fa10869a2396d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:15:32 +0700 Subject: [PATCH 175/328] hyprland: no annoying overlapping dolphin copy dialog --- .config/hypr/hyprland/rules.conf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index 0e324f5d..ffa3663f 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -28,11 +28,13 @@ windowrulev2 = float, title:.*Welcome windowrulev2 = float, title:^(illogical-impulse Settings)$ windowrulev2 = float, class:org.freedesktop.impl.portal.desktop.kde -# No appearance +# Move # kde-material-you-colors spawns a window when changing dark/light theme. This is to make sure it doesn't interfere at all. windowrulev2 = float, class:^(plasma-changeicons)$ windowrulev2 = noinitialfocus, class:^(plasma-changeicons)$ windowrulev2 = move 999999 999999, class:^(plasma-changeicons)$ +# stupid dolphin copy +windowrulev2 = move 40 80, title:^(Copying — Dolphin)$ # Tiling windowrulev2 = tile, class:^dev\.warp\.Warp$ From 33f2f960b9d1668cc54dabc3c36b6d7cf3c06192 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:26:17 +0700 Subject: [PATCH 176/328] quickshell: temporarily disable hyprland layer masking (#1479) --- .../backgroundWidgets/BackgroundWidgets.qml | 6 ++-- .../quickshell/modules/overview/Overview.qml | 6 ++-- .../modules/screenCorners/ScreenCorners.qml | 28 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml index 4197e495..35f30534 100644 --- a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml +++ b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml @@ -80,9 +80,9 @@ Scope { right: true } color: "transparent" - HyprlandWindow.visibleMask: Region { - item: widgetBackground - } + // HyprlandWindow.visibleMask: Region { // Buggy with scaled monitors + // item: widgetBackground + // } Rectangle { id: widgetBackground diff --git a/.config/quickshell/modules/overview/Overview.qml b/.config/quickshell/modules/overview/Overview.qml index 0bc3c6c0..952e5d29 100644 --- a/.config/quickshell/modules/overview/Overview.qml +++ b/.config/quickshell/modules/overview/Overview.qml @@ -33,9 +33,9 @@ Scope { mask: Region { item: GlobalStates.overviewOpen ? columnLayout : null } - HyprlandWindow.visibleMask: Region { - item: GlobalStates.overviewOpen ? columnLayout : null - } + // HyprlandWindow.visibleMask: Region { // Buggy with scaled monitors + // item: GlobalStates.overviewOpen ? columnLayout : null + // } anchors { diff --git a/.config/quickshell/modules/screenCorners/ScreenCorners.qml b/.config/quickshell/modules/screenCorners/ScreenCorners.qml index de213002..0946c03d 100644 --- a/.config/quickshell/modules/screenCorners/ScreenCorners.qml +++ b/.config/quickshell/modules/screenCorners/ScreenCorners.qml @@ -26,20 +26,20 @@ Scope { mask: Region { item: null } - HyprlandWindow.visibleMask: Region { - Region { - item: topLeftCorner - } - Region { - item: topRightCorner - } - Region { - item: bottomLeftCorner - } - Region { - item: bottomRightCorner - } - } + // HyprlandWindow.visibleMask: Region { + // Region { + // item: topLeftCorner + // } + // Region { + // item: topRightCorner + // } + // Region { + // item: bottomLeftCorner + // } + // Region { + // item: bottomRightCorner + // } + // } WlrLayershell.namespace: "quickshell:screenCorners" WlrLayershell.layer: WlrLayer.Overlay color: "transparent" From 5ee46cfc30f6b4a690bfada77d40b09cd1517c96 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 10 Jul 2025 20:08:47 +0700 Subject: [PATCH 177/328] overview: make icon sizes more acceptable (#1479) --- .config/quickshell/modules/overview/OverviewWidget.qml | 4 ++-- .config/quickshell/modules/overview/OverviewWindow.qml | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index b1602774..18e60c2f 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -19,7 +19,7 @@ Item { readonly property var toplevels: ToplevelManager.toplevels readonly property int workspacesShown: Config.options.overview.rows * Config.options.overview.columns readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / workspacesShown) - property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor.id) + property bool monitorIsFocused: (Hyprland.focusedMonitor?.name == monitor.name) property var windows: HyprlandData.windowList property var windowByAddress: HyprlandData.windowByAddress property var windowAddresses: HyprlandData.addresses @@ -163,7 +163,7 @@ Item { property var address: `0x${modelData.HyprlandToplevel.address}` windowData: windowByAddress[address] toplevel: modelData - monitorData: root.monitorData + monitorData: HyprlandData.monitors[monitorId] scale: root.scale availableWorkspaceWidth: root.workspaceImplicitWidth availableWorkspaceHeight: root.workspaceImplicitHeight diff --git a/.config/quickshell/modules/overview/OverviewWindow.qml b/.config/quickshell/modules/overview/OverviewWindow.qml index 56e1d106..bf023a09 100644 --- a/.config/quickshell/modules/overview/OverviewWindow.qml +++ b/.config/quickshell/modules/overview/OverviewWindow.qml @@ -91,7 +91,14 @@ Item { // Window Image { id: windowIcon - property var iconSize: Math.min(targetWindowWidth, targetWindowHeight) * (root.compactMode ? root.iconToWindowRatioCompact : root.iconToWindowRatio) + property var iconSize: { + // console.log("-=-=-", root.toplevel.title, "-=-=-") + // console.log("Target window size:", targetWindowWidth, targetWindowHeight) + // console.log("Icon ratio:", root.compactMode ? root.iconToWindowRatioCompact : root.iconToWindowRatio) + // console.log("Scale:", root.monitorData.scale) + // console.log("Final:", Math.min(targetWindowWidth, targetWindowHeight) * (root.compactMode ? root.iconToWindowRatioCompact : root.iconToWindowRatio) / root.monitorData.scale) + return Math.min(targetWindowWidth, targetWindowHeight) * (root.compactMode ? root.iconToWindowRatioCompact : root.iconToWindowRatio) / root.monitorData.scale; + } // mipmap: true Layout.alignment: Qt.AlignHCenter source: root.iconPath From c69eaf7777ad59884b94fc3a0dcfe42cbb11af64 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 10 Jul 2025 22:03:01 +0700 Subject: [PATCH 178/328] move quickshell config to subfolder to ease distribution https://quickshell.outfoxxed.me/docs/guide/distribution/ --- .config/hypr/hyprland.conf | 1 + .config/hypr/hyprland/keybinds.conf | 30 +++++++++--------- .config/quickshell/{ => ii}/.qmlformat.ini | 0 .config/quickshell/{ => ii}/GlobalStates.qml | 0 .config/quickshell/{ => ii}/ReloadPopup.qml | 0 .../assets/icons/ai-openai-symbolic.svg | 0 .../{ => ii}/assets/icons/arch-symbolic.svg | 0 .../assets/icons/cachyos-symbolic.svg | 0 .../assets/icons/cloudflare-dns-symbolic.svg | 0 .../assets/icons/crosshair-symbolic.svg | 0 .../{ => ii}/assets/icons/debian-symbolic.svg | 0 .../assets/icons/deepseek-symbolic.svg | 0 .../assets/icons/desktop-symbolic.svg | 0 .../assets/icons/endeavouros-symbolic.svg | 0 .../{ => ii}/assets/icons/fedora-symbolic.svg | 0 .../assets/icons/flatpak-symbolic.svg | 0 .../{ => ii}/assets/icons/github-symbolic.svg | 0 .../assets/icons/google-gemini-symbolic.svg | 0 .../{ => ii}/assets/icons/linux-symbolic.svg | 0 .../assets/icons/microsoft-symbolic.svg | 0 .../{ => ii}/assets/icons/nixos-symbolic.svg | 0 .../{ => ii}/assets/icons/ollama-symbolic.svg | 0 .../{ => ii}/assets/icons/openai-symbolic.svg | 0 .../assets/icons/openrouter-symbolic.svg | 0 .../{ => ii}/assets/icons/spark-symbolic.svg | 0 .../{ => ii}/assets/icons/ubuntu-symbolic.svg | 0 .../assets/images/default_wallpaper.png | Bin .../{ => ii}/defaults/ai/prompts/NoPrompt.md | 0 .../defaults/ai/prompts/ii-Default.md | 0 .../{ => ii}/defaults/ai/prompts/ii-Imouto.md | 0 .../ai/prompts/w-FourPointedSparkle.md | 0 .../ai/prompts/w-OpenMechanicalFlower.md | 0 .../backgroundWidgets/BackgroundWidgets.qml | 0 .../{ => ii}/modules/bar/ActiveWindow.qml | 0 .../quickshell/{ => ii}/modules/bar/Bar.qml | 0 .../{ => ii}/modules/bar/BarGroup.qml | 0 .../{ => ii}/modules/bar/BatteryIndicator.qml | 0 .../{ => ii}/modules/bar/CircleUtilButton.qml | 0 .../{ => ii}/modules/bar/ClockWidget.qml | 0 .../quickshell/{ => ii}/modules/bar/Media.qml | 0 .../{ => ii}/modules/bar/Resource.qml | 0 .../{ => ii}/modules/bar/Resources.qml | 0 .../{ => ii}/modules/bar/ScrollHint.qml | 0 .../{ => ii}/modules/bar/SysTray.qml | 0 .../{ => ii}/modules/bar/SysTrayItem.qml | 0 .../{ => ii}/modules/bar/UtilButtons.qml | 0 .../{ => ii}/modules/bar/Workspaces.qml | 0 .../modules/bar/weather/WeatherBar.qml | 0 .../modules/bar/weather/WeatherCard.qml | 0 .../modules/bar/weather/WeatherIcons.qml | 0 .../modules/bar/weather/WeatherPopup.qml | 0 .../modules/cheatsheet/Cheatsheet.qml | 0 .../modules/cheatsheet/CheatsheetKeybinds.qml | 0 .../cheatsheet/CheatsheetPeriodicTable.qml | 0 .../modules/cheatsheet/ElementTile.qml | 0 .../modules/cheatsheet/periodic_table.js | 0 .../{ => ii}/modules/common/Appearance.qml | 0 .../{ => ii}/modules/common/Config.qml | 0 .../{ => ii}/modules/common/Directories.qml | 6 ++-- .../{ => ii}/modules/common/Persistent.qml | 0 .../modules/common/PersistentStates.qml | 0 .../modules/common/functions/color_utils.js | 0 .../modules/common/functions/file_utils.js | 0 .../modules/common/functions/fuzzysort.js | 0 .../modules/common/functions/levendist.js | 0 .../modules/common/functions/object_utils.js | 0 .../modules/common/functions/string_utils.js | 0 .../modules/common/widgets/ButtonGroup.qml | 0 .../common/widgets/CircularProgress.qml | 0 .../modules/common/widgets/CliphistImage.qml | 0 .../modules/common/widgets/ConfigRow.qml | 0 .../common/widgets/ConfigSelectionArray.qml | 0 .../modules/common/widgets/ConfigSpinBox.qml | 0 .../modules/common/widgets/ConfigSwitch.qml | 0 .../modules/common/widgets/ContentPage.qml | 0 .../modules/common/widgets/ContentSection.qml | 0 .../common/widgets/ContentSubsection.qml | 0 .../common/widgets/ContentSubsectionLabel.qml | 0 .../modules/common/widgets/CustomIcon.qml | 0 .../modules/common/widgets/DialogButton.qml | 0 .../modules/common/widgets/DragManager.qml | 0 .../modules/common/widgets/Favicon.qml | 0 .../common/widgets/FloatingActionButton.qml | 0 .../common/widgets/FlowButtonGroup.qml | 0 .../modules/common/widgets/GroupButton.qml | 0 .../modules/common/widgets/KeyboardKey.qml | 0 .../widgets/LightDarkPreferenceButton.qml | 0 .../modules/common/widgets/MaterialSymbol.qml | 0 .../common/widgets/MaterialTextField.qml | 0 .../modules/common/widgets/MenuButton.qml | 0 .../modules/common/widgets/NavigationRail.qml | 0 .../common/widgets/NavigationRailButton.qml | 0 .../widgets/NavigationRailExpandButton.qml | 0 .../common/widgets/NavigationRailTabArray.qml | 0 .../widgets/NotificationActionButton.qml | 0 .../common/widgets/NotificationAppIcon.qml | 0 .../common/widgets/NotificationGroup.qml | 0 .../widgets/NotificationGroupExpandButton.qml | 0 .../common/widgets/NotificationItem.qml | 0 .../common/widgets/NotificationListView.qml | 0 .../widgets/PointingHandInteraction.qml | 0 .../common/widgets/PointingHandLinkHover.qml | 0 .../modules/common/widgets/PrimaryTabBar.qml | 0 .../common/widgets/PrimaryTabButton.qml | 0 .../modules/common/widgets/Revealer.qml | 0 .../modules/common/widgets/RippleButton.qml | 0 .../common/widgets/RippleButtonWithIcon.qml | 0 .../modules/common/widgets/RoundCorner.qml | 0 .../common/widgets/SecondaryTabButton.qml | 0 .../common/widgets/SelectionDialog.qml | 0 .../common/widgets/SelectionGroupButton.qml | 0 .../modules/common/widgets/StyledLabel.qml | 0 .../modules/common/widgets/StyledListView.qml | 0 .../common/widgets/StyledProgressBar.qml | 0 .../common/widgets/StyledRadioButton.qml | 0 .../widgets/StyledRectangularShadow.qml | 0 .../modules/common/widgets/StyledSlider.qml | 0 .../modules/common/widgets/StyledSpinBox.qml | 0 .../modules/common/widgets/StyledSwitch.qml | 0 .../modules/common/widgets/StyledText.qml | 0 .../modules/common/widgets/StyledTextArea.qml | 0 .../common/widgets/StyledTextInput.qml | 0 .../modules/common/widgets/StyledToolTip.qml | 0 .../common/widgets/VerticalButtonGroup.qml | 0 .../modules/common/widgets/WaveVisualizer.qml | 0 .../common/widgets/notification_utils.js | 0 .../quickshell/{ => ii}/modules/dock/Dock.qml | 0 .../{ => ii}/modules/dock/DockAppButton.qml | 0 .../{ => ii}/modules/dock/DockApps.qml | 0 .../{ => ii}/modules/dock/DockButton.qml | 0 .../{ => ii}/modules/dock/DockSeparator.qml | 0 .../modules/mediaControls/MediaControls.qml | 2 +- .../modules/mediaControls/PlayerControl.qml | 0 .../notificationPopup/NotificationPopup.qml | 0 .../OnScreenDisplayBrightness.qml | 0 .../onScreenDisplay/OnScreenDisplayVolume.qml | 0 .../onScreenDisplay/OsdValueIndicator.qml | 0 .../onScreenKeyboard/OnScreenKeyboard.qml | 0 .../modules/onScreenKeyboard/OskContent.qml | 0 .../modules/onScreenKeyboard/OskKey.qml | 0 .../modules/onScreenKeyboard/layouts.js | 0 .../{ => ii}/modules/overview/Overview.qml | 0 .../modules/overview/OverviewWidget.qml | 0 .../modules/overview/OverviewWindow.qml | 0 .../{ => ii}/modules/overview/SearchItem.qml | 0 .../modules/overview/SearchWidget.qml | 0 .../modules/screenCorners/ScreenCorners.qml | 0 .../{ => ii}/modules/session/Session.qml | 0 .../modules/session/SessionActionButton.qml | 0 .../{ => ii}/modules/settings/About.qml | 0 .../modules/settings/InterfaceConfig.qml | 0 .../modules/settings/ServicesConfig.qml | 0 .../{ => ii}/modules/settings/StyleConfig.qml | 2 +- .../{ => ii}/modules/sidebarLeft/AiChat.qml | 2 +- .../{ => ii}/modules/sidebarLeft/Anime.qml | 0 .../modules/sidebarLeft/ApiCommandButton.qml | 0 .../modules/sidebarLeft/DescriptionBox.qml | 0 .../modules/sidebarLeft/SidebarLeft.qml | 0 .../sidebarLeft/SidebarLeftContent.qml | 0 .../modules/sidebarLeft/Translator.qml | 0 .../modules/sidebarLeft/aiChat/AiMessage.qml | 0 .../aiChat/AiMessageControlButton.qml | 0 .../aiChat/AnnotationSourceButton.qml | 0 .../sidebarLeft/aiChat/MessageCodeBlock.qml | 0 .../sidebarLeft/aiChat/MessageTextBlock.qml | 0 .../sidebarLeft/aiChat/MessageThinkBlock.qml | 0 .../modules/sidebarLeft/anime/BooruImage.qml | 0 .../sidebarLeft/anime/BooruResponse.qml | 0 .../translator/LanguageSelectorButton.qml | 0 .../sidebarLeft/translator/TextCanvas.qml | 0 .../sidebarRight/BottomWidgetGroup.qml | 0 .../sidebarRight/CenterWidgetGroup.qml | 0 .../modules/sidebarRight/SidebarRight.qml | 2 +- .../calendar/CalendarDayButton.qml | 0 .../calendar/CalendarHeaderButton.qml | 0 .../sidebarRight/calendar/CalendarWidget.qml | 0 .../sidebarRight/calendar/calendar_layout.js | 0 .../notifications/NotificationList.qml | 0 .../NotificationStatusButton.qml | 0 .../quickToggles/BluetoothToggle.qml | 0 .../quickToggles/CloudflareWarp.qml | 0 .../sidebarRight/quickToggles/GameMode.qml | 0 .../quickToggles/IdleInhibitor.qml | 4 +-- .../quickToggles/NetworkToggle.qml | 0 .../sidebarRight/quickToggles/NightLight.qml | 0 .../quickToggles/QuickToggleButton.qml | 0 .../modules/sidebarRight/todo/TaskList.qml | 0 .../todo/TodoItemActionButton.qml | 0 .../modules/sidebarRight/todo/TodoWidget.qml | 0 .../volumeMixer/AudioDeviceSelectorButton.qml | 0 .../sidebarRight/volumeMixer/VolumeMixer.qml | 0 .../volumeMixer/VolumeMixerEntry.qml | 0 .config/quickshell/{ => ii}/screenshot.qml | 2 +- .../ai/show-installed-ollama-models.sh | 0 .../scripts/cava/raw_output_config.txt | 0 .../{ => ii}/scripts/colors/applycolor.sh | 7 ++-- .../colors/generate_colors_material.py | 0 .../ii/scripts/colors/random_konachan_wall.sh | 19 +++++++++++ .../scripts/colors/scheme_for_image.py | 0 .../{ => ii}/scripts/colors/switchwall.sh | 9 +++--- .../{ => ii}/scripts/hyprland/get_keybinds.py | 0 .../{ => ii}/scripts/images/find_regions.py | 0 .../{ => ii}/scripts/kvantum/adwsvg.py | 0 .../{ => ii}/scripts/kvantum/adwsvgDark.py | 0 .../scripts/kvantum/changeAdwColors.py | 0 .../{ => ii}/scripts/kvantum/materialQT.sh | 8 +++-- .../scripts/terminal/scheme-base.json | 0 .../{ => ii}/scripts/terminal/sequences.txt | 0 .../scripts/wayland-idle-inhibitor.py | 0 .config/quickshell/{ => ii}/services/Ai.qml | 2 +- .../{ => ii}/services/AiMessageData.qml | 0 .../{ => ii}/services/AppSearch.qml | 0 .../quickshell/{ => ii}/services/Audio.qml | 0 .../quickshell/{ => ii}/services/Battery.qml | 0 .../{ => ii}/services/Bluetooth.qml | 0 .../quickshell/{ => ii}/services/Booru.qml | 0 .../{ => ii}/services/BooruResponseData.qml | 0 .../{ => ii}/services/Brightness.qml | 0 .../quickshell/{ => ii}/services/Cliphist.qml | 0 .../quickshell/{ => ii}/services/DateTime.qml | 0 .../quickshell/{ => ii}/services/Emojis.qml | 0 .../{ => ii}/services/FirstRunExperience.qml | 4 +-- .../{ => ii}/services/HyprlandData.qml | 0 .../{ => ii}/services/HyprlandKeybinds.qml | 2 +- .../{ => ii}/services/KeyringStorage.qml | 0 .../{ => ii}/services/LatexRenderer.qml | 0 .../{ => ii}/services/MaterialThemeLoader.qml | 0 .../{ => ii}/services/MprisController.qml | 0 .../quickshell/{ => ii}/services/Network.qml | 0 .../{ => ii}/services/Notifications.qml | 0 .../{ => ii}/services/ResourceUsage.qml | 0 .../{ => ii}/services/SystemInfo.qml | 0 .config/quickshell/{ => ii}/services/Todo.qml | 0 .../quickshell/{ => ii}/services/Weather.qml | 0 .../quickshell/{ => ii}/services/Ydotool.qml | 0 .config/quickshell/{ => ii}/settings.qml | 0 .config/quickshell/{ => ii}/shell.qml | 0 .config/quickshell/{ => ii}/welcome.qml | 2 +- .../scripts/colors/random_konachan_wall.sh | 10 ------ 239 files changed, 65 insertions(+), 49 deletions(-) rename .config/quickshell/{ => ii}/.qmlformat.ini (100%) rename .config/quickshell/{ => ii}/GlobalStates.qml (100%) rename .config/quickshell/{ => ii}/ReloadPopup.qml (100%) rename .config/quickshell/{ => ii}/assets/icons/ai-openai-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/arch-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/cachyos-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/cloudflare-dns-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/crosshair-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/debian-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/deepseek-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/desktop-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/endeavouros-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/fedora-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/flatpak-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/github-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/google-gemini-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/linux-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/microsoft-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/nixos-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/ollama-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/openai-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/openrouter-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/spark-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/icons/ubuntu-symbolic.svg (100%) rename .config/quickshell/{ => ii}/assets/images/default_wallpaper.png (100%) rename .config/quickshell/{ => ii}/defaults/ai/prompts/NoPrompt.md (100%) rename .config/quickshell/{ => ii}/defaults/ai/prompts/ii-Default.md (100%) rename .config/quickshell/{ => ii}/defaults/ai/prompts/ii-Imouto.md (100%) rename .config/quickshell/{ => ii}/defaults/ai/prompts/w-FourPointedSparkle.md (100%) rename .config/quickshell/{ => ii}/defaults/ai/prompts/w-OpenMechanicalFlower.md (100%) rename .config/quickshell/{ => ii}/modules/backgroundWidgets/BackgroundWidgets.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/ActiveWindow.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/Bar.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/BarGroup.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/BatteryIndicator.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/CircleUtilButton.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/ClockWidget.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/Media.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/Resource.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/Resources.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/ScrollHint.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/SysTray.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/SysTrayItem.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/UtilButtons.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/Workspaces.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/weather/WeatherBar.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/weather/WeatherCard.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/weather/WeatherIcons.qml (100%) rename .config/quickshell/{ => ii}/modules/bar/weather/WeatherPopup.qml (100%) rename .config/quickshell/{ => ii}/modules/cheatsheet/Cheatsheet.qml (100%) rename .config/quickshell/{ => ii}/modules/cheatsheet/CheatsheetKeybinds.qml (100%) rename .config/quickshell/{ => ii}/modules/cheatsheet/CheatsheetPeriodicTable.qml (100%) rename .config/quickshell/{ => ii}/modules/cheatsheet/ElementTile.qml (100%) rename .config/quickshell/{ => ii}/modules/cheatsheet/periodic_table.js (100%) rename .config/quickshell/{ => ii}/modules/common/Appearance.qml (100%) rename .config/quickshell/{ => ii}/modules/common/Config.qml (100%) rename .config/quickshell/{ => ii}/modules/common/Directories.qml (91%) rename .config/quickshell/{ => ii}/modules/common/Persistent.qml (100%) rename .config/quickshell/{ => ii}/modules/common/PersistentStates.qml (100%) rename .config/quickshell/{ => ii}/modules/common/functions/color_utils.js (100%) rename .config/quickshell/{ => ii}/modules/common/functions/file_utils.js (100%) rename .config/quickshell/{ => ii}/modules/common/functions/fuzzysort.js (100%) rename .config/quickshell/{ => ii}/modules/common/functions/levendist.js (100%) rename .config/quickshell/{ => ii}/modules/common/functions/object_utils.js (100%) rename .config/quickshell/{ => ii}/modules/common/functions/string_utils.js (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/ButtonGroup.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/CircularProgress.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/CliphistImage.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/ConfigRow.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/ConfigSelectionArray.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/ConfigSpinBox.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/ConfigSwitch.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/ContentPage.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/ContentSection.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/ContentSubsection.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/ContentSubsectionLabel.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/CustomIcon.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/DialogButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/DragManager.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/Favicon.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/FloatingActionButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/FlowButtonGroup.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/GroupButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/KeyboardKey.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/LightDarkPreferenceButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/MaterialSymbol.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/MaterialTextField.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/MenuButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/NavigationRail.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/NavigationRailButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/NavigationRailExpandButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/NavigationRailTabArray.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/NotificationActionButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/NotificationAppIcon.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/NotificationGroup.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/NotificationGroupExpandButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/NotificationItem.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/NotificationListView.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/PointingHandInteraction.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/PointingHandLinkHover.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/PrimaryTabBar.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/PrimaryTabButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/Revealer.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/RippleButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/RippleButtonWithIcon.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/RoundCorner.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/SecondaryTabButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/SelectionDialog.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/SelectionGroupButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledLabel.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledListView.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledProgressBar.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledRadioButton.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledRectangularShadow.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledSlider.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledSpinBox.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledSwitch.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledText.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledTextArea.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledTextInput.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/StyledToolTip.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/VerticalButtonGroup.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/WaveVisualizer.qml (100%) rename .config/quickshell/{ => ii}/modules/common/widgets/notification_utils.js (100%) rename .config/quickshell/{ => ii}/modules/dock/Dock.qml (100%) rename .config/quickshell/{ => ii}/modules/dock/DockAppButton.qml (100%) rename .config/quickshell/{ => ii}/modules/dock/DockApps.qml (100%) rename .config/quickshell/{ => ii}/modules/dock/DockButton.qml (100%) rename .config/quickshell/{ => ii}/modules/dock/DockSeparator.qml (100%) rename .config/quickshell/{ => ii}/modules/mediaControls/MediaControls.qml (99%) rename .config/quickshell/{ => ii}/modules/mediaControls/PlayerControl.qml (100%) rename .config/quickshell/{ => ii}/modules/notificationPopup/NotificationPopup.qml (100%) rename .config/quickshell/{ => ii}/modules/onScreenDisplay/OnScreenDisplayBrightness.qml (100%) rename .config/quickshell/{ => ii}/modules/onScreenDisplay/OnScreenDisplayVolume.qml (100%) rename .config/quickshell/{ => ii}/modules/onScreenDisplay/OsdValueIndicator.qml (100%) rename .config/quickshell/{ => ii}/modules/onScreenKeyboard/OnScreenKeyboard.qml (100%) rename .config/quickshell/{ => ii}/modules/onScreenKeyboard/OskContent.qml (100%) rename .config/quickshell/{ => ii}/modules/onScreenKeyboard/OskKey.qml (100%) rename .config/quickshell/{ => ii}/modules/onScreenKeyboard/layouts.js (100%) rename .config/quickshell/{ => ii}/modules/overview/Overview.qml (100%) rename .config/quickshell/{ => ii}/modules/overview/OverviewWidget.qml (100%) rename .config/quickshell/{ => ii}/modules/overview/OverviewWindow.qml (100%) rename .config/quickshell/{ => ii}/modules/overview/SearchItem.qml (100%) rename .config/quickshell/{ => ii}/modules/overview/SearchWidget.qml (100%) rename .config/quickshell/{ => ii}/modules/screenCorners/ScreenCorners.qml (100%) rename .config/quickshell/{ => ii}/modules/session/Session.qml (100%) rename .config/quickshell/{ => ii}/modules/session/SessionActionButton.qml (100%) rename .config/quickshell/{ => ii}/modules/settings/About.qml (100%) rename .config/quickshell/{ => ii}/modules/settings/InterfaceConfig.qml (100%) rename .config/quickshell/{ => ii}/modules/settings/ServicesConfig.qml (100%) rename .config/quickshell/{ => ii}/modules/settings/StyleConfig.qml (99%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/AiChat.qml (99%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/Anime.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/ApiCommandButton.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/DescriptionBox.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/SidebarLeft.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/SidebarLeftContent.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/Translator.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/aiChat/AiMessage.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/aiChat/AiMessageControlButton.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/aiChat/MessageCodeBlock.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/aiChat/MessageTextBlock.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/aiChat/MessageThinkBlock.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/anime/BooruImage.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/anime/BooruResponse.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/translator/LanguageSelectorButton.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarLeft/translator/TextCanvas.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/BottomWidgetGroup.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/CenterWidgetGroup.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/SidebarRight.qml (98%) rename .config/quickshell/{ => ii}/modules/sidebarRight/calendar/CalendarDayButton.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/calendar/CalendarHeaderButton.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/calendar/CalendarWidget.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/calendar/calendar_layout.js (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/notifications/NotificationList.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/notifications/NotificationStatusButton.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/quickToggles/BluetoothToggle.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/quickToggles/CloudflareWarp.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/quickToggles/GameMode.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/quickToggles/IdleInhibitor.qml (75%) rename .config/quickshell/{ => ii}/modules/sidebarRight/quickToggles/NetworkToggle.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/quickToggles/NightLight.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/quickToggles/QuickToggleButton.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/todo/TaskList.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/todo/TodoItemActionButton.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/todo/TodoWidget.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/volumeMixer/VolumeMixer.qml (100%) rename .config/quickshell/{ => ii}/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml (100%) rename .config/quickshell/{ => ii}/screenshot.qml (99%) rename .config/quickshell/{ => ii}/scripts/ai/show-installed-ollama-models.sh (100%) rename .config/quickshell/{ => ii}/scripts/cava/raw_output_config.txt (100%) rename .config/quickshell/{ => ii}/scripts/colors/applycolor.sh (89%) rename .config/quickshell/{ => ii}/scripts/colors/generate_colors_material.py (100%) create mode 100755 .config/quickshell/ii/scripts/colors/random_konachan_wall.sh rename .config/quickshell/{ => ii}/scripts/colors/scheme_for_image.py (100%) rename .config/quickshell/{ => ii}/scripts/colors/switchwall.sh (98%) rename .config/quickshell/{ => ii}/scripts/hyprland/get_keybinds.py (100%) rename .config/quickshell/{ => ii}/scripts/images/find_regions.py (100%) rename .config/quickshell/{ => ii}/scripts/kvantum/adwsvg.py (100%) rename .config/quickshell/{ => ii}/scripts/kvantum/adwsvgDark.py (100%) rename .config/quickshell/{ => ii}/scripts/kvantum/changeAdwColors.py (100%) rename .config/quickshell/{ => ii}/scripts/kvantum/materialQT.sh (80%) rename .config/quickshell/{ => ii}/scripts/terminal/scheme-base.json (100%) rename .config/quickshell/{ => ii}/scripts/terminal/sequences.txt (100%) rename .config/quickshell/{ => ii}/scripts/wayland-idle-inhibitor.py (100%) rename .config/quickshell/{ => ii}/services/Ai.qml (99%) rename .config/quickshell/{ => ii}/services/AiMessageData.qml (100%) rename .config/quickshell/{ => ii}/services/AppSearch.qml (100%) rename .config/quickshell/{ => ii}/services/Audio.qml (100%) rename .config/quickshell/{ => ii}/services/Battery.qml (100%) rename .config/quickshell/{ => ii}/services/Bluetooth.qml (100%) rename .config/quickshell/{ => ii}/services/Booru.qml (100%) rename .config/quickshell/{ => ii}/services/BooruResponseData.qml (100%) rename .config/quickshell/{ => ii}/services/Brightness.qml (100%) rename .config/quickshell/{ => ii}/services/Cliphist.qml (100%) rename .config/quickshell/{ => ii}/services/DateTime.qml (100%) rename .config/quickshell/{ => ii}/services/Emojis.qml (100%) rename .config/quickshell/{ => ii}/services/FirstRunExperience.qml (88%) rename .config/quickshell/{ => ii}/services/HyprlandData.qml (100%) rename .config/quickshell/{ => ii}/services/HyprlandKeybinds.qml (96%) rename .config/quickshell/{ => ii}/services/KeyringStorage.qml (100%) rename .config/quickshell/{ => ii}/services/LatexRenderer.qml (100%) rename .config/quickshell/{ => ii}/services/MaterialThemeLoader.qml (100%) rename .config/quickshell/{ => ii}/services/MprisController.qml (100%) rename .config/quickshell/{ => ii}/services/Network.qml (100%) rename .config/quickshell/{ => ii}/services/Notifications.qml (100%) rename .config/quickshell/{ => ii}/services/ResourceUsage.qml (100%) rename .config/quickshell/{ => ii}/services/SystemInfo.qml (100%) rename .config/quickshell/{ => ii}/services/Todo.qml (100%) rename .config/quickshell/{ => ii}/services/Weather.qml (100%) rename .config/quickshell/{ => ii}/services/Ydotool.qml (100%) rename .config/quickshell/{ => ii}/settings.qml (100%) rename .config/quickshell/{ => ii}/shell.qml (100%) rename .config/quickshell/{ => ii}/welcome.qml (99%) delete mode 100755 .config/quickshell/scripts/colors/random_konachan_wall.sh diff --git a/.config/hypr/hyprland.conf b/.config/hypr/hyprland.conf index 48648f47..5698f594 100644 --- a/.config/hypr/hyprland.conf +++ b/.config/hypr/hyprland.conf @@ -1,6 +1,7 @@ # This file sources other files in `hyprland` and `custom` folders # You wanna add your stuff in files in `custom` +$qsConfig = ii exec = hyprctl dispatch submap global # DO NOT REMOVE THIS OR YOU WON'T BE ABLE TO USE ANY KEYBIND submap = global # This is required for catchall to work diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index a07d4255..0552c1b4 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -5,7 +5,7 @@ ##! Shell # These absolutely need to be on top, or they won't work consistently bindid = Super, Super_L, Toggle overview, global, quickshell:overviewToggleRelease # Toggle overview/launcher -bind = Super, Super_L, exec, qs ipc call TEST_ALIVE || pkill fuzzel || fuzzel # [hidden] Launcher (fallback) +bind = Super, Super_L, exec, qs -c $qsConfig ipc call TEST_ALIVE || pkill fuzzel || fuzzel # [hidden] Launcher (fallback) binditn = Super, catchall, global, quickshell:overviewToggleReleaseInterrupt # [hidden] bind = Ctrl, Super_L, global, quickshell:overviewToggleReleaseInterrupt # [hidden] bind = Super, mouse:272, global, quickshell:overviewToggleReleaseInterrupt # [hidden] @@ -30,11 +30,11 @@ bindd = Super, Slash, Toggle cheatsheet, global, quickshell:cheatsheetToggle # T bindd = Super, K, Toggle on-screen keyboard, global, quickshell:oskToggle # Toggle on-screen keyboard bindd = Super, M, Toggle media controls, global, quickshell:mediaControlsToggle # Toggle media controls bindd = Ctrl+Alt, Delete, Toggle session menu, global, quickshell:sessionToggle # Toggle session menu -bind = Ctrl+Alt, Delete, exec, qs ipc call TEST_ALIVE || pkill wlogout || wlogout -p layer-shell # [hidden] Session menu (fallback) -bind = Shift+Super+Alt, Slash, exec, qs -p ~/.config/quickshell/welcome.qml # [hidden] Launch welcome app +bind = Ctrl+Alt, Delete, exec, qs -c $qsConfig ipc call TEST_ALIVE || pkill wlogout || wlogout -p layer-shell # [hidden] Session menu (fallback) +bind = Shift+Super+Alt, Slash, exec, qs -p ~/.config/quickshell/$qsConfig/welcome.qml # [hidden] Launch welcome app -bindle=, XF86MonBrightnessUp, exec, qs ipc call brightness increment || brightnessctl s 5%+ # [hidden] -bindle=, XF86MonBrightnessDown, exec, qs ipc call brightness decrement || brightnessctl s 5%- # [hidden] +bindle=, XF86MonBrightnessUp, exec, qs -c $qsConfig ipc call brightness increment || brightnessctl s 5%+ # [hidden] +bindle=, XF86MonBrightnessDown, exec, qs -c $qsConfig ipc call brightness decrement || brightnessctl s 5%- # [hidden] bindle=, XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 2%+ # [hidden] bindle=, XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 2%- # [hidden] @@ -43,14 +43,14 @@ bindld = Super+Shift,M, Toggle mute, exec, wpctl set-mute @DEFAULT_SINK@ toggle bindl = Alt ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_SOURCE@ toggle # [hidden] bindl = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_SOURCE@ toggle # [hidden] bindld = Super+Alt,M, Toggle mic, exec, wpctl set-mute @DEFAULT_SOURCE@ toggle # [hidden] -bindd = Ctrl+Super, T, Change wallpaper, exec, ~/.config/quickshell/scripts/colors/switchwall.sh # Change wallpaper -bind = Ctrl+Super, R, exec, killall ags agsv1 gjs ydotool qs quickshell; qs & # Restart widgets +bindd = Ctrl+Super, T, Change wallpaper, exec, ~/.config/quickshell/$qsConfig/scripts/colors/switchwall.sh # Change wallpaper +bind = Ctrl+Super, R, exec, killall ags agsv1 gjs ydotool qs quickshell; qs -c $qsConfig & # Restart widgets ##! Utilities # Screenshot, Record, OCR, Color picker, Clipboard history -bindd = Super, V, Copy clipboard history entry, exec, qs ipc call TEST_ALIVE || pkill fuzzel || cliphist list | fuzzel --match-mode fzf --dmenu | cliphist decode | wl-copy # [hidden] Clipboard history >> clipboard (fallback) -bindd = Super, Period, Copy an emoji, exec, qs ipc call TEST_ALIVE || pkill fuzzel || ~/.config/hypr/hyprland/scripts/fuzzel-emoji.sh copy # [hidden] Emoji >> clipboard (fallback) -bindd = Super+Shift, S, Screen snip, exec, qs -p ~/.config/quickshell/screenshot.qml || pidof slurp || hyprshot --freeze --clipboard-only --mode region --silent # Screen snip +bindd = Super, V, Copy clipboard history entry, exec, qs -c $qsConfig ipc call TEST_ALIVE || pkill fuzzel || cliphist list | fuzzel --match-mode fzf --dmenu | cliphist decode | wl-copy # [hidden] Clipboard history >> clipboard (fallback) +bindd = Super, Period, Copy an emoji, exec, qs -c $qsConfig ipc call TEST_ALIVE || pkill fuzzel || ~/.config/hypr/hyprland/scripts/fuzzel-emoji.sh copy # [hidden] Emoji >> clipboard (fallback) +bindd = Super+Shift, S, Screen snip, exec, qs -p ~/.config/quickshell/$qsConfig/screenshot.qml || pidof slurp || hyprshot --freeze --clipboard-only --mode region --silent # Screen snip # OCR bindd = Super+Shift, T, Character recognition,exec,grim -g "$(slurp $SLURP_ARGS)" "tmp.png" && tesseract "tmp.png" - | wl-copy && rm "tmp.png" # [hidden] # Color picker @@ -183,10 +183,10 @@ bindd = Ctrl+Shift+Alt+Super, Delete, Shutdown, exec, systemctl poweroff || logi ##! Screen # Zoom -binde = Super, Minus, exec, qs ipc call zoom zoomOut # Zoom out -binde = Super, Equal, exec, qs ipc call zoom zoomIn # Zoom in -binde = Super, Minus, exec, qs ipc call TEST_ALIVE || ~/.config/hypr/hyprland/scripts/zoom.sh decrease 0.1 # [hidden] Zoom out -binde = Super, Equal, exec, qs ipc call TEST_ALIVE || ~/.config/hypr/hyprland/scripts/zoom.sh increase 0.1 # [hidden] Zoom in +binde = Super, Minus, exec, qs -c $qsConfig ipc call zoom zoomOut # Zoom out +binde = Super, Equal, exec, qs -c $qsConfig ipc call zoom zoomIn # Zoom in +binde = Super, Minus, exec, qs -c $qsConfig ipc call TEST_ALIVE || ~/.config/hypr/hyprland/scripts/zoom.sh decrease 0.1 # [hidden] Zoom out +binde = Super, Equal, exec, qs -c $qsConfig ipc call TEST_ALIVE || ~/.config/hypr/hyprland/scripts/zoom.sh increase 0.1 # [hidden] Zoom in ##! Media bindl= Super+Shift, N, exec, playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` # Next track @@ -209,7 +209,7 @@ bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh bind = Super+Shift, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "wps" "onlyoffice-desktopeditors" # Office software bind = Super, X, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kate" "gnome-text-editor" "emacs" # Text editor bind = Ctrl+Super, V, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol" # Volume mixer -bind = Super, I, exec, XDG_CURRENT_DESKTOP=gnome ~/.config/hypr/hyprland/scripts/launch_first_available.sh "qs -p ~/.config/quickshell/settings.qml" "systemsettings" "gnome-control-center" "better-control" # Settings app +bind = Super, I, exec, XDG_CURRENT_DESKTOP=gnome ~/.config/hypr/hyprland/scripts/launch_first_available.sh "qs -p ~/.config/quickshell/$qsConfig/settings.qml" "systemsettings" "gnome-control-center" "better-control" # Settings app bind = Ctrl+Shift, Escape, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "gnome-system-monitor" "plasma-systemmonitzor --page-name Processes" "command -v btop && kitty -1 fish -c btop" # Task manager # Cursed stuff diff --git a/.config/quickshell/.qmlformat.ini b/.config/quickshell/ii/.qmlformat.ini similarity index 100% rename from .config/quickshell/.qmlformat.ini rename to .config/quickshell/ii/.qmlformat.ini diff --git a/.config/quickshell/GlobalStates.qml b/.config/quickshell/ii/GlobalStates.qml similarity index 100% rename from .config/quickshell/GlobalStates.qml rename to .config/quickshell/ii/GlobalStates.qml diff --git a/.config/quickshell/ReloadPopup.qml b/.config/quickshell/ii/ReloadPopup.qml similarity index 100% rename from .config/quickshell/ReloadPopup.qml rename to .config/quickshell/ii/ReloadPopup.qml diff --git a/.config/quickshell/assets/icons/ai-openai-symbolic.svg b/.config/quickshell/ii/assets/icons/ai-openai-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/ai-openai-symbolic.svg rename to .config/quickshell/ii/assets/icons/ai-openai-symbolic.svg diff --git a/.config/quickshell/assets/icons/arch-symbolic.svg b/.config/quickshell/ii/assets/icons/arch-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/arch-symbolic.svg rename to .config/quickshell/ii/assets/icons/arch-symbolic.svg diff --git a/.config/quickshell/assets/icons/cachyos-symbolic.svg b/.config/quickshell/ii/assets/icons/cachyos-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/cachyos-symbolic.svg rename to .config/quickshell/ii/assets/icons/cachyos-symbolic.svg diff --git a/.config/quickshell/assets/icons/cloudflare-dns-symbolic.svg b/.config/quickshell/ii/assets/icons/cloudflare-dns-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/cloudflare-dns-symbolic.svg rename to .config/quickshell/ii/assets/icons/cloudflare-dns-symbolic.svg diff --git a/.config/quickshell/assets/icons/crosshair-symbolic.svg b/.config/quickshell/ii/assets/icons/crosshair-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/crosshair-symbolic.svg rename to .config/quickshell/ii/assets/icons/crosshair-symbolic.svg diff --git a/.config/quickshell/assets/icons/debian-symbolic.svg b/.config/quickshell/ii/assets/icons/debian-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/debian-symbolic.svg rename to .config/quickshell/ii/assets/icons/debian-symbolic.svg diff --git a/.config/quickshell/assets/icons/deepseek-symbolic.svg b/.config/quickshell/ii/assets/icons/deepseek-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/deepseek-symbolic.svg rename to .config/quickshell/ii/assets/icons/deepseek-symbolic.svg diff --git a/.config/quickshell/assets/icons/desktop-symbolic.svg b/.config/quickshell/ii/assets/icons/desktop-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/desktop-symbolic.svg rename to .config/quickshell/ii/assets/icons/desktop-symbolic.svg diff --git a/.config/quickshell/assets/icons/endeavouros-symbolic.svg b/.config/quickshell/ii/assets/icons/endeavouros-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/endeavouros-symbolic.svg rename to .config/quickshell/ii/assets/icons/endeavouros-symbolic.svg diff --git a/.config/quickshell/assets/icons/fedora-symbolic.svg b/.config/quickshell/ii/assets/icons/fedora-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/fedora-symbolic.svg rename to .config/quickshell/ii/assets/icons/fedora-symbolic.svg diff --git a/.config/quickshell/assets/icons/flatpak-symbolic.svg b/.config/quickshell/ii/assets/icons/flatpak-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/flatpak-symbolic.svg rename to .config/quickshell/ii/assets/icons/flatpak-symbolic.svg diff --git a/.config/quickshell/assets/icons/github-symbolic.svg b/.config/quickshell/ii/assets/icons/github-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/github-symbolic.svg rename to .config/quickshell/ii/assets/icons/github-symbolic.svg diff --git a/.config/quickshell/assets/icons/google-gemini-symbolic.svg b/.config/quickshell/ii/assets/icons/google-gemini-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/google-gemini-symbolic.svg rename to .config/quickshell/ii/assets/icons/google-gemini-symbolic.svg diff --git a/.config/quickshell/assets/icons/linux-symbolic.svg b/.config/quickshell/ii/assets/icons/linux-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/linux-symbolic.svg rename to .config/quickshell/ii/assets/icons/linux-symbolic.svg diff --git a/.config/quickshell/assets/icons/microsoft-symbolic.svg b/.config/quickshell/ii/assets/icons/microsoft-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/microsoft-symbolic.svg rename to .config/quickshell/ii/assets/icons/microsoft-symbolic.svg diff --git a/.config/quickshell/assets/icons/nixos-symbolic.svg b/.config/quickshell/ii/assets/icons/nixos-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/nixos-symbolic.svg rename to .config/quickshell/ii/assets/icons/nixos-symbolic.svg diff --git a/.config/quickshell/assets/icons/ollama-symbolic.svg b/.config/quickshell/ii/assets/icons/ollama-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/ollama-symbolic.svg rename to .config/quickshell/ii/assets/icons/ollama-symbolic.svg diff --git a/.config/quickshell/assets/icons/openai-symbolic.svg b/.config/quickshell/ii/assets/icons/openai-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/openai-symbolic.svg rename to .config/quickshell/ii/assets/icons/openai-symbolic.svg diff --git a/.config/quickshell/assets/icons/openrouter-symbolic.svg b/.config/quickshell/ii/assets/icons/openrouter-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/openrouter-symbolic.svg rename to .config/quickshell/ii/assets/icons/openrouter-symbolic.svg diff --git a/.config/quickshell/assets/icons/spark-symbolic.svg b/.config/quickshell/ii/assets/icons/spark-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/spark-symbolic.svg rename to .config/quickshell/ii/assets/icons/spark-symbolic.svg diff --git a/.config/quickshell/assets/icons/ubuntu-symbolic.svg b/.config/quickshell/ii/assets/icons/ubuntu-symbolic.svg similarity index 100% rename from .config/quickshell/assets/icons/ubuntu-symbolic.svg rename to .config/quickshell/ii/assets/icons/ubuntu-symbolic.svg diff --git a/.config/quickshell/assets/images/default_wallpaper.png b/.config/quickshell/ii/assets/images/default_wallpaper.png similarity index 100% rename from .config/quickshell/assets/images/default_wallpaper.png rename to .config/quickshell/ii/assets/images/default_wallpaper.png diff --git a/.config/quickshell/defaults/ai/prompts/NoPrompt.md b/.config/quickshell/ii/defaults/ai/prompts/NoPrompt.md similarity index 100% rename from .config/quickshell/defaults/ai/prompts/NoPrompt.md rename to .config/quickshell/ii/defaults/ai/prompts/NoPrompt.md diff --git a/.config/quickshell/defaults/ai/prompts/ii-Default.md b/.config/quickshell/ii/defaults/ai/prompts/ii-Default.md similarity index 100% rename from .config/quickshell/defaults/ai/prompts/ii-Default.md rename to .config/quickshell/ii/defaults/ai/prompts/ii-Default.md diff --git a/.config/quickshell/defaults/ai/prompts/ii-Imouto.md b/.config/quickshell/ii/defaults/ai/prompts/ii-Imouto.md similarity index 100% rename from .config/quickshell/defaults/ai/prompts/ii-Imouto.md rename to .config/quickshell/ii/defaults/ai/prompts/ii-Imouto.md diff --git a/.config/quickshell/defaults/ai/prompts/w-FourPointedSparkle.md b/.config/quickshell/ii/defaults/ai/prompts/w-FourPointedSparkle.md similarity index 100% rename from .config/quickshell/defaults/ai/prompts/w-FourPointedSparkle.md rename to .config/quickshell/ii/defaults/ai/prompts/w-FourPointedSparkle.md diff --git a/.config/quickshell/defaults/ai/prompts/w-OpenMechanicalFlower.md b/.config/quickshell/ii/defaults/ai/prompts/w-OpenMechanicalFlower.md similarity index 100% rename from .config/quickshell/defaults/ai/prompts/w-OpenMechanicalFlower.md rename to .config/quickshell/ii/defaults/ai/prompts/w-OpenMechanicalFlower.md diff --git a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml b/.config/quickshell/ii/modules/backgroundWidgets/BackgroundWidgets.qml similarity index 100% rename from .config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml rename to .config/quickshell/ii/modules/backgroundWidgets/BackgroundWidgets.qml diff --git a/.config/quickshell/modules/bar/ActiveWindow.qml b/.config/quickshell/ii/modules/bar/ActiveWindow.qml similarity index 100% rename from .config/quickshell/modules/bar/ActiveWindow.qml rename to .config/quickshell/ii/modules/bar/ActiveWindow.qml diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml similarity index 100% rename from .config/quickshell/modules/bar/Bar.qml rename to .config/quickshell/ii/modules/bar/Bar.qml diff --git a/.config/quickshell/modules/bar/BarGroup.qml b/.config/quickshell/ii/modules/bar/BarGroup.qml similarity index 100% rename from .config/quickshell/modules/bar/BarGroup.qml rename to .config/quickshell/ii/modules/bar/BarGroup.qml diff --git a/.config/quickshell/modules/bar/BatteryIndicator.qml b/.config/quickshell/ii/modules/bar/BatteryIndicator.qml similarity index 100% rename from .config/quickshell/modules/bar/BatteryIndicator.qml rename to .config/quickshell/ii/modules/bar/BatteryIndicator.qml diff --git a/.config/quickshell/modules/bar/CircleUtilButton.qml b/.config/quickshell/ii/modules/bar/CircleUtilButton.qml similarity index 100% rename from .config/quickshell/modules/bar/CircleUtilButton.qml rename to .config/quickshell/ii/modules/bar/CircleUtilButton.qml diff --git a/.config/quickshell/modules/bar/ClockWidget.qml b/.config/quickshell/ii/modules/bar/ClockWidget.qml similarity index 100% rename from .config/quickshell/modules/bar/ClockWidget.qml rename to .config/quickshell/ii/modules/bar/ClockWidget.qml diff --git a/.config/quickshell/modules/bar/Media.qml b/.config/quickshell/ii/modules/bar/Media.qml similarity index 100% rename from .config/quickshell/modules/bar/Media.qml rename to .config/quickshell/ii/modules/bar/Media.qml diff --git a/.config/quickshell/modules/bar/Resource.qml b/.config/quickshell/ii/modules/bar/Resource.qml similarity index 100% rename from .config/quickshell/modules/bar/Resource.qml rename to .config/quickshell/ii/modules/bar/Resource.qml diff --git a/.config/quickshell/modules/bar/Resources.qml b/.config/quickshell/ii/modules/bar/Resources.qml similarity index 100% rename from .config/quickshell/modules/bar/Resources.qml rename to .config/quickshell/ii/modules/bar/Resources.qml diff --git a/.config/quickshell/modules/bar/ScrollHint.qml b/.config/quickshell/ii/modules/bar/ScrollHint.qml similarity index 100% rename from .config/quickshell/modules/bar/ScrollHint.qml rename to .config/quickshell/ii/modules/bar/ScrollHint.qml diff --git a/.config/quickshell/modules/bar/SysTray.qml b/.config/quickshell/ii/modules/bar/SysTray.qml similarity index 100% rename from .config/quickshell/modules/bar/SysTray.qml rename to .config/quickshell/ii/modules/bar/SysTray.qml diff --git a/.config/quickshell/modules/bar/SysTrayItem.qml b/.config/quickshell/ii/modules/bar/SysTrayItem.qml similarity index 100% rename from .config/quickshell/modules/bar/SysTrayItem.qml rename to .config/quickshell/ii/modules/bar/SysTrayItem.qml diff --git a/.config/quickshell/modules/bar/UtilButtons.qml b/.config/quickshell/ii/modules/bar/UtilButtons.qml similarity index 100% rename from .config/quickshell/modules/bar/UtilButtons.qml rename to .config/quickshell/ii/modules/bar/UtilButtons.qml diff --git a/.config/quickshell/modules/bar/Workspaces.qml b/.config/quickshell/ii/modules/bar/Workspaces.qml similarity index 100% rename from .config/quickshell/modules/bar/Workspaces.qml rename to .config/quickshell/ii/modules/bar/Workspaces.qml diff --git a/.config/quickshell/modules/bar/weather/WeatherBar.qml b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml similarity index 100% rename from .config/quickshell/modules/bar/weather/WeatherBar.qml rename to .config/quickshell/ii/modules/bar/weather/WeatherBar.qml diff --git a/.config/quickshell/modules/bar/weather/WeatherCard.qml b/.config/quickshell/ii/modules/bar/weather/WeatherCard.qml similarity index 100% rename from .config/quickshell/modules/bar/weather/WeatherCard.qml rename to .config/quickshell/ii/modules/bar/weather/WeatherCard.qml diff --git a/.config/quickshell/modules/bar/weather/WeatherIcons.qml b/.config/quickshell/ii/modules/bar/weather/WeatherIcons.qml similarity index 100% rename from .config/quickshell/modules/bar/weather/WeatherIcons.qml rename to .config/quickshell/ii/modules/bar/weather/WeatherIcons.qml diff --git a/.config/quickshell/modules/bar/weather/WeatherPopup.qml b/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml similarity index 100% rename from .config/quickshell/modules/bar/weather/WeatherPopup.qml rename to .config/quickshell/ii/modules/bar/weather/WeatherPopup.qml diff --git a/.config/quickshell/modules/cheatsheet/Cheatsheet.qml b/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml similarity index 100% rename from .config/quickshell/modules/cheatsheet/Cheatsheet.qml rename to .config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml diff --git a/.config/quickshell/modules/cheatsheet/CheatsheetKeybinds.qml b/.config/quickshell/ii/modules/cheatsheet/CheatsheetKeybinds.qml similarity index 100% rename from .config/quickshell/modules/cheatsheet/CheatsheetKeybinds.qml rename to .config/quickshell/ii/modules/cheatsheet/CheatsheetKeybinds.qml diff --git a/.config/quickshell/modules/cheatsheet/CheatsheetPeriodicTable.qml b/.config/quickshell/ii/modules/cheatsheet/CheatsheetPeriodicTable.qml similarity index 100% rename from .config/quickshell/modules/cheatsheet/CheatsheetPeriodicTable.qml rename to .config/quickshell/ii/modules/cheatsheet/CheatsheetPeriodicTable.qml diff --git a/.config/quickshell/modules/cheatsheet/ElementTile.qml b/.config/quickshell/ii/modules/cheatsheet/ElementTile.qml similarity index 100% rename from .config/quickshell/modules/cheatsheet/ElementTile.qml rename to .config/quickshell/ii/modules/cheatsheet/ElementTile.qml diff --git a/.config/quickshell/modules/cheatsheet/periodic_table.js b/.config/quickshell/ii/modules/cheatsheet/periodic_table.js similarity index 100% rename from .config/quickshell/modules/cheatsheet/periodic_table.js rename to .config/quickshell/ii/modules/cheatsheet/periodic_table.js diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/ii/modules/common/Appearance.qml similarity index 100% rename from .config/quickshell/modules/common/Appearance.qml rename to .config/quickshell/ii/modules/common/Appearance.qml diff --git a/.config/quickshell/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml similarity index 100% rename from .config/quickshell/modules/common/Config.qml rename to .config/quickshell/ii/modules/common/Config.qml diff --git a/.config/quickshell/modules/common/Directories.qml b/.config/quickshell/ii/modules/common/Directories.qml similarity index 91% rename from .config/quickshell/modules/common/Directories.qml rename to .config/quickshell/ii/modules/common/Directories.qml index f4eb448c..38cfd73d 100644 --- a/.config/quickshell/modules/common/Directories.qml +++ b/.config/quickshell/ii/modules/common/Directories.qml @@ -16,7 +16,8 @@ Singleton { readonly property string downloads: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0] // Other dirs used by the shell, without "file://" - property string scriptPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts`) + property string assetsPath: Quickshell.configPath("assets") + property string scriptPath: Quickshell.configPath("scripts") property string favicons: FileUtils.trimFileProtocol(`${Directories.cache}/media/favicons`) property string coverArt: FileUtils.trimFileProtocol(`${Directories.cache}/media/coverart`) property string booruPreviews: FileUtils.trimFileProtocol(`${Directories.cache}/media/boorus`) @@ -30,8 +31,9 @@ Singleton { property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`) property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`) property string cliphistDecode: FileUtils.trimFileProtocol(`/tmp/quickshell/media/cliphist`) + property string screenshotTemp: "/tmp/quickshell/media/screenshot" property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/colors/switchwall.sh`) - property string defaultAiPrompts: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/defaults/ai/prompts`) + property string defaultAiPrompts: Quickshell.configPath("defaults/ai/prompts") property string userAiPrompts: FileUtils.trimFileProtocol(`${Directories.shellConfig}/ai/prompts`) property string aiChats: FileUtils.trimFileProtocol(`${Directories.state}/user/ai/chats`) // Cleanup on init diff --git a/.config/quickshell/modules/common/Persistent.qml b/.config/quickshell/ii/modules/common/Persistent.qml similarity index 100% rename from .config/quickshell/modules/common/Persistent.qml rename to .config/quickshell/ii/modules/common/Persistent.qml diff --git a/.config/quickshell/modules/common/PersistentStates.qml b/.config/quickshell/ii/modules/common/PersistentStates.qml similarity index 100% rename from .config/quickshell/modules/common/PersistentStates.qml rename to .config/quickshell/ii/modules/common/PersistentStates.qml diff --git a/.config/quickshell/modules/common/functions/color_utils.js b/.config/quickshell/ii/modules/common/functions/color_utils.js similarity index 100% rename from .config/quickshell/modules/common/functions/color_utils.js rename to .config/quickshell/ii/modules/common/functions/color_utils.js diff --git a/.config/quickshell/modules/common/functions/file_utils.js b/.config/quickshell/ii/modules/common/functions/file_utils.js similarity index 100% rename from .config/quickshell/modules/common/functions/file_utils.js rename to .config/quickshell/ii/modules/common/functions/file_utils.js diff --git a/.config/quickshell/modules/common/functions/fuzzysort.js b/.config/quickshell/ii/modules/common/functions/fuzzysort.js similarity index 100% rename from .config/quickshell/modules/common/functions/fuzzysort.js rename to .config/quickshell/ii/modules/common/functions/fuzzysort.js diff --git a/.config/quickshell/modules/common/functions/levendist.js b/.config/quickshell/ii/modules/common/functions/levendist.js similarity index 100% rename from .config/quickshell/modules/common/functions/levendist.js rename to .config/quickshell/ii/modules/common/functions/levendist.js diff --git a/.config/quickshell/modules/common/functions/object_utils.js b/.config/quickshell/ii/modules/common/functions/object_utils.js similarity index 100% rename from .config/quickshell/modules/common/functions/object_utils.js rename to .config/quickshell/ii/modules/common/functions/object_utils.js diff --git a/.config/quickshell/modules/common/functions/string_utils.js b/.config/quickshell/ii/modules/common/functions/string_utils.js similarity index 100% rename from .config/quickshell/modules/common/functions/string_utils.js rename to .config/quickshell/ii/modules/common/functions/string_utils.js diff --git a/.config/quickshell/modules/common/widgets/ButtonGroup.qml b/.config/quickshell/ii/modules/common/widgets/ButtonGroup.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/ButtonGroup.qml rename to .config/quickshell/ii/modules/common/widgets/ButtonGroup.qml diff --git a/.config/quickshell/modules/common/widgets/CircularProgress.qml b/.config/quickshell/ii/modules/common/widgets/CircularProgress.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/CircularProgress.qml rename to .config/quickshell/ii/modules/common/widgets/CircularProgress.qml diff --git a/.config/quickshell/modules/common/widgets/CliphistImage.qml b/.config/quickshell/ii/modules/common/widgets/CliphistImage.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/CliphistImage.qml rename to .config/quickshell/ii/modules/common/widgets/CliphistImage.qml diff --git a/.config/quickshell/modules/common/widgets/ConfigRow.qml b/.config/quickshell/ii/modules/common/widgets/ConfigRow.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/ConfigRow.qml rename to .config/quickshell/ii/modules/common/widgets/ConfigRow.qml diff --git a/.config/quickshell/modules/common/widgets/ConfigSelectionArray.qml b/.config/quickshell/ii/modules/common/widgets/ConfigSelectionArray.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/ConfigSelectionArray.qml rename to .config/quickshell/ii/modules/common/widgets/ConfigSelectionArray.qml diff --git a/.config/quickshell/modules/common/widgets/ConfigSpinBox.qml b/.config/quickshell/ii/modules/common/widgets/ConfigSpinBox.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/ConfigSpinBox.qml rename to .config/quickshell/ii/modules/common/widgets/ConfigSpinBox.qml diff --git a/.config/quickshell/modules/common/widgets/ConfigSwitch.qml b/.config/quickshell/ii/modules/common/widgets/ConfigSwitch.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/ConfigSwitch.qml rename to .config/quickshell/ii/modules/common/widgets/ConfigSwitch.qml diff --git a/.config/quickshell/modules/common/widgets/ContentPage.qml b/.config/quickshell/ii/modules/common/widgets/ContentPage.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/ContentPage.qml rename to .config/quickshell/ii/modules/common/widgets/ContentPage.qml diff --git a/.config/quickshell/modules/common/widgets/ContentSection.qml b/.config/quickshell/ii/modules/common/widgets/ContentSection.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/ContentSection.qml rename to .config/quickshell/ii/modules/common/widgets/ContentSection.qml diff --git a/.config/quickshell/modules/common/widgets/ContentSubsection.qml b/.config/quickshell/ii/modules/common/widgets/ContentSubsection.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/ContentSubsection.qml rename to .config/quickshell/ii/modules/common/widgets/ContentSubsection.qml diff --git a/.config/quickshell/modules/common/widgets/ContentSubsectionLabel.qml b/.config/quickshell/ii/modules/common/widgets/ContentSubsectionLabel.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/ContentSubsectionLabel.qml rename to .config/quickshell/ii/modules/common/widgets/ContentSubsectionLabel.qml diff --git a/.config/quickshell/modules/common/widgets/CustomIcon.qml b/.config/quickshell/ii/modules/common/widgets/CustomIcon.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/CustomIcon.qml rename to .config/quickshell/ii/modules/common/widgets/CustomIcon.qml diff --git a/.config/quickshell/modules/common/widgets/DialogButton.qml b/.config/quickshell/ii/modules/common/widgets/DialogButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/DialogButton.qml rename to .config/quickshell/ii/modules/common/widgets/DialogButton.qml diff --git a/.config/quickshell/modules/common/widgets/DragManager.qml b/.config/quickshell/ii/modules/common/widgets/DragManager.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/DragManager.qml rename to .config/quickshell/ii/modules/common/widgets/DragManager.qml diff --git a/.config/quickshell/modules/common/widgets/Favicon.qml b/.config/quickshell/ii/modules/common/widgets/Favicon.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/Favicon.qml rename to .config/quickshell/ii/modules/common/widgets/Favicon.qml diff --git a/.config/quickshell/modules/common/widgets/FloatingActionButton.qml b/.config/quickshell/ii/modules/common/widgets/FloatingActionButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/FloatingActionButton.qml rename to .config/quickshell/ii/modules/common/widgets/FloatingActionButton.qml diff --git a/.config/quickshell/modules/common/widgets/FlowButtonGroup.qml b/.config/quickshell/ii/modules/common/widgets/FlowButtonGroup.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/FlowButtonGroup.qml rename to .config/quickshell/ii/modules/common/widgets/FlowButtonGroup.qml diff --git a/.config/quickshell/modules/common/widgets/GroupButton.qml b/.config/quickshell/ii/modules/common/widgets/GroupButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/GroupButton.qml rename to .config/quickshell/ii/modules/common/widgets/GroupButton.qml diff --git a/.config/quickshell/modules/common/widgets/KeyboardKey.qml b/.config/quickshell/ii/modules/common/widgets/KeyboardKey.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/KeyboardKey.qml rename to .config/quickshell/ii/modules/common/widgets/KeyboardKey.qml diff --git a/.config/quickshell/modules/common/widgets/LightDarkPreferenceButton.qml b/.config/quickshell/ii/modules/common/widgets/LightDarkPreferenceButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/LightDarkPreferenceButton.qml rename to .config/quickshell/ii/modules/common/widgets/LightDarkPreferenceButton.qml diff --git a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml b/.config/quickshell/ii/modules/common/widgets/MaterialSymbol.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/MaterialSymbol.qml rename to .config/quickshell/ii/modules/common/widgets/MaterialSymbol.qml diff --git a/.config/quickshell/modules/common/widgets/MaterialTextField.qml b/.config/quickshell/ii/modules/common/widgets/MaterialTextField.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/MaterialTextField.qml rename to .config/quickshell/ii/modules/common/widgets/MaterialTextField.qml diff --git a/.config/quickshell/modules/common/widgets/MenuButton.qml b/.config/quickshell/ii/modules/common/widgets/MenuButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/MenuButton.qml rename to .config/quickshell/ii/modules/common/widgets/MenuButton.qml diff --git a/.config/quickshell/modules/common/widgets/NavigationRail.qml b/.config/quickshell/ii/modules/common/widgets/NavigationRail.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/NavigationRail.qml rename to .config/quickshell/ii/modules/common/widgets/NavigationRail.qml diff --git a/.config/quickshell/modules/common/widgets/NavigationRailButton.qml b/.config/quickshell/ii/modules/common/widgets/NavigationRailButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/NavigationRailButton.qml rename to .config/quickshell/ii/modules/common/widgets/NavigationRailButton.qml diff --git a/.config/quickshell/modules/common/widgets/NavigationRailExpandButton.qml b/.config/quickshell/ii/modules/common/widgets/NavigationRailExpandButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/NavigationRailExpandButton.qml rename to .config/quickshell/ii/modules/common/widgets/NavigationRailExpandButton.qml diff --git a/.config/quickshell/modules/common/widgets/NavigationRailTabArray.qml b/.config/quickshell/ii/modules/common/widgets/NavigationRailTabArray.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/NavigationRailTabArray.qml rename to .config/quickshell/ii/modules/common/widgets/NavigationRailTabArray.qml diff --git a/.config/quickshell/modules/common/widgets/NotificationActionButton.qml b/.config/quickshell/ii/modules/common/widgets/NotificationActionButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/NotificationActionButton.qml rename to .config/quickshell/ii/modules/common/widgets/NotificationActionButton.qml diff --git a/.config/quickshell/modules/common/widgets/NotificationAppIcon.qml b/.config/quickshell/ii/modules/common/widgets/NotificationAppIcon.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/NotificationAppIcon.qml rename to .config/quickshell/ii/modules/common/widgets/NotificationAppIcon.qml diff --git a/.config/quickshell/modules/common/widgets/NotificationGroup.qml b/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/NotificationGroup.qml rename to .config/quickshell/ii/modules/common/widgets/NotificationGroup.qml diff --git a/.config/quickshell/modules/common/widgets/NotificationGroupExpandButton.qml b/.config/quickshell/ii/modules/common/widgets/NotificationGroupExpandButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/NotificationGroupExpandButton.qml rename to .config/quickshell/ii/modules/common/widgets/NotificationGroupExpandButton.qml diff --git a/.config/quickshell/modules/common/widgets/NotificationItem.qml b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/NotificationItem.qml rename to .config/quickshell/ii/modules/common/widgets/NotificationItem.qml diff --git a/.config/quickshell/modules/common/widgets/NotificationListView.qml b/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/NotificationListView.qml rename to .config/quickshell/ii/modules/common/widgets/NotificationListView.qml diff --git a/.config/quickshell/modules/common/widgets/PointingHandInteraction.qml b/.config/quickshell/ii/modules/common/widgets/PointingHandInteraction.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/PointingHandInteraction.qml rename to .config/quickshell/ii/modules/common/widgets/PointingHandInteraction.qml diff --git a/.config/quickshell/modules/common/widgets/PointingHandLinkHover.qml b/.config/quickshell/ii/modules/common/widgets/PointingHandLinkHover.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/PointingHandLinkHover.qml rename to .config/quickshell/ii/modules/common/widgets/PointingHandLinkHover.qml diff --git a/.config/quickshell/modules/common/widgets/PrimaryTabBar.qml b/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/PrimaryTabBar.qml rename to .config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml diff --git a/.config/quickshell/modules/common/widgets/PrimaryTabButton.qml b/.config/quickshell/ii/modules/common/widgets/PrimaryTabButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/PrimaryTabButton.qml rename to .config/quickshell/ii/modules/common/widgets/PrimaryTabButton.qml diff --git a/.config/quickshell/modules/common/widgets/Revealer.qml b/.config/quickshell/ii/modules/common/widgets/Revealer.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/Revealer.qml rename to .config/quickshell/ii/modules/common/widgets/Revealer.qml diff --git a/.config/quickshell/modules/common/widgets/RippleButton.qml b/.config/quickshell/ii/modules/common/widgets/RippleButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/RippleButton.qml rename to .config/quickshell/ii/modules/common/widgets/RippleButton.qml diff --git a/.config/quickshell/modules/common/widgets/RippleButtonWithIcon.qml b/.config/quickshell/ii/modules/common/widgets/RippleButtonWithIcon.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/RippleButtonWithIcon.qml rename to .config/quickshell/ii/modules/common/widgets/RippleButtonWithIcon.qml diff --git a/.config/quickshell/modules/common/widgets/RoundCorner.qml b/.config/quickshell/ii/modules/common/widgets/RoundCorner.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/RoundCorner.qml rename to .config/quickshell/ii/modules/common/widgets/RoundCorner.qml diff --git a/.config/quickshell/modules/common/widgets/SecondaryTabButton.qml b/.config/quickshell/ii/modules/common/widgets/SecondaryTabButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/SecondaryTabButton.qml rename to .config/quickshell/ii/modules/common/widgets/SecondaryTabButton.qml diff --git a/.config/quickshell/modules/common/widgets/SelectionDialog.qml b/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/SelectionDialog.qml rename to .config/quickshell/ii/modules/common/widgets/SelectionDialog.qml diff --git a/.config/quickshell/modules/common/widgets/SelectionGroupButton.qml b/.config/quickshell/ii/modules/common/widgets/SelectionGroupButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/SelectionGroupButton.qml rename to .config/quickshell/ii/modules/common/widgets/SelectionGroupButton.qml diff --git a/.config/quickshell/modules/common/widgets/StyledLabel.qml b/.config/quickshell/ii/modules/common/widgets/StyledLabel.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledLabel.qml rename to .config/quickshell/ii/modules/common/widgets/StyledLabel.qml diff --git a/.config/quickshell/modules/common/widgets/StyledListView.qml b/.config/quickshell/ii/modules/common/widgets/StyledListView.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledListView.qml rename to .config/quickshell/ii/modules/common/widgets/StyledListView.qml diff --git a/.config/quickshell/modules/common/widgets/StyledProgressBar.qml b/.config/quickshell/ii/modules/common/widgets/StyledProgressBar.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledProgressBar.qml rename to .config/quickshell/ii/modules/common/widgets/StyledProgressBar.qml diff --git a/.config/quickshell/modules/common/widgets/StyledRadioButton.qml b/.config/quickshell/ii/modules/common/widgets/StyledRadioButton.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledRadioButton.qml rename to .config/quickshell/ii/modules/common/widgets/StyledRadioButton.qml diff --git a/.config/quickshell/modules/common/widgets/StyledRectangularShadow.qml b/.config/quickshell/ii/modules/common/widgets/StyledRectangularShadow.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledRectangularShadow.qml rename to .config/quickshell/ii/modules/common/widgets/StyledRectangularShadow.qml diff --git a/.config/quickshell/modules/common/widgets/StyledSlider.qml b/.config/quickshell/ii/modules/common/widgets/StyledSlider.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledSlider.qml rename to .config/quickshell/ii/modules/common/widgets/StyledSlider.qml diff --git a/.config/quickshell/modules/common/widgets/StyledSpinBox.qml b/.config/quickshell/ii/modules/common/widgets/StyledSpinBox.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledSpinBox.qml rename to .config/quickshell/ii/modules/common/widgets/StyledSpinBox.qml diff --git a/.config/quickshell/modules/common/widgets/StyledSwitch.qml b/.config/quickshell/ii/modules/common/widgets/StyledSwitch.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledSwitch.qml rename to .config/quickshell/ii/modules/common/widgets/StyledSwitch.qml diff --git a/.config/quickshell/modules/common/widgets/StyledText.qml b/.config/quickshell/ii/modules/common/widgets/StyledText.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledText.qml rename to .config/quickshell/ii/modules/common/widgets/StyledText.qml diff --git a/.config/quickshell/modules/common/widgets/StyledTextArea.qml b/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledTextArea.qml rename to .config/quickshell/ii/modules/common/widgets/StyledTextArea.qml diff --git a/.config/quickshell/modules/common/widgets/StyledTextInput.qml b/.config/quickshell/ii/modules/common/widgets/StyledTextInput.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledTextInput.qml rename to .config/quickshell/ii/modules/common/widgets/StyledTextInput.qml diff --git a/.config/quickshell/modules/common/widgets/StyledToolTip.qml b/.config/quickshell/ii/modules/common/widgets/StyledToolTip.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/StyledToolTip.qml rename to .config/quickshell/ii/modules/common/widgets/StyledToolTip.qml diff --git a/.config/quickshell/modules/common/widgets/VerticalButtonGroup.qml b/.config/quickshell/ii/modules/common/widgets/VerticalButtonGroup.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/VerticalButtonGroup.qml rename to .config/quickshell/ii/modules/common/widgets/VerticalButtonGroup.qml diff --git a/.config/quickshell/modules/common/widgets/WaveVisualizer.qml b/.config/quickshell/ii/modules/common/widgets/WaveVisualizer.qml similarity index 100% rename from .config/quickshell/modules/common/widgets/WaveVisualizer.qml rename to .config/quickshell/ii/modules/common/widgets/WaveVisualizer.qml diff --git a/.config/quickshell/modules/common/widgets/notification_utils.js b/.config/quickshell/ii/modules/common/widgets/notification_utils.js similarity index 100% rename from .config/quickshell/modules/common/widgets/notification_utils.js rename to .config/quickshell/ii/modules/common/widgets/notification_utils.js diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/ii/modules/dock/Dock.qml similarity index 100% rename from .config/quickshell/modules/dock/Dock.qml rename to .config/quickshell/ii/modules/dock/Dock.qml diff --git a/.config/quickshell/modules/dock/DockAppButton.qml b/.config/quickshell/ii/modules/dock/DockAppButton.qml similarity index 100% rename from .config/quickshell/modules/dock/DockAppButton.qml rename to .config/quickshell/ii/modules/dock/DockAppButton.qml diff --git a/.config/quickshell/modules/dock/DockApps.qml b/.config/quickshell/ii/modules/dock/DockApps.qml similarity index 100% rename from .config/quickshell/modules/dock/DockApps.qml rename to .config/quickshell/ii/modules/dock/DockApps.qml diff --git a/.config/quickshell/modules/dock/DockButton.qml b/.config/quickshell/ii/modules/dock/DockButton.qml similarity index 100% rename from .config/quickshell/modules/dock/DockButton.qml rename to .config/quickshell/ii/modules/dock/DockButton.qml diff --git a/.config/quickshell/modules/dock/DockSeparator.qml b/.config/quickshell/ii/modules/dock/DockSeparator.qml similarity index 100% rename from .config/quickshell/modules/dock/DockSeparator.qml rename to .config/quickshell/ii/modules/dock/DockSeparator.qml diff --git a/.config/quickshell/modules/mediaControls/MediaControls.qml b/.config/quickshell/ii/modules/mediaControls/MediaControls.qml similarity index 99% rename from .config/quickshell/modules/mediaControls/MediaControls.qml rename to .config/quickshell/ii/modules/mediaControls/MediaControls.qml index 446fa91c..0dde4d12 100644 --- a/.config/quickshell/modules/mediaControls/MediaControls.qml +++ b/.config/quickshell/ii/modules/mediaControls/MediaControls.qml @@ -79,7 +79,7 @@ Scope { root.visualizerPoints = []; } } - command: ["cava", "-p", `${FileUtils.trimFileProtocol(Directories.config)}/quickshell/scripts/cava/raw_output_config.txt`] + command: ["cava", "-p", `${FileUtils.trimFileProtocol(Directories.scriptPath)}/cava/raw_output_config.txt`] stdout: SplitParser { onRead: data => { // Parse `;`-separated values into the visualizerPoints array diff --git a/.config/quickshell/modules/mediaControls/PlayerControl.qml b/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml similarity index 100% rename from .config/quickshell/modules/mediaControls/PlayerControl.qml rename to .config/quickshell/ii/modules/mediaControls/PlayerControl.qml diff --git a/.config/quickshell/modules/notificationPopup/NotificationPopup.qml b/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml similarity index 100% rename from .config/quickshell/modules/notificationPopup/NotificationPopup.qml rename to .config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml diff --git a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml similarity index 100% rename from .config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml rename to .config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml diff --git a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml similarity index 100% rename from .config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml rename to .config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml diff --git a/.config/quickshell/modules/onScreenDisplay/OsdValueIndicator.qml b/.config/quickshell/ii/modules/onScreenDisplay/OsdValueIndicator.qml similarity index 100% rename from .config/quickshell/modules/onScreenDisplay/OsdValueIndicator.qml rename to .config/quickshell/ii/modules/onScreenDisplay/OsdValueIndicator.qml diff --git a/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml b/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml similarity index 100% rename from .config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml rename to .config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml diff --git a/.config/quickshell/modules/onScreenKeyboard/OskContent.qml b/.config/quickshell/ii/modules/onScreenKeyboard/OskContent.qml similarity index 100% rename from .config/quickshell/modules/onScreenKeyboard/OskContent.qml rename to .config/quickshell/ii/modules/onScreenKeyboard/OskContent.qml diff --git a/.config/quickshell/modules/onScreenKeyboard/OskKey.qml b/.config/quickshell/ii/modules/onScreenKeyboard/OskKey.qml similarity index 100% rename from .config/quickshell/modules/onScreenKeyboard/OskKey.qml rename to .config/quickshell/ii/modules/onScreenKeyboard/OskKey.qml diff --git a/.config/quickshell/modules/onScreenKeyboard/layouts.js b/.config/quickshell/ii/modules/onScreenKeyboard/layouts.js similarity index 100% rename from .config/quickshell/modules/onScreenKeyboard/layouts.js rename to .config/quickshell/ii/modules/onScreenKeyboard/layouts.js diff --git a/.config/quickshell/modules/overview/Overview.qml b/.config/quickshell/ii/modules/overview/Overview.qml similarity index 100% rename from .config/quickshell/modules/overview/Overview.qml rename to .config/quickshell/ii/modules/overview/Overview.qml diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/ii/modules/overview/OverviewWidget.qml similarity index 100% rename from .config/quickshell/modules/overview/OverviewWidget.qml rename to .config/quickshell/ii/modules/overview/OverviewWidget.qml diff --git a/.config/quickshell/modules/overview/OverviewWindow.qml b/.config/quickshell/ii/modules/overview/OverviewWindow.qml similarity index 100% rename from .config/quickshell/modules/overview/OverviewWindow.qml rename to .config/quickshell/ii/modules/overview/OverviewWindow.qml diff --git a/.config/quickshell/modules/overview/SearchItem.qml b/.config/quickshell/ii/modules/overview/SearchItem.qml similarity index 100% rename from .config/quickshell/modules/overview/SearchItem.qml rename to .config/quickshell/ii/modules/overview/SearchItem.qml diff --git a/.config/quickshell/modules/overview/SearchWidget.qml b/.config/quickshell/ii/modules/overview/SearchWidget.qml similarity index 100% rename from .config/quickshell/modules/overview/SearchWidget.qml rename to .config/quickshell/ii/modules/overview/SearchWidget.qml diff --git a/.config/quickshell/modules/screenCorners/ScreenCorners.qml b/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml similarity index 100% rename from .config/quickshell/modules/screenCorners/ScreenCorners.qml rename to .config/quickshell/ii/modules/screenCorners/ScreenCorners.qml diff --git a/.config/quickshell/modules/session/Session.qml b/.config/quickshell/ii/modules/session/Session.qml similarity index 100% rename from .config/quickshell/modules/session/Session.qml rename to .config/quickshell/ii/modules/session/Session.qml diff --git a/.config/quickshell/modules/session/SessionActionButton.qml b/.config/quickshell/ii/modules/session/SessionActionButton.qml similarity index 100% rename from .config/quickshell/modules/session/SessionActionButton.qml rename to .config/quickshell/ii/modules/session/SessionActionButton.qml diff --git a/.config/quickshell/modules/settings/About.qml b/.config/quickshell/ii/modules/settings/About.qml similarity index 100% rename from .config/quickshell/modules/settings/About.qml rename to .config/quickshell/ii/modules/settings/About.qml diff --git a/.config/quickshell/modules/settings/InterfaceConfig.qml b/.config/quickshell/ii/modules/settings/InterfaceConfig.qml similarity index 100% rename from .config/quickshell/modules/settings/InterfaceConfig.qml rename to .config/quickshell/ii/modules/settings/InterfaceConfig.qml diff --git a/.config/quickshell/modules/settings/ServicesConfig.qml b/.config/quickshell/ii/modules/settings/ServicesConfig.qml similarity index 100% rename from .config/quickshell/modules/settings/ServicesConfig.qml rename to .config/quickshell/ii/modules/settings/ServicesConfig.qml diff --git a/.config/quickshell/modules/settings/StyleConfig.qml b/.config/quickshell/ii/modules/settings/StyleConfig.qml similarity index 99% rename from .config/quickshell/modules/settings/StyleConfig.qml rename to .config/quickshell/ii/modules/settings/StyleConfig.qml index 6de02639..bc1998c8 100644 --- a/.config/quickshell/modules/settings/StyleConfig.qml +++ b/.config/quickshell/ii/modules/settings/StyleConfig.qml @@ -18,7 +18,7 @@ ContentPage { Process { id: konachanWallProc property string status: "" - command: ["bash", "-c", FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/random_konachan_wall.sh`)] + command: ["bash", "-c", FileUtils.trimFileProtocol(`${Directories.scriptPath}/colors/random_konachan_wall.sh`)] stdout: SplitParser { onRead: data => { console.log(`Konachan wall proc output: ${data}`); diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml similarity index 99% rename from .config/quickshell/modules/sidebarLeft/AiChat.qml rename to .config/quickshell/ii/modules/sidebarLeft/AiChat.qml index b6ef48c1..6c4e65f9 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml @@ -129,7 +129,7 @@ Mowe uwu wem ipsum! ### Formatting - *Italic*, \`Monospace\`, **Bold**, [Link](https://example.com) -- Arch lincox icon +- Arch lincox icon ### Table diff --git a/.config/quickshell/modules/sidebarLeft/Anime.qml b/.config/quickshell/ii/modules/sidebarLeft/Anime.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/Anime.qml rename to .config/quickshell/ii/modules/sidebarLeft/Anime.qml diff --git a/.config/quickshell/modules/sidebarLeft/ApiCommandButton.qml b/.config/quickshell/ii/modules/sidebarLeft/ApiCommandButton.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/ApiCommandButton.qml rename to .config/quickshell/ii/modules/sidebarLeft/ApiCommandButton.qml diff --git a/.config/quickshell/modules/sidebarLeft/DescriptionBox.qml b/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/DescriptionBox.qml rename to .config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml diff --git a/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/SidebarLeft.qml rename to .config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml diff --git a/.config/quickshell/modules/sidebarLeft/SidebarLeftContent.qml b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/SidebarLeftContent.qml rename to .config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml diff --git a/.config/quickshell/modules/sidebarLeft/Translator.qml b/.config/quickshell/ii/modules/sidebarLeft/Translator.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/Translator.qml rename to .config/quickshell/ii/modules/sidebarLeft/Translator.qml diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessage.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml rename to .config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessage.qml diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessageControlButton.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessageControlButton.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/aiChat/AiMessageControlButton.qml rename to .config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessageControlButton.qml diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml rename to .config/quickshell/ii/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageCodeBlock.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml rename to .config/quickshell/ii/modules/sidebarLeft/aiChat/MessageCodeBlock.qml diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageTextBlock.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml rename to .config/quickshell/ii/modules/sidebarLeft/aiChat/MessageTextBlock.qml diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageThinkBlock.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageThinkBlock.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/aiChat/MessageThinkBlock.qml rename to .config/quickshell/ii/modules/sidebarLeft/aiChat/MessageThinkBlock.qml diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/anime/BooruImage.qml rename to .config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruResponse.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml rename to .config/quickshell/ii/modules/sidebarLeft/anime/BooruResponse.qml diff --git a/.config/quickshell/modules/sidebarLeft/translator/LanguageSelectorButton.qml b/.config/quickshell/ii/modules/sidebarLeft/translator/LanguageSelectorButton.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/translator/LanguageSelectorButton.qml rename to .config/quickshell/ii/modules/sidebarLeft/translator/LanguageSelectorButton.qml diff --git a/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml b/.config/quickshell/ii/modules/sidebarLeft/translator/TextCanvas.qml similarity index 100% rename from .config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml rename to .config/quickshell/ii/modules/sidebarLeft/translator/TextCanvas.qml diff --git a/.config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/BottomWidgetGroup.qml rename to .config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml diff --git a/.config/quickshell/modules/sidebarRight/CenterWidgetGroup.qml b/.config/quickshell/ii/modules/sidebarRight/CenterWidgetGroup.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/CenterWidgetGroup.qml rename to .config/quickshell/ii/modules/sidebarRight/CenterWidgetGroup.qml diff --git a/.config/quickshell/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml similarity index 98% rename from .config/quickshell/modules/sidebarRight/SidebarRight.qml rename to .config/quickshell/ii/modules/sidebarRight/SidebarRight.qml index 71ce53db..ead2ff2a 100644 --- a/.config/quickshell/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml @@ -20,7 +20,7 @@ Scope { id: root property int sidebarWidth: Appearance.sizes.sidebarWidth property int sidebarPadding: 15 - property string settingsQmlPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/settings.qml`) + property string settingsQmlPath: Quickshell.configPath("settings.qml") PanelWindow { id: sidebarRoot diff --git a/.config/quickshell/modules/sidebarRight/calendar/CalendarDayButton.qml b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarDayButton.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/calendar/CalendarDayButton.qml rename to .config/quickshell/ii/modules/sidebarRight/calendar/CalendarDayButton.qml diff --git a/.config/quickshell/modules/sidebarRight/calendar/CalendarHeaderButton.qml b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarHeaderButton.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/calendar/CalendarHeaderButton.qml rename to .config/quickshell/ii/modules/sidebarRight/calendar/CalendarHeaderButton.qml diff --git a/.config/quickshell/modules/sidebarRight/calendar/CalendarWidget.qml b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/calendar/CalendarWidget.qml rename to .config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml diff --git a/.config/quickshell/modules/sidebarRight/calendar/calendar_layout.js b/.config/quickshell/ii/modules/sidebarRight/calendar/calendar_layout.js similarity index 100% rename from .config/quickshell/modules/sidebarRight/calendar/calendar_layout.js rename to .config/quickshell/ii/modules/sidebarRight/calendar/calendar_layout.js diff --git a/.config/quickshell/modules/sidebarRight/notifications/NotificationList.qml b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/notifications/NotificationList.qml rename to .config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml diff --git a/.config/quickshell/modules/sidebarRight/notifications/NotificationStatusButton.qml b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationStatusButton.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/notifications/NotificationStatusButton.qml rename to .config/quickshell/ii/modules/sidebarRight/notifications/NotificationStatusButton.qml diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/quickToggles/BluetoothToggle.qml rename to .config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/CloudflareWarp.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/quickToggles/CloudflareWarp.qml rename to .config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/GameMode.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/quickToggles/GameMode.qml rename to .config/quickshell/ii/modules/sidebarRight/quickToggles/GameMode.qml diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml similarity index 75% rename from .config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml rename to .config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml index b48d3467..b4b0401e 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml @@ -12,10 +12,10 @@ QuickToggleButton { onClicked: { if (toggled) { root.toggled = false - Hyprland.dispatch("exec pkill wayland-idle") // pkill doesn't accept too long names + Quickshell.execDetached(["pkill", "wayland-idle"]) // pkill doesn't accept too long names } else { root.toggled = true - Hyprland.dispatch('exec ${XDG_CONFIG_HOME:-$HOME/.config}/quickshell/scripts/wayland-idle-inhibitor.py') + Quickshell.execDetached([`${Directories.scriptPath}/wayland-idle-inhibitor.py`]) } } Process { diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml rename to .config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/NightLight.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/quickToggles/NightLight.qml rename to .config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/QuickToggleButton.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/QuickToggleButton.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/quickToggles/QuickToggleButton.qml rename to .config/quickshell/ii/modules/sidebarRight/quickToggles/QuickToggleButton.qml diff --git a/.config/quickshell/modules/sidebarRight/todo/TaskList.qml b/.config/quickshell/ii/modules/sidebarRight/todo/TaskList.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/todo/TaskList.qml rename to .config/quickshell/ii/modules/sidebarRight/todo/TaskList.qml diff --git a/.config/quickshell/modules/sidebarRight/todo/TodoItemActionButton.qml b/.config/quickshell/ii/modules/sidebarRight/todo/TodoItemActionButton.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/todo/TodoItemActionButton.qml rename to .config/quickshell/ii/modules/sidebarRight/todo/TodoItemActionButton.qml diff --git a/.config/quickshell/modules/sidebarRight/todo/TodoWidget.qml b/.config/quickshell/ii/modules/sidebarRight/todo/TodoWidget.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/todo/TodoWidget.qml rename to .config/quickshell/ii/modules/sidebarRight/todo/TodoWidget.qml diff --git a/.config/quickshell/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml rename to .config/quickshell/ii/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml diff --git a/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml rename to .config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml diff --git a/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml similarity index 100% rename from .config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml rename to .config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml diff --git a/.config/quickshell/screenshot.qml b/.config/quickshell/ii/screenshot.qml similarity index 99% rename from .config/quickshell/screenshot.qml rename to .config/quickshell/ii/screenshot.qml index 4e9422fe..f1555871 100644 --- a/.config/quickshell/screenshot.qml +++ b/.config/quickshell/ii/screenshot.qml @@ -22,7 +22,7 @@ import "./services/" ShellRoot { id: root - property string screenshotDir: "/tmp/quickshell/media/screenshot" + property string screenshotDir: Directories.screenshotTemp property color overlayColor: "#77111111" property color genericContentColor: Qt.alpha(root.overlayColor, 0.9) property color genericContentForeground: "#ddffffff" diff --git a/.config/quickshell/scripts/ai/show-installed-ollama-models.sh b/.config/quickshell/ii/scripts/ai/show-installed-ollama-models.sh similarity index 100% rename from .config/quickshell/scripts/ai/show-installed-ollama-models.sh rename to .config/quickshell/ii/scripts/ai/show-installed-ollama-models.sh diff --git a/.config/quickshell/scripts/cava/raw_output_config.txt b/.config/quickshell/ii/scripts/cava/raw_output_config.txt similarity index 100% rename from .config/quickshell/scripts/cava/raw_output_config.txt rename to .config/quickshell/ii/scripts/cava/raw_output_config.txt diff --git a/.config/quickshell/scripts/colors/applycolor.sh b/.config/quickshell/ii/scripts/colors/applycolor.sh similarity index 89% rename from .config/quickshell/scripts/colors/applycolor.sh rename to .config/quickshell/ii/scripts/colors/applycolor.sh index b36fc4d2..fe87e655 100755 --- a/.config/quickshell/scripts/colors/applycolor.sh +++ b/.config/quickshell/ii/scripts/colors/applycolor.sh @@ -1,11 +1,12 @@ #!/usr/bin/env bash +QUICKSHELL_CONFIG_NAME="ii" XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" -CONFIG_DIR="$XDG_CONFIG_HOME/quickshell" -CACHE_DIR="$XDG_CACHE_HOME/quickshell" -STATE_DIR="$XDG_STATE_HOME/quickshell" +CONFIG_DIR="$XDG_CONFIG_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +CACHE_DIR="$XDG_CACHE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +STATE_DIR="$XDG_STATE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" term_alpha=100 #Set this to < 100 make all your terminals transparent diff --git a/.config/quickshell/scripts/colors/generate_colors_material.py b/.config/quickshell/ii/scripts/colors/generate_colors_material.py similarity index 100% rename from .config/quickshell/scripts/colors/generate_colors_material.py rename to .config/quickshell/ii/scripts/colors/generate_colors_material.py diff --git a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh new file mode 100755 index 00000000..c44f3e3a --- /dev/null +++ b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +QUICKSHELL_CONFIG_NAME="ii" +XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" +XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" +XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" +CONFIG_DIR="$XDG_CONFIG_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +CACHE_DIR="$XDG_CACHE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +STATE_DIR="$XDG_STATE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +mkdir -p ~/Pictures/Wallpapers +page=$((1 + RANDOM % 1000)); +response=$(curl "https://konachan.com/post.json?tags=rating%3Asafe&limit=1&page=$page") +link=$(echo "$response" | jq '.[0].file_url' -r); +ext=$(echo "$link" | awk -F. '{print $NF}') +downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image.$ext" +curl "$link" -o "$downloadPath" +"$SCRIPT_DIR/switchwall.sh" --image "$downloadPath" diff --git a/.config/quickshell/scripts/colors/scheme_for_image.py b/.config/quickshell/ii/scripts/colors/scheme_for_image.py similarity index 100% rename from .config/quickshell/scripts/colors/scheme_for_image.py rename to .config/quickshell/ii/scripts/colors/scheme_for_image.py diff --git a/.config/quickshell/scripts/colors/switchwall.sh b/.config/quickshell/ii/scripts/colors/switchwall.sh similarity index 98% rename from .config/quickshell/scripts/colors/switchwall.sh rename to .config/quickshell/ii/scripts/colors/switchwall.sh index 11cf2a43..fa834bce 100755 --- a/.config/quickshell/scripts/colors/switchwall.sh +++ b/.config/quickshell/ii/scripts/colors/switchwall.sh @@ -1,14 +1,15 @@ #!/usr/bin/env bash +QUICKSHELL_CONFIG_NAME="ii" XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" -CONFIG_DIR="$XDG_CONFIG_HOME/quickshell" -CACHE_DIR="$XDG_CACHE_HOME/quickshell" -STATE_DIR="$XDG_STATE_HOME/quickshell" +CONFIG_DIR="$XDG_CONFIG_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +CACHE_DIR="$XDG_CACHE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +STATE_DIR="$XDG_STATE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" MATUGEN_DIR="$XDG_CONFIG_HOME/matugen" -terminalscheme="$XDG_CONFIG_HOME/quickshell/scripts/terminal/scheme-base.json" +terminalscheme="$SCRIPT_DIR/terminal/scheme-base.json" handle_kde_material_you_colors() { # Map $type_flag to allowed scheme variants for kde-material-you-colors-wrapper.sh diff --git a/.config/quickshell/scripts/hyprland/get_keybinds.py b/.config/quickshell/ii/scripts/hyprland/get_keybinds.py similarity index 100% rename from .config/quickshell/scripts/hyprland/get_keybinds.py rename to .config/quickshell/ii/scripts/hyprland/get_keybinds.py diff --git a/.config/quickshell/scripts/images/find_regions.py b/.config/quickshell/ii/scripts/images/find_regions.py similarity index 100% rename from .config/quickshell/scripts/images/find_regions.py rename to .config/quickshell/ii/scripts/images/find_regions.py diff --git a/.config/quickshell/scripts/kvantum/adwsvg.py b/.config/quickshell/ii/scripts/kvantum/adwsvg.py similarity index 100% rename from .config/quickshell/scripts/kvantum/adwsvg.py rename to .config/quickshell/ii/scripts/kvantum/adwsvg.py diff --git a/.config/quickshell/scripts/kvantum/adwsvgDark.py b/.config/quickshell/ii/scripts/kvantum/adwsvgDark.py similarity index 100% rename from .config/quickshell/scripts/kvantum/adwsvgDark.py rename to .config/quickshell/ii/scripts/kvantum/adwsvgDark.py diff --git a/.config/quickshell/scripts/kvantum/changeAdwColors.py b/.config/quickshell/ii/scripts/kvantum/changeAdwColors.py similarity index 100% rename from .config/quickshell/scripts/kvantum/changeAdwColors.py rename to .config/quickshell/ii/scripts/kvantum/changeAdwColors.py diff --git a/.config/quickshell/scripts/kvantum/materialQT.sh b/.config/quickshell/ii/scripts/kvantum/materialQT.sh similarity index 80% rename from .config/quickshell/scripts/kvantum/materialQT.sh rename to .config/quickshell/ii/scripts/kvantum/materialQT.sh index 3d1f8a7b..835706a2 100755 --- a/.config/quickshell/scripts/kvantum/materialQT.sh +++ b/.config/quickshell/ii/scripts/kvantum/materialQT.sh @@ -1,11 +1,13 @@ #!/usr/bin/env bash +QUICKSHELL_CONFIG_NAME="ii" XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" -CONFIG_DIR="$XDG_CONFIG_HOME/quickshell" -CACHE_DIR="$XDG_CACHE_HOME/quickshell" -STATE_DIR="$XDG_STATE_HOME/quickshell" +CONFIG_DIR="$XDG_CONFIG_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +CACHE_DIR="$XDG_CACHE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +STATE_DIR="$XDG_STATE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" get_light_dark() { current_mode=$(gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null | tr -d "'") diff --git a/.config/quickshell/scripts/terminal/scheme-base.json b/.config/quickshell/ii/scripts/terminal/scheme-base.json similarity index 100% rename from .config/quickshell/scripts/terminal/scheme-base.json rename to .config/quickshell/ii/scripts/terminal/scheme-base.json diff --git a/.config/quickshell/scripts/terminal/sequences.txt b/.config/quickshell/ii/scripts/terminal/sequences.txt similarity index 100% rename from .config/quickshell/scripts/terminal/sequences.txt rename to .config/quickshell/ii/scripts/terminal/sequences.txt diff --git a/.config/quickshell/scripts/wayland-idle-inhibitor.py b/.config/quickshell/ii/scripts/wayland-idle-inhibitor.py similarity index 100% rename from .config/quickshell/scripts/wayland-idle-inhibitor.py rename to .config/quickshell/ii/scripts/wayland-idle-inhibitor.py diff --git a/.config/quickshell/services/Ai.qml b/.config/quickshell/ii/services/Ai.qml similarity index 99% rename from .config/quickshell/services/Ai.qml rename to .config/quickshell/ii/services/Ai.qml index 639ae936..24521fb6 100644 --- a/.config/quickshell/services/Ai.qml +++ b/.config/quickshell/ii/services/Ai.qml @@ -237,7 +237,7 @@ Singleton { Process { id: getOllamaModels running: true - command: ["bash", "-c", `${Directories.config}/quickshell/scripts/ai/show-installed-ollama-models.sh`.replace(/file:\/\//, "")] + command: ["bash", "-c", `${Directories.scriptPath}/ai/show-installed-ollama-models.sh`.replace(/file:\/\//, "")] stdout: SplitParser { onRead: data => { try { diff --git a/.config/quickshell/services/AiMessageData.qml b/.config/quickshell/ii/services/AiMessageData.qml similarity index 100% rename from .config/quickshell/services/AiMessageData.qml rename to .config/quickshell/ii/services/AiMessageData.qml diff --git a/.config/quickshell/services/AppSearch.qml b/.config/quickshell/ii/services/AppSearch.qml similarity index 100% rename from .config/quickshell/services/AppSearch.qml rename to .config/quickshell/ii/services/AppSearch.qml diff --git a/.config/quickshell/services/Audio.qml b/.config/quickshell/ii/services/Audio.qml similarity index 100% rename from .config/quickshell/services/Audio.qml rename to .config/quickshell/ii/services/Audio.qml diff --git a/.config/quickshell/services/Battery.qml b/.config/quickshell/ii/services/Battery.qml similarity index 100% rename from .config/quickshell/services/Battery.qml rename to .config/quickshell/ii/services/Battery.qml diff --git a/.config/quickshell/services/Bluetooth.qml b/.config/quickshell/ii/services/Bluetooth.qml similarity index 100% rename from .config/quickshell/services/Bluetooth.qml rename to .config/quickshell/ii/services/Bluetooth.qml diff --git a/.config/quickshell/services/Booru.qml b/.config/quickshell/ii/services/Booru.qml similarity index 100% rename from .config/quickshell/services/Booru.qml rename to .config/quickshell/ii/services/Booru.qml diff --git a/.config/quickshell/services/BooruResponseData.qml b/.config/quickshell/ii/services/BooruResponseData.qml similarity index 100% rename from .config/quickshell/services/BooruResponseData.qml rename to .config/quickshell/ii/services/BooruResponseData.qml diff --git a/.config/quickshell/services/Brightness.qml b/.config/quickshell/ii/services/Brightness.qml similarity index 100% rename from .config/quickshell/services/Brightness.qml rename to .config/quickshell/ii/services/Brightness.qml diff --git a/.config/quickshell/services/Cliphist.qml b/.config/quickshell/ii/services/Cliphist.qml similarity index 100% rename from .config/quickshell/services/Cliphist.qml rename to .config/quickshell/ii/services/Cliphist.qml diff --git a/.config/quickshell/services/DateTime.qml b/.config/quickshell/ii/services/DateTime.qml similarity index 100% rename from .config/quickshell/services/DateTime.qml rename to .config/quickshell/ii/services/DateTime.qml diff --git a/.config/quickshell/services/Emojis.qml b/.config/quickshell/ii/services/Emojis.qml similarity index 100% rename from .config/quickshell/services/Emojis.qml rename to .config/quickshell/ii/services/Emojis.qml diff --git a/.config/quickshell/services/FirstRunExperience.qml b/.config/quickshell/ii/services/FirstRunExperience.qml similarity index 88% rename from .config/quickshell/services/FirstRunExperience.qml rename to .config/quickshell/ii/services/FirstRunExperience.qml index 4b1f034c..5bdae455 100644 --- a/.config/quickshell/services/FirstRunExperience.qml +++ b/.config/quickshell/ii/services/FirstRunExperience.qml @@ -12,8 +12,8 @@ Singleton { property string firstRunFileContent: "This file is just here to confirm you've been greeted :>" property string firstRunNotifSummary: "Welcome!" property string firstRunNotifBody: "Hit Super+/ for a list of keybinds" - property string defaultWallpaperPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/assets/images/default_wallpaper.png`) - property string welcomeQmlPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/welcome.qml`) + property string defaultWallpaperPath: FileUtils.trimFileProtocol(`${Directories.assetsPath}/images/default_wallpaper.png`) + property string welcomeQmlPath: FileUtils.trimFileProtocol(Quickshell.configPath("welcome.qml")) function load() { firstRunFileView.reload() diff --git a/.config/quickshell/services/HyprlandData.qml b/.config/quickshell/ii/services/HyprlandData.qml similarity index 100% rename from .config/quickshell/services/HyprlandData.qml rename to .config/quickshell/ii/services/HyprlandData.qml diff --git a/.config/quickshell/services/HyprlandKeybinds.qml b/.config/quickshell/ii/services/HyprlandKeybinds.qml similarity index 96% rename from .config/quickshell/services/HyprlandKeybinds.qml rename to .config/quickshell/ii/services/HyprlandKeybinds.qml index 189ba76d..a313ffc4 100644 --- a/.config/quickshell/services/HyprlandKeybinds.qml +++ b/.config/quickshell/ii/services/HyprlandKeybinds.qml @@ -15,7 +15,7 @@ import Quickshell.Hyprland */ Singleton { id: root - property string keybindParserPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/hyprland/get_keybinds.py`) + property string keybindParserPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/hyprland/get_keybinds.py`) property string defaultKeybindConfigPath: FileUtils.trimFileProtocol(`${Directories.config}/hypr/hyprland/keybinds.conf`) property string userKeybindConfigPath: FileUtils.trimFileProtocol(`${Directories.config}/hypr/custom/keybinds.conf`) property var defaultKeybinds: {"children": []} diff --git a/.config/quickshell/services/KeyringStorage.qml b/.config/quickshell/ii/services/KeyringStorage.qml similarity index 100% rename from .config/quickshell/services/KeyringStorage.qml rename to .config/quickshell/ii/services/KeyringStorage.qml diff --git a/.config/quickshell/services/LatexRenderer.qml b/.config/quickshell/ii/services/LatexRenderer.qml similarity index 100% rename from .config/quickshell/services/LatexRenderer.qml rename to .config/quickshell/ii/services/LatexRenderer.qml diff --git a/.config/quickshell/services/MaterialThemeLoader.qml b/.config/quickshell/ii/services/MaterialThemeLoader.qml similarity index 100% rename from .config/quickshell/services/MaterialThemeLoader.qml rename to .config/quickshell/ii/services/MaterialThemeLoader.qml diff --git a/.config/quickshell/services/MprisController.qml b/.config/quickshell/ii/services/MprisController.qml similarity index 100% rename from .config/quickshell/services/MprisController.qml rename to .config/quickshell/ii/services/MprisController.qml diff --git a/.config/quickshell/services/Network.qml b/.config/quickshell/ii/services/Network.qml similarity index 100% rename from .config/quickshell/services/Network.qml rename to .config/quickshell/ii/services/Network.qml diff --git a/.config/quickshell/services/Notifications.qml b/.config/quickshell/ii/services/Notifications.qml similarity index 100% rename from .config/quickshell/services/Notifications.qml rename to .config/quickshell/ii/services/Notifications.qml diff --git a/.config/quickshell/services/ResourceUsage.qml b/.config/quickshell/ii/services/ResourceUsage.qml similarity index 100% rename from .config/quickshell/services/ResourceUsage.qml rename to .config/quickshell/ii/services/ResourceUsage.qml diff --git a/.config/quickshell/services/SystemInfo.qml b/.config/quickshell/ii/services/SystemInfo.qml similarity index 100% rename from .config/quickshell/services/SystemInfo.qml rename to .config/quickshell/ii/services/SystemInfo.qml diff --git a/.config/quickshell/services/Todo.qml b/.config/quickshell/ii/services/Todo.qml similarity index 100% rename from .config/quickshell/services/Todo.qml rename to .config/quickshell/ii/services/Todo.qml diff --git a/.config/quickshell/services/Weather.qml b/.config/quickshell/ii/services/Weather.qml similarity index 100% rename from .config/quickshell/services/Weather.qml rename to .config/quickshell/ii/services/Weather.qml diff --git a/.config/quickshell/services/Ydotool.qml b/.config/quickshell/ii/services/Ydotool.qml similarity index 100% rename from .config/quickshell/services/Ydotool.qml rename to .config/quickshell/ii/services/Ydotool.qml diff --git a/.config/quickshell/settings.qml b/.config/quickshell/ii/settings.qml similarity index 100% rename from .config/quickshell/settings.qml rename to .config/quickshell/ii/settings.qml diff --git a/.config/quickshell/shell.qml b/.config/quickshell/ii/shell.qml similarity index 100% rename from .config/quickshell/shell.qml rename to .config/quickshell/ii/shell.qml diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/ii/welcome.qml similarity index 99% rename from .config/quickshell/welcome.qml rename to .config/quickshell/ii/welcome.qml index d9e0770d..7c1dff4a 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/ii/welcome.qml @@ -42,7 +42,7 @@ ApplicationWindow { Process { id: konachanWallProc property string status: "" - command: ["bash", "-c", FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/random_konachan_wall.sh`)] + command: ["bash", "-c", Quickshell.configPath("scripts/colors/random_konachan_wall.sh")] stdout: SplitParser { onRead: data => { console.log(`Konachan wall proc output: ${data}`); diff --git a/.config/quickshell/scripts/colors/random_konachan_wall.sh b/.config/quickshell/scripts/colors/random_konachan_wall.sh deleted file mode 100755 index 52853d09..00000000 --- a/.config/quickshell/scripts/colors/random_konachan_wall.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -mkdir -p ~/Pictures/Wallpapers -page=$((1 + RANDOM % 1000)); -response=$(curl "https://konachan.com/post.json?tags=rating%3Asafe&limit=1&page=$page") -link=$(echo "$response" | jq '.[0].file_url' -r); -ext=$(echo "$link" | awk -F. '{print $NF}') -downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image.$ext" -curl "$link" -o "$downloadPath" -~/.config/quickshell/scripts/colors/switchwall.sh --image "$downloadPath" From c2f12eedfcec74bbd9bde8b3f191ca97659d0c52 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 09:18:21 +0700 Subject: [PATCH 179/328] fix qs exec (fixes #1610) --- .config/hypr/hyprland/execs.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/execs.conf b/.config/hypr/hyprland/execs.conf index b723454a..a3d549ec 100644 --- a/.config/hypr/hyprland/execs.conf +++ b/.config/hypr/hyprland/execs.conf @@ -2,7 +2,7 @@ exec-once = ~/.config/hypr/hyprland/scripts/start_geoclue_agent.sh & gammastep exec-once = sleep 0.7; [ "$(hyprctl monitors -j | jq 'length')" -eq 1 ] && swww-daemon --format xrgb --no-cache || swww-daemon --format xrgb exec-once = sleep 0.7; swww img "$(cat ~/.local/state/quickshell/user/generated/wallpaper/path.txt)" --transition-step 100 --transition-fps 120 --transition-type grow --transition-angle 30 --transition-duration 1 -exec-once = qs & +exec-once = qs -c ii & # Input method exec-once = fcitx5 From 770c4de78b6323472bf3fd03774d28afdcda814c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 09:19:05 +0700 Subject: [PATCH 180/328] fix more properly --- .config/hypr/hyprland/execs.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/execs.conf b/.config/hypr/hyprland/execs.conf index a3d549ec..33fc3ffb 100644 --- a/.config/hypr/hyprland/execs.conf +++ b/.config/hypr/hyprland/execs.conf @@ -2,7 +2,7 @@ exec-once = ~/.config/hypr/hyprland/scripts/start_geoclue_agent.sh & gammastep exec-once = sleep 0.7; [ "$(hyprctl monitors -j | jq 'length')" -eq 1 ] && swww-daemon --format xrgb --no-cache || swww-daemon --format xrgb exec-once = sleep 0.7; swww img "$(cat ~/.local/state/quickshell/user/generated/wallpaper/path.txt)" --transition-step 100 --transition-fps 120 --transition-type grow --transition-angle 30 --transition-duration 1 -exec-once = qs -c ii & +exec-once = qs -c $qsConfig & # Input method exec-once = fcitx5 From f0a2438dea56a0122506c8fb5e9bcb78569bb297 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 09:26:18 +0700 Subject: [PATCH 181/328] fish: add alias for quickshell config --- .config/fish/config.fish | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/fish/config.fish b/.config/fish/config.fish index 4a86ee4f..8e0c95bf 100755 --- a/.config/fish/config.fish +++ b/.config/fish/config.fish @@ -20,6 +20,7 @@ end alias pamcan pacman alias ls 'eza --icons' alias clear "printf '\033[2J\033[3J\033[1;1H'" +alias q 'qs -c ii' # function fish_prompt From 35b687b4ea8ef66139e776bdddaa146c68016d88 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 09:29:58 +0700 Subject: [PATCH 182/328] fix dirs in scripts --- .config/quickshell/ii/scripts/colors/applycolor.sh | 4 ++-- .config/quickshell/ii/scripts/colors/random_konachan_wall.sh | 4 ++-- .config/quickshell/ii/scripts/colors/switchwall.sh | 4 ++-- .config/quickshell/ii/scripts/kvantum/materialQT.sh | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.config/quickshell/ii/scripts/colors/applycolor.sh b/.config/quickshell/ii/scripts/colors/applycolor.sh index fe87e655..843ac126 100755 --- a/.config/quickshell/ii/scripts/colors/applycolor.sh +++ b/.config/quickshell/ii/scripts/colors/applycolor.sh @@ -5,8 +5,8 @@ XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" CONFIG_DIR="$XDG_CONFIG_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" -CACHE_DIR="$XDG_CACHE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" -STATE_DIR="$XDG_STATE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +CACHE_DIR="$XDG_CACHE_HOME/quickshell" +STATE_DIR="$XDG_STATE_HOME/quickshell" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" term_alpha=100 #Set this to < 100 make all your terminals transparent diff --git a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh index c44f3e3a..079cad96 100755 --- a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh +++ b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh @@ -5,8 +5,8 @@ XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" CONFIG_DIR="$XDG_CONFIG_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" -CACHE_DIR="$XDG_CACHE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" -STATE_DIR="$XDG_STATE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +CACHE_DIR="$XDG_CACHE_HOME/quickshell" +STATE_DIR="$XDG_STATE_HOME/quickshell" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" mkdir -p ~/Pictures/Wallpapers diff --git a/.config/quickshell/ii/scripts/colors/switchwall.sh b/.config/quickshell/ii/scripts/colors/switchwall.sh index fa834bce..de76444f 100755 --- a/.config/quickshell/ii/scripts/colors/switchwall.sh +++ b/.config/quickshell/ii/scripts/colors/switchwall.sh @@ -5,8 +5,8 @@ XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" CONFIG_DIR="$XDG_CONFIG_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" -CACHE_DIR="$XDG_CACHE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" -STATE_DIR="$XDG_STATE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +CACHE_DIR="$XDG_CACHE_HOME/quickshell" +STATE_DIR="$XDG_STATE_HOME/quickshell" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" MATUGEN_DIR="$XDG_CONFIG_HOME/matugen" terminalscheme="$SCRIPT_DIR/terminal/scheme-base.json" diff --git a/.config/quickshell/ii/scripts/kvantum/materialQT.sh b/.config/quickshell/ii/scripts/kvantum/materialQT.sh index 835706a2..a049c553 100755 --- a/.config/quickshell/ii/scripts/kvantum/materialQT.sh +++ b/.config/quickshell/ii/scripts/kvantum/materialQT.sh @@ -5,8 +5,8 @@ XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" CONFIG_DIR="$XDG_CONFIG_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" -CACHE_DIR="$XDG_CACHE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" -STATE_DIR="$XDG_STATE_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" +CACHE_DIR="$XDG_CACHE_HOME/quickshell" +STATE_DIR="$XDG_STATE_HOME/quickshell" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" get_light_dark() { From a10f08a775033477a0330cb054d963f11bee4bbc Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 09:32:40 +0700 Subject: [PATCH 183/328] unfuck terminal color generation (#1612) --- .config/quickshell/ii/scripts/colors/applycolor.sh | 4 ++-- .../ii/scripts/{ => colors}/terminal/scheme-base.json | 0 .../quickshell/ii/scripts/{ => colors}/terminal/sequences.txt | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename .config/quickshell/ii/scripts/{ => colors}/terminal/scheme-base.json (100%) rename .config/quickshell/ii/scripts/{ => colors}/terminal/sequences.txt (100%) diff --git a/.config/quickshell/ii/scripts/colors/applycolor.sh b/.config/quickshell/ii/scripts/colors/applycolor.sh index 843ac126..b86fb679 100755 --- a/.config/quickshell/ii/scripts/colors/applycolor.sh +++ b/.config/quickshell/ii/scripts/colors/applycolor.sh @@ -29,13 +29,13 @@ colorvalues=($colorstrings) # Array of color values apply_term() { # Check if terminal escape sequence template exists - if [ ! -f "$CONFIG_DIR"/scripts/terminal/sequences.txt ]; then + if [ ! -f "$SCRIPT_DIR/terminal/sequences.txt" ]; then echo "Template file not found for Terminal. Skipping that." return fi # Copy template mkdir -p "$STATE_DIR"/user/generated/terminal - cp "$CONFIG_DIR"/scripts/terminal/sequences.txt "$STATE_DIR"/user/generated/terminal/sequences.txt + cp "$SCRIPT_DIR/terminal/sequences.txt" "$STATE_DIR"/user/generated/terminal/sequences.txt # Apply colors for i in "${!colorlist[@]}"; do sed -i "s/${colorlist[$i]} #/${colorvalues[$i]#\#}/g" "$STATE_DIR"/user/generated/terminal/sequences.txt diff --git a/.config/quickshell/ii/scripts/terminal/scheme-base.json b/.config/quickshell/ii/scripts/colors/terminal/scheme-base.json similarity index 100% rename from .config/quickshell/ii/scripts/terminal/scheme-base.json rename to .config/quickshell/ii/scripts/colors/terminal/scheme-base.json diff --git a/.config/quickshell/ii/scripts/terminal/sequences.txt b/.config/quickshell/ii/scripts/colors/terminal/sequences.txt similarity index 100% rename from .config/quickshell/ii/scripts/terminal/sequences.txt rename to .config/quickshell/ii/scripts/colors/terminal/sequences.txt From d05f1ce67f0e73835b68625c98a0df6b12382ffe Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 08:45:11 +0200 Subject: [PATCH 184/328] readme: add discord --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7da85827..05d764ce 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,13 @@
-![](https://img.shields.io/github/last-commit/end-4/dots-hyprland?&style=for-the-badge&color=FFB1C8&logoColor=D9E0EE&labelColor=292324) -![](https://img.shields.io/github/stars/end-4/dots-hyprland?style=for-the-badge&logo=andela&color=FFB686&logoColor=D9E0EE&labelColor=292324) -[![](https://img.shields.io/github/repo-size/end-4/dots-hyprland?color=CAC992&label=SIZE&logo=googledrive&style=for-the-badge&logoColor=D9E0EE&labelColor=292324)](https://github.com/end-4/hyprland) -![](https://img.shields.io/badge/issues-skill-green?style=for-the-badge&color=CCE8E9&logoColor=D9E0EE&labelColor=292324) - +![](https://img.shields.io/github/last-commit/end-4/dots-hyprland?&style=for-the-badge&color=FFB1C8&logoColor=D9E0EE&labelColor=1E202B) +![](https://img.shields.io/github/stars/end-4/dots-hyprland?style=for-the-badge&logo=andela&color=FFB686&logoColor=D9E0EE&labelColor=1E202B) +[![](https://img.shields.io/github/repo-size/end-4/dots-hyprland?color=CAC992&label=SIZE&logo=googledrive&style=for-the-badge&logoColor=D9E0EE&labelColor=1E202B)](https://github.com/end-4/hyprland) +![](https://img.shields.io/badge/issues-skill-green?style=for-the-badge&color=CCE8E9&logoColor=D9E0EE&labelColor=1E202B) + Dynamic JSON Badge + +
From 75d344c9dfbbb245cfd3e3b1002ef87ddbab7571 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 08:59:05 +0200 Subject: [PATCH 185/328] readme: update badge colors --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 05d764ce..89a3571d 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,10 @@
-![](https://img.shields.io/github/last-commit/end-4/dots-hyprland?&style=for-the-badge&color=FFB1C8&logoColor=D9E0EE&labelColor=1E202B) -![](https://img.shields.io/github/stars/end-4/dots-hyprland?style=for-the-badge&logo=andela&color=FFB686&logoColor=D9E0EE&labelColor=1E202B) -[![](https://img.shields.io/github/repo-size/end-4/dots-hyprland?color=CAC992&label=SIZE&logo=googledrive&style=for-the-badge&logoColor=D9E0EE&labelColor=1E202B)](https://github.com/end-4/hyprland) -![](https://img.shields.io/badge/issues-skill-green?style=for-the-badge&color=CCE8E9&logoColor=D9E0EE&labelColor=1E202B) - Dynamic JSON Badge +![](https://img.shields.io/github/last-commit/end-4/dots-hyprland?&style=for-the-badge&color=8ad7eb&logo=git&logoColor=D9E0EE&labelColor=1E202B) +![](https://img.shields.io/github/stars/end-4/dots-hyprland?style=for-the-badge&logo=andela&color=86dbd7&logoColor=D9E0EE&labelColor=1E202B) +[![](https://img.shields.io/github/repo-size/end-4/dots-hyprland?color=86dbce&label=SIZE&logo=protondrive&style=for-the-badge&logoColor=D9E0EE&labelColor=26230e)](https://github.com/end-4/hyprland) + Dynamic JSON Badge From ace114be0b6cf45053cc0583a5822673881421b4 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 09:13:39 +0200 Subject: [PATCH 186/328] Update README.md --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 89a3571d..6960c07f 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,8 @@ ![](https://img.shields.io/github/last-commit/end-4/dots-hyprland?&style=for-the-badge&color=8ad7eb&logo=git&logoColor=D9E0EE&labelColor=1E202B) ![](https://img.shields.io/github/stars/end-4/dots-hyprland?style=for-the-badge&logo=andela&color=86dbd7&logoColor=D9E0EE&labelColor=1E202B) -[![](https://img.shields.io/github/repo-size/end-4/dots-hyprland?color=86dbce&label=SIZE&logo=protondrive&style=for-the-badge&logoColor=D9E0EE&labelColor=26230e)](https://github.com/end-4/hyprland) - Dynamic JSON Badge - - +![](https://img.shields.io/github/repo-size/end-4/dots-hyprland?color=86dbce&label=SIZE&logo=protondrive&style=for-the-badge&logoColor=D9E0EE&labelColor=26230e) + Dynamic JSON Badge
@@ -19,7 +17,6 @@

-
Notable features @@ -65,6 +62,12 @@ - For a more comprehensive list of dependencies, see [scriptdata/dependencies.conf](https://github.com/end-4/dots-hyprland/blob/main/scriptdata/dependencies.conf)
+
+ Discord + Join the server + +
+

• screenshots •

From eec1251db6be6977976c27bfbd6390c073d8573a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:06:07 +0200 Subject: [PATCH 187/328] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6960c07f..dbff414e 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@
Discord - Join the server + Server link | I hope this provides a friendlier environment for support without needing me to personally accept every friend request/DM. For real issues, prefer GitHub
From b8f04bef41c8707a0850df9ff955133169b710be Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 12:35:49 +0200 Subject: [PATCH 188/328] Update README.md --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dbff414e..28fdb28e 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,8 @@ _latest and only style that I actively use. Other past styles are still there fo ### illogical-impulseQuickshell +Widget system: Quickshell | Support: Yes + [Showcase video](https://www.youtube.com/watch?v=RPwovTInagE) | AI, settings app | Some widgets | @@ -92,33 +94,47 @@ _latest and only style that I actively use. Other past styles are still there fo ### illogical-impulseAGS (Deprecated) +Widget system: AGS | Support: Limited, no new features + | AI | Common widgets | |:---|:---------------| | ![image](https://github.com/user-attachments/assets/9d7af13f-89ef-470d-ba78-d2288b79cf60) | ![image](https://github.com/end-4/dots-hyprland/assets/97237370/406b72b6-fa38-4f0d-a6c4-4d7d5d5ddcb7) | | Window management | Weeb power | | ![image](https://github.com/user-attachments/assets/02983b9b-79ba-4c25-8717-90bef2357ae5) | ![image](https://github.com/user-attachments/assets/bbb332ec-962a-4e88-a95b-486d0bd8ce76) | -### Unsupported stuff +### Very old stuff - Source code not likely to work but still available in the [`archive`](https://github.com/end-4/dots-hyprland/tree/archive) branch. Extremely spaghetti. - Click image for a presentation video #### m3ww + + Widget system: EWW | Support: No, dead + Material Eww! #### NovelKnock + + Widget system: EWW | Support: No, dead + Desktop Preview #### Hybrid + + Widget system: EWW | Support: No, dead + click the circles! #### Windoes + + Widget system: EWW | Support: No, dead + Desktop Preview From bb5eabb75e008b2653d79832501e19568c244b2a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 17:36:37 +0700 Subject: [PATCH 189/328] hyprland: fix plasma system monitor keybind --- .config/hypr/hyprland/keybinds.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index 0552c1b4..f7dc3ac3 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -210,7 +210,7 @@ bind = Super+Shift, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_availa bind = Super, X, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kate" "gnome-text-editor" "emacs" # Text editor bind = Ctrl+Super, V, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol" # Volume mixer bind = Super, I, exec, XDG_CURRENT_DESKTOP=gnome ~/.config/hypr/hyprland/scripts/launch_first_available.sh "qs -p ~/.config/quickshell/$qsConfig/settings.qml" "systemsettings" "gnome-control-center" "better-control" # Settings app -bind = Ctrl+Shift, Escape, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "gnome-system-monitor" "plasma-systemmonitzor --page-name Processes" "command -v btop && kitty -1 fish -c btop" # Task manager +bind = Ctrl+Shift, Escape, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "gnome-system-monitor" "plasma-systemmonitor --page-name Processes" "command -v btop && kitty -1 fish -c btop" # Task manager # Cursed stuff ## Make window not amogus large From 65179b23586a7700fa232b298779585671fd5a52 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 17:52:42 +0700 Subject: [PATCH 190/328] settings: add 24h/12h time format config --- .../ii/modules/settings/ServicesConfig.qml | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.config/quickshell/ii/modules/settings/ServicesConfig.qml b/.config/quickshell/ii/modules/settings/ServicesConfig.qml index ea4fac69..349aa237 100644 --- a/.config/quickshell/ii/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/ii/modules/settings/ServicesConfig.qml @@ -199,4 +199,36 @@ ContentPage { } } } + + ContentSection { + title: "Time" + + ColumnLayout { + // Format + ContentSubsectionLabel { + text: "Time format" + } + ConfigSelectionArray { + currentValue: Config.options.time.format + configOptionName: "time.format" + onSelected: newValue => { + Config.options.time.format = newValue; + } + options: [ + { + displayName: "24h", + value: "hh:mm" + }, + { + displayName: "12h am/pm", + value: "h:mm ap" + }, + { + displayName: "12h AM/PM", + value: "h:mm AP" + }, + ] + } + } + } } From 528f5e755b87d2ca8727abf7a323377ea2651f0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=8D=8E?= Date: Fri, 11 Jul 2025 14:57:40 +0300 Subject: [PATCH 191/328] fix hardcoded paths: /home/end -> ~ --- .config/kde-material-you-colors/config.conf | 2 +- .config/qt6ct/qt6ct.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/kde-material-you-colors/config.conf b/.config/kde-material-you-colors/config.conf index 1d63c840..da9b34a5 100644 --- a/.config/kde-material-you-colors/config.conf +++ b/.config/kde-material-you-colors/config.conf @@ -10,7 +10,7 @@ monitor = 0 # File containing absolute path of an image (Takes precedence over automatic wallpaper detection) # Commented by default -file = /home/end/.local/state/quickshell/user/wallpaper.txt +file = ~/.local/state/quickshell/user/wallpaper.txt # List of 7 space separated colors (hex or rgb) to be used for text in pywal/konsole/KSyntaxHighlighting instead of wallpaper ones # Accepted values are hex e.g #ff0000 and rgb e.g 255,0,0 colors (rgb is converted to hex) diff --git a/.config/qt6ct/qt6ct.conf b/.config/qt6ct/qt6ct.conf index e8163baa..f7bfd600 100644 --- a/.config/qt6ct/qt6ct.conf +++ b/.config/qt6ct/qt6ct.conf @@ -1,5 +1,5 @@ [Appearance] -color_scheme_path=/home/end/.config/qt6ct/style-colors.conf +color_scheme_path=~/.config/qt6ct/style-colors.conf custom_palette=true icon_theme=OneUI standard_dialogs=default From 4d3788cca6377ae8f3e36211e6f478f34c401f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=8D=8E?= Date: Fri, 11 Jul 2025 15:01:20 +0300 Subject: [PATCH 192/328] fix kde-material-you-colors: wallpaper path --- .config/kde-material-you-colors/config.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/kde-material-you-colors/config.conf b/.config/kde-material-you-colors/config.conf index da9b34a5..caa1fb8a 100644 --- a/.config/kde-material-you-colors/config.conf +++ b/.config/kde-material-you-colors/config.conf @@ -10,7 +10,7 @@ monitor = 0 # File containing absolute path of an image (Takes precedence over automatic wallpaper detection) # Commented by default -file = ~/.local/state/quickshell/user/wallpaper.txt +file = ~/.local/state/quickshell/user/generated/wallpaper/path.txt # List of 7 space separated colors (hex or rgb) to be used for text in pywal/konsole/KSyntaxHighlighting instead of wallpaper ones # Accepted values are hex e.g #ff0000 and rgb e.g 255,0,0 colors (rgb is converted to hex) From b1ee817c788faa1e1201467986ea76591a07a342 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 19:37:04 +0700 Subject: [PATCH 193/328] Update ServicesConfig.qml --- .../quickshell/ii/modules/settings/ServicesConfig.qml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.config/quickshell/ii/modules/settings/ServicesConfig.qml b/.config/quickshell/ii/modules/settings/ServicesConfig.qml index 349aa237..a9e34512 100644 --- a/.config/quickshell/ii/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/ii/modules/settings/ServicesConfig.qml @@ -203,11 +203,10 @@ ContentPage { ContentSection { title: "Time" - ColumnLayout { - // Format - ContentSubsectionLabel { - text: "Time format" - } + ContentSubsection { + title: "Format" + tooltip: "" + ConfigSelectionArray { currentValue: Config.options.time.format configOptionName: "time.format" From b958c0ad6c12b20e5da744a3147e74434f69881f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 11 Jul 2025 19:37:23 +0700 Subject: [PATCH 194/328] ai: save last chat, make sure model's messages are saved properly --- .config/quickshell/ii/services/Ai.qml | 28 +++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/.config/quickshell/ii/services/Ai.qml b/.config/quickshell/ii/services/Ai.qml index 24521fb6..fe1b4b83 100644 --- a/.config/quickshell/ii/services/Ai.qml +++ b/.config/quickshell/ii/services/Ai.qml @@ -461,6 +461,7 @@ Singleton { root.postResponseHook(); root.postResponseHook = null; // Reset hook after use } + root.saveChat("lastSession") } function buildGeminiRequestData(model, messages) { @@ -492,7 +493,7 @@ Singleton { return { "role": geminiApiRoleName, "parts": [{ - text: message.content, + text: message.rawContent, }] } }), @@ -517,7 +518,7 @@ Singleton { ...messages.filter(message => (message.role != Ai.interfaceRole)).map(message => { return { "role": message.role, - "content": message.content, + "content": message.rawContent, } }), ], @@ -594,12 +595,15 @@ Singleton { const functionCall = dataJson.candidates[0]?.content?.parts[0]?.functionCall; requester.message.functionName = functionCall.name; requester.message.functionCall = functionCall.name; - requester.message.content += `\n\n[[ Function: ${functionCall.name}(${JSON.stringify(functionCall.args, null, 2)}) ]]\n`; + const newContent = `\n\n[[ Function: ${functionCall.name}(${JSON.stringify(functionCall.args, null, 2)}) ]]\n` + requester.message.rawContent += newContent; + requester.message.content += newContent; root.handleGeminiFunctionCall(functionCall.name, functionCall.args); return } // Normal text response const responseContent = dataJson.candidates[0]?.content?.parts[0]?.text + requester.message.rawContent += responseContent; requester.message.content += responseContent; const annotationSources = dataJson.candidates[0]?.groundingMetadata?.groundingChunks?.map(chunk => { return { @@ -623,6 +627,7 @@ Singleton { // console.log(JSON.stringify(requester.message, null, 2)); } catch (e) { console.log("[AI] Could not parse response from stream: ", e); + requester.message.rawContent += requester.geminiBuffer; requester.message.content += requester.geminiBuffer } finally { requester.geminiBuffer = ""; @@ -664,15 +669,19 @@ Singleton { if (responseContent && responseContent.length > 0) { if (requester.isReasoning) { requester.isReasoning = false; - requester.message.content += "\n\n\n\n"; + const endBlock = "\n\n\n\n"; + requester.message.content += endBlock; + requester.message.rawContent += endBlock; } newContent = dataJson.choices[0]?.delta?.content || dataJson.message.content; } else if (responseReasoning && responseReasoning.length > 0) { // console.log("Reasoning content: ", dataJson.choices[0].delta.reasoning); if (!requester.isReasoning) { requester.isReasoning = true; - requester.message.content += "\n\n\n\n"; - } + const startBlock = "\n\n\n\n"; + requester.message.rawContent += startBlock; + requester.message.content += startBlock; + } newContent = dataJson.choices[0].delta.reasoning || dataJson.choices[0].delta.reasoning_content; } @@ -699,10 +708,12 @@ Singleton { } else { console.log("Unknown API format: ", requester.apiFormat); + requester.message.rawContent += data; requester.message.content += data; } } catch (e) { console.log("[AI] Could not parse response from stream: ", e); + requester.message.rawContent += data; requester.message.content += data; } } @@ -714,8 +725,9 @@ Singleton { try { // to parse full response into json for error handling // console.log("Full response: ", requester.message.content + "]"); - const parsedResponse = JSON.parse(requester.message.content + "]"); - requester.message.content = `\`\`\`json\n${JSON.stringify(parsedResponse, null, 2)}\n\`\`\``; + const parsedResponse = JSON.parse(requester.message.rawContent + "]"); + requester.message.rawContent = `\`\`\`json\n${JSON.stringify(parsedResponse, null, 2)}\n\`\`\``; + requester.message.content = requester.message.rawContent; } catch (e) { // console.log("[AI] Could not parse response on exit: ", e); } From f2831c2b88429e7fb7edb675880879b07d5af68b Mon Sep 17 00:00:00 2001 From: Sighthesia <87855491+Sighthesia@users.noreply.github.com> Date: Fri, 11 Jul 2025 21:44:11 +0800 Subject: [PATCH 195/328] Hug bar round corner transparency --- .config/quickshell/ii/modules/bar/Bar.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml index a46779e9..95cd912c 100644 --- a/.config/quickshell/ii/modules/bar/Bar.qml +++ b/.config/quickshell/ii/modules/bar/Bar.qml @@ -530,7 +530,6 @@ Scope { size: Appearance.rounding.screenRounding color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - opacity: 1.0 - Appearance.transparency corner: RoundCorner.CornerEnum.TopLeft states: State { @@ -550,7 +549,6 @@ Scope { } size: Appearance.rounding.screenRounding color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - opacity: 1.0 - Appearance.transparency corner: RoundCorner.CornerEnum.TopRight states: State { From d482796dc369772e729323346c9c9a6ee3f403ad Mon Sep 17 00:00:00 2001 From: 1cebp <131227161+1cebp@users.noreply.github.com> Date: Fri, 11 Jul 2025 11:17:27 -0400 Subject: [PATCH 196/328] Add Cursor to Code Editor keybind --- .config/hypr/hyprland/keybinds.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index f7dc3ac3..89998c86 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -205,7 +205,7 @@ bind = Super, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh bind = Ctrl+Alt, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] Kitty (for Ubuntu people) bind = Super, E, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "dolphin" "nautilus" "nemo" "thunar" "kitty -1 fish -c yazi" # File manager bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "google-chrome-stable" "zen-browser" "firefox" "brave" "chromium" "microsoft-edge-stable" "opera" # Browser -bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "code" "codium" "zed" "zedit" "zeditor" "kate" "gnome-text-editor" "emacs" "command -v nvim && kitty -1 nvim" # Code editor +bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "code" "codium" "cursor" "zed" "zedit" "zeditor" "kate" "gnome-text-editor" "emacs" "command -v nvim && kitty -1 nvim" # Code editor bind = Super+Shift, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "wps" "onlyoffice-desktopeditors" # Office software bind = Super, X, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kate" "gnome-text-editor" "emacs" # Text editor bind = Ctrl+Super, V, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol" # Volume mixer From f52cfc3df049beac51d304a90a18df2c3a6ea0e3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 12 Jul 2025 07:58:34 +0700 Subject: [PATCH 197/328] bar: add keybind to toggle (super+j) --- .config/hypr/hyprland/keybinds.conf | 1 + .config/quickshell/ii/GlobalStates.qml | 1 + .config/quickshell/ii/modules/bar/Bar.qml | 981 ++++++++++++---------- 3 files changed, 517 insertions(+), 466 deletions(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index 89998c86..d7c20864 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -30,6 +30,7 @@ bindd = Super, Slash, Toggle cheatsheet, global, quickshell:cheatsheetToggle # T bindd = Super, K, Toggle on-screen keyboard, global, quickshell:oskToggle # Toggle on-screen keyboard bindd = Super, M, Toggle media controls, global, quickshell:mediaControlsToggle # Toggle media controls bindd = Ctrl+Alt, Delete, Toggle session menu, global, quickshell:sessionToggle # Toggle session menu +bindd = Super, J, Toggle bar, global, quickshell:barToggle # Toggle bar bind = Ctrl+Alt, Delete, exec, qs -c $qsConfig ipc call TEST_ALIVE || pkill wlogout || wlogout -p layer-shell # [hidden] Session menu (fallback) bind = Shift+Super+Alt, Slash, exec, qs -p ~/.config/quickshell/$qsConfig/welcome.qml # [hidden] Launch welcome app diff --git a/.config/quickshell/ii/GlobalStates.qml b/.config/quickshell/ii/GlobalStates.qml index b7ddef5a..75f7bd2c 100644 --- a/.config/quickshell/ii/GlobalStates.qml +++ b/.config/quickshell/ii/GlobalStates.qml @@ -8,6 +8,7 @@ pragma ComponentBehavior: Bound Singleton { id: root + property bool barOpen: true property bool sidebarLeftOpen: false property bool sidebarRightOpen: false property bool overviewOpen: false diff --git a/.config/quickshell/ii/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml index 95cd912c..36863ec5 100644 --- a/.config/quickshell/ii/modules/bar/Bar.qml +++ b/.config/quickshell/ii/modules/bar/Bar.qml @@ -9,6 +9,7 @@ import QtQuick.Controls import QtQuick.Layouts import Qt5Compat.GraphicalEffects import Quickshell +import Quickshell.Io import Quickshell.Wayland import Quickshell.Hyprland import Quickshell.Services.UPower @@ -36,526 +37,531 @@ Scope { return screens; return screens.filter(screen => list.includes(screen.name)); } - - PanelWindow { // Bar window - id: barRoot + Loader { + id: barLoader + active: GlobalStates.barOpen required property ShellScreen modelData - screen: modelData + sourceComponent: PanelWindow { // Bar window + id: barRoot + screen: barLoader.modelData - property var brightnessMonitor: Brightness.getMonitorForScreen(modelData) - property real useShortenedForm: (Appearance.sizes.barHellaShortenScreenWidthThreshold >= screen.width) ? 2 : (Appearance.sizes.barShortenScreenWidthThreshold >= screen.width) ? 1 : 0 - readonly property int centerSideModuleWidth: (useShortenedForm == 2) ? Appearance.sizes.barCenterSideModuleWidthHellaShortened : (useShortenedForm == 1) ? Appearance.sizes.barCenterSideModuleWidthShortened : Appearance.sizes.barCenterSideModuleWidth + property var brightnessMonitor: Brightness.getMonitorForScreen(barLoader.modelData) + property real useShortenedForm: (Appearance.sizes.barHellaShortenScreenWidthThreshold >= screen.width) ? 2 : (Appearance.sizes.barShortenScreenWidthThreshold >= screen.width) ? 1 : 0 + readonly property int centerSideModuleWidth: (useShortenedForm == 2) ? Appearance.sizes.barCenterSideModuleWidthHellaShortened : (useShortenedForm == 1) ? Appearance.sizes.barCenterSideModuleWidthShortened : Appearance.sizes.barCenterSideModuleWidth - WlrLayershell.namespace: "quickshell:bar" - implicitHeight: Appearance.sizes.barHeight + Appearance.rounding.screenRounding - exclusiveZone: Appearance.sizes.baseBarHeight + (Config.options.bar.cornerStyle === 1 ? Appearance.sizes.hyprlandGapsOut : 0) - mask: Region { - item: barContent - } - color: "transparent" + WlrLayershell.namespace: "quickshell:bar" + implicitHeight: Appearance.sizes.barHeight + Appearance.rounding.screenRounding + exclusiveZone: Appearance.sizes.baseBarHeight + (Config.options.bar.cornerStyle === 1 ? Appearance.sizes.hyprlandGapsOut : 0) + mask: Region { + item: barContent + } + color: "transparent" - anchors { - top: !Config.options.bar.bottom - bottom: Config.options.bar.bottom - left: true - right: true - } - - Item { // Bar content region - id: barContent anchors { - right: parent.right - left: parent.left - top: parent.top - bottom: undefined - } - implicitHeight: Appearance.sizes.barHeight - height: Appearance.sizes.barHeight - - states: State { - name: "bottom" - when: Config.options.bar.bottom - AnchorChanges { - target: barContent - anchors { - right: parent.right - left: parent.left - top: undefined - bottom: parent.bottom - } - } + top: !Config.options.bar.bottom + bottom: Config.options.bar.bottom + left: true + right: true } - // Background shadow - Loader { - active: showBarBackground && Config.options.bar.cornerStyle === 1 - anchors.fill: barBackground - sourceComponent: StyledRectangularShadow { - anchors.fill: undefined // The loader's anchors act on this, and this should not have any anchor - target: barBackground - } - } - // Background - Rectangle { - id: barBackground + Item { // Bar content region + id: barContent anchors { - fill: parent - margins: Config.options.bar.cornerStyle === 1 ? (Appearance.sizes.hyprlandGapsOut) : 0 // idk why but +1 is needed + right: parent.right + left: parent.left + top: parent.top + bottom: undefined } - color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - radius: Config.options.bar.cornerStyle === 1 ? Appearance.rounding.windowRounding : 0 - border.width: Config.options.bar.cornerStyle === 1 ? 1 : 0 - border.color: Appearance.m3colors.m3outlineVariant - } - - MouseArea { // Left side | scroll to change brightness - id: barLeftSideMouseArea - anchors.left: parent.left - implicitHeight: Appearance.sizes.baseBarHeight + implicitHeight: Appearance.sizes.barHeight height: Appearance.sizes.barHeight - width: (barRoot.width - middleSection.width) / 2 - property bool hovered: false - property real lastScrollX: 0 - property real lastScrollY: 0 - property bool trackingScroll: false - acceptedButtons: Qt.LeftButton - hoverEnabled: true - propagateComposedEvents: true - onEntered: event => { - barLeftSideMouseArea.hovered = true; - } - onExited: event => { - barLeftSideMouseArea.hovered = false; - barLeftSideMouseArea.trackingScroll = false; - } - onPressed: event => { - if (event.button === Qt.LeftButton) { - Hyprland.dispatch('global quickshell:sidebarLeftOpen'); - } - } - // Scroll to change brightness - WheelHandler { - onWheel: event => { - if (event.angleDelta.y < 0) - barRoot.brightnessMonitor.setBrightness(barRoot.brightnessMonitor.brightness - 0.05); - else if (event.angleDelta.y > 0) - barRoot.brightnessMonitor.setBrightness(barRoot.brightnessMonitor.brightness + 0.05); - // Store the mouse position and start tracking - barLeftSideMouseArea.lastScrollX = event.x; - barLeftSideMouseArea.lastScrollY = event.y; - barLeftSideMouseArea.trackingScroll = true; - } - acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad - } - onPositionChanged: mouse => { - if (barLeftSideMouseArea.trackingScroll) { - const dx = mouse.x - barLeftSideMouseArea.lastScrollX; - const dy = mouse.y - barLeftSideMouseArea.lastScrollY; - if (Math.sqrt(dx * dx + dy * dy) > osdHideMouseMoveThreshold) { - Hyprland.dispatch('global quickshell:osdBrightnessHide'); - barLeftSideMouseArea.trackingScroll = false; + + states: State { + name: "bottom" + when: Config.options.bar.bottom + AnchorChanges { + target: barContent + anchors { + right: parent.right + left: parent.left + top: undefined + bottom: parent.bottom } } } - Item { - // Left section - anchors.fill: parent - implicitHeight: leftSectionRowLayout.implicitHeight - implicitWidth: leftSectionRowLayout.implicitWidth - ScrollHint { - reveal: barLeftSideMouseArea.hovered - icon: "light_mode" - tooltipText: qsTr("Scroll to change brightness") - side: "left" - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter + // Background shadow + Loader { + active: showBarBackground && Config.options.bar.cornerStyle === 1 + anchors.fill: barBackground + sourceComponent: StyledRectangularShadow { + anchors.fill: undefined // The loader's anchors act on this, and this should not have any anchor + target: barBackground } + } + // Background + Rectangle { + id: barBackground + anchors { + fill: parent + margins: Config.options.bar.cornerStyle === 1 ? (Appearance.sizes.hyprlandGapsOut) : 0 // idk why but +1 is needed + } + color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + radius: Config.options.bar.cornerStyle === 1 ? Appearance.rounding.windowRounding : 0 + border.width: Config.options.bar.cornerStyle === 1 ? 1 : 0 + border.color: Appearance.m3colors.m3outlineVariant + } - RowLayout { // Content - id: leftSectionRowLayout + MouseArea { // Left side | scroll to change brightness + id: barLeftSideMouseArea + anchors.left: parent.left + implicitHeight: Appearance.sizes.baseBarHeight + height: Appearance.sizes.barHeight + width: (barRoot.width - middleSection.width) / 2 + property bool hovered: false + property real lastScrollX: 0 + property real lastScrollY: 0 + property bool trackingScroll: false + acceptedButtons: Qt.LeftButton + hoverEnabled: true + propagateComposedEvents: true + onEntered: event => { + barLeftSideMouseArea.hovered = true; + } + onExited: event => { + barLeftSideMouseArea.hovered = false; + barLeftSideMouseArea.trackingScroll = false; + } + onPressed: event => { + if (event.button === Qt.LeftButton) { + Hyprland.dispatch('global quickshell:sidebarLeftOpen'); + } + } + // Scroll to change brightness + WheelHandler { + onWheel: event => { + if (event.angleDelta.y < 0) + barRoot.brightnessMonitor.setBrightness(barRoot.brightnessMonitor.brightness - 0.05); + else if (event.angleDelta.y > 0) + barRoot.brightnessMonitor.setBrightness(barRoot.brightnessMonitor.brightness + 0.05); + // Store the mouse position and start tracking + barLeftSideMouseArea.lastScrollX = event.x; + barLeftSideMouseArea.lastScrollY = event.y; + barLeftSideMouseArea.trackingScroll = true; + } + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad + } + onPositionChanged: mouse => { + if (barLeftSideMouseArea.trackingScroll) { + const dx = mouse.x - barLeftSideMouseArea.lastScrollX; + const dy = mouse.y - barLeftSideMouseArea.lastScrollY; + if (Math.sqrt(dx * dx + dy * dy) > osdHideMouseMoveThreshold) { + Hyprland.dispatch('global quickshell:osdBrightnessHide'); + barLeftSideMouseArea.trackingScroll = false; + } + } + } + Item { + // Left section anchors.fill: parent - spacing: 10 + implicitHeight: leftSectionRowLayout.implicitHeight + implicitWidth: leftSectionRowLayout.implicitWidth - RippleButton { - // Left sidebar button - Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter - Layout.leftMargin: Appearance.rounding.screenRounding - Layout.fillWidth: false - property real buttonPadding: 5 - implicitWidth: distroIcon.width + buttonPadding * 2 - implicitHeight: distroIcon.height + buttonPadding * 2 - - buttonRadius: Appearance.rounding.full - colBackground: barLeftSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1) - colBackgroundHover: Appearance.colors.colLayer1Hover - colRipple: Appearance.colors.colLayer1Active - colBackgroundToggled: Appearance.colors.colSecondaryContainer - colBackgroundToggledHover: Appearance.colors.colSecondaryContainerHover - colRippleToggled: Appearance.colors.colSecondaryContainerActive - toggled: GlobalStates.sidebarLeftOpen - property color colText: toggled ? Appearance.m3colors.m3onSecondaryContainer : Appearance.colors.colOnLayer0 - - onPressed: { - Hyprland.dispatch('global quickshell:sidebarLeftToggle'); - } - - CustomIcon { - id: distroIcon - anchors.centerIn: parent - width: 19.5 - height: 19.5 - source: Config.options.bar.topLeftIcon == 'distro' ? SystemInfo.distroIcon : "spark-symbolic" - colorize: true - color: Appearance.colors.colOnLayer0 - } + ScrollHint { + reveal: barLeftSideMouseArea.hovered + icon: "light_mode" + tooltipText: qsTr("Scroll to change brightness") + side: "left" + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter } - ActiveWindow { - visible: barRoot.useShortenedForm === 0 - Layout.rightMargin: Appearance.rounding.screenRounding - Layout.fillWidth: true - Layout.fillHeight: true - bar: barRoot - } - } - } - } - - RowLayout { // Middle section - id: middleSection - anchors.centerIn: parent - spacing: Config.options?.bar.borderless ? 4 : 8 - - BarGroup { - id: leftCenterGroup - Layout.preferredWidth: barRoot.centerSideModuleWidth - Layout.fillHeight: true - - Resources { - alwaysShowAllResources: barRoot.useShortenedForm === 2 - Layout.fillWidth: barRoot.useShortenedForm === 2 - } - - Media { - visible: barRoot.useShortenedForm < 2 - Layout.fillWidth: true - } - } - - VerticalBarSeparator { - visible: Config.options?.bar.borderless - } - - BarGroup { - id: middleCenterGroup - padding: workspacesWidget.widgetPadding - Layout.fillHeight: true - - Workspaces { - id: workspacesWidget - bar: barRoot - Layout.fillHeight: true - MouseArea { - // Right-click to toggle overview + RowLayout { // Content + id: leftSectionRowLayout anchors.fill: parent - acceptedButtons: Qt.RightButton + spacing: 10 - onPressed: event => { - if (event.button === Qt.RightButton) { - Hyprland.dispatch('global quickshell:overviewToggle'); + RippleButton { + // Left sidebar button + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + Layout.leftMargin: Appearance.rounding.screenRounding + Layout.fillWidth: false + property real buttonPadding: 5 + implicitWidth: distroIcon.width + buttonPadding * 2 + implicitHeight: distroIcon.height + buttonPadding * 2 + + buttonRadius: Appearance.rounding.full + colBackground: barLeftSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1) + colBackgroundHover: Appearance.colors.colLayer1Hover + colRipple: Appearance.colors.colLayer1Active + colBackgroundToggled: Appearance.colors.colSecondaryContainer + colBackgroundToggledHover: Appearance.colors.colSecondaryContainerHover + colRippleToggled: Appearance.colors.colSecondaryContainerActive + toggled: GlobalStates.sidebarLeftOpen + property color colText: toggled ? Appearance.m3colors.m3onSecondaryContainer : Appearance.colors.colOnLayer0 + + onPressed: { + Hyprland.dispatch('global quickshell:sidebarLeftToggle'); + } + + CustomIcon { + id: distroIcon + anchors.centerIn: parent + width: 19.5 + height: 19.5 + source: Config.options.bar.topLeftIcon == 'distro' ? SystemInfo.distroIcon : "spark-symbolic" + colorize: true + color: Appearance.colors.colOnLayer0 } } + + ActiveWindow { + visible: barRoot.useShortenedForm === 0 + Layout.rightMargin: Appearance.rounding.screenRounding + Layout.fillWidth: true + Layout.fillHeight: true + bar: barRoot + } } } } - VerticalBarSeparator { - visible: Config.options?.bar.borderless - } + RowLayout { // Middle section + id: middleSection + anchors.centerIn: parent + spacing: Config.options?.bar.borderless ? 4 : 8 - MouseArea { - id: rightCenterGroup - implicitWidth: rightCenterGroupContent.implicitWidth - implicitHeight: rightCenterGroupContent.implicitHeight - Layout.preferredWidth: barRoot.centerSideModuleWidth - Layout.fillHeight: true + BarGroup { + id: leftCenterGroup + Layout.preferredWidth: barRoot.centerSideModuleWidth + Layout.fillHeight: true - onPressed: { - Hyprland.dispatch('global quickshell:sidebarRightToggle'); + Resources { + alwaysShowAllResources: barRoot.useShortenedForm === 2 + Layout.fillWidth: barRoot.useShortenedForm === 2 + } + + Media { + visible: barRoot.useShortenedForm < 2 + Layout.fillWidth: true + } + } + + VerticalBarSeparator { + visible: Config.options?.bar.borderless } BarGroup { - id: rightCenterGroupContent - anchors.fill: parent + id: middleCenterGroup + padding: workspacesWidget.widgetPadding + Layout.fillHeight: true - ClockWidget { - showDate: (Config.options.bar.verbose && barRoot.useShortenedForm < 2) - Layout.alignment: Qt.AlignVCenter - Layout.fillWidth: true - } - - UtilButtons { - visible: (Config.options.bar.verbose && barRoot.useShortenedForm === 0) - Layout.alignment: Qt.AlignVCenter - } - - BatteryIndicator { - visible: (barRoot.useShortenedForm < 2 && UPower.displayDevice.isLaptopBattery) - Layout.alignment: Qt.AlignVCenter - } - } - } - - VerticalBarSeparator { - visible: Config.options.bar.borderless && Config.options.bar.weather.enable - } - } - - MouseArea { // Right side | scroll to change volume - id: barRightSideMouseArea - - anchors.right: parent.right - implicitHeight: Appearance.sizes.baseBarHeight - height: Appearance.sizes.barHeight - width: (barRoot.width - middleSection.width) / 2 - - property bool hovered: false - property real lastScrollX: 0 - property real lastScrollY: 0 - property bool trackingScroll: false - - acceptedButtons: Qt.LeftButton - hoverEnabled: true - propagateComposedEvents: true - onEntered: event => { - barRightSideMouseArea.hovered = true; - } - onExited: event => { - barRightSideMouseArea.hovered = false; - barRightSideMouseArea.trackingScroll = false; - } - onPressed: event => { - if (event.button === Qt.LeftButton) { - Hyprland.dispatch('global quickshell:sidebarRightOpen'); - } else if (event.button === Qt.RightButton) { - MprisController.activePlayer.next(); - } - } - // Scroll to change volume - WheelHandler { - onWheel: event => { - const currentVolume = Audio.value; - const step = currentVolume < 0.1 ? 0.01 : 0.02 || 0.2; - if (event.angleDelta.y < 0) - Audio.sink.audio.volume -= step; - else if (event.angleDelta.y > 0) - Audio.sink.audio.volume = Math.min(1, Audio.sink.audio.volume + step); - // Store the mouse position and start tracking - barRightSideMouseArea.lastScrollX = event.x; - barRightSideMouseArea.lastScrollY = event.y; - barRightSideMouseArea.trackingScroll = true; - } - acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad - } - onPositionChanged: mouse => { - if (barRightSideMouseArea.trackingScroll) { - const dx = mouse.x - barRightSideMouseArea.lastScrollX; - const dy = mouse.y - barRightSideMouseArea.lastScrollY; - if (Math.sqrt(dx * dx + dy * dy) > osdHideMouseMoveThreshold) { - Hyprland.dispatch('global quickshell:osdVolumeHide'); - barRightSideMouseArea.trackingScroll = false; - } - } - } - - Item { - anchors.fill: parent - implicitHeight: rightSectionRowLayout.implicitHeight - implicitWidth: rightSectionRowLayout.implicitWidth - - ScrollHint { - reveal: barRightSideMouseArea.hovered - icon: "volume_up" - tooltipText: qsTr("Scroll to change volume") - side: "right" - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - } - - RowLayout { - id: rightSectionRowLayout - anchors.fill: parent - spacing: 5 - layoutDirection: Qt.RightToLeft - - RippleButton { // Right sidebar button - id: rightSidebarButton - - Layout.alignment: Qt.AlignRight | Qt.AlignVCenter - Layout.rightMargin: Appearance.rounding.screenRounding - Layout.fillWidth: false - - implicitWidth: indicatorsRowLayout.implicitWidth + 10 * 2 - implicitHeight: indicatorsRowLayout.implicitHeight + 5 * 2 - - buttonRadius: Appearance.rounding.full - colBackground: barRightSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1) - colBackgroundHover: Appearance.colors.colLayer1Hover - colRipple: Appearance.colors.colLayer1Active - colBackgroundToggled: Appearance.colors.colSecondaryContainer - colBackgroundToggledHover: Appearance.colors.colSecondaryContainerHover - colRippleToggled: Appearance.colors.colSecondaryContainerActive - toggled: GlobalStates.sidebarRightOpen - property color colText: toggled ? Appearance.m3colors.m3onSecondaryContainer : Appearance.colors.colOnLayer0 - - Behavior on colText { - animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) - } - - onPressed: { - Hyprland.dispatch('global quickshell:sidebarRightToggle'); - } - - RowLayout { - id: indicatorsRowLayout - anchors.centerIn: parent - property real realSpacing: 15 - spacing: 0 - - Revealer { - reveal: Audio.sink?.audio?.muted ?? false - Layout.fillHeight: true - Layout.rightMargin: reveal ? indicatorsRowLayout.realSpacing : 0 - Behavior on Layout.rightMargin { - NumberAnimation { - duration: Appearance.animation.elementMoveFast.duration - easing.type: Appearance.animation.elementMoveFast.type - easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve - } - } - MaterialSymbol { - text: "volume_off" - iconSize: Appearance.font.pixelSize.larger - color: rightSidebarButton.colText - } - } - Revealer { - reveal: Audio.source?.audio?.muted ?? false - Layout.fillHeight: true - Layout.rightMargin: reveal ? indicatorsRowLayout.realSpacing : 0 - Behavior on Layout.rightMargin { - NumberAnimation { - duration: Appearance.animation.elementMoveFast.duration - easing.type: Appearance.animation.elementMoveFast.type - easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve - } - } - MaterialSymbol { - text: "mic_off" - iconSize: Appearance.font.pixelSize.larger - color: rightSidebarButton.colText - } - } - MaterialSymbol { - Layout.rightMargin: indicatorsRowLayout.realSpacing - text: Network.materialSymbol - iconSize: Appearance.font.pixelSize.larger - color: rightSidebarButton.colText - } - MaterialSymbol { - text: Bluetooth.bluetoothConnected ? "bluetooth_connected" : Bluetooth.bluetoothEnabled ? "bluetooth" : "bluetooth_disabled" - iconSize: Appearance.font.pixelSize.larger - color: rightSidebarButton.colText - } - } - } - - SysTray { + Workspaces { + id: workspacesWidget bar: barRoot - visible: barRoot.useShortenedForm === 0 - Layout.fillWidth: false Layout.fillHeight: true + MouseArea { + // Right-click to toggle overview + anchors.fill: parent + acceptedButtons: Qt.RightButton + + onPressed: event => { + if (event.button === Qt.RightButton) { + Hyprland.dispatch('global quickshell:overviewToggle'); + } + } + } + } + } + + VerticalBarSeparator { + visible: Config.options?.bar.borderless + } + + MouseArea { + id: rightCenterGroup + implicitWidth: rightCenterGroupContent.implicitWidth + implicitHeight: rightCenterGroupContent.implicitHeight + Layout.preferredWidth: barRoot.centerSideModuleWidth + Layout.fillHeight: true + + onPressed: { + Hyprland.dispatch('global quickshell:sidebarRightToggle'); } - Item { - Layout.fillWidth: true - Layout.fillHeight: true + BarGroup { + id: rightCenterGroupContent + anchors.fill: parent + + ClockWidget { + showDate: (Config.options.bar.verbose && barRoot.useShortenedForm < 2) + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + } + + UtilButtons { + visible: (Config.options.bar.verbose && barRoot.useShortenedForm === 0) + Layout.alignment: Qt.AlignVCenter + } + + BatteryIndicator { + visible: (barRoot.useShortenedForm < 2 && UPower.displayDevice.isLaptopBattery) + Layout.alignment: Qt.AlignVCenter + } + } + } + + VerticalBarSeparator { + visible: Config.options.bar.borderless && Config.options.bar.weather.enable + } + } + + MouseArea { // Right side | scroll to change volume + id: barRightSideMouseArea + + anchors.right: parent.right + implicitHeight: Appearance.sizes.baseBarHeight + height: Appearance.sizes.barHeight + width: (barRoot.width - middleSection.width) / 2 + + property bool hovered: false + property real lastScrollX: 0 + property real lastScrollY: 0 + property bool trackingScroll: false + + acceptedButtons: Qt.LeftButton + hoverEnabled: true + propagateComposedEvents: true + onEntered: event => { + barRightSideMouseArea.hovered = true; + } + onExited: event => { + barRightSideMouseArea.hovered = false; + barRightSideMouseArea.trackingScroll = false; + } + onPressed: event => { + if (event.button === Qt.LeftButton) { + Hyprland.dispatch('global quickshell:sidebarRightOpen'); + } else if (event.button === Qt.RightButton) { + MprisController.activePlayer.next(); + } + } + // Scroll to change volume + WheelHandler { + onWheel: event => { + const currentVolume = Audio.value; + const step = currentVolume < 0.1 ? 0.01 : 0.02 || 0.2; + if (event.angleDelta.y < 0) + Audio.sink.audio.volume -= step; + else if (event.angleDelta.y > 0) + Audio.sink.audio.volume = Math.min(1, Audio.sink.audio.volume + step); + // Store the mouse position and start tracking + barRightSideMouseArea.lastScrollX = event.x; + barRightSideMouseArea.lastScrollY = event.y; + barRightSideMouseArea.trackingScroll = true; + } + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad + } + onPositionChanged: mouse => { + if (barRightSideMouseArea.trackingScroll) { + const dx = mouse.x - barRightSideMouseArea.lastScrollX; + const dy = mouse.y - barRightSideMouseArea.lastScrollY; + if (Math.sqrt(dx * dx + dy * dy) > osdHideMouseMoveThreshold) { + Hyprland.dispatch('global quickshell:osdVolumeHide'); + barRightSideMouseArea.trackingScroll = false; + } + } + } + + Item { + anchors.fill: parent + implicitHeight: rightSectionRowLayout.implicitHeight + implicitWidth: rightSectionRowLayout.implicitWidth + + ScrollHint { + reveal: barRightSideMouseArea.hovered + icon: "volume_up" + tooltipText: qsTr("Scroll to change volume") + side: "right" + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter } - // Weather - Loader { - Layout.leftMargin: 8 - Layout.fillHeight: true - active: Config.options.bar.weather.enable - sourceComponent: BarGroup { - implicitHeight: Appearance.sizes.baseBarHeight - WeatherBar {} + RowLayout { + id: rightSectionRowLayout + anchors.fill: parent + spacing: 5 + layoutDirection: Qt.RightToLeft + + RippleButton { // Right sidebar button + id: rightSidebarButton + + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + Layout.rightMargin: Appearance.rounding.screenRounding + Layout.fillWidth: false + + implicitWidth: indicatorsRowLayout.implicitWidth + 10 * 2 + implicitHeight: indicatorsRowLayout.implicitHeight + 5 * 2 + + buttonRadius: Appearance.rounding.full + colBackground: barRightSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1) + colBackgroundHover: Appearance.colors.colLayer1Hover + colRipple: Appearance.colors.colLayer1Active + colBackgroundToggled: Appearance.colors.colSecondaryContainer + colBackgroundToggledHover: Appearance.colors.colSecondaryContainerHover + colRippleToggled: Appearance.colors.colSecondaryContainerActive + toggled: GlobalStates.sidebarRightOpen + property color colText: toggled ? Appearance.m3colors.m3onSecondaryContainer : Appearance.colors.colOnLayer0 + + Behavior on colText { + animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) + } + + onPressed: { + Hyprland.dispatch('global quickshell:sidebarRightToggle'); + } + + RowLayout { + id: indicatorsRowLayout + anchors.centerIn: parent + property real realSpacing: 15 + spacing: 0 + + Revealer { + reveal: Audio.sink?.audio?.muted ?? false + Layout.fillHeight: true + Layout.rightMargin: reveal ? indicatorsRowLayout.realSpacing : 0 + Behavior on Layout.rightMargin { + NumberAnimation { + duration: Appearance.animation.elementMoveFast.duration + easing.type: Appearance.animation.elementMoveFast.type + easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve + } + } + MaterialSymbol { + text: "volume_off" + iconSize: Appearance.font.pixelSize.larger + color: rightSidebarButton.colText + } + } + Revealer { + reveal: Audio.source?.audio?.muted ?? false + Layout.fillHeight: true + Layout.rightMargin: reveal ? indicatorsRowLayout.realSpacing : 0 + Behavior on Layout.rightMargin { + NumberAnimation { + duration: Appearance.animation.elementMoveFast.duration + easing.type: Appearance.animation.elementMoveFast.type + easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve + } + } + MaterialSymbol { + text: "mic_off" + iconSize: Appearance.font.pixelSize.larger + color: rightSidebarButton.colText + } + } + MaterialSymbol { + Layout.rightMargin: indicatorsRowLayout.realSpacing + text: Network.materialSymbol + iconSize: Appearance.font.pixelSize.larger + color: rightSidebarButton.colText + } + MaterialSymbol { + text: Bluetooth.bluetoothConnected ? "bluetooth_connected" : Bluetooth.bluetoothEnabled ? "bluetooth" : "bluetooth_disabled" + iconSize: Appearance.font.pixelSize.larger + color: rightSidebarButton.colText + } + } + } + + SysTray { + bar: barRoot + visible: barRoot.useShortenedForm === 0 + Layout.fillWidth: false + Layout.fillHeight: true + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + + // Weather + Loader { + Layout.leftMargin: 8 + Layout.fillHeight: true + active: Config.options.bar.weather.enable + sourceComponent: BarGroup { + implicitHeight: Appearance.sizes.baseBarHeight + WeatherBar {} + } } } } } } - } - // Round decorators - Loader { - id: roundDecorators - anchors { - left: parent.left - right: parent.right - } - y: Appearance.sizes.barHeight - width: parent.width - height: Appearance.rounding.screenRounding - active: showBarBackground && Config.options.bar.cornerStyle === 0 // Hug - - states: State { - name: "bottom" - when: Config.options.bar.bottom - PropertyChanges { - roundDecorators.y: 0 + // Round decorators + Loader { + id: roundDecorators + anchors { + left: parent.left + right: parent.right } - } + y: Appearance.sizes.barHeight + width: parent.width + height: Appearance.rounding.screenRounding + active: showBarBackground && Config.options.bar.cornerStyle === 0 // Hug - sourceComponent: Item { - implicitHeight: Appearance.rounding.screenRounding - RoundCorner { - id: leftCorner - anchors { - top: parent.top - bottom: parent.bottom - left: parent.left + states: State { + name: "bottom" + when: Config.options.bar.bottom + PropertyChanges { + roundDecorators.y: 0 } + } - size: Appearance.rounding.screenRounding - color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + sourceComponent: Item { + implicitHeight: Appearance.rounding.screenRounding + RoundCorner { + id: leftCorner + anchors { + top: parent.top + bottom: parent.bottom + left: parent.left + } - corner: RoundCorner.CornerEnum.TopLeft - states: State { - name: "bottom" - when: Config.options.bar.bottom - PropertyChanges { - leftCorner.corner: RoundCorner.CornerEnum.BottomLeft + size: Appearance.rounding.screenRounding + color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + opacity: 1.0 - Appearance.transparency + + corner: RoundCorner.CornerEnum.TopLeft + states: State { + name: "bottom" + when: Config.options.bar.bottom + PropertyChanges { + leftCorner.corner: RoundCorner.CornerEnum.BottomLeft + } } } - } - RoundCorner { - id: rightCorner - anchors { - right: parent.right - top: !Config.options.bar.bottom ? parent.top : undefined - bottom: Config.options.bar.bottom ? parent.bottom : undefined - } - size: Appearance.rounding.screenRounding - color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + RoundCorner { + id: rightCorner + anchors { + right: parent.right + top: !Config.options.bar.bottom ? parent.top : undefined + bottom: Config.options.bar.bottom ? parent.bottom : undefined + } + size: Appearance.rounding.screenRounding + color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" + opacity: 1.0 - Appearance.transparency - corner: RoundCorner.CornerEnum.TopRight - states: State { - name: "bottom" - when: Config.options.bar.bottom - PropertyChanges { - rightCorner.corner: RoundCorner.CornerEnum.BottomRight + corner: RoundCorner.CornerEnum.TopRight + states: State { + name: "bottom" + when: Config.options.bar.bottom + PropertyChanges { + rightCorner.corner: RoundCorner.CornerEnum.BottomRight + } } } } @@ -563,4 +569,47 @@ Scope { } } } + + IpcHandler { + target: "bar" + + function toggle(): void { + GlobalStates.barOpen = !GlobalStates.barOpen + } + + function close(): void { + GlobalStates.barOpen = false + } + + function open(): void { + GlobalStates.barOpen = true + } + } + + GlobalShortcut { + name: "barToggle" + description: qsTr("Toggles bar on press") + + onPressed: { + GlobalStates.barOpen = !GlobalStates.barOpen; + } + } + + GlobalShortcut { + name: "barOpen" + description: qsTr("Opens bar on press") + + onPressed: { + GlobalStates.barOpen = true; + } + } + + GlobalShortcut { + name: "barClose" + description: qsTr("Closes bar on press") + + onPressed: { + GlobalStates.barOpen = false; + } + } } From e42b0d20f8d192697629d5ac127b60aa68004e9a Mon Sep 17 00:00:00 2001 From: Habibul Fauzan <45551081+habibulfauzan@users.noreply.github.com> Date: Sat, 12 Jul 2025 09:24:47 +0700 Subject: [PATCH 198/328] Update rules.conf add windowrule for Zotero Update rules.conf add windowrule for Zotero --- .config/hypr/hyprland/rules.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index ffa3663f..6b6922a5 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -27,6 +27,9 @@ windowrulev2 = float, class:.*bluedevilwizard windowrulev2 = float, title:.*Welcome windowrulev2 = float, title:^(illogical-impulse Settings)$ windowrulev2 = float, class:org.freedesktop.impl.portal.desktop.kde +windowrulev2 = float, class:^(Zotero)$ +windowrulev2 = size 45%, class:^(Zotero)$ + # Move # kde-material-you-colors spawns a window when changing dark/light theme. This is to make sure it doesn't interfere at all. From c5982a3ee1ee819156cc02eb79555c5182d8f9db Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 12 Jul 2025 19:05:37 +0700 Subject: [PATCH 199/328] bar: use lazyloader --- .config/quickshell/ii/modules/bar/Bar.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml index 36863ec5..eeb77f99 100644 --- a/.config/quickshell/ii/modules/bar/Bar.qml +++ b/.config/quickshell/ii/modules/bar/Bar.qml @@ -37,11 +37,11 @@ Scope { return screens; return screens.filter(screen => list.includes(screen.name)); } - Loader { + LazyLoader { id: barLoader - active: GlobalStates.barOpen + activeAsync: GlobalStates.barOpen required property ShellScreen modelData - sourceComponent: PanelWindow { // Bar window + component: PanelWindow { // Bar window id: barRoot screen: barLoader.modelData From 1e1aeb26737e0cb8dafc70d1e647834cfb13eafb Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 12 Jul 2025 19:05:48 +0700 Subject: [PATCH 200/328] notif popup: fix right spacing --- .../modules/notificationPopup/NotificationPopup.qml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml b/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml index fb046343..3f10a92f 100644 --- a/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml +++ b/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml @@ -36,10 +36,13 @@ Scope { NotificationListView { id: listview - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - anchors.topMargin: 5 + anchors { + top: parent.top + bottom: parent.bottom + right: parent.right + rightMargin: 4 + topMargin: 4 + } implicitWidth: parent.width - Appearance.sizes.elevationMargin * 2 popup: true } From ae58e59d67b5b1633c062cf26828de351d606855 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 12 Jul 2025 19:15:41 +0700 Subject: [PATCH 201/328] search: konachan wallpaper command (#1624) --- .../ii/modules/overview/SearchWidget.qml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.config/quickshell/ii/modules/overview/SearchWidget.qml b/.config/quickshell/ii/modules/overview/SearchWidget.qml index 91998aa9..c5593e71 100644 --- a/.config/quickshell/ii/modules/overview/SearchWidget.qml +++ b/.config/quickshell/ii/modules/overview/SearchWidget.qml @@ -40,12 +40,6 @@ Item { // Wrapper } property var searchActions: [ - { - action: "img", - execute: () => { - executor.executeCommand(Directories.wallpaperSwitchScriptPath) - } - }, { action: "dark", execute: () => { @@ -58,6 +52,18 @@ Item { // Wrapper executor.executeCommand(`${Directories.wallpaperSwitchScriptPath} --mode light --noswitch`) } }, + { + action: "wall", + execute: () => { + executor.executeCommand(Directories.wallpaperSwitchScriptPath) + } + }, + { + action: "konachanwall", + execute: () => { + Quickshell.execDetached([Quickshell.configPath("scripts/colors/random_konachan_wall.sh")]) + } + }, { action: "accentcolor", execute: (args) => { From f6bb5385cfe275471511e9f61d4f244c63d7dd90 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 12 Jul 2025 19:25:08 +0700 Subject: [PATCH 202/328] search: use qs' execdetached instead of executor proc --- .../ii/modules/overview/SearchWidget.qml | 171 ++++++++---------- 1 file changed, 73 insertions(+), 98 deletions(-) diff --git a/.config/quickshell/ii/modules/overview/SearchWidget.qml b/.config/quickshell/ii/modules/overview/SearchWidget.qml index c5593e71..2754567e 100644 --- a/.config/quickshell/ii/modules/overview/SearchWidget.qml +++ b/.config/quickshell/ii/modules/overview/SearchWidget.qml @@ -4,14 +4,11 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/string_utils.js" as StringUtils import Qt5Compat.GraphicalEffects -import Qt.labs.platform import QtQuick import QtQuick.Controls -import QtQuick.Effects import QtQuick.Layouts import Quickshell import Quickshell.Io -import Quickshell.Hyprland Item { // Wrapper id: root @@ -29,9 +26,9 @@ Item { // Wrapper } function cancelSearch() { - searchInput.selectAll() - root.searchingText = "" - searchWidthBehavior.enabled = true; + searchInput.selectAll(); + root.searchingText = ""; + searchWidthBehavior.enabled = true; } function setSearchingText(text) { @@ -43,45 +40,44 @@ Item { // Wrapper { action: "dark", execute: () => { - executor.executeCommand(`${Directories.wallpaperSwitchScriptPath} --mode dark --noswitch`) + Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--mode", "dark", "--noswitch"]); } }, { action: "light", execute: () => { - executor.executeCommand(`${Directories.wallpaperSwitchScriptPath} --mode light --noswitch`) + Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--mode", "light", "--noswitch"]); } }, { - action: "wall", + action: "wall", execute: () => { - executor.executeCommand(Directories.wallpaperSwitchScriptPath) + Quickshell.execDetached([Directories.wallpaperSwitchScriptPath]); } }, { - action: "konachanwall", + action: "konachanwall", execute: () => { - Quickshell.execDetached([Quickshell.configPath("scripts/colors/random_konachan_wall.sh")]) + Quickshell.execDetached([Quickshell.configPath("scripts/colors/random_konachan_wall.sh")]); } }, { action: "accentcolor", - execute: (args) => { - executor.executeCommand( - `${Directories.wallpaperSwitchScriptPath} --noswitch --color ${args != '' ? ("'"+args+"'") : ""}` - ) + execute: args => { + Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--noswitch", "--color", ...(args != '' ? [`${args}`] : [])]); } }, { action: "todo", - execute: (args) => { - Todo.addTask(args) + execute: args => { + Todo.addTask(args); } }, ] function focusFirstItemIfNeeded() { - if (searchInput.focus) appResults.currentIndex = 0; // Focus the first item + if (searchInput.focus) + appResults.currentIndex = 0; // Focus the first item } Timer { @@ -96,32 +92,22 @@ Item { // Wrapper id: mathProcess property list baseCommand: ["qalc", "-t"] function calculateExpression(expression) { - mathProcess.running = false - mathProcess.command = baseCommand.concat(expression) - mathProcess.running = true + mathProcess.running = false; + mathProcess.command = baseCommand.concat(expression); + mathProcess.running = true; } stdout: SplitParser { onRead: data => { - root.mathResult = data - root.focusFirstItemIfNeeded() + root.mathResult = data; + root.focusFirstItemIfNeeded(); } } } - Process { - id: executor - property list baseCommand: ["bash", "-c"] - function executeCommand(command) { - executor.command = baseCommand.concat( - `${command}` - ) - executor.startDetached() - } - } - - Keys.onPressed: (event) => { + Keys.onPressed: event => { // Prevent Esc and Backspace from registering - if (event.key === Qt.Key_Escape) return; + if (event.key === Qt.Key_Escape) + return; // Handle Backspace: focus and delete character if not focused if (event.key === Qt.Key_Backspace) { @@ -142,8 +128,7 @@ Item { // Wrapper } else { // Delete character before cursor if any if (searchInput.cursorPosition > 0) { - searchInput.text = searchInput.text.slice(0, searchInput.cursorPosition - 1) + - searchInput.text.slice(searchInput.cursorPosition); + searchInput.text = searchInput.text.slice(0, searchInput.cursorPosition - 1) + searchInput.text.slice(searchInput.cursorPosition); searchInput.cursorPosition -= 1; } } @@ -156,19 +141,12 @@ Item { // Wrapper } // Only handle visible printable characters (ignore control chars, arrows, etc.) - if ( - event.text && - event.text.length === 1 && - event.key !== Qt.Key_Enter && - event.key !== Qt.Key_Return && - event.text.charCodeAt(0) >= 0x20 // ignore control chars like Backspace, Tab, etc. - ) { + if (event.text && event.text.length === 1 && event.key !== Qt.Key_Enter && event.key !== Qt.Key_Return && event.text.charCodeAt(0) >= 0x20) // ignore control chars like Backspace, Tab, etc. + { if (!searchInput.activeFocus) { searchInput.forceActiveFocus(); // Insert the character at the cursor position - searchInput.text = searchInput.text.slice(0, searchInput.cursorPosition) + - event.text + - searchInput.text.slice(searchInput.cursorPosition); + searchInput.text = searchInput.text.slice(0, searchInput.cursorPosition) + event.text + searchInput.text.slice(searchInput.cursorPosition); searchInput.cursorPosition += 1; event.accepted = true; } @@ -264,7 +242,8 @@ Item { // Wrapper } } - Rectangle { // Separator + Rectangle { + // Separator visible: root.showResults Layout.fillWidth: true height: 1 @@ -281,10 +260,11 @@ Item { // Wrapper bottomMargin: 10 spacing: 2 KeyNavigation.up: searchBar - highlightMoveDuration : 100 + highlightMoveDuration: 100 onFocusChanged: { - if(focus) appResults.currentIndex = 1; + if (focus) + appResults.currentIndex = 1; } Connections { @@ -297,12 +277,15 @@ Item { // Wrapper model: ScriptModel { id: model - values: { // Search results are handled here + values: { + // Search results are handled here ////////////////// Skip? ////////////////// - if(root.searchingText == "") return []; + if (root.searchingText == "") + return []; ///////////// Special cases /////////////// - if (root.searchingText.startsWith(Config.options.search.prefix.clipboard)) { // Clipboard + if (root.searchingText.startsWith(Config.options.search.prefix.clipboard)) { + // Clipboard const searchString = root.searchingText.slice(Config.options.search.prefix.clipboard.length); return Cliphist.fuzzyQuery(searchString).map(entry => { return { @@ -311,14 +294,13 @@ Item { // Wrapper clickActionName: "", type: `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`, execute: () => { - Quickshell.execDetached( - ["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`] - ); + Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`]); } }; }).filter(Boolean); - } - if (root.searchingText.startsWith(Config.options.search.prefix.emojis)) { // Clipboard + } + if (root.searchingText.startsWith(Config.options.search.prefix.emojis)) { + // Clipboard const searchString = root.searchingText.slice(Config.options.search.prefix.emojis.length); return Emojis.fuzzyQuery(searchString).map(entry => { return { @@ -328,12 +310,11 @@ Item { // Wrapper clickActionName: "", type: "Emoji", execute: () => { - Quickshell.clipboardText = entry.match(/^\s*(\S+)/)?.[1] + Quickshell.clipboardText = entry.match(/^\s*(\S+)/)?.[1]; } }; }).filter(Boolean); - } - + } ////////////////// Init /////////////////// nonAppResultsTimer.restart(); @@ -346,7 +327,7 @@ Item { // Wrapper execute: () => { Quickshell.clipboardText = root.mathResult; } - } + }; const commandResultObject = { name: searchingText.replace("file://", ""), clickActionName: qsTr("Run"), @@ -354,38 +335,34 @@ Item { // Wrapper fontType: "monospace", materialSymbol: 'terminal', execute: () => { - executor.executeCommand(searchingText.startsWith('sudo') ? `${Config.options.apps.terminal} fish -C '${root.searchingText.replace("file://", "")}'` : root.searchingText.replace("file://", "")); + const cleanedCommand = root.searchingText.replace("file://", ""); + Quickshell.execDetached(["bash", "-c", searchingText.startsWith('sudo') ? `${Config.options.apps.terminal} fish -C '${cleanedCommand}'` : cleanedCommand]); } - } - const launcherActionObjects = root.searchActions - .map(action => { - const actionString = `${Config.options.search.prefix.action}${action.action}`; - if (actionString.startsWith(root.searchingText) || root.searchingText.startsWith(actionString)) { - return { - name: root.searchingText.startsWith(actionString) ? root.searchingText : actionString, - clickActionName: qsTr("Run"), - type: qsTr("Action"), - materialSymbol: 'settings_suggest', - execute: () => { - action.execute(root.searchingText.split(" ").slice(1).join(" ")) - }, - }; - } - return null; - }) - .filter(Boolean); + }; + const launcherActionObjects = root.searchActions.map(action => { + const actionString = `${Config.options.search.prefix.action}${action.action}`; + if (actionString.startsWith(root.searchingText) || root.searchingText.startsWith(actionString)) { + return { + name: root.searchingText.startsWith(actionString) ? root.searchingText : actionString, + clickActionName: qsTr("Run"), + type: qsTr("Action"), + materialSymbol: 'settings_suggest', + execute: () => { + action.execute(root.searchingText.split(" ").slice(1).join(" ")); + } + }; + } + return null; + }).filter(Boolean); let result = []; //////////////// Apps ////////////////// - result = result.concat( - AppSearch.fuzzyQuery(root.searchingText) - .map((entry) => { - entry.clickActionName = qsTr("Launch"); - entry.type = qsTr("App"); - return entry; - }) - ); + result = result.concat(AppSearch.fuzzyQuery(root.searchingText).map(entry => { + entry.clickActionName = qsTr("Launch"); + entry.type = qsTr("App"); + return entry; + })); ////////// Launcher actions //////////// result = result.concat(launcherActionObjects); @@ -407,7 +384,7 @@ Item { // Wrapper type: qsTr("Search the web"), materialSymbol: 'travel_explore', execute: () => { - let url = Config.options.search.engineBaseUrl + root.searchingText + let url = Config.options.search.engineBaseUrl + root.searchingText; for (let site of Config.options.search.excludedSites) { url += ` -site:${site}`; } @@ -419,17 +396,15 @@ Item { // Wrapper } } - delegate: SearchItem { // The selectable item for each search result + delegate: SearchItem { + // The selectable item for each search result required property var modelData anchors.left: parent?.left anchors.right: parent?.right entry: modelData - query: root.searchingText.startsWith(Config.options.search.prefix.clipboard) ? - root.searchingText.slice(Config.options.search.prefix.clipboard.length) : - root.searchingText; + query: root.searchingText.startsWith(Config.options.search.prefix.clipboard) ? root.searchingText.slice(Config.options.search.prefix.clipboard.length) : root.searchingText } } - } } -} \ No newline at end of file +} From e59dd2cab273802d4f5f19acc3274392532cd6e7 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 12 Jul 2025 20:13:26 +0700 Subject: [PATCH 203/328] add option to disable theming (#1586) --- .../quickshell/ii/modules/common/Config.qml | 5 ++ .../ii/modules/settings/AdvancedConfig.qml | 46 +++++++++++++++++++ .../ii/scripts/colors/applycolor.sh | 15 +++++- .../ii/scripts/colors/switchwall.sh | 20 ++++++++ .config/quickshell/ii/settings.qml | 5 ++ 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 .config/quickshell/ii/modules/settings/AdvancedConfig.qml diff --git a/.config/quickshell/ii/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml index 5d427a97..1b9b1dd8 100644 --- a/.config/quickshell/ii/modules/common/Config.qml +++ b/.config/quickshell/ii/modules/common/Config.qml @@ -66,6 +66,11 @@ Singleton { property bool extraBackgroundTint: true property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen property bool transparency: false + property JsonObject wallpaperTheming: JsonObject { + property bool enableAppsAndShell: true + property bool enableQtApps: true + property bool enableTerminal: true + } property JsonObject palette: JsonObject { property string type: "auto" // Allowed: auto, scheme-content, scheme-expressive, scheme-fidelity, scheme-fruit-salad, scheme-monochrome, scheme-neutral, scheme-rainbow, scheme-tonal-spot } diff --git a/.config/quickshell/ii/modules/settings/AdvancedConfig.qml b/.config/quickshell/ii/modules/settings/AdvancedConfig.qml new file mode 100644 index 00000000..d0f22d4d --- /dev/null +++ b/.config/quickshell/ii/modules/settings/AdvancedConfig.qml @@ -0,0 +1,46 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import "root:/services/" +import "root:/modules/common/" +import "root:/modules/common/widgets/" + +ContentPage { + forceWidth: true + + ContentSection { + title: "Color generation" + + ConfigRow { + uniform: true + ConfigSwitch { + text: "Shell & utilities" + checked: Config.options.appearance.wallpaperTheming.enableAppsAndShell + onCheckedChanged: { + Config.options.appearance.wallpaperTheming.enableAppsAndShell = checked; + } + } + ConfigSwitch { + text: "Qt apps" + checked: Config.options.appearance.wallpaperTheming.enableQtApps + onCheckedChanged: { + Config.options.appearance.wallpaperTheming.enableQtApps = checked; + } + StyledToolTip { + content: "Shell & utilities theming must also be enabled" + } + } + ConfigSwitch { + text: "Terminal" + checked: Config.options.appearance.wallpaperTheming.enableTerminal + onCheckedChanged: { + Config.options.appearance.wallpaperTheming.enableTerminal = checked; + } + StyledToolTip { + content: "Shell & utilities theming must also be enabled" + } + } + + } + } +} diff --git a/.config/quickshell/ii/scripts/colors/applycolor.sh b/.config/quickshell/ii/scripts/colors/applycolor.sh index b86fb679..ddb93bd2 100755 --- a/.config/quickshell/ii/scripts/colors/applycolor.sh +++ b/.config/quickshell/ii/scripts/colors/applycolor.sh @@ -57,5 +57,16 @@ apply_qt() { python "$CONFIG_DIR/scripts/kvantum/changeAdwColors.py" # apply config colors } -apply_qt & -apply_term & +# Check if terminal theming is enabled in config +CONFIG_FILE="$XDG_CONFIG_HOME/illogical-impulse/config.json" +if [ -f "$CONFIG_FILE" ]; then + enable_terminal=$(jq -r '.appearance.wallpaperTheming.enableTerminal' "$CONFIG_FILE") + if [ "$enable_terminal" = "true" ]; then + apply_term & + fi +else + echo "Config file not found at $CONFIG_FILE. Applying terminal theming by default." + apply_term & +fi + +# apply_qt & # Qt theming is already handled by kde-material-colors diff --git a/.config/quickshell/ii/scripts/colors/switchwall.sh b/.config/quickshell/ii/scripts/colors/switchwall.sh index de76444f..0d9ffadb 100755 --- a/.config/quickshell/ii/scripts/colors/switchwall.sh +++ b/.config/quickshell/ii/scripts/colors/switchwall.sh @@ -12,6 +12,15 @@ MATUGEN_DIR="$XDG_CONFIG_HOME/matugen" terminalscheme="$SCRIPT_DIR/terminal/scheme-base.json" handle_kde_material_you_colors() { + # Check if Qt app theming is enabled in config + CONFIG_FILE="$XDG_CONFIG_HOME/illogical-impulse/config.json" + if [ -f "$CONFIG_FILE" ]; then + enable_qt_apps=$(jq -r '.appearance.wallpaperTheming.enableQtApps' "$CONFIG_FILE") + if [ "$enable_qt_apps" == "false" ]; then + return + fi + fi + # Map $type_flag to allowed scheme variants for kde-material-you-colors-wrapper.sh local kde_scheme_variant="" case "$type_flag" in @@ -46,6 +55,7 @@ post_process() { local screen_height="$2" local wallpaper_path="$3" + handle_kde_material_you_colors & # Determine the largest region on the wallpaper that's sufficiently un-busy to put widgets in @@ -242,6 +252,16 @@ switch() { pre_process "$mode_flag" + # Check if app and shell theming is enabled in config + CONFIG_FILE="$XDG_CONFIG_HOME/illogical-impulse/config.json" + if [ -f "$CONFIG_FILE" ]; then + enable_apps_shell=$(jq -r '.appearance.wallpaperTheming.enableAppsAndShell' "$CONFIG_FILE") + if [ "$enable_apps_shell" == "false" ]; then + echo "App and shell theming disabled, skipping matugen and color generation" + return + fi + fi + matugen "${matugen_args[@]}" source "$(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate" python3 "$SCRIPT_DIR/generate_colors_material.py" "${generate_colors_material_args[@]}" \ diff --git a/.config/quickshell/ii/settings.qml b/.config/quickshell/ii/settings.qml index 0e181e0b..e76f8dcb 100644 --- a/.config/quickshell/ii/settings.qml +++ b/.config/quickshell/ii/settings.qml @@ -42,6 +42,11 @@ ApplicationWindow { icon: "settings", component: "modules/settings/ServicesConfig.qml" }, + { + name: "Advanced", + icon: "construction", + component: "modules/settings/AdvancedConfig.qml" + }, { name: "About", icon: "info", From 271732ed0b1243dbe1bf867bcc02bf8adc59cdfc Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 12 Jul 2025 20:36:34 +0700 Subject: [PATCH 204/328] bar: weather: fix popup position for bottom bar --- .config/quickshell/ii/modules/bar/weather/WeatherBar.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml index eae1b613..a77a2a43 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml @@ -46,9 +46,11 @@ MouseArea { implicitWidth: weatherPopup.implicitWidth implicitHeight: weatherPopup.implicitHeight anchor.item: root - anchor.edges: Edges.Bottom + anchor.edges: Edges.Top anchor.rect.x: (root.implicitWidth - popupWindow.implicitWidth) / 2 - anchor.rect.y: root.implicitHeight + 10 + anchor.rect.y: Config.options.bar.bottom ? + (-weatherPopup.implicitHeight - 15) : + (root.implicitHeight + 15 ) color: "transparent" WeatherPopup { id: weatherPopup From fb0d3f7f405d168c350429ec2eb2c479218e262d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Sat, 12 Jul 2025 22:46:24 +0800 Subject: [PATCH 205/328] i18n:Replace qstr with Translation.tr and update the translation file --- .config/quickshell/ii/Translation.qml | 170 ++++++++++++++++++ .../ii/modules/sidebarLeft/AiChat.qml | 6 +- .../ii/modules/sidebarLeft/DescriptionBox.qml | 2 +- .../sidebarLeft/SidebarLeftContent.qml | 6 +- .../sidebarRight/BottomWidgetGroup.qml | 4 +- .../notifications/NotificationList.qml | 2 +- .config/quickshell/translations/en_US.json | 13 +- .config/quickshell/translations/zh_CN.json | 13 +- 8 files changed, 196 insertions(+), 20 deletions(-) create mode 100644 .config/quickshell/ii/Translation.qml diff --git a/.config/quickshell/ii/Translation.qml b/.config/quickshell/ii/Translation.qml new file mode 100644 index 00000000..97aff7c5 --- /dev/null +++ b/.config/quickshell/ii/Translation.qml @@ -0,0 +1,170 @@ +pragma Singleton + +import QtQuick +import Quickshell +import Quickshell.Io +import "root:/modules/common/" + +Singleton { + id: root + + property var translations: ({}) + property string currentLanguage: "en_US" + property var availableLanguages: ["en_US"] + property bool isScanning: false + property bool isLoading: false + + Process { + id: scanLanguagesProcess + command: ["find", Qt.resolvedUrl(Directories.config + "/quickshell/translations/").toString().replace("file://", ""), "-name", "*.json", "-exec", "basename", "{}", ".json", ";"] + running: false + + stdout: SplitParser { + onRead: data => { + if (data.trim().length === 0) return + + var files = data.trim().split('\n') + + for (var i = 0; i < files.length; i++) { + var lang = files[i].trim() + if (lang.length > 0 && root.availableLanguages.indexOf(lang) === -1) { + root.availableLanguages.push(lang) + } + } + } + } + + onExited: (exitCode, exitStatus) => { + root.isScanning = false + if (exitCode !== 0) { + root.availableLanguages = ["en_US"] + } + root.loadTranslations() + } + } + + FileView { + id: translationFileView + onLoaded: { + var textContent = "" + try { + textContent = text() + } catch (e) { + root.translations = {} + root.isLoading = false + return + } + + if (textContent.length === 0) { + root.translations = {} + root.isLoading = false + return + } + + try { + var jsonData = JSON.parse(textContent) + root.translations = jsonData + root.isLoading = false + } catch (e) { + root.translations = {} + root.isLoading = false + } + } + onLoadFailed: (error) => { + root.translations = {} + root.isLoading = false + } + } + + function detectSystemLanguage() { + var locale = Qt.locale().name + return locale + } + + function getLanguageCode() { + var configLang = "auto" + try { + configLang = ConfigOptions.language.ui + } catch (e) { + configLang = "auto" + } + + if (configLang === "auto") { + return detectSystemLanguage() + } else { + if (root.availableLanguages.indexOf(configLang) !== -1) { + return configLang + } else { + return detectSystemLanguage() + } + } + } + + function loadTranslations() { + if (root.isScanning) { + return + } + + var targetLang = getLanguageCode() + root.currentLanguage = targetLang + + // Use empty translations for English (default language) + if (targetLang === "en_US" || targetLang === "en") { + root.translations = {} + return + } + + // Check if target language is available + if (root.availableLanguages.indexOf(targetLang) === -1) { + root.currentLanguage = "en_US" + root.translations = {} + return + } + + // Load translation file + root.isLoading = true + var translationsPath = Qt.resolvedUrl(Directories.config + "/quickshell/translations/" + targetLang + ".json") + translationFileView.path = translationsPath + } + + function tr(text) { + if (!text) { + return "" + } + + var key = text.toString() + + if (root.isLoading) { + return key + } + + if (root.currentLanguage === "en_US" || root.currentLanguage === "en" || !root.translations) { + return key + } + + if (root.translations.hasOwnProperty(key)) { + var translation = root.translations[key] + if (translation && translation.toString().trim().length > 0) { + return translation.toString() + } else { + return translation.toString() + } + } + + return key // Fallback to key name + } + + function reloadTranslations() { + root.scanLanguages() + } + + function scanLanguages() { + var translationsDir = Qt.resolvedUrl(Directories.config + "/quickshell/translations/").toString().replace("file://", "") + root.isScanning = true + scanLanguagesProcess.running = true + } + + Component.onCompleted: { + root.scanLanguages() + } +} diff --git a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml index 87d9b8ff..e8a096a9 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml @@ -73,7 +73,7 @@ Item { }, { name: "save", - description: qsTr("Save chat"), + description: Translation.tr("Save chat"), execute: (args) => { const joinedArgs = args.join(" ") if (joinedArgs.trim().length == 0) { @@ -85,7 +85,7 @@ Item { }, { name: "load", - description: qsTr("Load chat"), + description: Translation.tr("Load chat"), execute: (args) => { const joinedArgs = args.join(" ") if (joinedArgs.trim().length == 0) { @@ -97,7 +97,7 @@ Item { }, { name: "clear", - description: qsTr("Clear chat history"), + description: Translation.tr("Clear chat history"), execute: () => { Ai.clearMessages(); } diff --git a/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml b/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml index cb2f7e24..2ac78f5b 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml @@ -47,7 +47,7 @@ Item { // Tag suggestion description } StyledText { visible: root.showArrows && root.showTab - text: qsTr("or") + text: Translation.tr("or") font.pixelSize: Appearance.font.pixelSize.smaller } KeyboardKey { diff --git a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml index c2fd9614..a40b855a 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml @@ -19,9 +19,9 @@ Item { required property var scopeRoot anchors.fill: parent property var tabButtonList: [ - ...(Config.options.policies.ai !== 0 ? [{"icon": "neurology", "name": qsTr("Intelligence")}] : []), - {"icon": "translate", "name": qsTr("Translator")}, - ...(Config.options.policies.weeb === 1 ? [{"icon": "bookmark_heart", "name": qsTr("Anime")}] : []) + ...(Config.options.policies.ai !== 0 ? [{"icon": "neurology", "name": Translation.tr("Intelligence")}] : []), + {"icon": "translate", "name": Translation.tr("Translator")}, + ...(Config.options.policies.weeb === 1 ? [{"icon": "bookmark_heart", "name": Translation.tr("Anime")}] : []) ] property int selectedTab: 0 diff --git a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml index efc34d9f..d2c4af9c 100644 --- a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml +++ b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml @@ -17,8 +17,8 @@ Rectangle { property int selectedTab: 0 property bool collapsed: Persistent.states.sidebar.bottomGroup.collapsed property var tabs: [ - {"type": "calendar", "name": "Calendar", "icon": "calendar_month", "widget": calendarWidget}, - {"type": "todo", "name": "To Do", "icon": "done_outline", "widget": todoWidget} + {"type": "calendar", "name": Translation.tr("Calendar"), "icon": "calendar_month", "widget": calendarWidget}, + {"type": "todo", "name": Translation.tr("To Do"), "icon": "done_outline", "widget": todoWidget} ] Behavior on implicitHeight { diff --git a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml index 461a671b..c334b052 100644 --- a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml +++ b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml @@ -85,7 +85,7 @@ Item { anchors.verticalCenter: parent.verticalCenter anchors.leftMargin: 10 horizontalAlignment: Text.AlignHCenter - text: `${Notifications.list.length} notifications` + text: `${Notifications.list.length} ${Translation.tr("notifications")}` opacity: Notifications.list.length > 0 ? 1 : 0 visible: opacity > 0 diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index b294db6e..0e6254fe 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -96,8 +96,6 @@ "Run command": "Run command", "Save": "Save", "Save to Downloads": "Save to Downloads", - "Scroll to change brightness": "Scroll to change brightness", - "Scroll to change volume": "Scroll to change volume", "Search": "Search", "Search the web": "Search the web", "Search, calculate or run": "Search, calculate or run", @@ -106,8 +104,6 @@ "Set API key": "Set API key", "Set temperature (randomness) of the model. Values range between 0 to 2 for Gemini, 0 to 1 for other models. Default is 0.5.": "Set temperature (randomness) of the model. Values range between 0 to 2 for Gemini, 0 to 1 for other models. Default is 0.5.", "Set the current API provider": "Set the current API provider", - "Shell configuration created": "Shell configuration created", - "Shell configuration failed to load": "Shell configuration failed to load", "Shutdown": "Shutdown", "Silent": "Silent", "Sleep": "Sleep", @@ -169,5 +165,12 @@ "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly", "Message the model... \"{0}\" for commands": "Message the model... \"{0}\" for commands", "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}": "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}", - "Settings": "Settings" + "Settings": "Settings", + "Save chat": "Save chat", + "Load chat": "Load chat", + "or": "or", + "Set the system prompt for the model.": "Set the system prompt for the model.", + "To Do": "To Do", + "Calendar": "Calendar", + "notifications": "notifications" } \ No newline at end of file diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index 1c2f1b7b..878dc566 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -96,8 +96,6 @@ "Run command": "运行命令", "Save": "保存", "Save to Downloads": "保存到下载文件夹", - "Scroll to change brightness": "滚动调节亮度", - "Scroll to change volume": "滚动调节音量", "Search": "搜索", "Search the web": "搜索网络", "Search, calculate or run": "搜索、计算或运行", @@ -106,8 +104,6 @@ "Set API key": "设置 API 密钥", "Set temperature (randomness) of the model. Values range between 0 to 2 for Gemini, 0 to 1 for other models. Default is 0.5.": "设置模型的温度(随机性)。Gemini 模型范围为 0 到 2,其他模型为 0 到 1。默认值为 0.5。", "Set the current API provider": "设置当前 API 提供商", - "Shell configuration created": "Shell 配置已创建", - "Shell configuration failed to load": "Shell 配置加载失败", "Shutdown": "关机", "Silent": "静音", "Sleep": "睡眠", @@ -169,5 +165,12 @@ "Online via {0} | {1}'s model": "通过 {0} 在线 | {1} 的模型", "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "没有找到结果。提示:\n- 检查您的标签和 NSFW 设置\n- 如果没有想到标签,请输入页码", "Online | Google's model\nGives up-to-date information with search.": "在线 | Google 模型\n通过搜索提供最新信息。", - "Settings": "设置" + "Settings": "设置", + "Save chat": "保存对话", + "Load chat": "加载对话", + "or": "或", + "Set the system prompt for the model.": "为模型设置系统提示。", + "To Do": "待办", + "Calendar": "日历", + "notifications": "条通知" } \ No newline at end of file From 1641425fffd05591c214d4b5094174011a3a4406 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 12 Jul 2025 22:37:38 +0700 Subject: [PATCH 206/328] reapply bar corner transparency fix --- .config/quickshell/ii/modules/bar/Bar.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml index eeb77f99..7c7f675d 100644 --- a/.config/quickshell/ii/modules/bar/Bar.qml +++ b/.config/quickshell/ii/modules/bar/Bar.qml @@ -533,7 +533,6 @@ Scope { size: Appearance.rounding.screenRounding color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - opacity: 1.0 - Appearance.transparency corner: RoundCorner.CornerEnum.TopLeft states: State { @@ -553,7 +552,6 @@ Scope { } size: Appearance.rounding.screenRounding color: showBarBackground ? Appearance.colors.colLayer0 : "transparent" - opacity: 1.0 - Appearance.transparency corner: RoundCorner.CornerEnum.TopRight states: State { From 59afc892f4978bcb206e85ee7b1b46c88cf6d8dd Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 12 Jul 2025 22:42:25 +0700 Subject: [PATCH 207/328] Revert "bar: use lazyloader" too lazy so revert, bar needed in most cases anyway --- .config/quickshell/ii/modules/bar/Bar.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml index 7c7f675d..27d5a6de 100644 --- a/.config/quickshell/ii/modules/bar/Bar.qml +++ b/.config/quickshell/ii/modules/bar/Bar.qml @@ -37,11 +37,11 @@ Scope { return screens; return screens.filter(screen => list.includes(screen.name)); } - LazyLoader { + Loader { id: barLoader - activeAsync: GlobalStates.barOpen + active: GlobalStates.barOpen required property ShellScreen modelData - component: PanelWindow { // Bar window + sourceComponent: PanelWindow { // Bar window id: barRoot screen: barLoader.modelData From e98f84d9bc34d2bc182d508ceabf30a561af9c9b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 13 Jul 2025 00:20:58 +0700 Subject: [PATCH 208/328] bar: fix media title spilling for non-verbose --- .config/quickshell/ii/modules/bar/Media.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/ii/modules/bar/Media.qml b/.config/quickshell/ii/modules/bar/Media.qml index 9e7ff96c..dfad0e20 100644 --- a/.config/quickshell/ii/modules/bar/Media.qml +++ b/.config/quickshell/ii/modules/bar/Media.qml @@ -68,6 +68,7 @@ Item { } StyledText { + visible: Config.options.bar.verbose width: rowLayout.width - (CircularProgress.size + rowLayout.spacing * 2) Layout.alignment: Qt.AlignVCenter Layout.fillWidth: true // Ensures the text takes up available space From f726c9495e61b2ecc0250ffbfe92a8d48e149b31 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 13 Jul 2025 01:53:40 +0700 Subject: [PATCH 209/328] media controls: fix black color on first open --- .config/quickshell/ii/modules/mediaControls/PlayerControl.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml b/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml index 9cce0111..b58bd742 100644 --- a/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml +++ b/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml @@ -23,7 +23,7 @@ Item { // Player instance property string artDownloadLocation: Directories.coverArt property string artFileName: Qt.md5(artUrl) + ".jpg" property string artFilePath: `${artDownloadLocation}/${artFileName}` - property color artDominantColor: ColorUtils.mix(colorQuantizer?.colors[0], Appearance.colors.colPrimaryContainer, 0.8) || Appearance.m3colors.m3secondaryContainer + property color artDominantColor: ColorUtils.mix((colorQuantizer?.colors[0] ?? Appearance.colors.colPrimary), Appearance.colors.colPrimaryContainer, 0.8) || Appearance.m3colors.m3secondaryContainer property bool downloaded: false property list visualizerPoints: [] property real maxVisualizerValue: 1000 // Max value in the data points From a5831cf3657dc91e92cf6a9fbf48858343485b1d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 13 Jul 2025 01:54:13 +0700 Subject: [PATCH 210/328] slider: more accurate sizes --- .../modules/common/widgets/StyledSlider.qml | 120 ++++++++++++------ 1 file changed, 81 insertions(+), 39 deletions(-) diff --git a/.config/quickshell/ii/modules/common/widgets/StyledSlider.qml b/.config/quickshell/ii/modules/common/widgets/StyledSlider.qml index ca098003..93fe43f3 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledSlider.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledSlider.qml @@ -6,26 +6,53 @@ import QtQuick.Controls import QtQuick.Layouts import Quickshell.Widgets -// Material 3 slider. See https://m3.material.io/components/sliders/overview +/** + * Material 3 slider. See https://m3.material.io/components/sliders/overview + * It doesn't exactly match the spec because it does not make sense to have stuff on a computer that fucking huge. + * Should be at 3/4 scale... + */ + Slider { id: root - property real scale: 0.85 - property real backgroundDotSize: 4 * scale - property real backgroundDotMargins: 4 * scale - // property real handleMargins: 0 * scale - property real handleMargins: (root.pressed ? 0 : 2) * scale - property real handleWidth: (root.pressed ? 3 : 5) * scale - property real handleHeight: 44 * scale - property real handleLimit: root.backgroundDotMargins - property real trackHeight: 30 * scale + + property list stopIndicatorValues: [1] + enum Configuration { + XS = 12, + S = 18, + M = 30, + L = 42, + XL = 72 + } + + property var configuration: StyledSlider.Configuration.S + + property real handleDefaultWidth: 3 + property real handlePressedWidth: 1.5 + property color highlightColor: Appearance.colors.colPrimary property color trackColor: Appearance.colors.colSecondaryContainer property color handleColor: Appearance.m3colors.m3onSecondaryContainer - property real trackRadius: Appearance.rounding.verysmall * scale + property color dotColor: Appearance.m3colors.m3onSecondaryContainer + property color dotColorHighlighted: Appearance.m3colors.m3onPrimary property real unsharpenRadius: Appearance.rounding.unsharpen - - property real limitedHandleRangeWidth: (root.availableWidth - handleWidth - root.handleLimit * 2) + property real trackWidth: configuration + property real trackRadius: trackWidth >= StyledSlider.Configuration.XL ? 21 + : trackWidth >= StyledSlider.Configuration.L ? 12 + : trackWidth >= StyledSlider.Configuration.M ? 9 + : 6 + property real handleHeight: Math.max(33, trackWidth + 9) + property real handleWidth: root.pressed ? handlePressedWidth : handleDefaultWidth + property real handleMargins: 4 + onHandleMarginsChanged: { + console.log("Handle margins changed to", handleMargins); + } + property real trackDotSize: 3 property string tooltipContent: `${Math.round(value * 100)}%` + + leftPadding: handleMargins + rightPadding: handleMargins + property real effectiveDraggingWidth: width - leftPadding - rightPadding + Layout.fillWidth: true from: 0 to: 1 @@ -37,10 +64,20 @@ Slider { } Behavior on handleMargins { - NumberAnimation { - duration: Appearance.animation.elementMoveFast.duration - easing.type: Appearance.animation.elementMoveFast.type - easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + + component TrackDot: Rectangle { + required property real value + anchors.verticalCenter: parent.verticalCenter + x: root.handleMargins + (value * root.effectiveDraggingWidth) - (root.trackDotSize / 2) + width: root.trackDotSize + height: root.trackDotSize + radius: Appearance.rounding.full + color: value > root.visualPosition ? root.dotColor : root.dotColorHighlighted + + Behavior on color { + animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) } } @@ -52,14 +89,17 @@ Slider { background: Item { anchors.verticalCenter: parent.verticalCenter - implicitHeight: trackHeight + width: parent.width + implicitHeight: trackWidth // Fill left Rectangle { - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - width: root.handleLimit * 2 + root.visualPosition * root.limitedHandleRangeWidth - (root.handleMargins + root.handleWidth / 2) - height: trackHeight + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + } + width: root.handleMargins + (root.visualPosition * root.effectiveDraggingWidth) - (root.handleWidth / 2 + root.handleMargins) + height: trackWidth color: root.highlightColor topLeftRadius: root.trackRadius bottomLeftRadius: root.trackRadius @@ -69,35 +109,37 @@ Slider { // Fill right Rectangle { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - width: root.handleLimit * 2 + (1 - root.visualPosition) * root.limitedHandleRangeWidth - (root.handleMargins + root.handleWidth / 2) - height: trackHeight + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + } + width: root.handleMargins + ((1 - root.visualPosition) * root.effectiveDraggingWidth) - (root.handleWidth / 2 + root.handleMargins) + height: trackWidth color: root.trackColor - topLeftRadius: root.unsharpenRadius - bottomLeftRadius: root.unsharpenRadius topRightRadius: root.trackRadius bottomRightRadius: root.trackRadius + topLeftRadius: root.unsharpenRadius + bottomLeftRadius: root.unsharpenRadius } - // Dot at the end - Rectangle { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: root.backgroundDotMargins - width: root.backgroundDotSize - height: root.backgroundDotSize - radius: Appearance.rounding.full - color: root.handleColor + // Stop indicators + Repeater { + model: root.stopIndicatorValues + TrackDot { + required property real modelData + value: modelData + anchors.verticalCenter: parent.verticalCenter + } } } handle: Rectangle { id: handle - x: root.leftPadding + root.handleLimit + root.visualPosition * root.limitedHandleRangeWidth - y: root.topPadding + root.availableHeight / 2 - height / 2 + implicitWidth: root.handleWidth implicitHeight: root.handleHeight + x: root.handleMargins + (root.visualPosition * root.effectiveDraggingWidth) - (root.handleWidth / 2) + anchors.verticalCenter: parent.verticalCenter radius: Appearance.rounding.full color: root.handleColor From 66d1d3e9c35163693c0d2520e84b15b7632b073a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 13 Jul 2025 01:54:30 +0700 Subject: [PATCH 211/328] volume mixer: adjust layout --- .../volumeMixer/VolumeMixerEntry.qml | 73 ++++++++++--------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml index c4600c7b..84cb572c 100644 --- a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml +++ b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml @@ -11,55 +11,56 @@ import Quickshell.Services.Pipewire Item { id: root - required property PwNode node; - PwObjectTracker { objects: [ node ] } + required property PwNode node + PwObjectTracker { + objects: [node] + } implicitHeight: rowLayout.implicitHeight RowLayout { id: rowLayout anchors.fill: parent - spacing: 10 + spacing: 6 + + Image { + property real size: slider.height * 0.9 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + visible: source != "" + sourceSize.width: size + sourceSize.height: size + source: { + let icon; + icon = AppSearch.guessIcon(root.node.properties["application.icon-name"]); + if (AppSearch.iconExists(icon)) + return Quickshell.iconPath(icon, "image-missing"); + icon = AppSearch.guessIcon(root.node.properties["node.name"]); + return Quickshell.iconPath(icon, "image-missing"); + } + } ColumnLayout { Layout.fillWidth: true - spacing: 0 + spacing: -4 - RowLayout { - StyledText { - Layout.fillWidth: true - font.pixelSize: Appearance.font.pixelSize.normal - elide: Text.ElideRight - text: { - // application.name -> description -> name - const app = root.node.properties["application.name"] ?? (root.node.description != "" ? root.node.description : root.node.name); - const media = root.node.properties["media.name"]; - return media != undefined ? `${app} • ${media}` : app; - } + StyledText { + Layout.fillWidth: true + font.pixelSize: Appearance.font.pixelSize.small + color: Appearance.colors.colSubtext + elide: Text.ElideRight + text: { + // application.name -> description -> name + const app = root.node.properties["application.name"] ?? (root.node.description != "" ? root.node.description : root.node.name); + const media = root.node.properties["media.name"]; + return media != undefined ? `${app} • ${media}` : app; } } - RowLayout { - Image { - property real size: slider.trackHeight * 1.3 - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - visible: source != "" - sourceSize.width: size - sourceSize.height: size - source: { - let icon; - icon = AppSearch.guessIcon(root.node.properties["application.icon-name"]); - if (AppSearch.iconExists(icon)) return Quickshell.iconPath(icon, "image-missing"); - icon = AppSearch.guessIcon(root.node.properties["node.name"]); - return Quickshell.iconPath(icon, "image-missing"); - } - } - StyledSlider { - id: slider - value: root.node.audio.volume - onValueChanged: root.node.audio.volume = value - } + StyledSlider { + id: slider + value: root.node.audio.volume + onValueChanged: root.node.audio.volume = value } } } -} \ No newline at end of file +} From 99af57fbc6675bcf9187f23acb28589956c97e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Sun, 13 Jul 2025 13:14:02 +0800 Subject: [PATCH 212/328] Updated Chinese translation --- .config/quickshell/translations/zh_CN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index 878dc566..0242aa2d 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -58,7 +58,7 @@ "Hold to show workspace numbers, release to show icons": "按住显示工作区编号,松开显示图标", "Increase brightness": "提高亮度", "Input": "输入", - "Intelligence": "智能", + "Intelligence": "智能体", "Interface": "界面", "Invalid arguments. Must provide `key` and `value`.": "参数无效。必须提供 `key` 和 `value`。", "Jump to current month": "跳转到当前月份", From bdb7657e22e175307a28493c1b9c831f9dca5b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Sun, 13 Jul 2025 13:19:53 +0800 Subject: [PATCH 213/328] i18n:Update the translation tool guide --- .../tools/translation-tools-guide.md | 395 ++++++++++-------- 1 file changed, 218 insertions(+), 177 deletions(-) diff --git a/.config/quickshell/translations/tools/translation-tools-guide.md b/.config/quickshell/translations/tools/translation-tools-guide.md index 52757632..96165b99 100644 --- a/.config/quickshell/translations/tools/translation-tools-guide.md +++ b/.config/quickshell/translations/tools/translation-tools-guide.md @@ -1,246 +1,287 @@ # Translation Management Tool Suite -This tool suite is used to manage project translation files, automatically extract translatable texts, compare differences between different language files, and provide maintenance functions. +This suite is used to manage project translation files, automatically extract translatable texts, compare differences between language files, and provide maintenance functions. ## Tool Components ### 1. `translation-manager.py` - Main Translation Manager - Extract translatable texts - Compare and update translation files -- Interactive adding/removing translation keys +- Interactive addition/removal of translation keys ### 2. `translation-cleaner.py` - Translation File Maintenance Tool - Clean unused translation keys -- Sync key structure across different language files +- Synchronize key structure across different language files ### 3. `manage-translations.sh` - Convenient Wrapper Script -- Provide unified command-line interface -- Display translation status -- Simplify common operations +- Provides a unified command-line interface +- Displays translation status +- Simplifies common operations ## Quick Start -### Check Translation Status +### Using the Wrapper Script (Recommended) + ```bash +# Enter the tools directory +cd .config/quickshell/translations/tools + +# Show help +./manage-translations.sh --help + +# Show current translation status ./manage-translations.sh status -``` -### Extract Translatable Texts -```bash +# Extract translatable texts ./manage-translations.sh extract -``` -### Update Translation Files -```bash -# Update all languages +# Update all translation files ./manage-translations.sh update -# Update specific language +# Update a specific language ./manage-translations.sh update -l zh_CN -``` -### Clean Unused Keys -```bash +# Clean unused keys ./manage-translations.sh clean + +# Synchronize keys across all language files +./manage-translations.sh sync ``` -### Sync Keys Across Languages +Or run from the project root: ```bash -./manage-translations.sh sync +# Run from the project root +.config/quickshell/translations/tools/manage-translations.sh status +.config/quickshell/translations/tools/manage-translations.sh update ``` ## Detailed Usage -### translation-manager.py +### Translation Manager (`translation-manager.py`) -The main translation management tool that extracts translatable texts from source code and manages translation files. - -#### Command Line Options +Basic usage: ```bash -python3 translation-manager.py [options] +# Process all languages +./translation-manager.py -Options: - -h, --help Show help message - -t, --translations-dir DIR Translation files directory (default: .config/quickshell/translations) - -s, --source-dir DIR Source code directory (default: .config/quickshell) - -l, --language LANG Specify language code to process (e.g., zh_CN) - -e, --extract-only Only extract translatable texts to temporary file - --show-temp Show temporary extracted file content +# Specify a particular language +./translation-manager.py --language zh_CN + +# Extract translatable texts only +./translation-manager.py --extract-only + +# Show extracted texts +./translation-manager.py --extract-only --show-temp ``` -#### Features -1. **Text Extraction**: Uses regex patterns to extract translatable texts from QML and JavaScript files -2. **Smart Filtering**: Automatically removes duplicates and cleans up extracted texts -3. **Interactive Updates**: Guides users through adding missing keys and removing extra ones -4. **Backup Support**: Creates backups before making changes +Parameter description: +- `--translations-dir`, `-t`: Translation files directory (default: `.config/quickshell/translations`) +- `--source-dir`, `-s`: Source code directory (default: `.config/quickshell`) +- `--language`, `-l`: Specify the language code to process +- `--extract-only`, `-e`: Only extract translatable texts +- `--show-temp`: Show the content of the temporary extraction file -#### Supported Text Patterns -- `qsTr("text")` and `qsTr('text')` -- `i18n.t("text")` and `i18n.t('text')` -- Supports nested quotes and escape characters -- Handles multiline strings +### Translation Cleaner (`translation-cleaner.py`) -### translation-cleaner.py - -A maintenance tool for cleaning up and synchronizing translation files. - -#### Command Line Options ```bash -python3 translation-cleaner.py [options] +# Clean unused translation keys +./translation-cleaner.py --clean -Options: - -h, --help Show help message - -t, --translations-dir DIR Translation files directory - -s, --source-dir DIR Source code directory - -c, --clean Clean unused translation keys - --sync Sync translation keys - --source-lang LANG Source language for syncing (default: en_US) - --no-backup Do not create backup files when cleaning +# Synchronize translation keys (using en_US as the base) +./translation-cleaner.py --sync + +# Specify a different source language for syncing +./translation-cleaner.py --sync --source-lang zh_CN + +# Clean without creating backups +./translation-cleaner.py --clean --no-backup ``` -#### Features -1. **Unused Key Cleanup**: Identifies and removes translation keys that are no longer used in the source code -2. **Key Synchronization**: Ensures all language files have the same set of keys -3. **Backup Protection**: Creates backup files before making destructive changes -4. **Interactive Confirmation**: Asks for user confirmation before deleting keys +## Workflow -### manage-translations.sh +### Regular Translation Update Workflow -A convenient wrapper script that provides a unified interface to all translation tools. +1. **Check status**: + ```bash + ./manage-translations.sh status + ``` + +2. **Update translations**: + ```bash + ./manage-translations.sh update + ``` + +3. **Clean unused keys** (optional): + ```bash + ./manage-translations.sh clean + ``` + +### Adding a New Language + +1. **Create a new language file**: + ```bash + ./manage-translations.sh update -l new_lang + ``` + +2. **Synchronize key structure**: + ```bash + ./manage-translations.sh sync + ``` + +### Cleanup After Large Refactoring + +1. **Backup translation files**: + ```bash + cp -r .config/quickshell/translations .config/quickshell/translations.backup + ``` + +2. **Clean unused keys**: + ```bash + ./manage-translations.sh clean + ``` + +3. **Synchronize all languages**: + ```bash + ./manage-translations.sh sync + ``` + +## Supported Translatable Text Formats + +The tool recognizes the following formats for translatable texts: + +```qml +// Basic format +Translation.tr("Hello, world!") +Translation.tr('Hello, world!') +Translation.tr(`Hello, world!`) + +// With line breaks +Translation.tr("Line 1\nLine 2") + +// With escape characters +Translation.tr("Say \"Hello\"") + +// With parameter placeholders +Translation.tr("Hello, %1!").arg(name) +Translation.tr("{0} files selected").arg(count) +``` + +## Example Output + +### Status Display +``` +$ ./manage-translations.sh status +Analyzing translation status... +=== Current Project Status === +166 translatable texts extracted + +=== Translation File Status === + en_US: 470 keys + zh_CN: 470 keys +``` + +### Update Translations +``` +$ ./manage-translations.sh update -l zh_CN +Updating translation files... +================================================== +Processing language: zh_CN +================================================== +Analysis result: + Missing keys: 5 + Extra keys: 20 + +Found 5 missing translation keys: +1. "New feature text" +2. "Another new text" +... + +Add these 5 missing keys? (y/n): y +5 keys added + +Found 20 extra translation keys: +1. "Removed old text" -> "已删除的旧文本" +... + +Delete these 20 extra keys? (y/n): y +20 keys deleted + +Translation file saved +``` + +### Clean Unused Keys +``` +$ ./manage-translations.sh clean +Cleaning unused translation keys... +Processing language: zh_CN +Found 50 unused keys: + 1. "old_unused_text" + 2. "deprecated_message" + ... + +Delete these 50 unused keys? (y/n): y +50 keys deleted +Original key count: 470, after cleaning: 420 +``` + +## Advanced Features + +### Custom Directory Structure -#### Commands ```bash -./manage-translations.sh [options] - -Commands: - extract Extract translatable texts to temporary file - update Update translation files (add missing/remove extra keys) - clean Clean unused translation keys - sync Sync keys across all language files - status Show translation status - -Options: - -l, --lang LANG Specify language (e.g.: zh_CN) - -t, --trans-dir DIR Translation files directory - -s, --source-dir DIR Source code directory - -h, --help Show help message +# Use custom directories +./translation-manager.py \ + --translations-dir /path/to/translations \ + --source-dir /path/to/source ``` -## Workflow Examples +### Batch Processing -### Initial Setup -1. Create translation directory structure -2. Extract all translatable texts: `./manage-translations.sh extract` -3. Create initial translation files: `./manage-translations.sh update` +```bash +# Create a processing script +cat > update-all-translations.sh << 'EOF' +#!/bin/bash +for lang in zh_CN ja_JP ko_KR; do + echo "Processing $lang..." + ./manage-translations.sh update -l $lang +done +EOF -### Regular Maintenance -1. Check status: `./manage-translations.sh status` -2. Update translations after code changes: `./manage-translations.sh update` -3. Clean up unused keys periodically: `./manage-translations.sh clean` - -### Adding New Language -1. Create new language file: `./manage-translations.sh update -l new_lang` -2. Sync keys if needed: `./manage-translations.sh sync` - -## File Structure - -``` -translations/ -├── tools/ # Translation management tools -│ ├── translation-manager.py # Main extraction and update tool -│ ├── translation-cleaner.py # Cleanup and sync tool -│ ├── manage-translations.sh # Wrapper script -│ └── translation-tools-guide.md # This documentation -├── en_US.json # English translations (reference) -├── zh_CN.json # Chinese translations -└── [other_lang].json # Other language files +chmod +x update-all-translations.sh +./update-all-translations.sh ``` -## Configuration +## Notes -### Text Extraction Patterns +1. **Backup is important**: The tool automatically creates backups before cleaning, but it is recommended to manually back up important files -The tool uses regex patterns to identify translatable texts. Current patterns include: +2. **Text extraction limitations**: + - Only supports static strings, not dynamically constructed strings + - Must use the `Translation.tr()` format -1. **QML qsTr patterns**: - - `qsTr("text")` and `qsTr('text')` - - Supports escaped quotes and nested quotes +3. **File encoding**: All files must use UTF-8 encoding -2. **JavaScript i18n patterns**: - - `i18n.t("text")` and `i18n.t('text')` - - Supports template literals and complex expressions - -3. **Custom patterns** can be added by modifying the patterns list in `translation-manager.py` - -### File Extensions - -By default, the tool processes: -- `.qml` files (QML/QtQuick) -- `.js` files (JavaScript) - -Additional file types can be added by modifying the file extension filters. - -## Best Practices - -1. **Regular Updates**: Run `./manage-translations.sh status` regularly to check for new translatable texts -2. **Clean Periodically**: Use `./manage-translations.sh clean` to remove unused keys -3. **Backup Important**: Always backup translation files before major changes -4. **Consistent Patterns**: Use consistent function calls (`qsTr`, `i18n.t`) for translatable texts -5. **Review Changes**: Always review the changes before confirming deletions or additions +4. **Key naming conventions**: It is recommended to use English for key names and avoid special characters ## Troubleshooting ### Common Issues -1. **Missing Texts**: If some translatable texts are not extracted, check if they match the supported patterns -2. **Path Issues**: Ensure the source and translation directory paths are correct -3. **Permission Errors**: Make sure the script has write permissions to the translation directory -4. **Encoding Issues**: All files should be saved in UTF-8 encoding +**Q: The number of extracted texts does not match expectations?** +A: Check whether all translatable texts use the `Translation.tr()` format and ensure there are no dynamically constructed strings. -### Getting Help +**Q: Some translations are missing after syncing?** +A: Check whether the source language file contains all necessary keys, and consider using a different source language for syncing. -For additional help: -- Use `--help` option with any tool -- Check the console output for error messages -- Verify file paths and permissions +**Q: The cleaning operation deleted needed keys?** +A: Restore from the automatically created backup file and check whether `Translation.tr()` is used correctly in the source code. -## Advanced Usage - -### Custom Regex Patterns - -To add support for new translation function patterns, modify the `patterns` list in `TranslationManager.extract_translatable_texts()`: - -```python -patterns = [ - # Existing patterns... - r'customTranslate\s*\(\s*(["\'])((?:\\.|(?!\1)[^\\])*?)\1\s*\)', # Custom pattern -] -``` - -### Batch Processing - -For processing multiple projects or directories: +### Restore Backup ```bash -# Process multiple directories -for dir in project1 project2 project3; do - ./manage-translations.sh -s "$dir" -t "$dir/translations" update -done +# Restore a single file +cp .config/quickshell/translations/zh_CN.json.backup .config/quickshell/translations/zh_CN.json + +# Restore all files +cp .config/quickshell/translations.backup/* .config/quickshell/translations/ ``` - -### Integration with Build Systems - -The tools can be integrated into build systems to automatically update translations: - -```bash -# In your build script -./manage-translations.sh update --non-interactive -``` - -## Version History - -- **v1.0**: Initial version with basic extraction and update functionality -- **v1.1**: Added improved regex patterns for better text extraction -- **v1.2**: Added cleaning and synchronization tools -- **v1.3**: Added English output and improved user interface -- **v1.4**: Moved all tools to dedicated tools directory and improved documentation From 0c2b807447a94ac7bce58c4f117a9c2a3485c5c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Sun, 13 Jul 2025 15:24:29 +0800 Subject: [PATCH 214/328] i18n: update translations/tools/README.md --- .../quickshell/translations/tools/README.md | 305 ++++++++++++++---- 1 file changed, 241 insertions(+), 64 deletions(-) diff --git a/.config/quickshell/translations/tools/README.md b/.config/quickshell/translations/tools/README.md index 1840f6c3..e41c742e 100644 --- a/.config/quickshell/translations/tools/README.md +++ b/.config/quickshell/translations/tools/README.md @@ -1,111 +1,288 @@ -# Translation Management Tools +# Translation Management Tool Suite -This directory contains a toolset for managing project translation files. +This suite is used to manage project translation files, automatically extract translatable texts, compare differences between language files, and provide maintenance functions. -## Directory Structure +## Tool Components -``` -translations/ -├── tools/ # Translation management tools directory -│ ├── translation-manager.py # Main translation manager -│ ├── translation-cleaner.py # Translation maintenance tool -│ ├── manage-translations.sh # Convenient wrapper script -│ ├── translation-tools-guide.md # Detailed usage documentation -│ └── README.md # This file -├── en_US.json # English translation file -├── zh_CN.json # Chinese translation file -└── ... # Other language files -``` +### 1. `translation-manager.py` - Main Translation Manager +- Extract translatable texts +- Compare and update translation files +- Interactive addition/removal of translation keys + +### 2. `translation-cleaner.py` - Translation File Maintenance Tool +- Clean unused translation keys +- Synchronize key structure across different language files + +### 3. `manage-translations.sh` - Convenient Wrapper Script +- Provides a unified command-line interface +- Displays translation status +- Simplifies common operations ## Quick Start -### Running from tools directory +### Using the Wrapper Script (Recommended) ```bash -# Enter tools directory +# Enter the tools directory cd .config/quickshell/translations/tools -# Check current translation status +# Show help +./manage-translations.sh --help + +# Show current translation status ./manage-translations.sh status +# Extract translatable texts +./manage-translations.sh extract + # Update all translation files ./manage-translations.sh update -# Update specific language +# Update a specific language ./manage-translations.sh update -l zh_CN # Clean unused keys ./manage-translations.sh clean -# Sync all language files +# Synchronize keys across all language files ./manage-translations.sh sync ``` -### Running from project root directory - +Or run from the project root: ```bash -# Run from project root directory (recommended to use relative paths) +# Run from the project root .config/quickshell/translations/tools/manage-translations.sh status .config/quickshell/translations/tools/manage-translations.sh update ``` -## Tool Description +## Detailed Usage -### 🛠️ `manage-translations.sh` - Main Entry Point -Convenient command-line interface that integrates all translation management functions. +### Translation Manager (`translation-manager.py`) -### 🔍 `translation-manager.py` - Core Manager -- Extract translatable texts -- Compare translation file differences -- Interactive translation updates - -### 🧹 `translation-cleaner.py` - Maintenance Tool -- Clean unused translation keys -- Sync language file structure -- Create backup files - -## Common Workflows - -### After adding new translatable texts +Basic usage: ```bash -./manage-translations.sh update +# Process all languages +./translation-manager.py + +# Specify a particular language +./translation-manager.py --language zh_CN + +# Extract translatable texts only +./translation-manager.py --extract-only + +# Show extracted texts +./translation-manager.py --extract-only --show-temp ``` -### Clean up after code refactoring +Parameter description: +- `--translations-dir`, `-t`: Translation files directory (default: `.config/quickshell/translations`) +- `--source-dir`, `-s`: Source code directory (default: `.config/quickshell`) +- `--language`, `-l`: Specify the language code to process +- `--extract-only`, `-e`: Only extract translatable texts +- `--show-temp`: Show the content of the temporary extraction file + +### Translation Cleaner (`translation-cleaner.py`) + ```bash -./manage-translations.sh clean +# Clean unused translation keys +./translation-cleaner.py --clean + +# Synchronize translation keys (using en_US as the base) +./translation-cleaner.py --sync + +# Specify a different source language for syncing +./translation-cleaner.py --sync --source-lang zh_CN + +# Clean without creating backups +./translation-cleaner.py --clean --no-backup ``` -### Add new language -```bash -./manage-translations.sh update -l new_language_code -``` +## Workflow -### Check translation status -```bash -./manage-translations.sh status -``` +### Regular Translation Update Workflow -## Documentation +1. **Check status**: + ```bash + ./manage-translations.sh status + ``` -- 📖 [Detailed Usage Guide](./translation-tools-guide.md) +2. **Update translations**: + ```bash + ./manage-translations.sh update + ``` -## Important Notes +3. **Clean unused keys** (optional): + ```bash + ./manage-translations.sh clean + ``` -1. **Running Location**: Tools automatically detect relative paths, can be run from tools directory or project root -2. **Backup**: Cleanup operations automatically create backup files -3. **Encoding**: All files use UTF-8 encoding -4. **Permissions**: Ensure scripts have execution permissions +### Adding a New Language -## Supported Translation Formats +1. **Create a new language file**: + ```bash + ./manage-translations.sh update -l new_lang + ``` + +2. **Synchronize key structure**: + ```bash + ./manage-translations.sh sync + ``` + +### Cleanup After Large Refactoring + +1. **Backup translation files**: + ```bash + cp -r .config/quickshell/translations .config/quickshell/translations.backup + ``` + +2. **Clean unused keys**: + ```bash + ./manage-translations.sh clean + ``` + +3. **Synchronize all languages**: + ```bash + ./manage-translations.sh sync + ``` + +## Supported Translatable Text Formats + +The tool recognizes the following formats for translatable texts: -The tool recognizes translatable texts in the following formats: ```qml -qsTr("Your text here") -qsTr('Single quotes work too') -i18n.t("JavaScript translations") +// Basic format +Translation.tr("Hello, world!") +Translation.tr('Hello, world!') +Translation.tr(`Hello, world!`) + +// With line breaks +Translation.tr("Line 1\nLine 2") + +// With escape characters +Translation.tr("Say \"Hello\"") + +// With parameter placeholders +Translation.tr("Hello, %1!").arg(name) +Translation.tr("{0} files selected").arg(count) ``` ---- +## Example Output + +### Status Display +``` +$ ./manage-translations.sh status +Analyzing translation status... +=== Current Project Status === +166 translatable texts extracted + +=== Translation File Status === + en_US: 470 keys + zh_CN: 470 keys +``` + +### Update Translations +``` +$ ./manage-translations.sh update -l zh_CN +Updating translation files... +================================================== +Processing language: zh_CN +================================================== +Analysis result: + Missing keys: 5 + Extra keys: 20 + +Found 5 missing translation keys: +1. "New feature text" +2. "Another new text" +... + +Add these 5 missing keys? (y/n): y +5 keys added + +Found 20 extra translation keys: +1. "Removed old text" -> "已删除的旧文本" +... + +Delete these 20 extra keys? (y/n): y +20 keys deleted + +Translation file saved +``` + +### Clean Unused Keys +``` +$ ./manage-translations.sh clean +Cleaning unused translation keys... +Processing language: zh_CN +Found 50 unused keys: + 1. "old_unused_text" + 2. "deprecated_message" + ... + +Delete these 50 unused keys? (y/n): y +50 keys deleted +Original key count: 470, after cleaning: 420 +``` + +## Advanced Features + +### Custom Directory Structure + +```bash +# Use custom directories +./translation-manager.py \ + --translations-dir /path/to/translations \ + --source-dir /path/to/source +``` + +### Batch Processing + +```bash +# Create a processing script +cat > update-all-translations.sh << 'EOF' +#!/bin/bash +for lang in zh_CN ja_JP ko_KR; do + echo "Processing $lang..." + ./manage-translations.sh update -l $lang +done +EOF + +chmod +x update-all-translations.sh +./update-all-translations.sh +``` + +## Notes + +1. **Backup is important**: The tool automatically creates backups before cleaning, but it is recommended to manually back up important files + +2. **Text extraction limitations**: + - Only supports static strings, not dynamically constructed strings + - Must use the `Translation.tr()` format + +3. **File encoding**: All files must use UTF-8 encoding + +4. **Key naming conventions**: It is recommended to use English for key names and avoid special characters + +## Troubleshooting + +### Common Issues + +**Q: The number of extracted texts does not match expectations?** +A: Check whether all translatable texts use the `Translation.tr()` format and ensure there are no dynamically constructed strings. + +**Q: Some translations are missing after syncing?** +A: Check whether the source language file contains all necessary keys, and consider using a different source language for syncing. + +**Q: The cleaning operation deleted needed keys?** +A: Restore from the automatically created backup file and check whether `Translation.tr()` is used correctly in the source code. + +### Restore Backup + +```bash +# Restore a single file +cp .config/quickshell/translations/zh_CN.json.backup .config/quickshell/translations/zh_CN.json + +# Restore all files +cp .config/quickshell/translations.backup/* .config/quickshell/translations/ +``` -If you have any issues, please refer to the detailed documentation or check error messages in script output. From 8f3b2474d20b6871ad18a2cce9468334291fb871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Mon, 14 Jul 2025 00:33:03 +0800 Subject: [PATCH 215/328] i18n: Add multilingual support for the Settings interface and update the Simplified Chinese translation file. --- .../widgets/LightDarkPreferenceButton.qml | 3 +- .../quickshell/ii/modules/settings/About.qml | 22 +-- .../ii/modules/settings/AdvancedConfig.qml | 12 +- .../ii/modules/settings/InterfaceConfig.qml | 100 ++++++------- .../ii/modules/settings/ServicesConfig.qml | 62 ++++----- .../ii/modules/settings/StyleConfig.qml | 56 ++++---- .config/quickshell/ii/settings.qml | 14 +- .config/quickshell/ii/welcome.qml | 56 ++++---- .config/quickshell/translations/en_US.json | 131 +++++++++++++++++- .config/quickshell/translations/zh_CN.json | 131 +++++++++++++++++- 10 files changed, 423 insertions(+), 164 deletions(-) diff --git a/.config/quickshell/ii/modules/common/widgets/LightDarkPreferenceButton.qml b/.config/quickshell/ii/modules/common/widgets/LightDarkPreferenceButton.qml index 1733bca3..69db7567 100644 --- a/.config/quickshell/ii/modules/common/widgets/LightDarkPreferenceButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/LightDarkPreferenceButton.qml @@ -1,3 +1,4 @@ +import "root:/" import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/color_utils.js" as ColorUtils @@ -115,7 +116,7 @@ GroupButton { } StyledText { Layout.fillWidth: true - text: dark ? "Dark" : "Light" + text: dark ? Translation.tr("Dark") : Translation.tr("Light") color: lightDarkButtonRoot.toggled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer2 horizontalAlignment: Text.AlignHCenter } diff --git a/.config/quickshell/ii/modules/settings/About.qml b/.config/quickshell/ii/modules/settings/About.qml index dc1c93d7..4db99b68 100644 --- a/.config/quickshell/ii/modules/settings/About.qml +++ b/.config/quickshell/ii/modules/settings/About.qml @@ -12,7 +12,7 @@ ContentPage { forceWidth: true ContentSection { - title: "Distro" + title: Translation.tr("Distro") RowLayout { Layout.alignment: Qt.AlignHCenter @@ -48,21 +48,21 @@ ContentPage { RippleButtonWithIcon { materialIcon: "auto_stories" - mainText: "Documentation" + mainText: Translation.tr("Documentation") onClicked: { Qt.openUrlExternally(SystemInfo.documentationUrl) } } RippleButtonWithIcon { materialIcon: "support" - mainText: "Help & Support" + mainText: Translation.tr("Help & Support") onClicked: { Qt.openUrlExternally(SystemInfo.supportUrl) } } RippleButtonWithIcon { materialIcon: "bug_report" - mainText: "Report a Bug" + mainText: Translation.tr("Report a Bug") onClicked: { Qt.openUrlExternally(SystemInfo.bugReportUrl) } @@ -70,7 +70,7 @@ ContentPage { RippleButtonWithIcon { materialIcon: "policy" materialIconFill: false - mainText: "Privacy Policy" + mainText: Translation.tr("Privacy Policy") onClicked: { Qt.openUrlExternally(SystemInfo.privacyPolicyUrl) } @@ -80,7 +80,7 @@ ContentPage { } ContentSection { - title: "Dotfiles" + title: Translation.tr("Dotfiles") RowLayout { Layout.alignment: Qt.AlignHCenter @@ -95,7 +95,7 @@ ContentPage { Layout.alignment: Qt.AlignVCenter // spacing: 10 StyledText { - text: "illogical-impulse" + text: Translation.tr("illogical-impulse") font.pixelSize: Appearance.font.pixelSize.title } StyledText { @@ -116,7 +116,7 @@ ContentPage { RippleButtonWithIcon { materialIcon: "auto_stories" - mainText: "Documentation" + mainText: Translation.tr("Documentation") onClicked: { Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/02usage/") } @@ -124,21 +124,21 @@ ContentPage { RippleButtonWithIcon { materialIcon: "adjust" materialIconFill: false - mainText: "Issues" + mainText: Translation.tr("Issues") onClicked: { Qt.openUrlExternally("https://github.com/end-4/dots-hyprland/issues") } } RippleButtonWithIcon { materialIcon: "forum" - mainText: "Discussions" + mainText: Translation.tr("Discussions") onClicked: { Qt.openUrlExternally("https://github.com/end-4/dots-hyprland/discussions") } } RippleButtonWithIcon { materialIcon: "favorite" - mainText: "Donate" + mainText: Translation.tr("Donate") onClicked: { Qt.openUrlExternally("https://github.com/sponsors/end-4") } diff --git a/.config/quickshell/ii/modules/settings/AdvancedConfig.qml b/.config/quickshell/ii/modules/settings/AdvancedConfig.qml index d0f22d4d..c7292231 100644 --- a/.config/quickshell/ii/modules/settings/AdvancedConfig.qml +++ b/.config/quickshell/ii/modules/settings/AdvancedConfig.qml @@ -9,35 +9,35 @@ ContentPage { forceWidth: true ContentSection { - title: "Color generation" + title: Translation.tr("Color generation") ConfigRow { uniform: true ConfigSwitch { - text: "Shell & utilities" + text: Translation.tr("Shell & utilities") checked: Config.options.appearance.wallpaperTheming.enableAppsAndShell onCheckedChanged: { Config.options.appearance.wallpaperTheming.enableAppsAndShell = checked; } } ConfigSwitch { - text: "Qt apps" + text: Translation.tr("Qt apps") checked: Config.options.appearance.wallpaperTheming.enableQtApps onCheckedChanged: { Config.options.appearance.wallpaperTheming.enableQtApps = checked; } StyledToolTip { - content: "Shell & utilities theming must also be enabled" + content: Translation.tr("Shell & utilities theming must also be enabled") } } ConfigSwitch { - text: "Terminal" + text: Translation.tr("Terminal") checked: Config.options.appearance.wallpaperTheming.enableTerminal onCheckedChanged: { Config.options.appearance.wallpaperTheming.enableTerminal = checked; } StyledToolTip { - content: "Shell & utilities theming must also be enabled" + content: Translation.tr("Shell & utilities theming must also be enabled") } } diff --git a/.config/quickshell/ii/modules/settings/InterfaceConfig.qml b/.config/quickshell/ii/modules/settings/InterfaceConfig.qml index 2d692442..9a269143 100644 --- a/.config/quickshell/ii/modules/settings/InterfaceConfig.qml +++ b/.config/quickshell/ii/modules/settings/InterfaceConfig.qml @@ -8,13 +8,13 @@ import "root:/modules/common/widgets/" ContentPage { forceWidth: true ContentSection { - title: "Policies" + title: Translation.tr("Policies") ConfigRow { ColumnLayout { // Weeb policy ContentSubsectionLabel { - text: "Weeb" + text: Translation.tr("Weeb") } ConfigSelectionArray { currentValue: Config.options.policies.weeb @@ -24,15 +24,15 @@ ContentPage { } options: [ { - displayName: "No", + displayName: Translation.tr("No"), value: 0 }, { - displayName: "Yes", + displayName: Translation.tr("Yes"), value: 1 }, { - displayName: "Closet", + displayName: Translation.tr("Closet"), value: 2 } ] @@ -42,7 +42,7 @@ ContentPage { ColumnLayout { // AI policy ContentSubsectionLabel { - text: "AI" + text: Translation.tr("AI") } ConfigSelectionArray { currentValue: Config.options.policies.ai @@ -52,15 +52,15 @@ ContentPage { } options: [ { - displayName: "No", + displayName: Translation.tr("No"), value: 0 }, { - displayName: "Yes", + displayName: Translation.tr("Yes"), value: 1 }, { - displayName: "Local only", + displayName: Translation.tr("Local only"), value: 2 } ] @@ -70,7 +70,7 @@ ContentPage { } ContentSection { - title: "Bar" + title: Translation.tr("Bar") ConfigSelectionArray { currentValue: Config.options.bar.cornerStyle @@ -80,57 +80,57 @@ ContentPage { } options: [ { - displayName: "Hug", + displayName: Translation.tr("Hug"), value: 0 }, { - displayName: "Float", + displayName: Translation.tr("Float"), value: 1 }, { - displayName: "Plain rectangle", + displayName: Translation.tr("Plain rectangle"), value: 2 } ] } ContentSubsection { - title: "Appearance" + title: Translation.tr("Appearance") ConfigRow { uniform: true ConfigSwitch { - text: 'Borderless' + text: Translation.tr('Borderless') checked: Config.options.bar.borderless onCheckedChanged: { Config.options.bar.borderless = checked; } } ConfigSwitch { - text: 'Show background' + text: Translation.tr('Show background') checked: Config.options.bar.showBackground onCheckedChanged: { Config.options.bar.showBackground = checked; } StyledToolTip { - content: "Note: turning off can hurt readability" + content: Translation.tr("Note: turning off can hurt readability") } } } } ContentSubsection { - title: "Buttons" + title: Translation.tr("Buttons") ConfigRow { uniform: true ConfigSwitch { - text: "Screen snip" + text: Translation.tr("Screen snip") checked: Config.options.bar.utilButtons.showScreenSnip onCheckedChanged: { Config.options.bar.utilButtons.showScreenSnip = checked; } } ConfigSwitch { - text: "Color picker" + text: Translation.tr("Color picker") checked: Config.options.bar.utilButtons.showColorPicker onCheckedChanged: { Config.options.bar.utilButtons.showColorPicker = checked; @@ -140,14 +140,14 @@ ContentPage { ConfigRow { uniform: true ConfigSwitch { - text: "Mic toggle" + text: Translation.tr("Mic toggle") checked: Config.options.bar.utilButtons.showMicToggle onCheckedChanged: { Config.options.bar.utilButtons.showMicToggle = checked; } } ConfigSwitch { - text: "Keyboard toggle" + text: Translation.tr("Keyboard toggle") checked: Config.options.bar.utilButtons.showKeyboardToggle onCheckedChanged: { Config.options.bar.utilButtons.showKeyboardToggle = checked; @@ -157,7 +157,7 @@ ContentPage { ConfigRow { uniform: true ConfigSwitch { - text: "Dark/Light toggle" + text: Translation.tr("Dark/Light toggle") checked: Config.options.bar.utilButtons.showDarkModeToggle onCheckedChanged: { Config.options.bar.utilButtons.showDarkModeToggle = checked; @@ -171,20 +171,20 @@ ContentPage { } ContentSubsection { - title: "Workspaces" - tooltip: "Tip: Hide icons and always show numbers for\nthe classic illogical-impulse experience" + title: Translation.tr("Workspaces") + tooltip: Translation.tr("Tip: Hide icons and always show numbers for\nthe classic illogical-impulse experience") ConfigRow { uniform: true ConfigSwitch { - text: 'Show app icons' + text: Translation.tr('Show app icons') checked: Config.options.bar.workspaces.showAppIcons onCheckedChanged: { Config.options.bar.workspaces.showAppIcons = checked; } } ConfigSwitch { - text: 'Always show numbers' + text: Translation.tr('Always show numbers') checked: Config.options.bar.workspaces.alwaysShowNumbers onCheckedChanged: { Config.options.bar.workspaces.alwaysShowNumbers = checked; @@ -192,7 +192,7 @@ ContentPage { } } ConfigSpinBox { - text: "Workspaces shown" + text: Translation.tr("Workspaces shown") value: Config.options.bar.workspaces.shown from: 1 to: 30 @@ -202,7 +202,7 @@ ContentPage { } } ConfigSpinBox { - text: "Number show delay when pressing Super (ms)" + text: Translation.tr("Number show delay when pressing Super (ms)") value: Config.options.bar.workspaces.showNumberDelay from: 0 to: 1000 @@ -214,9 +214,9 @@ ContentPage { } ContentSubsection { - title: "Weather" + title: Translation.tr("Weather") ConfigSwitch { - text: "Enable" + text: Translation.tr("Enable") checked: Config.options.bar.weather.enable onCheckedChanged: { Config.options.bar.weather.enable = checked; @@ -226,12 +226,12 @@ ContentPage { } ContentSection { - title: "Battery" + title: Translation.tr("Battery") ConfigRow { uniform: true ConfigSpinBox { - text: "Low warning" + text: Translation.tr("Low warning") value: Config.options.battery.low from: 0 to: 100 @@ -241,7 +241,7 @@ ContentPage { } } ConfigSpinBox { - text: "Critical warning" + text: Translation.tr("Critical warning") value: Config.options.battery.critical from: 0 to: 100 @@ -254,17 +254,17 @@ ContentPage { ConfigRow { uniform: true ConfigSwitch { - text: "Automatic suspend" + text: Translation.tr("Automatic suspend") checked: Config.options.battery.automaticSuspend onCheckedChanged: { Config.options.battery.automaticSuspend = checked; } StyledToolTip { - content: "Automatically suspends the system when battery is low" + content: Translation.tr("Automatically suspends the system when battery is low") } } ConfigSpinBox { - text: "Suspend at" + text: Translation.tr("Suspend at") value: Config.options.battery.suspend from: 0 to: 100 @@ -277,10 +277,10 @@ ContentPage { } ContentSection { - title: "Dock" + title: Translation.tr("Dock") ConfigSwitch { - text: "Enable" + text: Translation.tr("Enable") checked: Config.options.dock.enable onCheckedChanged: { Config.options.dock.enable = checked; @@ -290,14 +290,14 @@ ContentPage { ConfigRow { uniform: true ConfigSwitch { - text: "Hover to reveal" + text: Translation.tr("Hover to reveal") checked: Config.options.dock.hoverToReveal onCheckedChanged: { Config.options.dock.hoverToReveal = checked; } } ConfigSwitch { - text: "Pinned on startup" + text: Translation.tr("Pinned on startup") checked: Config.options.dock.pinnedOnStartup onCheckedChanged: { Config.options.dock.pinnedOnStartup = checked; @@ -307,9 +307,9 @@ ContentPage { } ContentSection { - title: "On-screen display" + title: Translation.tr("On-screen display") ConfigSpinBox { - text: "Timeout (ms)" + text: Translation.tr("Timeout (ms)") value: Config.options.osd.timeout from: 100 to: 3000 @@ -321,9 +321,9 @@ ContentPage { } ContentSection { - title: "Overview" + title: Translation.tr("Overview") ConfigSpinBox { - text: "Scale (%)" + text: Translation.tr("Scale (%)") value: Config.options.overview.scale * 100 from: 1 to: 100 @@ -335,7 +335,7 @@ ContentPage { ConfigRow { uniform: true ConfigSpinBox { - text: "Rows" + text: Translation.tr("Rows") value: Config.options.overview.rows from: 1 to: 20 @@ -345,7 +345,7 @@ ContentPage { } } ConfigSpinBox { - text: "Columns" + text: Translation.tr("Columns") value: Config.options.overview.columns from: 1 to: 20 @@ -358,16 +358,16 @@ ContentPage { } ContentSection { - title: "Screenshot tool" + title: Translation.tr("Screenshot tool") ConfigSwitch { - text: 'Show regions of potential interest' + text: Translation.tr('Show regions of potential interest') checked: Config.options.screenshotTool.showContentRegions onCheckedChanged: { Config.options.screenshotTool.showContentRegions = checked; } StyledToolTip { - content: "Such regions could be images or parts of the screen that have some containment.\nMight not always be accurate.\nThis is done with an image processing algorithm run locally and no AI is used." + content: Translation.tr("Such regions could be images or parts of the screen that have some containment.\nMight not always be accurate.\nThis is done with an image processing algorithm run locally and no AI is used.") } } } diff --git a/.config/quickshell/ii/modules/settings/ServicesConfig.qml b/.config/quickshell/ii/modules/settings/ServicesConfig.qml index a9e34512..cc0c6185 100644 --- a/.config/quickshell/ii/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/ii/modules/settings/ServicesConfig.qml @@ -9,22 +9,22 @@ ContentPage { forceWidth: true ContentSection { - title: "Audio" + title: Translation.tr("Audio") ConfigSwitch { - text: "Earbang protection" + text: Translation.tr("Earbang protection") checked: Config.options.audio.protection.enable onCheckedChanged: { Config.options.audio.protection.enable = checked; } StyledToolTip { - content: "Prevents abrupt increments and restricts volume limit" + content: Translation.tr("Prevents abrupt increments and restricts volume limit") } } ConfigRow { // uniform: true ConfigSpinBox { - text: "Max allowed increase" + text: Translation.tr("Max allowed increase") value: Config.options.audio.protection.maxAllowedIncrease from: 0 to: 100 @@ -34,7 +34,7 @@ ContentPage { } } ConfigSpinBox { - text: "Volume limit" + text: Translation.tr("Volume limit") value: Config.options.audio.protection.maxAllowed from: 0 to: 100 @@ -46,10 +46,10 @@ ContentPage { } } ContentSection { - title: "AI" + title: Translation.tr("AI") MaterialTextField { Layout.fillWidth: true - placeholderText: "System prompt" + placeholderText: Translation.tr("System prompt") text: Config.options.ai.systemPrompt wrapMode: TextEdit.Wrap onTextChanged: { @@ -61,12 +61,12 @@ ContentPage { } ContentSection { - title: "Battery" + title: Translation.tr("Battery") ConfigRow { uniform: true ConfigSpinBox { - text: "Low warning" + text: Translation.tr("Low warning") value: Config.options.battery.low from: 0 to: 100 @@ -76,7 +76,7 @@ ContentPage { } } ConfigSpinBox { - text: "Critical warning" + text: Translation.tr("Critical warning") value: Config.options.battery.critical from: 0 to: 100 @@ -89,17 +89,17 @@ ContentPage { ConfigRow { uniform: true ConfigSwitch { - text: "Automatic suspend" + text: Translation.tr("Automatic suspend") checked: Config.options.battery.automaticSuspend onCheckedChanged: { Config.options.battery.automaticSuspend = checked; } StyledToolTip { - content: "Automatically suspends the system when battery is low" + content: Translation.tr("Automatically suspends the system when battery is low") } } ConfigSpinBox { - text: "Suspend at" + text: Translation.tr("Suspend at") value: Config.options.battery.suspend from: 0 to: 100 @@ -112,10 +112,10 @@ ContentPage { } ContentSection { - title: "Networking" + title: Translation.tr("Networking") MaterialTextField { Layout.fillWidth: true - placeholderText: "User agent (for services that require it)" + placeholderText: Translation.tr("User agent (for services that require it)") text: Config.options.networking.userAgent wrapMode: TextEdit.Wrap onTextChanged: { @@ -125,9 +125,9 @@ ContentPage { } ContentSection { - title: "Resources" + title: Translation.tr("Resources") ConfigSpinBox { - text: "Polling interval (ms)" + text: Translation.tr("Polling interval (ms)") value: Config.options.resources.updateInterval from: 100 to: 10000 @@ -139,27 +139,27 @@ ContentPage { } ContentSection { - title: "Search" + title: Translation.tr("Search") ConfigSwitch { - text: "Use Levenshtein distance-based algorithm instead of fuzzy" + text: Translation.tr("Use Levenshtein distance-based algorithm instead of fuzzy") checked: Config.options.search.sloppy onCheckedChanged: { Config.options.search.sloppy = checked; } StyledToolTip { - content: "Could be better if you make a ton of typos,\nbut results can be weird and might not work with acronyms\n(e.g. \"GIMP\" might not give you the paint program)" + content: Translation.tr("Could be better if you make a ton of typos,\nbut results can be weird and might not work with acronyms\n(e.g. \"GIMP\" might not give you the paint program)") } } ContentSubsection { - title: "Prefixes" + title: Translation.tr("Prefixes") ConfigRow { uniform: true MaterialTextField { Layout.fillWidth: true - placeholderText: "Action" + placeholderText: Translation.tr("Action") text: Config.options.search.prefix.action wrapMode: TextEdit.Wrap onTextChanged: { @@ -168,7 +168,7 @@ ContentPage { } MaterialTextField { Layout.fillWidth: true - placeholderText: "Clipboard" + placeholderText: Translation.tr("Clipboard") text: Config.options.search.prefix.clipboard wrapMode: TextEdit.Wrap onTextChanged: { @@ -177,7 +177,7 @@ ContentPage { } MaterialTextField { Layout.fillWidth: true - placeholderText: "Emojis" + placeholderText: Translation.tr("Emojis") text: Config.options.search.prefix.emojis wrapMode: TextEdit.Wrap onTextChanged: { @@ -187,10 +187,10 @@ ContentPage { } } ContentSubsection { - title: "Web search" + title: Translation.tr("Web search") MaterialTextField { Layout.fillWidth: true - placeholderText: "Base URL" + placeholderText: Translation.tr("Base URL") text: Config.options.search.engineBaseUrl wrapMode: TextEdit.Wrap onTextChanged: { @@ -201,10 +201,10 @@ ContentPage { } ContentSection { - title: "Time" + title: Translation.tr("Time") ContentSubsection { - title: "Format" + title: Translation.tr("Format") tooltip: "" ConfigSelectionArray { @@ -215,15 +215,15 @@ ContentPage { } options: [ { - displayName: "24h", + displayName: Translation.tr("24h"), value: "hh:mm" }, { - displayName: "12h am/pm", + displayName: Translation.tr("12h am/pm"), value: "h:mm ap" }, { - displayName: "12h AM/PM", + displayName: Translation.tr("12h AM/PM"), value: "h:mm AP" }, ] diff --git a/.config/quickshell/ii/modules/settings/StyleConfig.qml b/.config/quickshell/ii/modules/settings/StyleConfig.qml index bc1998c8..31dea05b 100644 --- a/.config/quickshell/ii/modules/settings/StyleConfig.qml +++ b/.config/quickshell/ii/modules/settings/StyleConfig.qml @@ -28,7 +28,7 @@ ContentPage { } ContentSection { - title: "Colors & Wallpaper" + title: Translation.tr("Colors & Wallpaper") // Light/Dark mode preference ButtonGroup { @@ -44,7 +44,7 @@ ContentPage { // Material palette selection ContentSubsection { - title: "Material palette" + title: Translation.tr("Material palette") ConfigSelectionArray { currentValue: Config.options.appearance.palette.type configOptionName: "appearance.palette.type" @@ -53,15 +53,15 @@ ContentPage { Quickshell.execDetached(["bash", "-c", `${Directories.wallpaperSwitchScriptPath} --noswitch`]) } options: [ - {"value": "auto", "displayName": "Auto"}, - {"value": "scheme-content", "displayName": "Content"}, - {"value": "scheme-expressive", "displayName": "Expressive"}, - {"value": "scheme-fidelity", "displayName": "Fidelity"}, - {"value": "scheme-fruit-salad", "displayName": "Fruit Salad"}, - {"value": "scheme-monochrome", "displayName": "Monochrome"}, - {"value": "scheme-neutral", "displayName": "Neutral"}, - {"value": "scheme-rainbow", "displayName": "Rainbow"}, - {"value": "scheme-tonal-spot", "displayName": "Tonal Spot"} + {"value": "auto", "displayName": Translation.tr("Auto")}, + {"value": "scheme-content", "displayName": Translation.tr("Content")}, + {"value": "scheme-expressive", "displayName": Translation.tr("Expressive")}, + {"value": "scheme-fidelity", "displayName": Translation.tr("Fidelity")}, + {"value": "scheme-fruit-salad", "displayName": Translation.tr("Fruit Salad")}, + {"value": "scheme-monochrome", "displayName": Translation.tr("Monochrome")}, + {"value": "scheme-neutral", "displayName": Translation.tr("Neutral")}, + {"value": "scheme-rainbow", "displayName": Translation.tr("Rainbow")}, + {"value": "scheme-tonal-spot", "displayName": Translation.tr("Tonal Spot")} ] } } @@ -69,26 +69,26 @@ ContentPage { // Wallpaper selection ContentSubsection { - title: "Wallpaper" + title: Translation.tr("Wallpaper") RowLayout { Layout.alignment: Qt.AlignHCenter RippleButtonWithIcon { id: rndWallBtn buttonRadius: Appearance.rounding.small materialIcon: "wallpaper" - mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan" + mainText: konachanWallProc.running ? Translation.tr("Be patient...") : Translation.tr("Random: Konachan") onClicked: { console.log(konachanWallProc.command.join(" ")) konachanWallProc.running = true; } StyledToolTip { - content: "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers" + content: Translation.tr("Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers") } } RippleButtonWithIcon { materialIcon: "wallpaper" StyledToolTip { - content: "Pick wallpaper image on your system" + content: Translation.tr("Pick wallpaper image on your system") } onClicked: { Quickshell.execDetached(`${Directories.wallpaperSwitchScriptPath}`) @@ -98,7 +98,7 @@ ContentPage { spacing: 10 StyledText { font.pixelSize: Appearance.font.pixelSize.small - text: "Choose file" + text: Translation.tr("Choose file") color: Appearance.colors.colOnSecondaryContainer } RowLayout { @@ -126,7 +126,7 @@ ContentPage { StyledText { Layout.topMargin: 5 Layout.alignment: Qt.AlignHCenter - text: "Alternatively use /dark, /light, /img in the launcher" + text: Translation.tr("Alternatively use /dark, /light, /img in the launcher") font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.colors.colSubtext } @@ -134,27 +134,27 @@ ContentPage { } ContentSection { - title: "Decorations & Effects" + title: Translation.tr("Decorations & Effects") ContentSubsection { - title: "Transparency" + title: Translation.tr("Transparency") ConfigRow { ConfigSwitch { - text: "Enable" + text: Translation.tr("Enable") checked: Config.options.appearance.transparency onCheckedChanged: { Config.options.appearance.transparency = checked; } StyledToolTip { - content: "Might look ass. Unsupported." + content: Translation.tr("Might look ass. Unsupported.") } } } } ContentSubsection { - title: "Fake screen rounding" + title: Translation.tr("Fake screen rounding") ButtonGroup { id: fakeScreenRoundingButtonGroup @@ -163,7 +163,7 @@ ContentPage { SelectionGroupButton { property int value: 0 leftmost: true - buttonText: "No" + buttonText: Translation.tr("No") toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) onClicked: { Config.options.appearance.fakeScreenRounding = value; @@ -171,7 +171,7 @@ ContentPage { } SelectionGroupButton { property int value: 1 - buttonText: "Yes" + buttonText: Translation.tr("Yes") toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) onClicked: { Config.options.appearance.fakeScreenRounding = value; @@ -180,7 +180,7 @@ ContentPage { SelectionGroupButton { property int value: 2 rightmost: true - buttonText: "When not fullscreen" + buttonText: Translation.tr("When not fullscreen") toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value) onClicked: { Config.options.appearance.fakeScreenRounding = value; @@ -190,19 +190,19 @@ ContentPage { } ContentSubsection { - title: "Shell windows" + title: Translation.tr("Shell windows") ConfigRow { uniform: true ConfigSwitch { - text: "Title bar" + text: Translation.tr("Title bar") checked: Config.options.windows.showTitlebar onCheckedChanged: { Config.options.windows.showTitlebar = checked; } } ConfigSwitch { - text: "Center title" + text: Translation.tr("Center title") checked: Config.options.windows.centerTitle onCheckedChanged: { Config.options.windows.centerTitle = checked; diff --git a/.config/quickshell/ii/settings.qml b/.config/quickshell/ii/settings.qml index e76f8dcb..91bd61f7 100644 --- a/.config/quickshell/ii/settings.qml +++ b/.config/quickshell/ii/settings.qml @@ -28,27 +28,27 @@ ApplicationWindow { property bool showNextTime: false property var pages: [ { - name: "Style", + name: Translation.tr("Style"), icon: "palette", component: "modules/settings/StyleConfig.qml" }, { - name: "Interface", + name: Translation.tr("Interface"), icon: "cards", component: "modules/settings/InterfaceConfig.qml" }, { - name: "Services", + name: Translation.tr("Services"), icon: "settings", component: "modules/settings/ServicesConfig.qml" }, { - name: "Advanced", + name: Translation.tr("Advanced"), icon: "construction", component: "modules/settings/AdvancedConfig.qml" }, { - name: "About", + name: Translation.tr("About"), icon: "info", component: "modules/settings/About.qml" } @@ -110,7 +110,7 @@ ApplicationWindow { leftMargin: 12 } color: Appearance.colors.colOnLayer0 - text: "Settings" + text: Translation.tr("Settings") font.pixelSize: Appearance.font.pixelSize.title font.family: Appearance.font.family.title } @@ -162,7 +162,7 @@ ApplicationWindow { FloatingActionButton { id: fab iconText: "edit" - buttonText: "Edit config" + buttonText: Translation.tr("Edit config") expanded: navRail.expanded onClicked: { Qt.openUrlExternally(`${Directories.config}/illogical-impulse/config.json`); diff --git a/.config/quickshell/ii/welcome.qml b/.config/quickshell/ii/welcome.qml index 7c1dff4a..40d49653 100644 --- a/.config/quickshell/ii/welcome.qml +++ b/.config/quickshell/ii/welcome.qml @@ -27,7 +27,7 @@ ApplicationWindow { property bool showNextTime: false visible: true onClosing: Qt.quit() - title: "illogical-impulse Welcome" + title: Translation.tr("illogical-impulse Welcome") Component.onCompleted: { MaterialThemeLoader.reapplyTheme() @@ -70,7 +70,7 @@ ApplicationWindow { leftMargin: 12 } color: Appearance.colors.colOnLayer0 - text: "Yooooo hi there" + text: Translation.tr("Yooooo hi there") font.pixelSize: Appearance.font.pixelSize.title font.family: Appearance.font.family.title } @@ -80,7 +80,7 @@ ApplicationWindow { anchors.right: parent.right StyledText { font.pixelSize: Appearance.font.pixelSize.smaller - text: "Show next time" + text: Translation.tr("Show next time") } StyledSwitch { id: showNextTimeSwitch @@ -123,7 +123,7 @@ ApplicationWindow { anchors.fill: parent ContentSection { - title: "Bar style" + title: Translation.tr("Bar style") ConfigSelectionArray { currentValue: Config.options.bar.cornerStyle @@ -132,15 +132,15 @@ ApplicationWindow { Config.options.bar.cornerStyle = newValue; // Update local copy } options: [ - { displayName: "Hug", value: 0 }, - { displayName: "Float", value: 1 }, - { displayName: "Plain rectangle", value: 2 } + { displayName: Translation.tr("Hug"), value: 0 }, + { displayName: Translation.tr("Float"), value: 1 }, + { displayName: Translation.tr("Plain rectangle"), value: 2 } ] } } ContentSection { - title: "Style & wallpaper" + title: Translation.tr("Style & wallpaper") ButtonGroup { Layout.fillWidth: true @@ -159,19 +159,19 @@ ApplicationWindow { Layout.alignment: Qt.AlignHCenter buttonRadius: Appearance.rounding.small materialIcon: "wallpaper" - mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan" + mainText: konachanWallProc.running ? Translation.tr("Be patient...") : Translation.tr("Random: Konachan") onClicked: { console.log(konachanWallProc.command.join(" ")) konachanWallProc.running = true; } StyledToolTip { - content: "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers" + content: Translation.tr("Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers") } } RippleButtonWithIcon { materialIcon: "wallpaper" StyledToolTip { - content: "Pick wallpaper image on your system" + content: Translation.tr("Pick wallpaper image on your system") } onClicked: { Quickshell.execDetached([`${Directories.wallpaperSwitchScriptPath}`]) @@ -181,7 +181,7 @@ ApplicationWindow { spacing: 10 StyledText { font.pixelSize: Appearance.font.pixelSize.small - text: "Choose file" + text: Translation.tr("Choose file") color: Appearance.colors.colOnSecondaryContainer } RowLayout { @@ -207,19 +207,19 @@ ApplicationWindow { StyledText { Layout.alignment: Qt.AlignHCenter - text: "Change any time later with /dark, /light, /img in the launcher" + text: Translation.tr("Change any time later with /dark, /light, /img in the launcher") font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.colors.colSubtext } } ContentSection { - title: "Policies" + title: Translation.tr("Policies") ConfigRow { ColumnLayout { // Weeb policy ContentSubsectionLabel { - text: "Weeb" + text: Translation.tr("Weeb") } ConfigSelectionArray { currentValue: Config.options.policies.weeb @@ -228,16 +228,16 @@ ApplicationWindow { Config.options.policies.weeb = newValue; } options: [ - { displayName: "No", value: 0 }, - { displayName: "Yes", value: 1 }, - { displayName: "Closet", value: 2 } + { displayName: Translation.tr("No"), value: 0 }, + { displayName: Translation.tr("Yes"), value: 1 }, + { displayName: Translation.tr("Closet"), value: 2 } ] } } ColumnLayout { // AI policy ContentSubsectionLabel { - text: "AI" + text: Translation.tr("AI") } ConfigSelectionArray { currentValue: Config.options.policies.ai @@ -246,9 +246,9 @@ ApplicationWindow { Config.options.policies.ai = newValue; } options: [ - { displayName: "No", value: 0 }, - { displayName: "Yes", value: 1 }, - { displayName: "Local only", value: 2 } + { displayName: Translation.tr("No"), value: 0 }, + { displayName: Translation.tr("Yes"), value: 1 }, + { displayName: Translation.tr("Local only"), value: 2 } ] } } @@ -256,7 +256,7 @@ ApplicationWindow { } ContentSection { - title: "Info" + title: Translation.tr("Info") Flow { Layout.fillWidth: true @@ -272,7 +272,7 @@ ApplicationWindow { spacing: 10 StyledText { font.pixelSize: Appearance.font.pixelSize.small - text: "Keybinds" + text: Translation.tr("Keybinds") color: Appearance.colors.colOnSecondaryContainer } RowLayout { @@ -294,14 +294,14 @@ ApplicationWindow { RippleButtonWithIcon { materialIcon: "help" - mainText: "Usage" + mainText: Translation.tr("Usage") onClicked: { Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/02usage/") } } RippleButtonWithIcon { materialIcon: "construction" - mainText: "Configuration" + mainText: Translation.tr("Configuration") onClicked: { Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/03config/") } @@ -310,7 +310,7 @@ ApplicationWindow { } ContentSection { - title: "Useless buttons" + title: Translation.tr("Useless buttons") Flow { Layout.fillWidth: true @@ -318,7 +318,7 @@ ApplicationWindow { RippleButtonWithIcon { nerdIcon: "󰊤" - mainText: "GitHub" + mainText: Translation.tr("GitHub") onClicked: { Qt.openUrlExternally("https://github.com/end-4/dots-hyprland") } diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index 0e6254fe..b757d3d3 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -172,5 +172,134 @@ "Set the system prompt for the model.": "Set the system prompt for the model.", "To Do": "To Do", "Calendar": "Calendar", - "notifications": "notifications" + "notifications": "notifications", + "Advanced": "Advanced", + "About": "About", + "Services": "Services", + "Style": "Style", + "Edit config": "Edit config", + "Colors & Wallpaper": "Colors & Wallpaper", + "Light": "Light", + "Dark": "Dark", + "Material palette": "Material palette", + "Fidelity": "Fidelity", + "Fruit Salad": "Fruit Salad", + "Alternatively use /dark, /light, /img in the launcher": "Alternatively use /dark, /light, /img in the launcher", + "Fake screen rounding": "Fake screen rounding", + "When not fullscreen": "When not fullscreen", + "Choose file": "Choose file", + "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers": "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers", + "Be patient...": "Be patient...", + "Decorations & Effects": "Decorations & Effects", + "Tonal Spot": "Tonal Spot", + "Shell windows": "Shell windows", + "Auto": "Auto", + "Wallpaper": "Wallpaper", + "Content": "Content", + "Title bar": "Title bar", + "Transparency": "Transparency", + "Expressive": "Expressive", + "Yes": "Yes", + "Enable": "Enable", + "Rainbow": "Rainbow", + "Might look ass. Unsupported.": "Might look ass. Unsupported.", + "Monochrome": "Monochrome", + "Random: Konachan": "Random: Konachan", + "Center title": "Center title", + "Neutral": "Neutral", + "Pick wallpaper image on your system": "Pick wallpaper image on your system", + "No": "No", + "AI": "AI", + "Local only": "Local only", + "Policies": "Policies", + "Weeb": "Weeb", + "Closet": "Closet", + "Bar style": "Bar style", + "Show next time": "Show next time", + "Usage": "Usage", + "Plain rectangle": "Plain rectangle", + "Useless buttons": "Useless buttons", + "GitHub": "GitHub", + "Style & wallpaper": "Style & wallpaper", + "Configuration": "Configuration", + "Change any time later with /dark, /light, /img in the launcher": "Change any time later with /dark, /light, /img in the launcher", + "Keybinds": "Keybinds", + "Float": "Float", + "Hug": "Hug", + "Yooooo hi there": "Yooooo hi there", + "illogical-impulse Welcome": "illogical-impulse Welcome", + "Info": "Info", + "Volume limit": "Volume limit", + "Prevents abrupt increments and restricts volume limit": "Prevents abrupt increments and restricts volume limit", + "Resources": "Resources", + "12h am/pm": "12h am/pm", + "Base URL": "Base URL", + "Audio": "Audio", + "Networking": "Networking", + "Format": "Format", + "Time": "Time", + "Battery": "Battery", + "Prefixes": "Prefixes", + "Emojis": "Emojis", + "Earbang protection": "Earbang protection", + "Automatically suspends the system when battery is low": "Automatically suspends the system when battery is low", + "Automatic suspend": "Automatic suspend", + "Suspend at": "Suspend at", + "Max allowed increase": "Max allowed increase", + "Web search": "Web search", + "Polling interval (ms)": "Polling interval (ms)", + "Clipboard": "Clipboard", + "Low warning": "Low warning", + "24h": "24h", + "Use Levenshtein distance-based algorithm instead of fuzzy": "Use Levenshtein distance-based algorithm instead of fuzzy", + "System prompt": "System prompt", + "12h AM/PM": "12h AM/PM", + "Could be better if you make a ton of typos,\nbut results can be weird and might not work with acronyms\n(e.g. \"GIMP\" might not give you the paint program)": "Could be better if you make a ton of typos,\nbut results can be weird and might not work with acronyms\n(e.g. \"GIMP\" might not give you the paint program)", + "Critical warning": "Critical warning", + "User agent (for services that require it)": "User agent (for services that require it)", + "Such regions could be images or parts of the screen that have some containment.\nMight not always be accurate.\nThis is done with an image processing algorithm run locally and no AI is used.": "Such regions could be images or parts of the screen that have some containment.\nMight not always be accurate.\nThis is done with an image processing algorithm run locally and no AI is used.", + "Note: turning off can hurt readability": "Note: turning off can hurt readability", + "Workspaces shown": "Workspaces shown", + "Dark/Light toggle": "Dark/Light toggle", + "Dock": "Dock", + "Weather": "Weather", + "Pinned on startup": "Pinned on startup", + "Tip: Hide icons and always show numbers for\nthe classic illogical-impulse experience": "Tip: Hide icons and always show numbers for\nthe classic illogical-impulse experience", + "Appearance": "Appearance", + "Always show numbers": "Always show numbers", + "Buttons": "Buttons", + "Keyboard toggle": "Keyboard toggle", + "Scale (%)": "Scale (%)", + "Overview": "Overview", + "Rows": "Rows", + "Borderless": "Borderless", + "Screenshot tool": "Screenshot tool", + "Number show delay when pressing Super (ms)": "Number show delay when pressing Super (ms)", + "Timeout (ms)": "Timeout (ms)", + "Show app icons": "Show app icons", + "Workspaces": "Workspaces", + "Columns": "Columns", + "On-screen display": "On-screen display", + "Screen snip": "Screen snip", + "Mic toggle": "Mic toggle", + "Hover to reveal": "Hover to reveal", + "Bar": "Bar", + "Show background": "Show background", + "Show regions of potential interest": "Show regions of potential interest", + "Color picker": "Color picker", + "Help & Support": "Help & Support", + "Discussions": "Discussions", + "Color generation": "Color generation", + "Dotfiles": "Dotfiles", + "Distro": "Distro", + "Privacy Policy": "Privacy Policy", + "Documentation": "Documentation", + "Shell & utilities theming must also be enabled": "Shell & utilities theming must also be enabled", + "illogical-impulse": "illogical-impulse", + "Donate": "Donate", + "Terminal": "Terminal", + "Shell & utilities": "Shell & utilities", + "Qt apps": "Qt apps", + "Report a Bug": "Report a Bug", + "Issues": "Issues" } \ No newline at end of file diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index 0242aa2d..fe4e577d 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -172,5 +172,134 @@ "Set the system prompt for the model.": "为模型设置系统提示。", "To Do": "待办", "Calendar": "日历", - "notifications": "条通知" + "notifications": "条通知", + "Advanced": "高级", + "About": "关于", + "Services": "服务", + "Style": "样式", + "Edit config": "编辑配置", + "Colors & Wallpaper": "颜色和壁纸", + "Light": "浅色", + "Dark": "深色", + "Material palette": "颜色主题", + "Fidelity": "保真度", + "Fruit Salad": "水果沙拉", + "Alternatively use /dark, /light, /img in the launcher": "或者在启动器中使用 /dark、/light、/img", + "Fake screen rounding": "伪造屏幕圆角", + "When not fullscreen": "非全屏时", + "Choose file": "选择文件", + "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers": "随机 Konachan SFW 动漫壁纸\n图片保存到 ~/Pictures/Wallpapers", + "Be patient...": "请耐心等待...", + "Decorations & Effects": "装饰与特效", + "Tonal Spot": "色调点", + "Shell windows": "Shell 窗口", + "Auto": "自动", + "Wallpaper": "壁纸", + "Content": "内容", + "Title bar": "标题栏", + "Transparency": "透明度", + "Expressive": "表现力", + "Yes": "是", + "Enable": "启用", + "Rainbow": "彩虹", + "Might look ass. Unsupported.": "可能效果很差。不支持。", + "Monochrome": "单色", + "Random: Konachan": "随机:Konachan", + "Center title": "标题居中", + "Neutral": "中性", + "Pick wallpaper image on your system": "在系统中选择壁纸图片", + "No": "否", + "AI": "AI", + "Local only": "仅本地", + "Policies": "策略", + "Weeb": "二次元", + "Closet": "隐藏", + "Bar style": "Bar 样式", + "Show next time": "下次显示", + "Usage": "用法", + "Plain rectangle": "纯矩形", + "Useless buttons": "无用按钮", + "GitHub": "GitHub", + "Style & wallpaper": "样式与壁纸", + "Configuration": "配置", + "Change any time later with /dark, /light, /img in the launcher": "之后可在启动器用 /dark、/light、/img 更改", + "Keybinds": "快捷键", + "Float": "浮动", + "Hug": "贴合", + "Yooooo hi there": "哟嗬,您好呀", + "illogical-impulse Welcome": "illogical-impulse 欢迎页", + "Info": "信息", + "Volume limit": "音量限制", + "Prevents abrupt increments and restricts volume limit": "防止骤增并限制音量", + "Resources": "资源", + "12h am/pm": "12小时 上午/下午", + "Base URL": "基础 URL", + "Audio": "声音", + "Networking": "网络", + "Format": "格式", + "Time": "时间", + "Battery": "电池", + "Prefixes": "前缀", + "Emojis": "表情符号", + "Earbang protection": "防爆音保护", + "Automatically suspends the system when battery is low": "电池电量低时自动挂起系统", + "Automatic suspend": "自动挂起", + "Suspend at": "挂起阈值", + "Max allowed increase": "最大允许增幅", + "Web search": "网页搜索", + "Polling interval (ms)": "轮询间隔(毫秒)", + "Clipboard": "剪贴板", + "Low warning": "低电量警告", + "24h": "24小时制", + "Use Levenshtein distance-based algorithm instead of fuzzy": "使用 Levenshtein 距离算法替代模糊匹配", + "System prompt": "系统提示词", + "12h AM/PM": "12小时 AM/PM", + "Could be better if you make a ton of typos,\nbut results can be weird and might not work with acronyms\n(e.g. \"GIMP\" might not give you the paint program)": "如果你经常打错字可能更好用,但结果可能很奇怪,并且可能无法匹配缩写(如 \"GIMP\" 可能搜不到绘图程序)", + "Critical warning": "临界警告", + "User agent (for services that require it)": "用户代理(部分服务需要)", + "Such regions could be images or parts of the screen that have some containment.\nMight not always be accurate.\nThis is done with an image processing algorithm run locally and no AI is used.": "这些区域可能是图片或屏幕中具有一定包容性的部分。\n可能并不总是准确。\n这是通过本地运行的图像处理算法实现的,没有使用 AI。", + "Note: turning off can hurt readability": "注意:关闭后可能影响可读性", + "Workspaces shown": "显示的工作区数", + "Dark/Light toggle": "深浅色切换", + "Dock": "停靠栏", + "Weather": "天气", + "Pinned on startup": "启动时固定", + "Tip: Hide icons and always show numbers for\nthe classic illogical-impulse experience": "提示:隐藏图标并始终显示数字以获得经典体验", + "Appearance": "外观", + "Always show numbers": "总是显示数字", + "Buttons": "按钮", + "Keyboard toggle": "键盘切换", + "Scale (%)": "缩放比例(%)", + "Overview": "概览", + "Rows": "行数", + "Borderless": "无边框", + "Screenshot tool": "截图工具", + "Number show delay when pressing Super (ms)": "按下 Super 时数字显示延迟(ms)", + "Timeout (ms)": "超时时间(ms)", + "Show app icons": "显示应用图标", + "Workspaces": "工作区", + "Columns": "列数", + "On-screen display": "屏幕显示", + "Screen snip": "屏幕截图", + "Mic toggle": "麦克风切换", + "Hover to reveal": "悬停显示", + "Bar": "Bar", + "Show background": "显示背景", + "Show regions of potential interest": "显示可能感兴趣的区域", + "Color picker": "取色器", + "Help & Support": "帮助与支持", + "Discussions": "讨论区", + "Color generation": "配色生成", + "Dotfiles": "配置文件", + "Distro": "发行版", + "Privacy Policy": "隐私政策", + "Documentation": "文档", + "Shell & utilities theming must also be enabled": "必须同时启用 Shell 与工具主题", + "illogical-impulse": "illogical-impulse", + "Donate": "捐助", + "Terminal": "终端", + "Shell & utilities": "Shell 与工具", + "Qt apps": "Qt 应用", + "Report a Bug": "报告问题", + "Issues": "问题追踪" } \ No newline at end of file From 2eff8d6db41a9e1e6ae2d9ef5dfbf9455988e298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Mon, 14 Jul 2025 15:08:40 +0800 Subject: [PATCH 216/328] i18n: Fix translatable string extraction tool bug. --- .config/quickshell/ii/screenshot.qml | 2 +- .config/quickshell/translations/en_US.json | 3 ++- .../translations/tools/translation-cleaner.py | 5 ++--- .../translations/tools/translation-manager.py | 19 +++++++++++++++---- .config/quickshell/translations/zh_CN.json | 3 ++- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/.config/quickshell/ii/screenshot.qml b/.config/quickshell/ii/screenshot.qml index f1555871..d4a55de0 100644 --- a/.config/quickshell/ii/screenshot.qml +++ b/.config/quickshell/ii/screenshot.qml @@ -444,7 +444,7 @@ ShellRoot { } } StyledText { - text: "Drag or click a region • LMB: Copy • RMB: Edit" + text: Translation.tr("Drag or click a region • LMB: Copy • RMB: Edit") color: root.genericContentForeground } } diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index b757d3d3..f1da949c 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -301,5 +301,6 @@ "Shell & utilities": "Shell & utilities", "Qt apps": "Qt apps", "Report a Bug": "Report a Bug", - "Issues": "Issues" + "Issues": "Issues", + "Drag or click a region • LMB: Copy • RMB: Edit": "Drag or click a region • LMB: Copy • RMB: Edit" } \ No newline at end of file diff --git a/.config/quickshell/translations/tools/translation-cleaner.py b/.config/quickshell/translations/tools/translation-cleaner.py index e53082fd..afc290ad 100755 --- a/.config/quickshell/translations/tools/translation-cleaner.py +++ b/.config/quickshell/translations/tools/translation-cleaner.py @@ -154,10 +154,9 @@ def sync_translations(translations_dir: str, source_lang: str = "en_US", target_ del target_translations[key] print(f" Deleted {len(extra_keys)} extra keys") - # Save file - with open(target_file, 'w', encoding='utf-8') as f: + # Save file (ensure UTF-8, fix for special chars) + with open(target_file, 'w', encoding='utf-8', newline='') as f: json.dump(target_translations, f, ensure_ascii=False, indent=2) - print(f" Saved: {target_file}") def main(): diff --git a/.config/quickshell/translations/tools/translation-manager.py b/.config/quickshell/translations/tools/translation-manager.py index ffcb2609..1b1a604a 100755 --- a/.config/quickshell/translations/tools/translation-manager.py +++ b/.config/quickshell/translations/tools/translation-manager.py @@ -56,11 +56,22 @@ class TranslationManager: text = match[0] if match else "" else: text = match - - # Decode escape characters + try: - clean_text = text.encode().decode('unicode_escape') - except: + if '\\u' in text or '\\x' in text: + clean_text = bytes(text, "utf-8").decode("unicode_escape") + else: + clean_text = ( + text.replace('\\n', '\n') + .replace('\\t', '\t') + .replace('\\r', '\r') + .replace('\\"', '"') + .replace('\\\'', "'") + .replace('\\f', '\f') + .replace('\\b', '\b') + .replace('\\\\', '\\') + ) + except Exception: clean_text = text # Clean text (remove extra whitespace) diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index fe4e577d..a51b8a79 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -301,5 +301,6 @@ "Shell & utilities": "Shell 与工具", "Qt apps": "Qt 应用", "Report a Bug": "报告问题", - "Issues": "问题追踪" + "Issues": "问题追踪", + "Drag or click a region • LMB: Copy • RMB: Edit": "拖动或点击一个区域 • 鼠标左键:复制 • 鼠标右键:编辑" } \ No newline at end of file From efa60d09fc271f254c1cc30198ef634d2cf6af1a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 14 Jul 2025 09:31:22 +0200 Subject: [PATCH 217/328] Update CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aaaa3de8..3bd5c8f8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ # Contributing - Please understand that dotfiles are personal -- If you make new stuff, I'll probably nitpick as I want quality -- FFS pls make multiple PRs if you have many features 😭🙏 +- If you add new stuff, ask me first to not waste your work +- FFS make multiple PRs if you have many features From 631303bffe197646428b303e3638773e7abb1d49 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 14 Jul 2025 20:43:52 +0700 Subject: [PATCH 218/328] use quickshell for wallpaper --- .config/hypr/hyprland/execs.conf | 2 - .../ii/modules/background/Background.qml | 152 ++++++++++++++++++ .../backgroundWidgets/BackgroundWidgets.qml | 139 ---------------- .config/quickshell/ii/modules/bar/Bar.qml | 2 +- .../quickshell/ii/modules/common/Config.qml | 1 + .../ii/scripts/colors/switchwall.sh | 27 ++-- .../ii/scripts/images}/least_busy_region.py | 2 +- .../ii/services/FirstRunExperience.qml | 2 +- .config/quickshell/ii/shell.qml | 6 +- .../illogical-impulse-widgets/PKGBUILD | 1 - 10 files changed, 173 insertions(+), 161 deletions(-) create mode 100644 .config/quickshell/ii/modules/background/Background.qml delete mode 100644 .config/quickshell/ii/modules/backgroundWidgets/BackgroundWidgets.qml rename .config/{matugen/scripts => quickshell/ii/scripts/images}/least_busy_region.py (99%) diff --git a/.config/hypr/hyprland/execs.conf b/.config/hypr/hyprland/execs.conf index 33fc3ffb..0d04c512 100644 --- a/.config/hypr/hyprland/execs.conf +++ b/.config/hypr/hyprland/execs.conf @@ -1,7 +1,5 @@ # Bar, wallpaper exec-once = ~/.config/hypr/hyprland/scripts/start_geoclue_agent.sh & gammastep -exec-once = sleep 0.7; [ "$(hyprctl monitors -j | jq 'length')" -eq 1 ] && swww-daemon --format xrgb --no-cache || swww-daemon --format xrgb -exec-once = sleep 0.7; swww img "$(cat ~/.local/state/quickshell/user/generated/wallpaper/path.txt)" --transition-step 100 --transition-fps 120 --transition-type grow --transition-angle 30 --transition-duration 1 exec-once = qs -c $qsConfig & # Input method diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml new file mode 100644 index 00000000..cfd0678b --- /dev/null +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -0,0 +1,152 @@ +pragma ComponentBehavior: Bound + +import "root:/" +import "root:/modules/common" +import "root:/modules/common/widgets" +import "root:/services" +import "root:/modules/common/functions/color_utils.js" as ColorUtils +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Wayland + +// TODO REMOVE BACKGROUNDWIDGETS + +Scope { + id: root + readonly property bool fixedClockPosition: Config.options.background.fixedClockPosition + readonly property real fixedClockX: Config.options.background.clockX + readonly property real fixedClockY: Config.options.background.clockY + + Variants { + // For each monitor + model: Quickshell.screens + + PanelWindow { + id: bgRoot + + required property var modelData + property string wallpaperPath: Config.options.background.wallpaperPath + // Position + property real clockX: modelData.width / 2 + property real clockY: modelData.height / 2 + property var textHorizontalAlignment: clockX < screen.width / 3 ? Text.AlignLeft : + (clockX > screen.width * 2 / 3 ? Text.AlignRight : Text.AlignHCenter) + // Colors + property color dominantColor: Appearance.colors.colPrimary + property bool dominantColorIsDark: dominantColor.hslLightness < 0.5 + property color colText: ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (dominantColorIsDark ? 0.8 : 0.12)) + + // Layer props + screen: modelData + WlrLayershell.layer: WlrLayer.Bottom + WlrLayershell.namespace: "quickshell:background" + anchors { + top: true + bottom: true + left: true + right: true + } + color: "transparent" + + // Clock positioning + function updateClockPosition() { + leastBusyRegionProc.path = wallpaperPath // Somehow this is needed to make the proc correctly use the new path + leastBusyRegionProc.contentWidth = clock.implicitWidth + leastBusyRegionProc.contentHeight = clock.implicitHeight + leastBusyRegionProc.running = false; + leastBusyRegionProc.running = true; + } + onWallpaperPathChanged: { + // console.log("[Background] Wallpaper path changed to:", wallpaperPath) + bgRoot.updateClockPosition() + } + Process { + id: leastBusyRegionProc + running: true + property string path: bgRoot.wallpaperPath + property int contentWidth: bgRoot.screen.width + property int contentHeight: bgRoot.screen.height + command: [Quickshell.configPath("scripts/images/least_busy_region.py"), + "--screen-width", bgRoot.screen.width, + "--screen-height", bgRoot.screen.height, + "--width", contentWidth, + "--height", contentHeight, + path + ] + stdout: StdioCollector { + id: leastBusyRegionOutputCollector + onStreamFinished: { + const output = leastBusyRegionOutputCollector.text + console.log("[Background] Least busy region output:", output) + if (output.length === 0) return; + const parsedContent = JSON.parse(output) + bgRoot.clockX = parsedContent.center_x + bgRoot.clockY = parsedContent.center_y + bgRoot.dominantColor = parsedContent.dominant_color || Appearance.colors.colPrimary + } + } + } + + // Wallpaper + AnimatedImage { + z: 0 + anchors.fill: parent + source: bgRoot.wallpaperPath + fillMode: Image.PreserveAspectCrop + sourceSize { + width: bgRoot.screen.width + height: bgRoot.screen.height + } + } + + // The clock + Item { + id: clock + z: 1 + anchors { + left: parent.left + top: parent.top + leftMargin: (root.fixedClockPosition ? root.fixedClockX : bgRoot.clockX) - implicitWidth / 2 + topMargin: (root.fixedClockPosition ? root.fixedClockY : bgRoot.clockY) - implicitHeight / 2 + Behavior on leftMargin { + animation: Appearance.animation.elementMove.numberAnimation.createObject(this) + } + Behavior on topMargin { + animation: Appearance.animation.elementMove.numberAnimation.createObject(this) + } + } + + implicitWidth: clockColumn.implicitWidth + implicitHeight: clockColumn.implicitHeight + + ColumnLayout { + id: clockColumn + anchors.centerIn: parent + spacing: -5 + + StyledText { + Layout.fillWidth: true + horizontalAlignment: bgRoot.textHorizontalAlignment + font.pixelSize: 95 + color: bgRoot.colText + style: Text.Raised + styleColor: Appearance.colors.colShadow + text: DateTime.time + } + StyledText { + Layout.fillWidth: true + horizontalAlignment: bgRoot.textHorizontalAlignment + font.pixelSize: 25 + color: bgRoot.colText + style: Text.Raised + styleColor: Appearance.colors.colShadow + text: DateTime.date + } + } + } + } + } +} diff --git a/.config/quickshell/ii/modules/backgroundWidgets/BackgroundWidgets.qml b/.config/quickshell/ii/modules/backgroundWidgets/BackgroundWidgets.qml deleted file mode 100644 index 35f30534..00000000 --- a/.config/quickshell/ii/modules/backgroundWidgets/BackgroundWidgets.qml +++ /dev/null @@ -1,139 +0,0 @@ -import "root:/" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Quickshell.Io -import Quickshell.Wayland -import Quickshell.Hyprland -import Quickshell.Services.UPower - -Scope { - id: root - property string filePath: `${Directories.state}/user/generated/wallpaper/least_busy_region.json` - property real defaultX: (Config.options?.background.clockX ?? -500) - property real defaultY: (Config.options?.background.clockY ?? -500) - property real centerX: defaultX - property real centerY: defaultY - property real effectiveCenterX: Config.options?.background.fixedClockPosition ? defaultX : centerX - property real effectiveCenterY: Config.options?.background.fixedClockPosition ? defaultY : centerY - property color dominantColor: Appearance.colors.colPrimary - property bool dominantColorIsDark: dominantColor.hslLightness < 0.5 - property color colBackground: ColorUtils.transparentize(ColorUtils.mix(Appearance.colors.colPrimary, Appearance.colors.colSecondaryContainer), 1) - property color colText: ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (root.dominantColorIsDark ? 0.8 : 0.12)) - - function updateWidgetPosition(fileContent) { - // console.log("[BackgroundWidgets] Updating widget position with content:", fileContent) - const parsedContent = JSON.parse(fileContent) - root.centerX = parsedContent.center_x - root.centerY = parsedContent.center_y - root.dominantColor = parsedContent.dominant_color || Appearance.colors.colPrimary - } - - Timer { - id: delayedFileRead - interval: Config.options.hacks.arbitraryRaceConditionDelay - running: false - onTriggered: { - root.updateWidgetPosition(leastBusyRegionFileView.text()) - } - } - - FileView { - id: leastBusyRegionFileView - path: Qt.resolvedUrl(root.filePath) - watchChanges: !Config.options?.background.fixedClockPosition - onFileChanged: { - this.reload() - delayedFileRead.start() - } - onLoadedChanged: { - const fileContent = leastBusyRegionFileView.text() - root.updateWidgetPosition(fileContent) - } - } - - Variants { // For each monitor - model: Quickshell.screens - - LazyLoader { - required property var modelData - readonly property HyprlandMonitor monitor: Hyprland.monitorFor(modelData) - activeAsync: !ToplevelManager.activeToplevel?.activated - component: PanelWindow { // Window - id: windowRoot - screen: modelData - property var textHorizontalAlignment: root.effectiveCenterX / monitor.scale < windowRoot.width / 3 ? Text.AlignLeft : - (root.effectiveCenterX / monitor.scale > windowRoot.width * 2 / 3 ? Text.AlignRight : Text.AlignHCenter) - - WlrLayershell.layer: WlrLayer.Bottom - WlrLayershell.namespace: "quickshell:backgroundWidgets" - - anchors { - top: true - bottom:true - left: true - right: true - } - color: "transparent" - // HyprlandWindow.visibleMask: Region { // Buggy with scaled monitors - // item: widgetBackground - // } - - Rectangle { - id: widgetBackground - property real verticalPadding: 20 - property real horizontalPadding: 30 - radius: 40 - color: root.colBackground - implicitHeight: columnLayout.implicitHeight + verticalPadding * 2 - implicitWidth: columnLayout.implicitWidth + horizontalPadding * 2 - anchors { - left: parent.left - top: parent.top - leftMargin: (root.effectiveCenterX / monitor.scale - implicitWidth / 2) - topMargin: (root.effectiveCenterY / monitor.scale - implicitHeight / 2) - Behavior on leftMargin { - animation: Appearance.animation.elementMove.numberAnimation.createObject(this) - } - Behavior on topMargin { - animation: Appearance.animation.elementMove.numberAnimation.createObject(this) - } - } - - ColumnLayout { - id: columnLayout - anchors.centerIn: parent - spacing: -5 - - StyledText { - Layout.fillWidth: true - horizontalAlignment: windowRoot.textHorizontalAlignment - font.pixelSize: 95 - color: root.colText - style: Text.Raised - styleColor: Appearance.colors.colShadow - text: DateTime.time - } - StyledText { - Layout.fillWidth: true - horizontalAlignment: windowRoot.textHorizontalAlignment - font.pixelSize: 25 - color: root.colText - style: Text.Raised - styleColor: Appearance.colors.colShadow - text: DateTime.date - } - } - } - - } - } - - } - -} diff --git a/.config/quickshell/ii/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml index 27d5a6de..08383c10 100644 --- a/.config/quickshell/ii/modules/bar/Bar.qml +++ b/.config/quickshell/ii/modules/bar/Bar.qml @@ -3,7 +3,7 @@ import "root:/services" import "root:/modules/common/" import "root:/modules/common/widgets" import "root:/modules/common/functions/color_utils.js" as ColorUtils -import "root:/modules/bar/weather" +import "./weather" import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml index 1b9b1dd8..64f13651 100644 --- a/.config/quickshell/ii/modules/common/Config.qml +++ b/.config/quickshell/ii/modules/common/Config.qml @@ -98,6 +98,7 @@ Singleton { property bool fixedClockPosition: false property real clockX: -500 property real clockY: -500 + property string wallpaperPath: Quickshell.configPath("assets/images/default_wallpaper.png") } property JsonObject bar: JsonObject { diff --git a/.config/quickshell/ii/scripts/colors/switchwall.sh b/.config/quickshell/ii/scripts/colors/switchwall.sh index 0d9ffadb..e0be2dac 100755 --- a/.config/quickshell/ii/scripts/colors/switchwall.sh +++ b/.config/quickshell/ii/scripts/colors/switchwall.sh @@ -8,6 +8,7 @@ CONFIG_DIR="$XDG_CONFIG_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" CACHE_DIR="$XDG_CACHE_HOME/quickshell" STATE_DIR="$XDG_STATE_HOME/quickshell" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SHELL_CONFIG_FILE="$XDG_CONFIG_HOME/illogical-impulse/config.json" MATUGEN_DIR="$XDG_CONFIG_HOME/matugen" terminalscheme="$SCRIPT_DIR/terminal/scheme-base.json" @@ -59,14 +60,14 @@ post_process() { handle_kde_material_you_colors & # Determine the largest region on the wallpaper that's sufficiently un-busy to put widgets in - if [ ! -f "$MATUGEN_DIR/scripts/least_busy_region.py" ]; then - echo "Error: least_busy_region.py script not found in $MATUGEN_DIR/scripts/" - else - "$MATUGEN_DIR/scripts/least_busy_region.py" \ - --screen-width "$screen_width" --screen-height "$screen_height" \ - --width 300 --height 200 \ - "$wallpaper_path" > "$STATE_DIR"/user/generated/wallpaper/least_busy_region.json - fi + # if [ ! -f "$MATUGEN_DIR/scripts/least_busy_region.py" ]; then + # echo "Error: least_busy_region.py script not found in $MATUGEN_DIR/scripts/" + # else + # "$MATUGEN_DIR/scripts/least_busy_region.py" \ + # --screen-width "$screen_width" --screen-height "$screen_height" \ + # --width 300 --height 200 \ + # "$wallpaper_path" > "$STATE_DIR"/user/generated/wallpaper/least_busy_region.json + # fi } check_and_prompt_upscale() { @@ -227,10 +228,10 @@ switch() { else matugen_args=(image "$imgpath") generate_colors_material_args=(--path "$imgpath") - # Set wallpaper with swww - swww img "$imgpath" --transition-step 100 --transition-fps 120 \ - --transition-type grow --transition-angle 30 --transition-duration 1 \ - --transition-pos "$cursorposx, $cursorposy_inverted" & + # Update wallpaper path in config + if [ -f "$SHELL_CONFIG_FILE" ]; then + jq --arg path "$imgpath" '.background.wallpaperPath = $path' "$SHELL_CONFIG_FILE" > "$SHELL_CONFIG_FILE.tmp" && mv "$SHELL_CONFIG_FILE.tmp" "$SHELL_CONFIG_FILE" + fi remove_restore fi fi @@ -318,7 +319,7 @@ main() { ;; --noswitch) noswitch_flag="1" - imgpath=$(swww query | head -1 | awk -F 'image: ' '{print $2}') + imgpath=$(jq -r '.background.wallpaperPath' "$SHELL_CONFIG_FILE" 2>/dev/null || echo "") shift ;; *) diff --git a/.config/matugen/scripts/least_busy_region.py b/.config/quickshell/ii/scripts/images/least_busy_region.py similarity index 99% rename from .config/matugen/scripts/least_busy_region.py rename to .config/quickshell/ii/scripts/images/least_busy_region.py index a1f2f47b..bad58bd8 100755 --- a/.config/matugen/scripts/least_busy_region.py +++ b/.config/quickshell/ii/scripts/images/least_busy_region.py @@ -257,7 +257,7 @@ def main(): parser.add_argument("-v", "--visual-output", action="store_true", help="Output image with rectangle") parser.add_argument("--screen-width", type=int, default=1920, help="Screen width for wallpaper scaling") parser.add_argument("--screen-height", type=int, default=1080, help="Screen height for wallpaper scaling") - parser.add_argument("--stride", type=int, default=4, help="Step size for sliding window (higher is faster, less precise)") + parser.add_argument("--stride", type=int, default=10, help="Step size for sliding window (higher is faster, less precise)") parser.add_argument("--screen-mode", choices=["fill", "fit"], default="fill", help="Wallpaper scaling mode: 'fill' (default) or 'fit'") parser.add_argument("--verbose", action="store_true", help="Print verbose output") parser.add_argument("-l", "--largest-region", action="store_true", help="Find the largest region under the variance threshold and output its center") diff --git a/.config/quickshell/ii/services/FirstRunExperience.qml b/.config/quickshell/ii/services/FirstRunExperience.qml index 5bdae455..350c3159 100644 --- a/.config/quickshell/ii/services/FirstRunExperience.qml +++ b/.config/quickshell/ii/services/FirstRunExperience.qml @@ -27,7 +27,7 @@ Singleton { } function handleFirstRun() { - Quickshell.execDetached(["bash", "-c", `swww query | grep 'image' || '${Directories.wallpaperSwitchScriptPath}' '${root.defaultWallpaperPath}'`]) + Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, root.defaultWallpaperPath]) Quickshell.execDetached(["bash", "-c", `qs -p '${root.welcomeQmlPath}'`]) } diff --git a/.config/quickshell/ii/shell.qml b/.config/quickshell/ii/shell.qml index 68d1502f..a026342d 100644 --- a/.config/quickshell/ii/shell.qml +++ b/.config/quickshell/ii/shell.qml @@ -6,7 +6,7 @@ //@ pragma Env QT_SCALE_FACTOR=1 import "./modules/common/" -import "./modules/backgroundWidgets/" +import "./modules/background/" import "./modules/bar/" import "./modules/cheatsheet/" import "./modules/dock/" @@ -30,7 +30,7 @@ ShellRoot { // Enable/disable modules here. False = not loaded at all, so rest assured // no unnecessary stuff will take up memory if you decide to only use, say, the overview. property bool enableBar: true - property bool enableBackgroundWidgets: true + property bool enableBackground: true property bool enableCheatsheet: true property bool enableDock: true property bool enableMediaControls: true @@ -53,7 +53,7 @@ ShellRoot { } LazyLoader { active: enableBar; component: Bar {} } - LazyLoader { active: enableBackgroundWidgets; component: BackgroundWidgets {} } + LazyLoader { active: enableBackground; component: Background {} } LazyLoader { active: enableCheatsheet; component: Cheatsheet {} } LazyLoader { active: enableDock && Config.options.dock.enable; component: Dock {} } LazyLoader { active: enableMediaControls; component: MediaControls {} } diff --git a/arch-packages/illogical-impulse-widgets/PKGBUILD b/arch-packages/illogical-impulse-widgets/PKGBUILD index ae26fc90..9aa690dc 100644 --- a/arch-packages/illogical-impulse-widgets/PKGBUILD +++ b/arch-packages/illogical-impulse-widgets/PKGBUILD @@ -13,7 +13,6 @@ depends=( hyprpicker nm-connection-editor quickshell-git - swww translate-shell wlogout ) From 78c91500d6e417c4f400a7a27a2abb70836e2118 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 14 Jul 2025 22:55:15 +0700 Subject: [PATCH 219/328] wallpaper: fix stretch --- .config/quickshell/ii/modules/background/Background.qml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index cfd0678b..0e5a8522 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -12,8 +12,6 @@ import Quickshell import Quickshell.Io import Quickshell.Wayland -// TODO REMOVE BACKGROUNDWIDGETS - Scope { id: root readonly property bool fixedClockPosition: Config.options.background.fixedClockPosition @@ -80,7 +78,7 @@ Scope { id: leastBusyRegionOutputCollector onStreamFinished: { const output = leastBusyRegionOutputCollector.text - console.log("[Background] Least busy region output:", output) + // console.log("[Background] Least busy region output:", output) if (output.length === 0) return; const parsedContent = JSON.parse(output) bgRoot.clockX = parsedContent.center_x @@ -91,7 +89,7 @@ Scope { } // Wallpaper - AnimatedImage { + Image { z: 0 anchors.fill: parent source: bgRoot.wallpaperPath From 3110df8974fd27b337711ae68e23ec7927e5f216 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 15 Jul 2025 09:27:05 +0700 Subject: [PATCH 220/328] background: make it fill properly --- .config/quickshell/ii/modules/background/Background.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index 0e5a8522..d507d5d1 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -39,6 +39,7 @@ Scope { // Layer props screen: modelData + exclusionMode: ExclusionMode.Ignore WlrLayershell.layer: WlrLayer.Bottom WlrLayershell.namespace: "quickshell:background" anchors { From 86d3f75d12416df4fa0c9caeca4724a428a09ae1 Mon Sep 17 00:00:00 2001 From: nahilrasheed <88521572+nahilrasheed@users.noreply.github.com> Date: Tue, 15 Jul 2025 14:34:44 +0300 Subject: [PATCH 221/328] hyprland: add window rules for xdg-portal file dialogs Add windowrulev2 entries for file picker dialogs with titles like "wants to save" and "wants to open" to float and center them. --- .config/hypr/hyprland/rules.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index 6b6922a5..aa9eb7e3 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -58,6 +58,8 @@ windowrulev2 = center, title:^(Open Folder)(.*)$ windowrulev2 = center, title:^(Save As)(.*)$ windowrulev2 = center, title:^(Library)(.*)$ windowrulev2 = center, title:^(File Upload)(.*)$ +windowrulev2 = center, title:^(.*)(wants to save)$ +windowrulev2 = center, title:^(.*)(wants to open)$ windowrulev2 = float, title:^(Open File)(.*)$ windowrulev2 = float, title:^(Select a File)(.*)$ windowrulev2 = float, title:^(Choose wallpaper)(.*)$ @@ -65,6 +67,8 @@ windowrulev2 = float, title:^(Open Folder)(.*)$ windowrulev2 = float, title:^(Save As)(.*)$ windowrulev2 = float, title:^(Library)(.*)$ windowrulev2 = float, title:^(File Upload)(.*)$ +windowrulev2 = float, title:^(.*)(wants to save)$ +windowrulev2 = float, title:^(.*)(wants to open)$ # --- Tearing --- From ffe1783aa3397786097d628b13748442cba54921 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 15 Jul 2025 20:37:25 +0700 Subject: [PATCH 222/328] background: clock: fly in from random direction --- .config/quickshell/ii/modules/background/Background.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index d507d5d1..341b6513 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -28,8 +28,8 @@ Scope { required property var modelData property string wallpaperPath: Config.options.background.wallpaperPath // Position - property real clockX: modelData.width / 2 - property real clockY: modelData.height / 2 + property real clockX: (modelData.width / 2) + ((Math.random() < 0.5 ? -1 : 1) * modelData.width) + property real clockY: (modelData.height / 2) + ((Math.random() < 0.5 ? -1 : 1) * modelData.height) property var textHorizontalAlignment: clockX < screen.width / 3 ? Text.AlignLeft : (clockX > screen.width * 2 / 3 ? Text.AlignRight : Text.AlignHCenter) // Colors From 77c5923782dcff57d87de76371699d8b00b14fc3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 15 Jul 2025 20:37:36 +0700 Subject: [PATCH 223/328] cheatsheet: fix weird popup anim --- .config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml b/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml index 8e409ab9..733adad3 100644 --- a/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml +++ b/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml @@ -158,14 +158,20 @@ Scope { // Scope spacing: 10 Behavior on implicitWidth { + id: contentWidthBehavior + enabled: false animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } Behavior on implicitHeight { + id: contentHeightBehavior + enabled: false animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } currentIndex: tabBar.externalTrackedTab onCurrentIndexChanged: { + contentWidthBehavior.enabled = true; + contentHeightBehavior.enabled = true; tabBar.enableIndicatorAnimation = true; root.selectedTab = currentIndex; } From 4d10ee603605daf8e218a5910b6b424bf9e50500 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 15 Jul 2025 20:44:17 +0700 Subject: [PATCH 224/328] media controls: adjust color overlay transparency --- .config/quickshell/ii/modules/mediaControls/PlayerControl.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml b/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml index b58bd742..0da91a99 100644 --- a/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml +++ b/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml @@ -149,7 +149,7 @@ Item { // Player instance Rectangle { anchors.fill: parent - color: ColorUtils.transparentize(blendedColors.colLayer0, 0.25) + color: ColorUtils.transparentize(blendedColors.colLayer0, 0.3) radius: root.popupRounding } } From c46a4cb3eff433f90d2f2731cfc0ccfca43f6a86 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 15 Jul 2025 22:45:34 +0700 Subject: [PATCH 225/328] nuke anyrun --- .config/anyrun/config.ron | 13 -------- .config/anyrun/style.css | 66 --------------------------------------- 2 files changed, 79 deletions(-) delete mode 100644 .config/anyrun/config.ron delete mode 100644 .config/anyrun/style.css diff --git a/.config/anyrun/config.ron b/.config/anyrun/config.ron deleted file mode 100644 index c3eafd7a..00000000 --- a/.config/anyrun/config.ron +++ /dev/null @@ -1,13 +0,0 @@ -Config( - x: Fraction(0.500000), - y: Absolute(15), - width: Fraction(0.300000), - height: Absolute(0), - hide_icons: false, - ignore_exclusive_zones: false, - layer: Overlay, - hide_plugin_info: true, - close_on_click: true, - show_results_immediately: false, - max_entries: None, -) diff --git a/.config/anyrun/style.css b/.config/anyrun/style.css deleted file mode 100644 index ca45f260..00000000 --- a/.config/anyrun/style.css +++ /dev/null @@ -1,66 +0,0 @@ -* { - all: unset; - font-size: 1.3rem; -} - -#window, -#match, -#entry, -#plugin, -#main { - background: transparent; -} - -#match.activatable { - border-radius: 16px; - padding: 0.3rem 0.9rem; - margin-top: 0.01rem; -} -#match.activatable:first-child { - margin-top: 0.7rem; -} -#match.activatable:last-child { - margin-bottom: 0.6rem; -} - -#plugin:hover #match.activatable { - border-radius: 10px; - padding: 0.3rem; - margin-top: 0.01rem; - margin-bottom: 0; -} - -#match:selected, -#match:hover, -#plugin:hover { - background: #2e3131; -} - -#entry { - background: #0b0f10; - border: 1px solid #0b0f10; - border-radius: 16px; - margin: 0.5rem; - padding: 0.3rem 1rem; -} - -list > #plugin { - border-radius: 16px; - margin: 0 0.3rem; -} -list > #plugin:first-child { - margin-top: 0.3rem; -} -list > #plugin:last-child { - margin-bottom: 0.3rem; -} -list > #plugin:hover { - padding: 0.6rem; -} - -box#main { - background: #0b0f10; - box-shadow: inset 0 0 0 1px #0b0f10, 0 0 0 1px #0b0f10; - border-radius: 24px; - padding: 0.3rem; -} From abc9b4cdb783b5e7b435fff3d0b82bac3baa7223 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 15 Jul 2025 23:20:08 +0700 Subject: [PATCH 226/328] systeminfo: fix distro id --- .config/quickshell/ii/services/SystemInfo.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/ii/services/SystemInfo.qml b/.config/quickshell/ii/services/SystemInfo.qml index cd3d9f38..cb96b54b 100644 --- a/.config/quickshell/ii/services/SystemInfo.qml +++ b/.config/quickshell/ii/services/SystemInfo.qml @@ -36,9 +36,9 @@ Singleton { const nameMatch = textOsRelease.match(/^NAME="(.+?)"/m) distroName = prettyNameMatch ? prettyNameMatch[1] : (nameMatch ? nameMatch[1].replace(/Linux/i, "").trim() : "Unknown") - // Extract the ID (LOGO field, fallback to "unknown") - const logoMatch = textOsRelease.match(/^LOGO=(.+)$/m) - distroId = logoMatch ? logoMatch[1].replace(/"/g, "") : "unknown" + // Extract the ID + const idMatch = textOsRelease.match(/^ID="?(.+?)"?$/m) + distroId = idMatch ? idMatch[1] : "unknown" // Extract additional URLs and logo const homeUrlMatch = textOsRelease.match(/^HOME_URL="(.+?)"/m) From 08e3a9bddb7ad2ed8b073aa63cbceeecc33f3771 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 00:15:31 +0700 Subject: [PATCH 227/328] background: parallax wallpaper --- .../ii/modules/background/Background.qml | 176 ++++++++++++------ .../quickshell/ii/modules/common/Config.qml | 4 + .../ii/scripts/images/least_busy_region.py | 29 +-- 3 files changed, 142 insertions(+), 67 deletions(-) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index 341b6513..55d13d64 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -11,6 +11,7 @@ import QtQuick.Layouts import Quickshell import Quickshell.Io import Quickshell.Wayland +import Quickshell.Hyprland Scope { id: root @@ -26,7 +27,19 @@ Scope { id: bgRoot required property var modelData + // Workspaces + property HyprlandMonitor monitor: Hyprland.monitorFor(modelData) + property list relevantWindows: HyprlandData.windowList.filter(win => win.monitor == monitor.id && win.workspace.id >= 0).sort((a, b) => a.workspace.id - b.workspace.id) + property int firstWorkspaceId: relevantWindows[0]?.workspace.id || 1 + property int lastWorkspaceId: relevantWindows[relevantWindows.length - 1]?.workspace.id || 10 + // Wallpaper property string wallpaperPath: Config.options.background.wallpaperPath + property real preferredWallpaperScale: Config.options.background.parallax.workspaceZoom + property real effectiveWallpaperScale: 1 // Some reasonable init value, to be updated + property int wallpaperWidth: modelData.width // Some reasonable init value, to be updated + property int wallpaperHeight: modelData.height // Some reasonable init value, to be updated + property real movableXSpace: (effectiveWallpaperScale - 1) / 2 * screen.width + property real movableYSpace: (effectiveWallpaperScale - 1) / 2 * screen.height // Position property real clockX: (modelData.width / 2) + ((Math.random() < 0.5 ? -1 : 1) * modelData.width) property real clockY: (modelData.height / 2) + ((Math.random() < 0.5 ? -1 : 1) * modelData.height) @@ -50,29 +63,63 @@ Scope { } color: "transparent" + onWallpaperPathChanged: { + bgRoot.updateZoomScale() + // Clock position gets updated after zoom scale is updated + } + + // Wallpaper zoom scale + function updateZoomScale() { + getWallpaperSizeProc.path = bgRoot.wallpaperPath + getWallpaperSizeProc.running = true; + } + Process { + id: getWallpaperSizeProc + property string path: bgRoot.wallpaperPath + command: [ "magick", "identify", "-format", "%w %h", path ] + stdout: StdioCollector { + id: wallpaperSizeOutputCollector + onStreamFinished: { + const output = wallpaperSizeOutputCollector.text + const [width, height] = output.split(" ").map(Number); + bgRoot.wallpaperWidth = width + bgRoot.wallpaperHeight = height + bgRoot.effectiveWallpaperScale = Math.max(1, Math.min( + bgRoot.preferredWallpaperScale, + width / bgRoot.screen.width, + height / bgRoot.screen.height + )); + + bgRoot.updateClockPosition() + } + } + } + // Clock positioning function updateClockPosition() { - leastBusyRegionProc.path = wallpaperPath // Somehow this is needed to make the proc correctly use the new path + // Somehow all this manual setting is needed to make the proc correctly use the new values + leastBusyRegionProc.path = bgRoot.wallpaperPath leastBusyRegionProc.contentWidth = clock.implicitWidth leastBusyRegionProc.contentHeight = clock.implicitHeight + leastBusyRegionProc.horizontalPadding = (effectiveWallpaperScale - 1) / 2 * screen.width + 100 + leastBusyRegionProc.verticalPadding = (effectiveWallpaperScale - 1) / 2 * screen.height + 100 leastBusyRegionProc.running = false; leastBusyRegionProc.running = true; } - onWallpaperPathChanged: { - // console.log("[Background] Wallpaper path changed to:", wallpaperPath) - bgRoot.updateClockPosition() - } Process { id: leastBusyRegionProc - running: true property string path: bgRoot.wallpaperPath - property int contentWidth: bgRoot.screen.width - property int contentHeight: bgRoot.screen.height + property int contentWidth: 300 + property int contentHeight: 300 + property int horizontalPadding: bgRoot.movableXSpace + property int verticalPadding: bgRoot.movableYSpace command: [Quickshell.configPath("scripts/images/least_busy_region.py"), "--screen-width", bgRoot.screen.width, "--screen-height", bgRoot.screen.height, "--width", contentWidth, "--height", contentHeight, + "--horizontal-padding", horizontalPadding, + "--vertical-padding", verticalPadding, path ] stdout: StdioCollector { @@ -91,58 +138,79 @@ Scope { // Wallpaper Image { - z: 0 - anchors.fill: parent + property real value // 0 to 1, for offset + value: { + // Range = half-groups that workspaces span on + const chunkSize = 3; + const lower = Math.floor(bgRoot.firstWorkspaceId / chunkSize) * chunkSize; + const upper = Math.ceil(bgRoot.lastWorkspaceId / chunkSize) * chunkSize; + const range = upper - lower; + return (bgRoot.monitor.activeWorkspace.id - lower) / range; + } + property real effectiveValue: Math.max(0, Math.min(1, value)) + x: -(bgRoot.movableXSpace) - (effectiveValue - 0.5) * 2 * bgRoot.movableXSpace + y: -(bgRoot.movableYSpace) source: bgRoot.wallpaperPath fillMode: Image.PreserveAspectCrop + Behavior on x { + NumberAnimation { + duration: 600 + easing.type: Easing.OutCubic + } + } sourceSize { - width: bgRoot.screen.width - height: bgRoot.screen.height - } - } - - // The clock - Item { - id: clock - z: 1 - anchors { - left: parent.left - top: parent.top - leftMargin: (root.fixedClockPosition ? root.fixedClockX : bgRoot.clockX) - implicitWidth / 2 - topMargin: (root.fixedClockPosition ? root.fixedClockY : bgRoot.clockY) - implicitHeight / 2 - Behavior on leftMargin { - animation: Appearance.animation.elementMove.numberAnimation.createObject(this) - } - Behavior on topMargin { - animation: Appearance.animation.elementMove.numberAnimation.createObject(this) - } + width: bgRoot.screen.width * bgRoot.effectiveWallpaperScale + height: bgRoot.screen.height * bgRoot.effectiveWallpaperScale } - implicitWidth: clockColumn.implicitWidth - implicitHeight: clockColumn.implicitHeight - - ColumnLayout { - id: clockColumn - anchors.centerIn: parent - spacing: -5 - - StyledText { - Layout.fillWidth: true - horizontalAlignment: bgRoot.textHorizontalAlignment - font.pixelSize: 95 - color: bgRoot.colText - style: Text.Raised - styleColor: Appearance.colors.colShadow - text: DateTime.time + // The clock + Item { + id: clock + anchors { + left: parent.left + top: parent.top + leftMargin: ((root.fixedClockPosition ? root.fixedClockX : bgRoot.clockX * bgRoot.effectiveWallpaperScale) - implicitWidth / 2) + topMargin: ((root.fixedClockPosition ? root.fixedClockY : bgRoot.clockY * bgRoot.effectiveWallpaperScale) - implicitHeight / 2) + Behavior on leftMargin { + animation: Appearance.animation.elementMove.numberAnimation.createObject(this) + } + Behavior on topMargin { + animation: Appearance.animation.elementMove.numberAnimation.createObject(this) + } } - StyledText { - Layout.fillWidth: true - horizontalAlignment: bgRoot.textHorizontalAlignment - font.pixelSize: 25 - color: bgRoot.colText - style: Text.Raised - styleColor: Appearance.colors.colShadow - text: DateTime.date + + implicitWidth: clockColumn.implicitWidth + implicitHeight: clockColumn.implicitHeight + + ColumnLayout { + id: clockColumn + anchors.centerIn: parent + spacing: -5 + + StyledText { + Layout.fillWidth: true + horizontalAlignment: bgRoot.textHorizontalAlignment + font { + pixelSize: 85 + weight: Font.Medium + } + color: bgRoot.colText + style: Text.Raised + styleColor: Appearance.colors.colShadow + text: DateTime.time + } + StyledText { + Layout.fillWidth: true + horizontalAlignment: bgRoot.textHorizontalAlignment + font { + pixelSize: 20 + weight: Font.Medium + } + color: bgRoot.colText + style: Text.Raised + styleColor: Appearance.colors.colShadow + text: DateTime.date + } } } } diff --git a/.config/quickshell/ii/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml index 64f13651..582c11d8 100644 --- a/.config/quickshell/ii/modules/common/Config.qml +++ b/.config/quickshell/ii/modules/common/Config.qml @@ -99,6 +99,10 @@ Singleton { property real clockX: -500 property real clockY: -500 property string wallpaperPath: Quickshell.configPath("assets/images/default_wallpaper.png") + property JsonObject parallax: JsonObject { + property real workspaceZoom: 1.07 // Relative to your screen, not wallpaper size + property bool enableWorkspace: true + } } property JsonObject bar: JsonObject { diff --git a/.config/quickshell/ii/scripts/images/least_busy_region.py b/.config/quickshell/ii/scripts/images/least_busy_region.py index bad58bd8..2b1d104e 100755 --- a/.config/quickshell/ii/scripts/images/least_busy_region.py +++ b/.config/quickshell/ii/scripts/images/least_busy_region.py @@ -18,7 +18,7 @@ def center_crop(img, target_w, target_h): y2 = y1 + target_h return img[y1:y2, x1:x2] -def find_least_busy_region(image_path, region_width=300, region_height=200, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", padding=50): +def find_least_busy_region(image_path, region_width=300, region_height=200, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", horizontal_padding=50, vertical_padding=50): img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if img is None: raise FileNotFoundError(f"Image not found: {image_path}") @@ -59,10 +59,10 @@ def find_least_busy_region(image_path, region_width=300, region_height=200, scre min_var = None min_coords = (0, 0) area = region_width * region_height - x_start = padding - y_start = padding - x_end = w - region_width - padding + 1 - y_end = h - region_height - padding + 1 + x_start = horizontal_padding + y_start = vertical_padding + x_end = w - region_width - horizontal_padding + 1 + y_end = h - region_height - vertical_padding + 1 for y in range(y_start, max(y_end, y_start+1), stride): for x in range(x_start, max(x_end, x_start+1), stride): x1, y1 = x, y @@ -76,7 +76,7 @@ def find_least_busy_region(image_path, region_width=300, region_height=200, scre min_coords = (x, y) return min_coords, min_var -def find_largest_region(image_path, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", threshold=100.0, aspect_ratio=1.0, padding=50): +def find_largest_region(image_path, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", threshold=100.0, aspect_ratio=1.0, horizontal_padding=50, vertical_padding=50): img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if img is None: raise FileNotFoundError(f"Image not found: {image_path}") @@ -130,10 +130,10 @@ def find_largest_region(image_path, screen_width=None, screen_height=None, verbo max_size = mid - 1 continue found = False - x_start = padding - y_start = padding - x_end = w - region_w - padding + 1 - y_end = h - region_h - padding + 1 + x_start = horizontal_padding + y_start = vertical_padding + x_end = w - region_w - horizontal_padding + 1 + y_end = h - region_h - vertical_padding + 1 for y in range(y_start, max(y_end, y_start+1), stride): for x in range(x_start, max(x_end, x_start+1), stride): x1, y1 = x, y @@ -263,7 +263,8 @@ def main(): parser.add_argument("-l", "--largest-region", action="store_true", help="Find the largest region under the variance threshold and output its center") parser.add_argument("-t", "--variance-threshold", type=float, default=1000.0, help="Variance threshold for largest region mode") parser.add_argument("--aspect-ratio", type=float, default=1.78, help="Aspect ratio (width/height) for largest region mode") - parser.add_argument("--padding", type=int, default=50, help="Minimum distance from region to image edge (default: 50)") + parser.add_argument("--horizontal-padding", "-hp", type=int, default=50, help="Minimum horizontal distance from region to image edge") + parser.add_argument("--vertical-padding", "-vp", type=int, default=50, help="Minimum vertical distance from region to image edge") args = parser.parse_args() if args.largest_region: @@ -276,7 +277,8 @@ def main(): screen_mode=args.screen_mode, threshold=args.variance_threshold, aspect_ratio=args.aspect_ratio, - padding=args.padding + horizontal_padding=args.horizontal_padding, + vertical_padding=args.vertical_padding ) if center: if args.visual_output: @@ -312,7 +314,8 @@ def main(): verbose=args.verbose, stride=args.stride, screen_mode=args.screen_mode, - padding=args.padding + horizontal_padding=args.horizontal_padding, + vertical_padding=args.vertical_padding ) if args.visual_output: draw_region(args.image_path, coords, region_width=args.width, region_height=args.height, screen_width=args.screen_width, screen_height=args.screen_height, screen_mode=args.screen_mode) From bb221326eba85d3dd72d83c0d7e6b8eec51d8d28 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 00:17:18 +0700 Subject: [PATCH 228/328] background parallax: make half groups really half group --- .config/quickshell/ii/modules/background/Background.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index 55d13d64..acaf63cc 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -141,7 +141,7 @@ Scope { property real value // 0 to 1, for offset value: { // Range = half-groups that workspaces span on - const chunkSize = 3; + const chunkSize = 5; const lower = Math.floor(bgRoot.firstWorkspaceId / chunkSize) * chunkSize; const upper = Math.ceil(bgRoot.lastWorkspaceId / chunkSize) * chunkSize; const range = upper - lower; From 06ed6dd1e73e29c0c3d664f1f6c3a4e9d81baea6 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 09:04:20 +0700 Subject: [PATCH 229/328] use space grotesk for clocks --- .config/hypr/hyprlock.conf | 2 +- .config/matugen/templates/hyprland/hyprlock.conf | 6 +++--- .../ii/modules/background/Background.qml | 2 ++ .../quickshell/ii/modules/common/Appearance.qml | 1 + .../ii/modules/screenCorners/ScreenCorners.qml | 14 -------------- .config/quickshell/ii/modules/session/Session.qml | 1 - .../illogical-impulse-fonts-themes/PKGBUILD | 1 + 7 files changed, 8 insertions(+), 19 deletions(-) diff --git a/.config/hypr/hyprlock.conf b/.config/hypr/hyprlock.conf index 1e936ce5..ea1d8f0f 100644 --- a/.config/hypr/hyprlock.conf +++ b/.config/hypr/hyprlock.conf @@ -58,7 +58,7 @@ label { # Date text = cmd[update:5000] date +"%A, %B %d" color = $text_color font_size = 17 - font_family = $font_family + font_family = $font_family_clock position = 0, 240 halign = center diff --git a/.config/matugen/templates/hyprland/hyprlock.conf b/.config/matugen/templates/hyprland/hyprlock.conf index eab16719..d557f706 100644 --- a/.config/matugen/templates/hyprland/hyprlock.conf +++ b/.config/matugen/templates/hyprland/hyprlock.conf @@ -2,8 +2,8 @@ $text_color = rgba({{colors.primary_fixed.default.hex_stripped}}FF) $entry_background_color = rgba({{colors.on_primary_fixed.default.hex_stripped}}11) $entry_border_color = rgba({{colors.outline.default.hex_stripped}}55) $entry_color = rgba({{colors.primary_fixed.default.hex_stripped}}FF) -$font_family = Rubik Light -$font_family_clock = Rubik Light +$font_family = Rubik +$font_family_clock = Space Grotesk $font_material_symbols = Material Symbols Rounded background { @@ -58,7 +58,7 @@ label { # Date text = cmd[update:5000] date +"%A, %B %d" color = $text_color font_size = 17 - font_family = $font_family + font_family = $font_family_clock position = 0, 240 halign = center diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index acaf63cc..8bf4b6ec 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -191,6 +191,7 @@ Scope { Layout.fillWidth: true horizontalAlignment: bgRoot.textHorizontalAlignment font { + family: Appearance.font.family.expressive pixelSize: 85 weight: Font.Medium } @@ -203,6 +204,7 @@ Scope { Layout.fillWidth: true horizontalAlignment: bgRoot.textHorizontalAlignment font { + family: Appearance.font.family.expressive pixelSize: 20 weight: Font.Medium } diff --git a/.config/quickshell/ii/modules/common/Appearance.qml b/.config/quickshell/ii/modules/common/Appearance.qml index 88e04bd3..7cc555ec 100644 --- a/.config/quickshell/ii/modules/common/Appearance.qml +++ b/.config/quickshell/ii/modules/common/Appearance.qml @@ -168,6 +168,7 @@ Singleton { property string iconNerd: "SpaceMono NF" property string monospace: "JetBrains Mono NF" property string reading: "Readex Pro" + property string expressive: "Space Grotesk" } property QtObject pixelSize: QtObject { property int smallest: 10 diff --git a/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml b/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml index 0946c03d..b5fc4828 100644 --- a/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml +++ b/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml @@ -26,20 +26,6 @@ Scope { mask: Region { item: null } - // HyprlandWindow.visibleMask: Region { - // Region { - // item: topLeftCorner - // } - // Region { - // item: topRightCorner - // } - // Region { - // item: bottomLeftCorner - // } - // Region { - // item: bottomRightCorner - // } - // } WlrLayershell.namespace: "quickshell:screenCorners" WlrLayershell.layer: WlrLayer.Overlay color: "transparent" diff --git a/.config/quickshell/ii/modules/session/Session.qml b/.config/quickshell/ii/modules/session/Session.qml index 69414f1b..da627d9a 100644 --- a/.config/quickshell/ii/modules/session/Session.qml +++ b/.config/quickshell/ii/modules/session/Session.qml @@ -76,7 +76,6 @@ Scope { StyledText { // Small instruction Layout.alignment: Qt.AlignHCenter horizontalAlignment: Text.AlignHCenter - font.family: Appearance.font.family.title font.pixelSize: Appearance.font.pixelSize.normal text: qsTr("Arrow keys to navigate, Enter to select\nEsc or click anywhere to cancel") } diff --git a/arch-packages/illogical-impulse-fonts-themes/PKGBUILD b/arch-packages/illogical-impulse-fonts-themes/PKGBUILD index 8c5f567c..fd2ee207 100644 --- a/arch-packages/illogical-impulse-fonts-themes/PKGBUILD +++ b/arch-packages/illogical-impulse-fonts-themes/PKGBUILD @@ -15,6 +15,7 @@ depends=( kde-material-you-colors kitty matugen-bin + otf-space-grotesk starship ttf-gabarito-git ttf-jetbrains-mono-nerd From a08e9e0e799c785167c4484cdbe4cecb304c120d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 09:34:22 +0700 Subject: [PATCH 230/328] screen corners: not have a fullscreen layer --- .../modules/screenCorners/ScreenCorners.qml | 85 +++++++++---------- 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml b/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml index b5fc4828..b7d9ee67 100644 --- a/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml +++ b/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml @@ -11,63 +11,56 @@ Scope { id: screenCorners readonly property Toplevel activeWindow: ToplevelManager.activeToplevel + component CornerPanelWindow: PanelWindow { + id: cornerPanelWindow + visible: (Config.options.appearance.fakeScreenRounding === 1 || (Config.options.appearance.fakeScreenRounding === 2 && !activeWindow?.fullscreen)) + property var corner + + exclusionMode: ExclusionMode.Ignore + mask: Region { + item: null + } + WlrLayershell.namespace: "quickshell:screenCorners" + WlrLayershell.layer: WlrLayer.Overlay + color: "transparent" + + anchors { + top: cornerPanelWindow.corner === RoundCorner.CornerEnum.TopLeft || cornerPanelWindow.corner === RoundCorner.CornerEnum.TopRight + left: cornerPanelWindow.corner === RoundCorner.CornerEnum.TopLeft || cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomLeft + bottom: cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomLeft || cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomRight + right: cornerPanelWindow.corner === RoundCorner.CornerEnum.TopRight || cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomRight + } + + implicitWidth: cornerWidget.implicitWidth + implicitHeight: cornerWidget.implicitHeight + RoundCorner { + id: cornerWidget + size: Appearance.rounding.screenRounding + corner: cornerPanelWindow.corner + } + } + Variants { model: Quickshell.screens - PanelWindow { - visible: (Config.options.appearance.fakeScreenRounding === 1 - || (Config.options.appearance.fakeScreenRounding === 2 - && !activeWindow?.fullscreen)) - - property var modelData - - screen: modelData - exclusionMode: ExclusionMode.Ignore - mask: Region { - item: null - } - WlrLayershell.namespace: "quickshell:screenCorners" - WlrLayershell.layer: WlrLayer.Overlay - color: "transparent" - - anchors { - top: true - left: true - right: true - bottom: true - } - - RoundCorner { - id: topLeftCorner - anchors.top: parent.top - anchors.left: parent.left - size: Appearance.rounding.screenRounding + Scope { + required property var modelData + CornerPanelWindow { + screen: modelData corner: RoundCorner.CornerEnum.TopLeft } - RoundCorner { - id: topRightCorner - anchors.top: parent.top - anchors.right: parent.right - size: Appearance.rounding.screenRounding + CornerPanelWindow { + screen: modelData corner: RoundCorner.CornerEnum.TopRight } - RoundCorner { - id: bottomLeftCorner - anchors.bottom: parent.bottom - anchors.left: parent.left - size: Appearance.rounding.screenRounding + CornerPanelWindow { + screen: modelData corner: RoundCorner.CornerEnum.BottomLeft } - RoundCorner { - id: bottomRightCorner - anchors.bottom: parent.bottom - anchors.right: parent.right - size: Appearance.rounding.screenRounding + CornerPanelWindow { + screen: modelData corner: RoundCorner.CornerEnum.BottomRight } - } - } - } From 7821cfe131d7c88e66b2ab5d4f408389da501288 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 09:34:36 +0700 Subject: [PATCH 231/328] dock: dont aggressively unload --- .config/quickshell/ii/modules/dock/Dock.qml | 214 ++++++++++---------- 1 file changed, 104 insertions(+), 110 deletions(-) diff --git a/.config/quickshell/ii/modules/dock/Dock.qml b/.config/quickshell/ii/modules/dock/Dock.qml index 04af9810..0cf51fd7 100644 --- a/.config/quickshell/ii/modules/dock/Dock.qml +++ b/.config/quickshell/ii/modules/dock/Dock.qml @@ -19,131 +19,125 @@ Scope { // Scope Variants { // For each monitor model: Quickshell.screens - LazyLoader { - id: dockLoader - required property var modelData - activeAsync: Config.options?.dock.hoverToReveal || (!ToplevelManager.activeToplevel?.activated) + PanelWindow { // Window + id: dockRoot + screen: dockLoader.modelData + + property bool reveal: root.pinned + || (Config.options?.dock.hoverToReveal && dockMouseArea.containsMouse) + || dockApps.requestDockShow + || (!ToplevelManager.activeToplevel?.activated) - component: PanelWindow { // Window - id: dockRoot - screen: dockLoader.modelData - - property bool reveal: root.pinned - || (Config.options?.dock.hoverToReveal && dockMouseArea.containsMouse) - || dockApps.requestDockShow - || (!ToplevelManager.activeToplevel?.activated) + anchors { + bottom: true + left: true + right: true + } - anchors { - bottom: true - left: true - right: true + exclusiveZone: root.pinned ? implicitHeight + - (Appearance.sizes.hyprlandGapsOut) + - (Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut) : 0 + + implicitWidth: dockBackground.implicitWidth + WlrLayershell.namespace: "quickshell:dock" + color: "transparent" + + implicitHeight: (Config.options?.dock.height ?? 70) + Appearance.sizes.elevationMargin + Appearance.sizes.hyprlandGapsOut + + mask: Region { + item: dockMouseArea + } + + MouseArea { + id: dockMouseArea + anchors.top: parent.top + height: parent.height + anchors.topMargin: dockRoot.reveal ? 0 : + Config.options?.dock.hoverToReveal ? (dockRoot.implicitHeight - Config.options.dock.hoverRegionHeight) : + (dockRoot.implicitHeight + 1) + + anchors.left: parent.left + anchors.right: parent.right + hoverEnabled: true + + Behavior on anchors.topMargin { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - exclusiveZone: root.pinned ? implicitHeight - - (Appearance.sizes.hyprlandGapsOut) - - (Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut) : 0 + Item { + id: dockHoverRegion + anchors.fill: parent - implicitWidth: dockBackground.implicitWidth - WlrLayershell.namespace: "quickshell:dock" - color: "transparent" + Item { // Wrapper for the dock background + id: dockBackground + anchors { + top: parent.top + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } - implicitHeight: (Config.options?.dock.height ?? 70) + Appearance.sizes.elevationMargin + Appearance.sizes.hyprlandGapsOut + implicitWidth: dockRow.implicitWidth + 5 * 2 + height: parent.height - Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut - mask: Region { - item: dockMouseArea - } + StyledRectangularShadow { + target: dockVisualBackground + } + Rectangle { // The real rectangle that is visible + id: dockVisualBackground + property real margin: Appearance.sizes.elevationMargin + anchors.fill: parent + anchors.topMargin: Appearance.sizes.elevationMargin + anchors.bottomMargin: Appearance.sizes.hyprlandGapsOut + color: Appearance.colors.colLayer0 + border.width: 1 + border.color: Appearance.m3colors.m3outlineVariant + radius: Appearance.rounding.large + } - MouseArea { - id: dockMouseArea - anchors.top: parent.top - height: parent.height - anchors.topMargin: dockRoot.reveal ? 0 : - Config.options?.dock.hoverToReveal ? (dockRoot.implicitHeight - Config.options.dock.hoverRegionHeight) : - (dockRoot.implicitHeight + 1) - - anchors.left: parent.left - anchors.right: parent.right - hoverEnabled: true + RowLayout { + id: dockRow + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + spacing: 3 + property real padding: 5 - Behavior on anchors.topMargin { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } - - Item { - id: dockHoverRegion - anchors.fill: parent - - Item { // Wrapper for the dock background - id: dockBackground - anchors { - top: parent.top - bottom: parent.bottom - horizontalCenter: parent.horizontalCenter - } - - implicitWidth: dockRow.implicitWidth + 5 * 2 - height: parent.height - Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut - - StyledRectangularShadow { - target: dockVisualBackground - } - Rectangle { // The real rectangle that is visible - id: dockVisualBackground - property real margin: Appearance.sizes.elevationMargin - anchors.fill: parent - anchors.topMargin: Appearance.sizes.elevationMargin - anchors.bottomMargin: Appearance.sizes.hyprlandGapsOut - color: Appearance.colors.colLayer0 - border.width: 1 - border.color: Appearance.m3colors.m3outlineVariant - radius: Appearance.rounding.large - } - - RowLayout { - id: dockRow - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - spacing: 3 - property real padding: 5 - - VerticalButtonGroup { - Layout.topMargin: Appearance.sizes.hyprlandGapsOut // why does this work - GroupButton { // Pin button - baseWidth: 35 - baseHeight: 35 - clickedWidth: baseWidth - clickedHeight: baseHeight + 20 - buttonRadius: Appearance.rounding.normal - toggled: root.pinned - onClicked: root.pinned = !root.pinned - contentItem: MaterialSymbol { - text: "keep" - horizontalAlignment: Text.AlignHCenter - iconSize: Appearance.font.pixelSize.larger - color: root.pinned ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer0 - } - } - } - DockSeparator {} - DockApps { id: dockApps; } - DockSeparator {} - DockButton { - Layout.fillHeight: true - onClicked: Hyprland.dispatch("global quickshell:overviewToggle") + VerticalButtonGroup { + Layout.topMargin: Appearance.sizes.hyprlandGapsOut // why does this work + GroupButton { // Pin button + baseWidth: 35 + baseHeight: 35 + clickedWidth: baseWidth + clickedHeight: baseHeight + 20 + buttonRadius: Appearance.rounding.normal + toggled: root.pinned + onClicked: root.pinned = !root.pinned contentItem: MaterialSymbol { - anchors.fill: parent + text: "keep" horizontalAlignment: Text.AlignHCenter - font.pixelSize: parent.width / 2 - text: "apps" - color: Appearance.colors.colOnLayer0 + iconSize: Appearance.font.pixelSize.larger + color: root.pinned ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer0 } } } - } - } - + DockSeparator {} + DockApps { id: dockApps; } + DockSeparator {} + DockButton { + Layout.fillHeight: true + onClicked: Hyprland.dispatch("global quickshell:overviewToggle") + contentItem: MaterialSymbol { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + font.pixelSize: parent.width / 2 + text: "apps" + color: Appearance.colors.colOnLayer0 + } + } + } + } } + } } } From 36390e107b7508830ef1616982cc29b0df07c53b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 09:35:42 +0700 Subject: [PATCH 232/328] dock: dont anchor left right --- .config/quickshell/ii/modules/dock/Dock.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.config/quickshell/ii/modules/dock/Dock.qml b/.config/quickshell/ii/modules/dock/Dock.qml index 0cf51fd7..72681875 100644 --- a/.config/quickshell/ii/modules/dock/Dock.qml +++ b/.config/quickshell/ii/modules/dock/Dock.qml @@ -30,8 +30,6 @@ Scope { // Scope anchors { bottom: true - left: true - right: true } exclusiveZone: root.pinned ? implicitHeight From eedd5d8f27f132f6df9aaf4fb56d57937c3d1166 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 09:39:53 +0700 Subject: [PATCH 233/328] hyprland keybinds: remove trailing comma (#1559) --- .config/quickshell/ii/services/HyprlandKeybinds.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/services/HyprlandKeybinds.qml b/.config/quickshell/ii/services/HyprlandKeybinds.qml index a313ffc4..45dc6548 100644 --- a/.config/quickshell/ii/services/HyprlandKeybinds.qml +++ b/.config/quickshell/ii/services/HyprlandKeybinds.qml @@ -41,7 +41,7 @@ Singleton { Process { id: getDefaultKeybinds running: true - command: [root.keybindParserPath, "--path", root.defaultKeybindConfigPath,] + command: [root.keybindParserPath, "--path", root.defaultKeybindConfigPath] stdout: SplitParser { onRead: data => { From 77f21d8e8980ea55583421458aadcbbeb55082c2 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 09:52:46 +0700 Subject: [PATCH 234/328] overview: don't fill the screen --- .config/quickshell/ii/modules/overview/Overview.qml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.config/quickshell/ii/modules/overview/Overview.qml b/.config/quickshell/ii/modules/overview/Overview.qml index 952e5d29..34a8b05c 100644 --- a/.config/quickshell/ii/modules/overview/Overview.qml +++ b/.config/quickshell/ii/modules/overview/Overview.qml @@ -37,12 +37,8 @@ Scope { // item: GlobalStates.overviewOpen ? columnLayout : null // } - anchors { top: true - left: true - right: true - bottom: true } HyprlandFocusGrab { From 623cd842a648106af0b7e3468510b6d2b12bdefb Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 10:00:48 +0700 Subject: [PATCH 235/328] search: prevent shaky while typing, prevent clipboard scrolling to bottom --- .config/quickshell/ii/modules/overview/Overview.qml | 2 ++ .config/quickshell/ii/modules/overview/SearchWidget.qml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.config/quickshell/ii/modules/overview/Overview.qml b/.config/quickshell/ii/modules/overview/Overview.qml index 34a8b05c..46204b3a 100644 --- a/.config/quickshell/ii/modules/overview/Overview.qml +++ b/.config/quickshell/ii/modules/overview/Overview.qml @@ -39,6 +39,7 @@ Scope { anchors { top: true + bottom: true } HyprlandFocusGrab { @@ -81,6 +82,7 @@ Scope { function setSearchingText(text) { searchWidget.setSearchingText(text); + searchWidget.focusFirstItemIfNeeded(); } ColumnLayout { diff --git a/.config/quickshell/ii/modules/overview/SearchWidget.qml b/.config/quickshell/ii/modules/overview/SearchWidget.qml index 2754567e..5304d096 100644 --- a/.config/quickshell/ii/modules/overview/SearchWidget.qml +++ b/.config/quickshell/ii/modules/overview/SearchWidget.qml @@ -396,6 +396,8 @@ Item { // Wrapper } } + onModelChanged: root.focusFirstItemIfNeeded() + delegate: SearchItem { // The selectable item for each search result required property var modelData From d176d385522e1f8d30dd11cc6e9ee5be03f8d541 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 10:23:21 +0700 Subject: [PATCH 236/328] dock: fix hover region and weird popup cutoff --- .config/quickshell/ii/modules/dock/Dock.qml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.config/quickshell/ii/modules/dock/Dock.qml b/.config/quickshell/ii/modules/dock/Dock.qml index 72681875..ff0717fc 100644 --- a/.config/quickshell/ii/modules/dock/Dock.qml +++ b/.config/quickshell/ii/modules/dock/Dock.qml @@ -30,6 +30,8 @@ Scope { // Scope anchors { bottom: true + left: true + right: true } exclusiveZone: root.pinned ? implicitHeight @@ -48,14 +50,15 @@ Scope { // Scope MouseArea { id: dockMouseArea - anchors.top: parent.top height: parent.height - anchors.topMargin: dockRoot.reveal ? 0 : - Config.options?.dock.hoverToReveal ? (dockRoot.implicitHeight - Config.options.dock.hoverRegionHeight) : - (dockRoot.implicitHeight + 1) - - anchors.left: parent.left - anchors.right: parent.right + anchors { + top: parent.top + topMargin: dockRoot.reveal ? 0 : + Config.options?.dock.hoverToReveal ? (dockRoot.implicitHeight - Config.options.dock.hoverRegionHeight) : + (dockRoot.implicitHeight + 1) + horizontalCenter: parent.horizontalCenter + } + implicitWidth: dockHoverRegion.implicitWidth + Appearance.sizes.elevationMargin * 2 hoverEnabled: true Behavior on anchors.topMargin { @@ -65,6 +68,7 @@ Scope { // Scope Item { id: dockHoverRegion anchors.fill: parent + implicitWidth: dockBackground.implicitWidth Item { // Wrapper for the dock background id: dockBackground From 19aa66568fd025d97b8a32f5405a3bd05868086a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 10:38:21 +0700 Subject: [PATCH 237/328] background: add parallax for sidebars --- .config/quickshell/ii/modules/background/Background.qml | 4 +++- .config/quickshell/ii/modules/common/Config.qml | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index 8bf4b6ec..8c41e926 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -145,7 +145,9 @@ Scope { const lower = Math.floor(bgRoot.firstWorkspaceId / chunkSize) * chunkSize; const upper = Math.ceil(bgRoot.lastWorkspaceId / chunkSize) * chunkSize; const range = upper - lower; - return (bgRoot.monitor.activeWorkspace.id - lower) / range; + return (bgRoot.monitor.activeWorkspace.id - lower) / range + + (0.15 * GlobalStates.sidebarRightOpen * Config.options.background.parallax.enableSidebar) + - (0.15 * GlobalStates.sidebarLeftOpen * Config.options.background.parallax.enableSidebar) } property real effectiveValue: Math.max(0, Math.min(1, value)) x: -(bgRoot.movableXSpace) - (effectiveValue - 0.5) * 2 * bgRoot.movableXSpace diff --git a/.config/quickshell/ii/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml index 582c11d8..33ebc94c 100644 --- a/.config/quickshell/ii/modules/common/Config.qml +++ b/.config/quickshell/ii/modules/common/Config.qml @@ -100,8 +100,9 @@ Singleton { property real clockY: -500 property string wallpaperPath: Quickshell.configPath("assets/images/default_wallpaper.png") property JsonObject parallax: JsonObject { - property real workspaceZoom: 1.07 // Relative to your screen, not wallpaper size property bool enableWorkspace: true + property real workspaceZoom: 1.07 // Relative to your screen, not wallpaper size + property bool enableSidebar: true } } From 93ef3c3bdae59538f18fa1fa6e7891ca0d84d3d0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 10:54:39 +0700 Subject: [PATCH 238/328] dock: fix screen --- .config/quickshell/ii/modules/dock/Dock.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/dock/Dock.qml b/.config/quickshell/ii/modules/dock/Dock.qml index ff0717fc..5b8e1b19 100644 --- a/.config/quickshell/ii/modules/dock/Dock.qml +++ b/.config/quickshell/ii/modules/dock/Dock.qml @@ -20,8 +20,9 @@ Scope { // Scope model: Quickshell.screens PanelWindow { // Window + required property var modelData id: dockRoot - screen: dockLoader.modelData + screen: modelData property bool reveal: root.pinned || (Config.options?.dock.hoverToReveal && dockMouseArea.containsMouse) From b98e843a9d2f10946e1c8b8e73e28372460fe0a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Wed, 16 Jul 2025 16:48:21 +0800 Subject: [PATCH 239/328] i18n: removed duplicate translation services and fixed imports --- .config/quickshell/ii/GlobalStates.qml | 2 +- .../ii/modules/bar/ActiveWindow.qml | 2 +- .config/quickshell/ii/modules/bar/Media.qml | 1 + .../modules/common/widgets/PrimaryTabBar.qml | 2 +- .../common/widgets/SelectionDialog.qml | 2 +- .../modules/mediaControls/MediaControls.qml | 1 + .../OnScreenDisplayBrightness.qml | 1 + .../onScreenDisplay/OnScreenDisplayVolume.qml | 1 + .../ii/modules/overview/Overview.qml | 1 - .../quickshell/ii/modules/session/Session.qml | 1 + .../quickshell/ii/modules/settings/About.qml | 1 + .../ii/modules/settings/AdvancedConfig.qml | 1 + .../ii/modules/settings/InterfaceConfig.qml | 1 + .../ii/modules/settings/ServicesConfig.qml | 1 + .../ii/modules/settings/StyleConfig.qml | 1 + .../ii/modules/sidebarLeft/DescriptionBox.qml | 1 + .../ii/modules/sidebarLeft/SidebarLeft.qml | 1 - .../sidebarRight/BottomWidgetGroup.qml | 1 + .../sidebarRight/CenterWidgetGroup.qml | 2 +- .../ii/modules/sidebarRight/SidebarRight.qml | 1 - .../sidebarRight/calendar/CalendarWidget.qml | 1 + .../notifications/NotificationList.qml | 2 +- .../quickToggles/BluetoothToggle.qml | 1 + .../sidebarRight/quickToggles/GameMode.qml | 2 +- .../quickToggles/IdleInhibitor.qml | 2 +- .../quickToggles/NetworkToggle.qml | 2 +- .../sidebarRight/quickToggles/NightLight.qml | 2 +- .../modules/sidebarRight/todo/TodoWidget.qml | 1 + .../volumeMixer/AudioDeviceSelectorButton.qml | 2 +- .../sidebarRight/volumeMixer/VolumeMixer.qml | 2 +- .config/quickshell/ii/screenshot.qml | 2 +- .config/quickshell/ii/services/Ai.qml | 2 +- .config/quickshell/ii/services/Booru.qml | 2 +- .config/quickshell/ii/services/Brightness.qml | 2 +- .../quickshell/ii/services/KeyringStorage.qml | 2 +- .../ii/services/MprisController.qml | 2 +- .../quickshell/ii/services/Translation.qml | 170 ------------------ .config/quickshell/ii/settings.qml | 2 +- .config/quickshell/ii/welcome.qml | 2 +- .../translations/tools/translation-cleaner.py | 2 +- 40 files changed, 36 insertions(+), 194 deletions(-) delete mode 100644 .config/quickshell/ii/services/Translation.qml diff --git a/.config/quickshell/ii/GlobalStates.qml b/.config/quickshell/ii/GlobalStates.qml index 037ffe0c..d473af35 100644 --- a/.config/quickshell/ii/GlobalStates.qml +++ b/.config/quickshell/ii/GlobalStates.qml @@ -1,5 +1,5 @@ import "root:/modules/common/" -import "root:/services/" +import "root:/" import QtQuick import Quickshell import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/bar/ActiveWindow.qml b/.config/quickshell/ii/modules/bar/ActiveWindow.qml index b0f8e049..9187848e 100644 --- a/.config/quickshell/ii/modules/bar/ActiveWindow.qml +++ b/.config/quickshell/ii/modules/bar/ActiveWindow.qml @@ -1,7 +1,7 @@ import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" -import "root:/services/" +import "root:/" import QtQuick import QtQuick.Layouts import Quickshell.Wayland diff --git a/.config/quickshell/ii/modules/bar/Media.qml b/.config/quickshell/ii/modules/bar/Media.qml index 3c6e76ae..9d548623 100644 --- a/.config/quickshell/ii/modules/bar/Media.qml +++ b/.config/quickshell/ii/modules/bar/Media.qml @@ -1,6 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" +import "root:/" import "root:/modules/common/functions/string_utils.js" as StringUtils import QtQuick import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml b/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml index c8843bc2..0c35781f 100644 --- a/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml +++ b/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml @@ -1,5 +1,5 @@ import "root:/modules/common" -import "root:/services/" +import "root:/" import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml b/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml index 9a6d0b7f..5170c6c7 100644 --- a/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml +++ b/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml @@ -1,7 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" -import "root:/services/" +import "root:/" import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/mediaControls/MediaControls.qml b/.config/quickshell/ii/modules/mediaControls/MediaControls.qml index 045a9a75..f918ff70 100644 --- a/.config/quickshell/ii/modules/mediaControls/MediaControls.qml +++ b/.config/quickshell/ii/modules/mediaControls/MediaControls.qml @@ -1,6 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" +import "root:/" import "root:/modules/common/functions/string_utils.js" as StringUtils import "root:/modules/common/functions/file_utils.js" as FileUtils import Qt5Compat.GraphicalEffects diff --git a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml index 32dbefa7..00f9e68e 100644 --- a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml +++ b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml @@ -1,3 +1,4 @@ +import "root:/" import "root:/services/" import "root:/modules/common" import "root:/modules/common/widgets" diff --git a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml index 9850f5ff..5ae1575e 100644 --- a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml +++ b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml @@ -1,3 +1,4 @@ +import "root:/" import "root:/services/" import "root:/modules/common" import "root:/modules/common/widgets" diff --git a/.config/quickshell/ii/modules/overview/Overview.qml b/.config/quickshell/ii/modules/overview/Overview.qml index a4a784d0..1e90674d 100644 --- a/.config/quickshell/ii/modules/overview/Overview.qml +++ b/.config/quickshell/ii/modules/overview/Overview.qml @@ -2,7 +2,6 @@ import "root:/" import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" -import "root:/services/" import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/session/Session.qml b/.config/quickshell/ii/modules/session/Session.qml index dda7ad6d..6d98d98e 100644 --- a/.config/quickshell/ii/modules/session/Session.qml +++ b/.config/quickshell/ii/modules/session/Session.qml @@ -1,4 +1,5 @@ import "root:/modules/common" +import "root:/" import "root:/services/" import "root:/modules/common/widgets" import "root:/modules/common/functions/color_utils.js" as ColorUtils diff --git a/.config/quickshell/ii/modules/settings/About.qml b/.config/quickshell/ii/modules/settings/About.qml index 4db99b68..e2937dfe 100644 --- a/.config/quickshell/ii/modules/settings/About.qml +++ b/.config/quickshell/ii/modules/settings/About.qml @@ -4,6 +4,7 @@ import QtQuick.Layouts import Quickshell import Quickshell.Io import Quickshell.Widgets +import "root:/" import "root:/services/" import "root:/modules/common/" import "root:/modules/common/widgets/" diff --git a/.config/quickshell/ii/modules/settings/AdvancedConfig.qml b/.config/quickshell/ii/modules/settings/AdvancedConfig.qml index c7292231..cd256f38 100644 --- a/.config/quickshell/ii/modules/settings/AdvancedConfig.qml +++ b/.config/quickshell/ii/modules/settings/AdvancedConfig.qml @@ -1,6 +1,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts +import "root:/" import "root:/services/" import "root:/modules/common/" import "root:/modules/common/widgets/" diff --git a/.config/quickshell/ii/modules/settings/InterfaceConfig.qml b/.config/quickshell/ii/modules/settings/InterfaceConfig.qml index 9a269143..30a2a37b 100644 --- a/.config/quickshell/ii/modules/settings/InterfaceConfig.qml +++ b/.config/quickshell/ii/modules/settings/InterfaceConfig.qml @@ -1,6 +1,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts +import "root:/" import "root:/services/" import "root:/modules/common/" import "root:/modules/common/widgets/" diff --git a/.config/quickshell/ii/modules/settings/ServicesConfig.qml b/.config/quickshell/ii/modules/settings/ServicesConfig.qml index cc0c6185..550a36f1 100644 --- a/.config/quickshell/ii/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/ii/modules/settings/ServicesConfig.qml @@ -1,6 +1,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts +import "root:/" import "root:/services/" import "root:/modules/common/" import "root:/modules/common/widgets/" diff --git a/.config/quickshell/ii/modules/settings/StyleConfig.qml b/.config/quickshell/ii/modules/settings/StyleConfig.qml index 31dea05b..b710abce 100644 --- a/.config/quickshell/ii/modules/settings/StyleConfig.qml +++ b/.config/quickshell/ii/modules/settings/StyleConfig.qml @@ -5,6 +5,7 @@ import Quickshell import Quickshell.Io import Quickshell.Widgets import Quickshell.Hyprland +import "root:/" import "root:/services/" import "root:/modules/common/" import "root:/modules/common/widgets/" diff --git a/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml b/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml index 2ac78f5b..835b679d 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml @@ -1,3 +1,4 @@ +import "root:/" import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" diff --git a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml index 97a82791..751287f1 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml @@ -2,7 +2,6 @@ import "root:/" import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" -import "root:/services/" import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml index d2c4af9c..0dd71884 100644 --- a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml +++ b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml @@ -1,5 +1,6 @@ import "root:/modules/common" import "root:/modules/common/widgets" +import "root:/" import "root:/services" import "./calendar" import "./todo" diff --git a/.config/quickshell/ii/modules/sidebarRight/CenterWidgetGroup.qml b/.config/quickshell/ii/modules/sidebarRight/CenterWidgetGroup.qml index 76e47888..126b98c0 100644 --- a/.config/quickshell/ii/modules/sidebarRight/CenterWidgetGroup.qml +++ b/.config/quickshell/ii/modules/sidebarRight/CenterWidgetGroup.qml @@ -5,7 +5,7 @@ import "./calendar" import "./notifications" import "./todo" import "./volumeMixer" -import "root:/services/" +import "root:/" import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml index bd4d5d55..c73a262e 100644 --- a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml @@ -5,7 +5,6 @@ import "root:/modules/common/widgets" import "root:/modules/common/functions/string_utils.js" as StringUtils import "root:/modules/common/functions/file_utils.js" as FileUtils import "./quickToggles/" -import "root:/services/" import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml index 7fd72db4..0c79fcef 100644 --- a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml +++ b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml @@ -1,4 +1,5 @@ import "root:/modules/common" +import "root:/" import "root:/modules/common/widgets" import "./calendar_layout.js" as CalendarLayout import QtQuick diff --git a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml index c334b052..d26693f7 100644 --- a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml +++ b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml @@ -1,7 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" -import "root:/services/" +import "root:/" import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml index 37c3650c..bdbfa959 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml @@ -1,4 +1,5 @@ import "../" +import "root:/" import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/GameMode.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/GameMode.qml index ffee4de1..0c635dbc 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/GameMode.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/GameMode.qml @@ -1,7 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "../" -import "root:/services/" +import "root:/" import Quickshell import Quickshell.Io import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml index ced345f7..2e24b3b1 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml @@ -1,7 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "../" -import "root:/services/" +import "root:/" import Quickshell.Io import Quickshell import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml index a90fe2aa..6ed954c2 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml @@ -3,7 +3,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/string_utils.js" as StringUtils import "../" -import "root:/services/" +import "root:/" import QtQuick import Quickshell import Quickshell.Io diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml index f71d80a2..3cdfad13 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml @@ -1,7 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "../" -import "root:/services/" +import "root:/" import Quickshell.Io import Quickshell diff --git a/.config/quickshell/ii/modules/sidebarRight/todo/TodoWidget.qml b/.config/quickshell/ii/modules/sidebarRight/todo/TodoWidget.qml index fa72061f..f59adcc3 100644 --- a/.config/quickshell/ii/modules/sidebarRight/todo/TodoWidget.qml +++ b/.config/quickshell/ii/modules/sidebarRight/todo/TodoWidget.qml @@ -1,6 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" +import "root:/" import "root:/modules/common/functions/color_utils.js" as ColorUtils import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml index 0e5f37bb..70e3b7ac 100644 --- a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml +++ b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml @@ -1,7 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" -import "root:/services/" +import "root:/" import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml index ec842353..7c74afd6 100644 --- a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml +++ b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml @@ -1,7 +1,7 @@ import "root:/modules/common" import "root:/modules/common/widgets" import "root:/services" -import "root:/services/" +import "root:/" import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/screenshot.qml b/.config/quickshell/ii/screenshot.qml index d4a55de0..99b3b1c2 100644 --- a/.config/quickshell/ii/screenshot.qml +++ b/.config/quickshell/ii/screenshot.qml @@ -6,6 +6,7 @@ //@ pragma Env QT_SCALE_FACTOR=1 pragma ComponentBehavior: "Bound" +import "./" import "./modules/common/" import "./modules/common/widgets" import "./modules/common/functions/string_utils.js" as StringUtils @@ -18,7 +19,6 @@ import Quickshell.Io import Quickshell.Widgets import Quickshell.Wayland import Quickshell.Hyprland -import "./services/" ShellRoot { id: root diff --git a/.config/quickshell/ii/services/Ai.qml b/.config/quickshell/ii/services/Ai.qml index 7c12d5b7..93764ca8 100644 --- a/.config/quickshell/ii/services/Ai.qml +++ b/.config/quickshell/ii/services/Ai.qml @@ -4,7 +4,7 @@ pragma ComponentBehavior: Bound import "root:/modules/common/functions/string_utils.js" as StringUtils import "root:/modules/common/functions/object_utils.js" as ObjectUtils import "root:/modules/common" -import "root:/services/" +import "root:/" import Quickshell; import Quickshell.Io; import Qt.labs.platform diff --git a/.config/quickshell/ii/services/Booru.qml b/.config/quickshell/ii/services/Booru.qml index 5efd1fe3..ce2493f9 100644 --- a/.config/quickshell/ii/services/Booru.qml +++ b/.config/quickshell/ii/services/Booru.qml @@ -2,7 +2,7 @@ pragma Singleton pragma ComponentBehavior: Bound import "root:/modules/common" -import "root:/services/" +import "root:/" import Quickshell; import Quickshell.Io; import Qt.labs.platform diff --git a/.config/quickshell/ii/services/Brightness.qml b/.config/quickshell/ii/services/Brightness.qml index a81c01d5..129da7b2 100644 --- a/.config/quickshell/ii/services/Brightness.qml +++ b/.config/quickshell/ii/services/Brightness.qml @@ -4,7 +4,7 @@ pragma ComponentBehavior: Bound // From https://github.com/caelestia-dots/shell/ (`quickshell` branch) with modifications. // License: GPLv3 -import "root:/services/" +import "root:/" import Quickshell import Quickshell.Io import Quickshell.Hyprland diff --git a/.config/quickshell/ii/services/KeyringStorage.qml b/.config/quickshell/ii/services/KeyringStorage.qml index 3ec7560b..8138f28b 100644 --- a/.config/quickshell/ii/services/KeyringStorage.qml +++ b/.config/quickshell/ii/services/KeyringStorage.qml @@ -1,6 +1,6 @@ pragma Singleton pragma ComponentBehavior: Bound - +import "root:/" import "root:/modules/common" import "root:/modules/common/functions/string_utils.js" as StringUtils import Quickshell; diff --git a/.config/quickshell/ii/services/MprisController.qml b/.config/quickshell/ii/services/MprisController.qml index 90d72ed5..ebc78898 100644 --- a/.config/quickshell/ii/services/MprisController.qml +++ b/.config/quickshell/ii/services/MprisController.qml @@ -4,7 +4,7 @@ pragma ComponentBehavior: Bound // From https://git.outfoxxed.me/outfoxxed/nixnew // It does not have a license, but the author is okay with redistribution. -import "root:/services/" +import "root:/" import QtQml.Models import QtQuick import Quickshell diff --git a/.config/quickshell/ii/services/Translation.qml b/.config/quickshell/ii/services/Translation.qml deleted file mode 100644 index 97aff7c5..00000000 --- a/.config/quickshell/ii/services/Translation.qml +++ /dev/null @@ -1,170 +0,0 @@ -pragma Singleton - -import QtQuick -import Quickshell -import Quickshell.Io -import "root:/modules/common/" - -Singleton { - id: root - - property var translations: ({}) - property string currentLanguage: "en_US" - property var availableLanguages: ["en_US"] - property bool isScanning: false - property bool isLoading: false - - Process { - id: scanLanguagesProcess - command: ["find", Qt.resolvedUrl(Directories.config + "/quickshell/translations/").toString().replace("file://", ""), "-name", "*.json", "-exec", "basename", "{}", ".json", ";"] - running: false - - stdout: SplitParser { - onRead: data => { - if (data.trim().length === 0) return - - var files = data.trim().split('\n') - - for (var i = 0; i < files.length; i++) { - var lang = files[i].trim() - if (lang.length > 0 && root.availableLanguages.indexOf(lang) === -1) { - root.availableLanguages.push(lang) - } - } - } - } - - onExited: (exitCode, exitStatus) => { - root.isScanning = false - if (exitCode !== 0) { - root.availableLanguages = ["en_US"] - } - root.loadTranslations() - } - } - - FileView { - id: translationFileView - onLoaded: { - var textContent = "" - try { - textContent = text() - } catch (e) { - root.translations = {} - root.isLoading = false - return - } - - if (textContent.length === 0) { - root.translations = {} - root.isLoading = false - return - } - - try { - var jsonData = JSON.parse(textContent) - root.translations = jsonData - root.isLoading = false - } catch (e) { - root.translations = {} - root.isLoading = false - } - } - onLoadFailed: (error) => { - root.translations = {} - root.isLoading = false - } - } - - function detectSystemLanguage() { - var locale = Qt.locale().name - return locale - } - - function getLanguageCode() { - var configLang = "auto" - try { - configLang = ConfigOptions.language.ui - } catch (e) { - configLang = "auto" - } - - if (configLang === "auto") { - return detectSystemLanguage() - } else { - if (root.availableLanguages.indexOf(configLang) !== -1) { - return configLang - } else { - return detectSystemLanguage() - } - } - } - - function loadTranslations() { - if (root.isScanning) { - return - } - - var targetLang = getLanguageCode() - root.currentLanguage = targetLang - - // Use empty translations for English (default language) - if (targetLang === "en_US" || targetLang === "en") { - root.translations = {} - return - } - - // Check if target language is available - if (root.availableLanguages.indexOf(targetLang) === -1) { - root.currentLanguage = "en_US" - root.translations = {} - return - } - - // Load translation file - root.isLoading = true - var translationsPath = Qt.resolvedUrl(Directories.config + "/quickshell/translations/" + targetLang + ".json") - translationFileView.path = translationsPath - } - - function tr(text) { - if (!text) { - return "" - } - - var key = text.toString() - - if (root.isLoading) { - return key - } - - if (root.currentLanguage === "en_US" || root.currentLanguage === "en" || !root.translations) { - return key - } - - if (root.translations.hasOwnProperty(key)) { - var translation = root.translations[key] - if (translation && translation.toString().trim().length > 0) { - return translation.toString() - } else { - return translation.toString() - } - } - - return key // Fallback to key name - } - - function reloadTranslations() { - root.scanLanguages() - } - - function scanLanguages() { - var translationsDir = Qt.resolvedUrl(Directories.config + "/quickshell/translations/").toString().replace("file://", "") - root.isScanning = true - scanLanguagesProcess.running = true - } - - Component.onCompleted: { - root.scanLanguages() - } -} diff --git a/.config/quickshell/ii/settings.qml b/.config/quickshell/ii/settings.qml index 91bd61f7..ed511a04 100644 --- a/.config/quickshell/ii/settings.qml +++ b/.config/quickshell/ii/settings.qml @@ -13,7 +13,7 @@ import QtQuick.Window import Quickshell import Quickshell.Io import Quickshell.Hyprland -import "root:/services/" +import "root:/" import "root:/modules/common/" import "root:/modules/common/widgets/" import "root:/modules/common/functions/color_utils.js" as ColorUtils diff --git a/.config/quickshell/ii/welcome.qml b/.config/quickshell/ii/welcome.qml index 40d49653..9e643b77 100644 --- a/.config/quickshell/ii/welcome.qml +++ b/.config/quickshell/ii/welcome.qml @@ -12,7 +12,7 @@ import QtQuick.Window import Quickshell import Quickshell.Io import Quickshell.Hyprland -import "root:/services/" +import "root:/" import "root:/modules/common/" import "root:/modules/common/widgets/" import "root:/modules/common/functions/color_utils.js" as ColorUtils diff --git a/.config/quickshell/translations/tools/translation-cleaner.py b/.config/quickshell/translations/tools/translation-cleaner.py index afc290ad..642101d1 100755 --- a/.config/quickshell/translations/tools/translation-cleaner.py +++ b/.config/quickshell/translations/tools/translation-cleaner.py @@ -52,7 +52,7 @@ def clean_translation_files(translations_dir: str, source_dir: str, backup: bool if backup: # Create backup - backup_file = Path(translations_dir) / f"{lang}.json.backup" + backup_file = Path(translations_dir) / f"{lang}.json.bak" with open(backup_file, 'w', encoding='utf-8') as f: json.dump(translations, f, ensure_ascii=False, indent=2) print(f"Created backup: {backup_file}") From 2ad60a40a8bebe75ae063ef721cb50ee9e431e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Wed, 16 Jul 2025 21:11:27 +0800 Subject: [PATCH 240/328] i18n: Refactor string formatting to use arg() method for translations --- .../ii/modules/sidebarLeft/AiChat.qml | 7 +-- .../ii/modules/sidebarLeft/Anime.qml | 9 ++-- .../modules/sidebarLeft/anime/BooruImage.qml | 2 +- .../sidebarLeft/anime/BooruResponse.qml | 2 +- .../ii/modules/sidebarRight/SidebarRight.qml | 2 +- .../quickToggles/BluetoothToggle.qml | 2 +- .../quickToggles/NetworkToggle.qml | 2 +- .config/quickshell/ii/services/Ai.qml | 37 ++++++++------- .../quickshell/ii/services/KeyringStorage.qml | 2 +- .config/quickshell/translations/en_US.json | 46 ++++++++++--------- .config/quickshell/translations/zh_CN.json | 46 ++++++++++--------- 11 files changed, 85 insertions(+), 72 deletions(-) diff --git a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml index e8a096a9..afd9f41c 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml @@ -377,7 +377,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) Layout.fillWidth: true padding: 10 color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant - placeholderText: StringUtils.format(Translation.tr('Message the model... "{0}" for commands'), root.commandPrefix) + placeholderText: Translation.tr('Message the model... "%1" for commands').arg(root.commandPrefix) background: null @@ -577,8 +577,9 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) id: toolTip extraVisibleCondition: false alternativeVisibleCondition: mouseArea.containsMouse // Show tooltip when hovered - content: StringUtils.format(Translation.tr("Current model: {0}\nSet it with {1}model MODEL"), - Ai.getModel().name, root.commandPrefix) + content: Translation.tr("Current model: %1\nSet it with %2model MODEL") + .arg(Ai.getModel().name) + .arg(root.commandPrefix) } MouseArea { diff --git a/.config/quickshell/ii/modules/sidebarLeft/Anime.qml b/.config/quickshell/ii/modules/sidebarLeft/Anime.qml index 7498dceb..304d8f32 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/Anime.qml @@ -242,7 +242,7 @@ Item { font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.m3colors.m3inverseOnSurface wrapMode: Text.Wrap - text: StringUtils.format(Translation.tr("{0} queries pending"), Booru.runningRequests) + text: Translation.tr("%1 queries pending").arg(Booru.runningRequests) } } } @@ -354,7 +354,7 @@ Item { padding: 10 color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant renderType: Text.NativeRendering - placeholderText: StringUtils.format(Translation.tr('Enter tags, or "{0}" for commands'), root.commandPrefix) + placeholderText: Translation.tr('Enter tags, or "%1" for commands').arg(root.commandPrefix) background: null @@ -518,8 +518,9 @@ Item { extraVisibleCondition: false alternativeVisibleCondition: mouseArea.containsMouse // Show tooltip when hovered // content: Translation.tr("The current API used. Endpoint: ") + Booru.providers[Booru.currentProvider].url + Translation.tr("\nSet with /mode PROVIDER") - content: StringUtils.format(Translation.tr("Current API endpoint: {0}\nSet it with {1}mode PROVIDER"), - Booru.providers[Booru.currentProvider].url, root.commandPrefix) + content: Translation.tr("Current API endpoint: %1\nSet it with %2mode PROVIDER") + .arg(Booru.providers[Booru.currentProvider].url) + .arg(root.commandPrefix) } MouseArea { diff --git a/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml index a260dec5..9ead3116 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml @@ -165,7 +165,7 @@ Button { id: sourceButton visible: root.imageData.source && root.imageData.source.length > 0 Layout.fillWidth: true - buttonText: StringUtils.format(Translation.tr("Go to source ({0})"), StringUtils.getDomain(root.imageData.source)) + buttonText: Translation.tr("Go to source (%1)").arg(StringUtils.getDomain(root.imageData.source)) enabled: root.imageData.source && root.imageData.source.length > 0 onClicked: { root.showActions = false diff --git a/.config/quickshell/ii/modules/sidebarLeft/anime/BooruResponse.qml b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruResponse.qml index 574d57e2..3676e24f 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/anime/BooruResponse.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruResponse.qml @@ -95,7 +95,7 @@ Rectangle { font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.colors.colOnLayer2 // text: `Page ${root.responseData.page}` - text: StringUtils.format(Translation.tr("Page {0}"), root.responseData.page) + text: Translation.tr("Page %1").arg(root.responseData.page) } } } diff --git a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml index c73a262e..9c9af649 100644 --- a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml @@ -124,7 +124,7 @@ Scope { StyledText { font.pixelSize: Appearance.font.pixelSize.normal color: Appearance.colors.colOnLayer0 - text: StringUtils.format(Translation.tr("Uptime: {0}"), DateTime.uptime) + text: Translation.tr("Uptime: %1").arg(DateTime.uptime) textFormat: Text.MarkdownText } diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml index bdbfa959..2b35f8ce 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml @@ -29,7 +29,7 @@ QuickToggleButton { } } StyledToolTip { - content: StringUtils.format(Translation.tr("{0} | Right-click to configure"), + content: Translation.tr("%1 | Right-click to configure").arg( (Bluetooth.bluetoothEnabled && Bluetooth.bluetoothDeviceName.length > 0) ? Bluetooth.bluetoothDeviceName : Translation.tr("Bluetooth")) diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml index 6ed954c2..06238f72 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml @@ -29,6 +29,6 @@ QuickToggleButton { } } StyledToolTip { - content: StringUtils.format(Translation.tr("{0} | Right-click to configure"), Network.networkName) + content: Translation.tr("%1 | Right-click to configure").arg(Network.networkName) } } diff --git a/.config/quickshell/ii/services/Ai.qml b/.config/quickshell/ii/services/Ai.qml index 93764ca8..31724d8e 100644 --- a/.config/quickshell/ii/services/Ai.qml +++ b/.config/quickshell/ii/services/Ai.qml @@ -185,7 +185,7 @@ Singleton { "openrouter-llama4-maverick": { "name": "Llama 4 Maverick", "icon": "ollama-symbolic", - "description": StringUtils.format(Translation.tr("Online via {0} | {1}'s model"), "OpenRouter", "Meta"), + "description": Translation.tr("Online via %1 | %2's model").arg("OpenRouter").arg("Meta"), "homepage": "https://openrouter.ai/meta-llama/llama-4-maverick:free", "endpoint": "https://openrouter.ai/api/v1/chat/completions", "model": "meta-llama/llama-4-maverick:free", @@ -197,7 +197,7 @@ Singleton { "openrouter-deepseek-r1": { "name": "DeepSeek R1", "icon": "deepseek-symbolic", - "description": StringUtils.format(Translation.tr("Online via {0} | {1}'s model"), "OpenRouter", "DeepSeek"), + "description": Translation.tr("Online via %1 | %2's model").arg("OpenRouter").arg("DeepSeek"), "homepage": "https://openrouter.ai/deepseek/deepseek-r1:free", "endpoint": "https://openrouter.ai/api/v1/chat/completions", "model": "deepseek/deepseek-r1:free", @@ -250,7 +250,7 @@ Singleton { root.models[safeModelName] = { "name": guessModelName(model), "icon": guessModelLogo(model), - "description": StringUtils.format(Translation.tr("Local Ollama model | {0}"), model), + "description": Translation.tr("Local Ollama model | %1").arg(model), "homepage": `https://ollama.com/library/${model}`, "endpoint": "http://localhost:11434/v1/chat/completions", "model": model, @@ -314,12 +314,12 @@ Singleton { onLoadedChanged: { if (!promptLoader.loaded) return; Config.options.ai.systemPrompt = promptLoader.text(); - root.addMessage(StringUtils.format("Loaded the following system prompt\n\n---\n\n{0}", Config.options.ai.systemPrompt), root.interfaceRole); + root.addMessage(Translation.tr("Loaded the following system prompt\n\n---\n\n%1").arg(Config.options.ai.systemPrompt), root.interfaceRole); } } function printPrompt() { - root.addMessage(StringUtils.format("The current system prompt is\n\n---\n\n{0}", Config.options.ai.systemPrompt), root.interfaceRole); + root.addMessage(Translation.tr("The current system prompt is\n\n---\n\n%1").arg(Config.options.ai.systemPrompt), root.interfaceRole); } function loadPrompt(filePath) { @@ -352,8 +352,8 @@ Singleton { function addApiKeyAdvice(model) { root.addMessage( - StringUtils.format(Translation.tr('To set an API key, pass it with the command\n\nTo view the key, pass "get" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}'), - model.name, model.key_get_link, model.key_get_description ?? Translation.tr("No further instruction provided")), + Translation.tr('To set an API key, pass it with the command\n\nTo view the key, pass "get" with the command
\n\n### For %1:\n\n**Link**: %2\n\n%3') + .arg(model.name).arg(model.key_get_link).arg(model.key_get_description ?? Translation.tr("No further instruction provided")), Ai.interfaceRole ); } @@ -371,11 +371,14 @@ Singleton { if (model?.requires_key) KeyringStorage.fetchKeyringData(); // See if policy prevents online models if (Config.options.policies.ai === 2 && !model.endpoint.includes("localhost")) { - root.addMessage(StringUtils.format(StringUtils.format("Online models disallowed\n\nControlled by `policies.ai` config option"), model.name), root.interfaceRole); + root.addMessage( + Translation.tr("Online models disallowed for %1\n\nControlled by `policies.ai` config option").arg(model.name), + root.interfaceRole + ); return; } if (setPersistentState) Persistent.states.ai.model = modelId; - if (feedback) root.addMessage(StringUtils.format("Model set to {0}", model.name), root.interfaceRole); + if (feedback) root.addMessage(Translation.tr("Model set to %1").arg(model.name), root.interfaceRole); if (model.requires_key) { // If key not there show advice if (root.apiKeysLoaded && (!root.apiKeys[model.key_id] || root.apiKeys[model.key_id].length === 0)) { @@ -398,13 +401,13 @@ Singleton { } Persistent.states.ai.temperature = value; root.temperature = value; - root.addMessage(StringUtils.format(Translation.tr("Temperature set to {0}"), value), Ai.interfaceRole); + root.addMessage(Translation.tr("Temperature set to %1").arg(value), Ai.interfaceRole); } function setApiKey(key) { const model = models[currentModelId]; if (!model.requires_key) { - root.addMessage(StringUtils.format(Translation.tr("{0} does not require an API key"), model.name), Ai.interfaceRole); + root.addMessage(Translation.tr("%1 does not require an API key").arg(model.name), Ai.interfaceRole); return; } if (!key || key.length === 0) { @@ -413,7 +416,7 @@ Singleton { return; } KeyringStorage.setNestedField(["apiKeys", model.key_id], key.trim()); - root.addMessage(StringUtils.format(Translation.tr("API key set for {0}"), model.name, Ai.interfaceRole)); + root.addMessage(Translation.tr("API key set for %1").arg(model.name), Ai.interfaceRole); } function printApiKey() { @@ -421,17 +424,17 @@ Singleton { if (model.requires_key) { const key = root.apiKeys[model.key_id]; if (key) { - root.addMessage(StringUtils.format(Translation.tr("API key:\n\n```txt\n{0}\n```"), key), Ai.interfaceRole); + root.addMessage(Translation.tr("API key:\n\n```txt\n%1\n```").arg(key), Ai.interfaceRole); } else { - root.addMessage(StringUtils.format(Translation.tr("No API key set for {0}"), model.name), Ai.interfaceRole); + root.addMessage(Translation.tr("No API key set for %1").arg(model.name), Ai.interfaceRole); } } else { - root.addMessage(StringUtils.format(Translation.tr("{0} does not require an API key"), model.name), Ai.interfaceRole); + root.addMessage(Translation.tr("%1 does not require an API key").arg(model.name), Ai.interfaceRole); } } function printTemperature() { - root.addMessage(StringUtils.format(Translation.tr("Temperature: {0}"), root.temperature), Ai.interfaceRole); + root.addMessage(Translation.tr("Temperature: %1").arg(root.temperature), Ai.interfaceRole); } function clearMessages() { @@ -799,7 +802,7 @@ Singleton { const value = args.value; Config.setNestedValue(key, value); } - else root.addMessage(Translation.tr("Unknown function call: {0}"), "assistant"); + else root.addMessage(Translation.tr("Unknown function call: %1").arg(name), "assistant"); } function chatToJson() { diff --git a/.config/quickshell/ii/services/KeyringStorage.qml b/.config/quickshell/ii/services/KeyringStorage.qml index 8138f28b..33cfcd3b 100644 --- a/.config/quickshell/ii/services/KeyringStorage.qml +++ b/.config/quickshell/ii/services/KeyringStorage.qml @@ -27,7 +27,7 @@ Singleton { return arr.concat([key, root.properties[key]]); }, [] ) - property string keyringLabel: StringUtils.format(Translation.tr("{0} Safe Storage"), "illogical-impulse") + property string keyringLabel: Translation.tr("%1 Safe Storage").arg("illogical-impulse") function setNestedField(path, value) { if (!root.keyringData) root.keyringData = {}; diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index f1da949c..3f4118e1 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -4,8 +4,6 @@ "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key", ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!": ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!", "No further instruction provided": "No further instruction provided", - "API key set for {0}": "API key set for {0}", - "API key:\n\n```txt\n{0}\n```": "API key:\n\n```txt\n{0}\n```", "Action": "Action", "Add": "Add", "Add task": "Add task", @@ -35,8 +33,6 @@ "Closes right sidebar on press": "Closes right sidebar on press", "Copy": "Copy", "Copy code": "Copy code", - "Current API endpoint: {0}\nSet it with {1}mode PROVIDER": "Current API endpoint: {0}\nSet it with {1}mode PROVIDER", - "Current model: {0}\nSet it with {1}model MODEL": "Current model: {0}\nSet it with {1}model MODEL", "Decrease brightness": "Decrease brightness", "Delete": "Delete", "Desktop": "Desktop", @@ -51,7 +47,6 @@ "For storing API keys and other sensitive information": "For storing API keys and other sensitive information", "Game mode": "Game mode", "Get the next page of results": "Get the next page of results", - "Go to source ({0})": "Go to source ({0})", "Hibernate": "Hibernate", "Hides brightness OSD on press": "Hides brightness OSD on press", "Hides volume OSD on press": "Hides volume OSD on press", @@ -66,13 +61,11 @@ "Large images | God tier quality, no NSFW.": "Large images | God tier quality, no NSFW.", "Large language models": "Large language models", "Launch": "Launch", - "Local Ollama model | {0}": "Local Ollama model | {0}", "Lock": "Lock", "Logout": "Logout", "Markdown test": "Markdown test", "Math result": "Math result", "Night Light": "Night Light", - "No API key set for {0}": "No API key set for {0}", "No audio source": "No audio source", "No media": "No media", "No notifications": "No notifications", @@ -88,7 +81,6 @@ "Opens right sidebar on press": "Opens right sidebar on press", "Opens session screen on press": "Opens session screen on press", "Output": "Output", - "Page {0}": "Page {0}", "Reboot": "Reboot", "Reboot to firmware settings": "Reboot to firmware settings", "Reload Hyprland & Quickshell": "Reload Hyprland & Quickshell", @@ -111,8 +103,6 @@ "Task Manager": "Task Manager", "Task description": "Task description", "Temperature must be between 0 and 2": "Temperature must be between 0 and 2", - "Temperature set to {0}": "Temperature set to {0}", - "Temperature: {0}": "Temperature: {0}", "The hentai one | Great quantity, a lot of NSFW, quality varies wildly": "The hentai one | Great quantity, a lot of NSFW, quality varies wildly", "The popular one | Best quantity, but quality can vary wildly": "The popular one | Best quantity, but quality can vary wildly", "Thinking": "Thinking", @@ -136,18 +126,12 @@ "Unknown Album": "Unknown Album", "Unknown Artist": "Unknown Artist", "Unknown Title": "Unknown Title", - "Unknown function call: {0}": "Unknown function call: {0}", - "Uptime: {0}": "Uptime: {0}", "View Markdown source": "View Markdown source", "Volume": "Volume", "Volume mixer": "Volume mixer", "Waifus only | Excellent quality, limited quantity": "Waifus only | Excellent quality, limited quantity", "Waiting for response...": "Waiting for response...", "Workspace": "Workspace", - "{0} Safe Storage": "{0} Safe Storage", - "{0} does not require an API key": "{0} does not require an API key", - "{0} queries pending": "{0} queries pending", - "{0} | Right-click to configure": "{0} | Right-click to configure", "Set with /mode PROVIDER": "Set with /mode PROVIDER", "Invalid API provider. Supported: \n-": "Invalid API provider. Supported: \n-", "Unknown command:": "Unknown command:", @@ -157,14 +141,10 @@ "Provider set to": "Provider set to", "Invalid model. Supported: \n```": "Invalid model. Supported: \n```", "Interrupts possibility of overview being toggled on release.": "Interrupts possibility of overview being toggled on release.", - "Enter tags, or \"{0}\" for commands": "Enter tags, or \"{0}\" for commands", "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number", "Online | Google's model\nGives up-to-date information with search.": "Online | Google's model\nGives up-to-date information with search.", - "Online via {0} | {1}'s model": "Online via {0} | {1}'s model", "Switched to search mode. Continue with the user's request.": "Switched to search mode. Continue with the user's request.", "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly", - "Message the model... \"{0}\" for commands": "Message the model... \"{0}\" for commands", - "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}": "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}", "Settings": "Settings", "Save chat": "Save chat", "Load chat": "Load chat", @@ -302,5 +282,29 @@ "Qt apps": "Qt apps", "Report a Bug": "Report a Bug", "Issues": "Issues", - "Drag or click a region • LMB: Copy • RMB: Edit": "Drag or click a region • LMB: Copy • RMB: Edit" + "Drag or click a region • LMB: Copy • RMB: Edit": "Drag or click a region • LMB: Copy • RMB: Edit", + "Current model: %1\nSet it with %2model MODEL": "Current model: %1\nSet it with %2model MODEL", + "Message the model... \"%1\" for commands": "Message the model... \"%1\" for commands", + "No API key set for %1": "No API key set for %1", + "Loaded the following system prompt\n\n---\n\n%1": "Loaded the following system prompt\n\n---\n\n%1", + "%1 | Right-click to configure": "%1 | Right-click to configure", + "API key set for %1": "API key set for %1", + "Online models disallowed for %1\n\nControlled by `policies.ai` config option": "Online models disallowed for %1\n\nControlled by `policies.ai` config option", + "Online via %1 | %2's model": "Online via %1 | %2's model", + "Current API endpoint: %1\nSet it with %2mode PROVIDER": "Current API endpoint: %1\nSet it with %2mode PROVIDER", + "Go to source (%1)": "Go to source (%1)", + "Temperature set to %1": "Temperature set to %1", + "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For %1:\n\n**Link**: %2\n\n%3": "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For %1:\n\n**Link**: %2\n\n%3", + "Enter tags, or \"%1\" for commands": "Enter tags, or \"%1\" for commands", + "%1 queries pending": "%1 queries pending", + "API key:\n\n```txt\n%1\n```": "API key:\n\n```txt\n%1\n```", + "Uptime: %1": "Uptime: %1", + "%1 Safe Storage": "%1 Safe Storage", + "%1 does not require an API key": "%1 does not require an API key", + "Temperature: %1": "Temperature: %1", + "Model set to %1": "Model set to %1", + "Page %1": "Page %1", + "Local Ollama model | %1": "Local Ollama model | %1", + "The current system prompt is\n\n---\n\n%1": "The current system prompt is\n\n---\n\n%1", + "Unknown function call: %1": "Unknown function call: %1" } \ No newline at end of file diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index a51b8a79..71e64d7e 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -4,8 +4,8 @@ "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key": "**价格**:免费。数据使用政策取决于您的 OpenRouter 账户设置。\n\n**说明**:登录 OpenRouter 账户,在右上角菜单中选择 Keys,点击创建 API 密钥", ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!": ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!", "No further instruction provided": "未提供进一步说明", - "API key set for {0}": "已为 {0} 设置 API 密钥", - "API key:\n\n```txt\n{0}\n```": "API 密钥:\n\n```txt\n{0}\n```", + "API key set for %1": "已为 %1 设置 API 密钥", + "API key:\n\n```txt\n%1\n```": "API 密钥:\n\n```txt\n%1\n```", "Action": "操作", "Add": "添加", "Add task": "添加任务", @@ -35,8 +35,7 @@ "Closes right sidebar on press": "按下时关闭右侧边栏", "Copy": "复制", "Copy code": "复制代码", - "Current API endpoint: {0}\nSet it with {1}mode PROVIDER": "当前 API 端点:{0}\n使用 {1}mode PROVIDER 设置", - "Current model: {0}\nSet it with {1}model MODEL": "当前模型:{0}\n使用 {1}model MODEL 设置", + "Current API endpoint: %1\nSet it with %2mode PROVIDER": "当前 API 端点:%1\n使用 %2mode PROVIDER 设置", "Decrease brightness": "降低亮度", "Delete": "删除", "Desktop": "桌面", @@ -51,7 +50,7 @@ "For storing API keys and other sensitive information": "用于存储 API 密钥和其他敏感信息", "Game mode": "游戏模式", "Get the next page of results": "获取下一页结果", - "Go to source ({0})": "转到源 ({0})", + "Go to source (%1)": "转到源 (%1)", "Hibernate": "休眠", "Hides brightness OSD on press": "按下时隐藏亮度显示", "Hides volume OSD on press": "按下时隐藏音量显示", @@ -66,13 +65,13 @@ "Large images | God tier quality, no NSFW.": "大尺寸图片 | 顶级质量,无 NSFW", "Large language models": "大语言模型", "Launch": "启动", - "Local Ollama model | {0}": "本地 Ollama 模型 | {0}", + "Local Ollama model | %1": "本地 Ollama 模型 | %1", "Lock": "锁定", "Logout": "注销", "Markdown test": "Markdown 测试", "Math result": "数学结果", "Night Light": "护眼模式", - "No API key set for {0}": "未为 {0} 设置 API 密钥", + "No API key set for %1": "未为 %1 设置 API 密钥", "No audio source": "无音频源", "No media": "无媒体", "No notifications": "无通知", @@ -88,7 +87,7 @@ "Opens right sidebar on press": "按下时打开右侧边栏", "Opens session screen on press": "按下时打开会话屏幕", "Output": "输出", - "Page {0}": "第 {0} 页", + "Page %1": "第 %1 页", "Reboot": "重启", "Reboot to firmware settings": "重启到固件设置", "Reload Hyprland & Quickshell": "重新加载 Hyprland 和 Quickshell", @@ -111,8 +110,8 @@ "Task Manager": "任务管理器", "Task description": "任务描述", "Temperature must be between 0 and 2": "温度必须在 0 到 2 之间", - "Temperature set to {0}": "温度设置为 {0}", - "Temperature: {0}": "温度:{0}", + "Temperature set to %1": "温度设置为 %1", + "Temperature: %1": "温度:%1", "The hentai one | Great quantity, a lot of NSFW, quality varies wildly": "成人向 | 数量巨大,大量 NSFW,质量参差不齐", "The popular one | Best quantity, but quality can vary wildly": "最受欢迎 | 数量最多,但质量参差不齐", "Thinking": "思考中", @@ -136,18 +135,18 @@ "Unknown Album": "未知专辑", "Unknown Artist": "未知艺术家", "Unknown Title": "未知标题", - "Unknown function call: {0}": "未知函数调用:{0}", - "Uptime: {0}": "运行时间:{0}", + "Unknown function call: %1": "未知函数调用:%1", + "Uptime: %1": "运行时间:%1", "View Markdown source": "查看 Markdown 源码", "Volume": "音量", "Volume mixer": "音量混合器", "Waifus only | Excellent quality, limited quantity": "仅限角色 | 优秀质量,数量有限", "Waiting for response...": "等待响应...", "Workspace": "工作区", - "{0} Safe Storage": "{0} 安全存储", - "{0} does not require an API key": "{0} 不需要 API 密钥", - "{0} queries pending": "{0} 个查询等待中", - "{0} | Right-click to configure": "{0} | 右键点击进行配置", + "%1 Safe Storage": "%1 安全存储", + "%1 does not require an API key": "%1 不需要 API 密钥", + "%1 queries pending": "%1 个查询等待中", + "%1 | Right-click to configure": "%1 | 右键点击进行配置", "Set with /mode PROVIDER": "使用 /mode PROVIDER 设置", "Invalid API provider. Supported: \n-": "无效的 API 提供商。支持的:\n-", "Unknown command:": "未知命令:", @@ -158,11 +157,10 @@ "Invalid model. Supported: \n```": "无效模型。支持的:\n```", "Interrupts possibility of overview being toggled on release.": "中断松开时切换概览的可能性。", "Switched to search mode. Continue with the user's request.": "已切换到搜索模式。继续处理用户请求。", - "Message the model... \"{0}\" for commands": "与模型对话... \"{0}\" 查看命令", "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "实验性 | 在线 | Google 模型\n功能更多但搜索速度较慢", - "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For {0}:\n\n**Link**: {1}\n\n{2}": "要设置 API 密钥,请将其与命令一起传递\n\n要查看密钥,请将 \"get\" 与命令一起传递
\n\n### 对于 {0}:\n\n**链接**:{1}\n\n{2}", - "Enter tags, or \"{0}\" for commands": "输入标签,或 \"{0}\" 查看命令", - "Online via {0} | {1}'s model": "通过 {0} 在线 | {1} 的模型", + "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For %1:\n\n**Link**: %2\n\n%3": "要设置 API 密钥,请将其与命令一起传递\n\n要查看密钥,请将 \"get\" 与命令一起传递
\n\n### 对于 %1:\n\n**链接**:%2\n\n%3", + "Enter tags, or \"%1\" for commands": "输入标签,或 \"%1\" 查看命令", + "Online via %1 | %2's model": "通过 %1 在线 | %2 的模型", "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "没有找到结果。提示:\n- 检查您的标签和 NSFW 设置\n- 如果没有想到标签,请输入页码", "Online | Google's model\nGives up-to-date information with search.": "在线 | Google 模型\n通过搜索提供最新信息。", "Settings": "设置", @@ -302,5 +300,11 @@ "Qt apps": "Qt 应用", "Report a Bug": "报告问题", "Issues": "问题追踪", - "Drag or click a region • LMB: Copy • RMB: Edit": "拖动或点击一个区域 • 鼠标左键:复制 • 鼠标右键:编辑" + "Drag or click a region • LMB: Copy • RMB: Edit": "拖动或点击一个区域 • 鼠标左键:复制 • 鼠标右键:编辑", + "Current model: %1\nSet it with %2model MODEL": "当前模型:%1\n使用 %2model MODEL 设置", + "Message the model... \"%1\" for commands": "与模型对话... \"%1\" 查看命令", + "The current system prompt is\n\n---\n\n%1": "The current system prompt is\n\n---\n\n%1", + "Model set to %1": "Model set to %1", + "Online models disallowed for %1\n\nControlled by `policies.ai` config option": "Online models disallowed for %1\n\nControlled by `policies.ai` config option", + "Loaded the following system prompt\n\n---\n\n%1": "Loaded the following system prompt\n\n---\n\n%1" } \ No newline at end of file From db82175b6145f74629fad41c2c5d7fa8ac6bcdf9 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 15:54:23 +0200 Subject: [PATCH 241/328] Update CONTRIBUTING.md --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3bd5c8f8..026726a8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ # Contributing -- Please understand that dotfiles are personal -- If you add new stuff, ask me first to not waste your work -- FFS make multiple PRs if you have many features +- Please understand that dotfiles are after all personal. I can accept features I do not personally want, but in that case I will ask you to make it configurable/optionally loaded +- If you add new stuff, it's a good idea to ask me first to not waste your work +- Please make multiple PRs if you have many features From 8a68cf207abe820da21d21586d1d5649cd19e5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Wed, 16 Jul 2025 23:36:47 +0800 Subject: [PATCH 242/328] i18n: Refactor translation management tools and add ignore feature for dynamic resources - Updated README.md to reflect changes in translation management tools and added ignore mark feature for dynamic resources. - Created Chinese translation guide for the translation management tools. - Created English translation guide for the translation management tools. - Enhanced translation-cleaner.py to skip keys marked with /*keep*/ during cleanup. - Improved translation-manager.py to create backups only when updating keys interactively. - Updated zh_CN.json with new translations and added ignore marks for dynamic values. --- .config/quickshell/ii/Translation.qml | 9 ++- .../ii/modules/sidebarLeft/AiChat.qml | 6 +- .../sidebarRight/calendar/CalendarWidget.qml | 2 +- .../notifications/NotificationList.qml | 2 +- .config/quickshell/translations/en_US.json | 14 ++++- .../quickshell/translations/tools/README.md | 33 +++++------ .../translation-tools-guide-zh_CN.md} | 33 ++++++----- .../{ => guide}/translation-tools-guide.md | 32 +++++------ .../translations/tools/translation-cleaner.py | 31 ++++++----- .../translations/tools/translation-manager.py | 55 +++++++++++++------ .config/quickshell/translations/zh_CN.json | 26 ++++++--- 11 files changed, 145 insertions(+), 98 deletions(-) rename .config/quickshell/translations/tools/{翻译管理脚本说明.md => guide/translation-tools-guide-zh_CN.md} (89%) rename .config/quickshell/translations/tools/{ => guide}/translation-tools-guide.md (87%) diff --git a/.config/quickshell/ii/Translation.qml b/.config/quickshell/ii/Translation.qml index 97aff7c5..74a3e6ba 100644 --- a/.config/quickshell/ii/Translation.qml +++ b/.config/quickshell/ii/Translation.qml @@ -145,12 +145,17 @@ Singleton { if (root.translations.hasOwnProperty(key)) { var translation = root.translations[key] if (translation && translation.toString().trim().length > 0) { - return translation.toString() + var str = translation.toString().trim() + if (str.endsWith("/*keep*/")) { + return str.substring(0, str.length - 8).trim() + } else { + return str + } } else { return translation.toString() } } - + return key // Fallback to key name } diff --git a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml index afd9f41c..26f8e583 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml @@ -419,7 +419,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) return { name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "prompt ") : ""}${file.target}`, displayName: `${FileUtils.trimFileExt(FileUtils.fileNameForPath(file.target))}`, - description: `Load prompt from ${file.target}`, + description: Translation.tr("Load prompt from %1").arg(file.target), } }) } else if (messageInputField.text.startsWith(`${root.commandPrefix}save`)) { @@ -438,7 +438,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) return { name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "save ") : ""}${chatName}`, displayName: `${chatName}`, - description: `Save chat from ${chatName}`, + description: Translation.tr("Save chat from %1").arg(chatName), } }) } else if (messageInputField.text.startsWith(`${root.commandPrefix}load`)) { @@ -457,7 +457,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) return { name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "load ") : ""}${chatName}`, displayName: `${chatName}`, - description: `Load chat from ${file.target}`, + description: Translation.tr(`Load chat from %1`).arg(file.target), } }) } else if(messageInputField.text.startsWith(root.commandPrefix)) { diff --git a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml index 0c79fcef..3aac3604 100644 --- a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml +++ b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml @@ -93,7 +93,7 @@ Item { Repeater { model: CalendarLayout.weekDays delegate: CalendarDayButton { - day: modelData.day + day: Translation.tr(modelData.day) isToday: modelData.today bold: true enabled: false diff --git a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml index d26693f7..4c95b9a5 100644 --- a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml +++ b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml @@ -85,7 +85,7 @@ Item { anchors.verticalCenter: parent.verticalCenter anchors.leftMargin: 10 horizontalAlignment: Text.AlignHCenter - text: `${Notifications.list.length} ${Translation.tr("notifications")}` + text: Translation.tr("%1 notifications").arg(Notifications.list.length) opacity: Notifications.list.length > 0 ? 1 : 0 visible: opacity > 0 diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index 3f4118e1..a9ee4e93 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -1,4 +1,11 @@ { + "Mo": "Mo/*keep*/", + "Tu": "Tu/*keep*/", + "We": "We/*keep*/", + "Th": "Th/*keep*/", + "Fr": "Fr/*keep*/", + "Sa": "Sa/*keep*/", + "Su": "Su/*keep*/", "%1 characters": "%1 characters", "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key": "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key", "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key", @@ -152,7 +159,6 @@ "Set the system prompt for the model.": "Set the system prompt for the model.", "To Do": "To Do", "Calendar": "Calendar", - "notifications": "notifications", "Advanced": "Advanced", "About": "About", "Services": "Services", @@ -306,5 +312,9 @@ "Page %1": "Page %1", "Local Ollama model | %1": "Local Ollama model | %1", "The current system prompt is\n\n---\n\n%1": "The current system prompt is\n\n---\n\n%1", - "Unknown function call: %1": "Unknown function call: %1" + "Unknown function call: %1": "Unknown function call: %1", + "%1 notifications": "%1 notifications", + "Save chat from %1": "Save chat from %1", + "Load chat from %1": "Load chat from %1", + "Load prompt from %1": "Load prompt from %1" } \ No newline at end of file diff --git a/.config/quickshell/translations/tools/README.md b/.config/quickshell/translations/tools/README.md index e41c742e..94c21363 100644 --- a/.config/quickshell/translations/tools/README.md +++ b/.config/quickshell/translations/tools/README.md @@ -163,7 +163,6 @@ Translation.tr("Say \"Hello\"") // With parameter placeholders Translation.tr("Hello, %1!").arg(name) -Translation.tr("{0} files selected").arg(count) ``` ## Example Output @@ -235,20 +234,15 @@ Original key count: 470, after cleaning: 420 --source-dir /path/to/source ``` -### Batch Processing +### Ignore Mark Feature -```bash -# Create a processing script -cat > update-all-translations.sh << 'EOF' -#!/bin/bash -for lang in zh_CN ja_JP ko_KR; do - echo "Processing $lang..." - ./manage-translations.sh update -l $lang -done -EOF +For dynamic resources or special texts that should not be automatically cleaned, you can add `/*keep*/` at the end of the translation value. The tool will automatically ignore these keys and will not delete them during cleaning or syncing. -chmod +x update-all-translations.sh -./update-all-translations.sh +Example: +```json +{ + "dynamic_key": "Some dynamic value /*keep*/" +} ``` ## Notes @@ -256,7 +250,8 @@ chmod +x update-all-translations.sh 1. **Backup is important**: The tool automatically creates backups before cleaning, but it is recommended to manually back up important files 2. **Text extraction limitations**: - - Only supports static strings, not dynamically constructed strings + - ~~Only supports static strings, not dynamically constructed strings~~ + - Dynamic resources (such as variable concatenation or runtime-generated text) cannot be automatically extracted. You need to manually add them to the translation file and use the `/*keep*/` mark for ignore management. - Must use the `Translation.tr()` format 3. **File encoding**: All files must use UTF-8 encoding @@ -267,13 +262,16 @@ chmod +x update-all-translations.sh ### Common Issues -**Q: The number of extracted texts does not match expectations?** +**Q: Text does not appear after adding Translation.tr?** +A: You need to import the translation feature in your QML file using `import "root:/"`, otherwise the translation text will not be displayed correctly. + +**Q: The number of extracted texts does not match expectations?** A: Check whether all translatable texts use the `Translation.tr()` format and ensure there are no dynamically constructed strings. -**Q: Some translations are missing after syncing?** +**Q: Some translations are missing after syncing?** A: Check whether the source language file contains all necessary keys, and consider using a different source language for syncing. -**Q: The cleaning operation deleted needed keys?** +**Q: The cleaning operation deleted needed keys?** A: Restore from the automatically created backup file and check whether `Translation.tr()` is used correctly in the source code. ### Restore Backup @@ -285,4 +283,3 @@ cp .config/quickshell/translations/zh_CN.json.backup .config/quickshell/translat # Restore all files cp .config/quickshell/translations.backup/* .config/quickshell/translations/ ``` - diff --git a/.config/quickshell/translations/tools/翻译管理脚本说明.md b/.config/quickshell/translations/tools/guide/translation-tools-guide-zh_CN.md similarity index 89% rename from .config/quickshell/translations/tools/翻译管理脚本说明.md rename to .config/quickshell/translations/tools/guide/translation-tools-guide-zh_CN.md index fa9850cf..821533be 100644 --- a/.config/quickshell/translations/tools/翻译管理脚本说明.md +++ b/.config/quickshell/translations/tools/guide/translation-tools-guide-zh_CN.md @@ -163,7 +163,6 @@ Translation.tr("Say \"Hello\"") // 带参数占位符 Translation.tr("Hello, %1!").arg(name) -Translation.tr("{0} files selected").arg(count) ``` ## 示例输出 @@ -235,29 +234,25 @@ $ ./manage-translations.sh clean --source-dir /path/to/source ``` -### 批量处理 - -```bash -# 创建处理脚本 -cat > update-all-translations.sh << 'EOF' -#!/bin/bash -for lang in zh_CN ja_JP ko_KR; do - echo "Processing $lang..." - ./manage-translations.sh update -l $lang -done -EOF - -chmod +x update-all-translations.sh -./update-all-translations.sh -``` ## 注意事项 1. **备份重要**:在执行清理操作前,工具会自动创建备份,但建议手动备份重要文件 2. **文本提取限制**: - - 只支持静态字符串,不支持动态构建的字符串 + - ~~只支持静态字符串,不支持动态构建的字符串~~ + - 动态资源(如变量拼接、运行时生成的文本)无法自动提取,需要在翻译文件中手动添加,并使用 `/*keep*/` 标记进行忽略管理。 - 必须使用 `Translation.tr()` 格式 +### 忽略标记功能 + +对于动态资源或特殊文本,如果不希望被自动清理,可在翻译值末尾添加 `/*keep*/`,工具会自动忽略这些键,不会在清理和同步时删除。 + +示例: +```json +{ + "dynamic_key": "Some dynamic value /*keep*/" +} +``` 3. **文件编码**:所有文件必须使用 UTF-8 编码 @@ -267,6 +262,10 @@ chmod +x update-all-translations.sh ### 常见问题 + +**Q: 添加了 Translation.tr 后文字不显示?** +A: 需要在 QML 文件中使用 `import "root:/"` 导入翻译功能,否则无法正常显示翻译文本。 + **Q: 提取的文本数量与预期不符?** A: 检查是否所有可翻译文本都使用了 `Translation.tr()` 格式,确保没有动态构建的字符串。 diff --git a/.config/quickshell/translations/tools/translation-tools-guide.md b/.config/quickshell/translations/tools/guide/translation-tools-guide.md similarity index 87% rename from .config/quickshell/translations/tools/translation-tools-guide.md rename to .config/quickshell/translations/tools/guide/translation-tools-guide.md index 96165b99..94c21363 100644 --- a/.config/quickshell/translations/tools/translation-tools-guide.md +++ b/.config/quickshell/translations/tools/guide/translation-tools-guide.md @@ -163,7 +163,6 @@ Translation.tr("Say \"Hello\"") // With parameter placeholders Translation.tr("Hello, %1!").arg(name) -Translation.tr("{0} files selected").arg(count) ``` ## Example Output @@ -235,20 +234,15 @@ Original key count: 470, after cleaning: 420 --source-dir /path/to/source ``` -### Batch Processing +### Ignore Mark Feature -```bash -# Create a processing script -cat > update-all-translations.sh << 'EOF' -#!/bin/bash -for lang in zh_CN ja_JP ko_KR; do - echo "Processing $lang..." - ./manage-translations.sh update -l $lang -done -EOF +For dynamic resources or special texts that should not be automatically cleaned, you can add `/*keep*/` at the end of the translation value. The tool will automatically ignore these keys and will not delete them during cleaning or syncing. -chmod +x update-all-translations.sh -./update-all-translations.sh +Example: +```json +{ + "dynamic_key": "Some dynamic value /*keep*/" +} ``` ## Notes @@ -256,7 +250,8 @@ chmod +x update-all-translations.sh 1. **Backup is important**: The tool automatically creates backups before cleaning, but it is recommended to manually back up important files 2. **Text extraction limitations**: - - Only supports static strings, not dynamically constructed strings + - ~~Only supports static strings, not dynamically constructed strings~~ + - Dynamic resources (such as variable concatenation or runtime-generated text) cannot be automatically extracted. You need to manually add them to the translation file and use the `/*keep*/` mark for ignore management. - Must use the `Translation.tr()` format 3. **File encoding**: All files must use UTF-8 encoding @@ -267,13 +262,16 @@ chmod +x update-all-translations.sh ### Common Issues -**Q: The number of extracted texts does not match expectations?** +**Q: Text does not appear after adding Translation.tr?** +A: You need to import the translation feature in your QML file using `import "root:/"`, otherwise the translation text will not be displayed correctly. + +**Q: The number of extracted texts does not match expectations?** A: Check whether all translatable texts use the `Translation.tr()` format and ensure there are no dynamically constructed strings. -**Q: Some translations are missing after syncing?** +**Q: Some translations are missing after syncing?** A: Check whether the source language file contains all necessary keys, and consider using a different source language for syncing. -**Q: The cleaning operation deleted needed keys?** +**Q: The cleaning operation deleted needed keys?** A: Restore from the automatically created backup file and check whether `Translation.tr()` is used correctly in the source code. ### Restore Backup diff --git a/.config/quickshell/translations/tools/translation-cleaner.py b/.config/quickshell/translations/tools/translation-cleaner.py index 642101d1..b26e3fbd 100755 --- a/.config/quickshell/translations/tools/translation-cleaner.py +++ b/.config/quickshell/translations/tools/translation-cleaner.py @@ -50,29 +50,34 @@ def clean_translation_files(translations_dir: str, source_dir: str, backup: bool translations = manager.load_translation_file(lang) original_count = len(translations) - if backup: - # Create backup - backup_file = Path(translations_dir) / f"{lang}.json.bak" - with open(backup_file, 'w', encoding='utf-8') as f: - json.dump(translations, f, ensure_ascii=False, indent=2) - print(f"Created backup: {backup_file}") - - # Find unused keys - unused_keys = set(translations.keys()) - current_texts - + # Find unused keys, skip those whose value ends with /*keep*/ + unused_keys = set() + for k in translations.keys(): + v = translations[k] + if k not in current_texts: + if isinstance(v, str) and v.strip().endswith('/*keep*/'): + continue + unused_keys.add(k) + if unused_keys: print(f"Found {len(unused_keys)} unused keys:") for i, key in enumerate(sorted(unused_keys)[:10], 1): # Only show first 10 print(f" {i}. \"{key[:50]}{'...' if len(key) > 50 else ''}\"") if len(unused_keys) > 10: print(f" ... and {len(unused_keys) - 10} more keys") - + response = input(f"Delete these {len(unused_keys)} unused keys? (y/n): ") if response.lower().strip() in ['y', 'yes']: + if backup: + # Create backup only when user confirms deletion + backup_file = Path(translations_dir) / f"{lang}.json.bak" + with open(backup_file, 'w', encoding='utf-8') as f: + json.dump(translations, f, ensure_ascii=False, indent=2) + print(f"Created backup: {backup_file}") # Delete unused keys for key in unused_keys: del translations[key] - + # Save cleaned file manager.save_translation_file(lang, translations) removed_count = len(unused_keys) @@ -82,7 +87,7 @@ def clean_translation_files(translations_dir: str, source_dir: str, backup: bool print("Skipped deletion") else: print("No unused keys found") - + new_count = len(translations) print(f"Original key count: {original_count}, after cleanup: {new_count}") diff --git a/.config/quickshell/translations/tools/translation-manager.py b/.config/quickshell/translations/tools/translation-manager.py index 1b1a604a..a3105446 100755 --- a/.config/quickshell/translations/tools/translation-manager.py +++ b/.config/quickshell/translations/tools/translation-manager.py @@ -138,35 +138,52 @@ class TranslationManager: return missing_keys, extra_keys def interactive_update(self, lang_code: str, missing_keys: Set[str], extra_keys: Set[str]): - """Interactively update translation file""" + """Interactively update translation file, create backup only if updating""" translations = self.load_translation_file(lang_code) modified = False - + backup_created = False + # Handle missing keys if missing_keys: print(f"\nFound {len(missing_keys)} missing translation keys:") for i, key in enumerate(sorted(missing_keys), 1): print(f"{i}. \"{key}\"") - + if self.ask_yes_no(f"\nAdd these {len(missing_keys)} missing keys?"): + if not backup_created: + backup_file = self.translations_dir / f"{lang_code}.json.bak" + with open(backup_file, 'w', encoding='utf-8') as f: + json.dump(translations, f, ensure_ascii=False, indent=2) + print(f"Created backup: {backup_file}") + backup_created = True for key in missing_keys: translations[key] = key # Default value is the key itself modified = True print(f"Added {len(missing_keys)} keys") - + # Handle extra keys if extra_keys: - print(f"\nFound {len(extra_keys)} extra translation keys:") - for i, key in enumerate(sorted(extra_keys), 1): - print(f"{i}. \"{key}\" -> \"{translations.get(key, '')}\"") - - if self.ask_yes_no(f"\nDelete these {len(extra_keys)} extra keys?"): - for key in extra_keys: - if key in translations: - del translations[key] - modified = True - print(f"Deleted {len(extra_keys)} keys") - + # Only show extra keys that are not marked with /*keep*/ + filtered_extra_keys = [key for key in extra_keys if not (isinstance(translations.get(key, ""), str) and translations.get(key, "").strip().endswith('/*keep*/'))] + if filtered_extra_keys: + print(f"\nFound {len(filtered_extra_keys)} extra translation keys:") + for i, key in enumerate(sorted(filtered_extra_keys), 1): + print(f"{i}. \"{key}\" -> \"{translations.get(key, '')}\"") + if self.ask_yes_no(f"\nDelete these {len(filtered_extra_keys)} extra keys?"): + if not backup_created: + backup_file = self.translations_dir / f"{lang_code}.json.bak" + with open(backup_file, 'w', encoding='utf-8') as f: + json.dump(translations, f, ensure_ascii=False, indent=2) + print(f"Created backup: {backup_file}") + backup_created = True + deleted_count = 0 + for key in filtered_extra_keys: + if key in translations: + del translations[key] + modified = True + deleted_count += 1 + print(f"Deleted {deleted_count} keys") + # Save changes if modified: self.save_translation_file(lang_code, translations) @@ -288,7 +305,13 @@ def main(): print(f"Analysis results:") print(f" Missing keys: {len(missing_keys)}") - print(f" Extra keys: {len(extra_keys)}") + # Load translation file for current lang to get values + current_translations = manager.load_translation_file(lang) + filtered_extra_keys = [key for key in extra_keys if not (isinstance(current_translations.get(key, ""), str) and current_translations.get(key, "").strip().endswith('/*keep*/'))] + ignored_extra_keys = [key for key in extra_keys if (isinstance(current_translations.get(key, ""), str) and current_translations.get(key, "").strip().endswith('/*keep*/'))] + print(f" Extra keys: {len(filtered_extra_keys)}") + if ignored_extra_keys: + print(f" Ignored keys: {len(ignored_extra_keys)} (marked with /*keep*/)") if missing_keys or extra_keys: manager.interactive_update(lang, missing_keys, extra_keys) diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index 71e64d7e..c3749d2f 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -1,4 +1,11 @@ { + "Mo": "一/*keep*/", + "Tu": "二/*keep*/", + "We": "三/*keep*/", + "Th": "四/*keep*/", + "Fr": "五/*keep*/", + "Sa": "六/*keep*/", + "Su": "日/*keep*/", "%1 characters": "%1 个字符", "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**价格**:免费。数据用于训练。\n\n**说明**:登录 Google 账户,允许 AI Studio 创建 Google Cloud 项目或其他要求,然后返回并点击获取 API 密钥", "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key": "**价格**:免费。数据使用政策取决于您的 OpenRouter 账户设置。\n\n**说明**:登录 OpenRouter 账户,在右上角菜单中选择 Keys,点击创建 API 密钥", @@ -96,7 +103,7 @@ "Save": "保存", "Save to Downloads": "保存到下载文件夹", "Search": "搜索", - "Search the web": "搜索网络", + "Search the web": "在网络上搜索", "Search, calculate or run": "搜索、计算或运行", "Select Language": "选择语言", "Session": "会话", @@ -170,7 +177,6 @@ "Set the system prompt for the model.": "为模型设置系统提示。", "To Do": "待办", "Calendar": "日历", - "notifications": "条通知", "Advanced": "高级", "About": "关于", "Services": "服务", @@ -212,7 +218,7 @@ "Policies": "策略", "Weeb": "二次元", "Closet": "隐藏", - "Bar style": "Bar 样式", + "Bar style": "条栏样式", "Show next time": "下次显示", "Usage": "用法", "Plain rectangle": "纯矩形", @@ -281,7 +287,7 @@ "Screen snip": "屏幕截图", "Mic toggle": "麦克风切换", "Hover to reveal": "悬停显示", - "Bar": "Bar", + "Bar": "条栏", "Show background": "显示背景", "Show regions of potential interest": "显示可能感兴趣的区域", "Color picker": "取色器", @@ -303,8 +309,12 @@ "Drag or click a region • LMB: Copy • RMB: Edit": "拖动或点击一个区域 • 鼠标左键:复制 • 鼠标右键:编辑", "Current model: %1\nSet it with %2model MODEL": "当前模型:%1\n使用 %2model MODEL 设置", "Message the model... \"%1\" for commands": "与模型对话... \"%1\" 查看命令", - "The current system prompt is\n\n---\n\n%1": "The current system prompt is\n\n---\n\n%1", - "Model set to %1": "Model set to %1", - "Online models disallowed for %1\n\nControlled by `policies.ai` config option": "Online models disallowed for %1\n\nControlled by `policies.ai` config option", - "Loaded the following system prompt\n\n---\n\n%1": "Loaded the following system prompt\n\n---\n\n%1" + "The current system prompt is\n\n---\n\n%1": "当前系统提示词为\n\n---\n\n%1", + "Model set to %1": "模型已设置为 %1", + "Online models disallowed for %1\n\nControlled by `policies.ai` config option": "%1 禁止使用在线模型\n\n由 `policies.ai` 配置项控制", + "Loaded the following system prompt\n\n---\n\n%1": "已加载以下系统提示词\n\n---\n\n%1", + "%1 notifications": "%1 条通知", + "Save chat from %1": "保存聊天记录到 %1", + "Load chat from %1": "从 %1 加载聊天记录", + "Load prompt from %1": "从 %1 加载提示词" } \ No newline at end of file From 864c83172b6a6a3a01190a6f7d9b59c7beee2b71 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 16 Jul 2025 17:41:16 +0200 Subject: [PATCH 243/328] readme: make the ii logo on the left and note on the right --- README.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 28fdb28e..da76e53e 100644 --- a/README.md +++ b/README.md @@ -74,11 +74,17 @@

-
- illogical-impulse logo -
+ + + + + +
+ illogical-impulse logo + + latest and only style that I actively use. Other past styles are still there for your viewing pleasure and not actual use, but code is still available, see below. +
-_latest and only style that I actively use. Other past styles are still there for your viewing pleasure and not actual use, but code is still available, see below._ ### illogical-impulseQuickshell @@ -152,6 +158,8 @@ Widget system: AGS | Support: Limited, no new features - EWW: [fufexan's config](https://github.com/fufexan/dotfiles) (he thanks more people there btw) - AI bots for providing useful examples + [@tokyobot](https://github.com/tokyob0t) for saying hi +

• stonks •

From 2b2733679cff0403be9c038b109f26d0edf8ba22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Wed, 16 Jul 2025 23:46:02 +0800 Subject: [PATCH 244/328] i18n: Update translation for online model disallowance message to remove model name reference --- .config/quickshell/ii/services/Ai.qml | 2 +- .config/quickshell/translations/en_US.json | 4 ++-- .config/quickshell/translations/zh_CN.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/ii/services/Ai.qml b/.config/quickshell/ii/services/Ai.qml index 31724d8e..db47ea49 100644 --- a/.config/quickshell/ii/services/Ai.qml +++ b/.config/quickshell/ii/services/Ai.qml @@ -372,7 +372,7 @@ Singleton { // See if policy prevents online models if (Config.options.policies.ai === 2 && !model.endpoint.includes("localhost")) { root.addMessage( - Translation.tr("Online models disallowed for %1\n\nControlled by `policies.ai` config option").arg(model.name), + Translation.tr("Online models disallowed for \n\nControlled by `policies.ai` config option"), root.interfaceRole ); return; diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index a9ee4e93..71b5e608 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -295,7 +295,6 @@ "Loaded the following system prompt\n\n---\n\n%1": "Loaded the following system prompt\n\n---\n\n%1", "%1 | Right-click to configure": "%1 | Right-click to configure", "API key set for %1": "API key set for %1", - "Online models disallowed for %1\n\nControlled by `policies.ai` config option": "Online models disallowed for %1\n\nControlled by `policies.ai` config option", "Online via %1 | %2's model": "Online via %1 | %2's model", "Current API endpoint: %1\nSet it with %2mode PROVIDER": "Current API endpoint: %1\nSet it with %2mode PROVIDER", "Go to source (%1)": "Go to source (%1)", @@ -316,5 +315,6 @@ "%1 notifications": "%1 notifications", "Save chat from %1": "Save chat from %1", "Load chat from %1": "Load chat from %1", - "Load prompt from %1": "Load prompt from %1" + "Load prompt from %1": "Load prompt from %1", + "Online models disallowed for \n\nControlled by `policies.ai` config option": "Online models disallowed for \n\nControlled by `policies.ai` config option" } \ No newline at end of file diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index c3749d2f..489f3ad5 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -311,7 +311,7 @@ "Message the model... \"%1\" for commands": "与模型对话... \"%1\" 查看命令", "The current system prompt is\n\n---\n\n%1": "当前系统提示词为\n\n---\n\n%1", "Model set to %1": "模型已设置为 %1", - "Online models disallowed for %1\n\nControlled by `policies.ai` config option": "%1 禁止使用在线模型\n\n由 `policies.ai` 配置项控制", + "Online models disallowed for \n\nControlled by `policies.ai` config option": "禁止使用在线模型\n\n由 `policies.ai` 配置项控制", "Loaded the following system prompt\n\n---\n\n%1": "已加载以下系统提示词\n\n---\n\n%1", "%1 notifications": "%1 条通知", "Save chat from %1": "保存聊天记录到 %1", From 3b0574bd46db3c2035db61e2f90547029a0e8ae9 Mon Sep 17 00:00:00 2001 From: 1cebp <1cebp@protonmail.com> Date: Wed, 16 Jul 2025 13:16:01 -0400 Subject: [PATCH 245/328] Fix monitor offset w/ left-of-center monitors in overview --- .../quickshell/ii/modules/overview/OverviewWidget.qml | 10 ++++------ .../quickshell/ii/modules/overview/OverviewWindow.qml | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.config/quickshell/ii/modules/overview/OverviewWidget.qml b/.config/quickshell/ii/modules/overview/OverviewWidget.qml index 18e60c2f..ab5d4332 100644 --- a/.config/quickshell/ii/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/ii/modules/overview/OverviewWidget.qml @@ -175,10 +175,8 @@ Item { property int workspaceColIndex: (windowData?.workspace.id - 1) % Config.options.overview.columns property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / Config.options.overview.columns) - xOffset: { - return (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - (monitor?.x * root.scale) - } - yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex - (monitor?.y * root.scale) + xOffset: (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex + yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex Timer { id: updateWindowPosition @@ -186,8 +184,8 @@ Item { repeat: false running: false onTriggered: { - window.x = Math.round(Math.max((windowData?.at[0] - monitorData?.reserved[0]) * root.scale, 0) + xOffset) - window.y = Math.round(Math.max((windowData?.at[1] - monitorData?.reserved[1]) * root.scale, 0) + yOffset) + window.x = Math.round(Math.max((windowData?.at[0] - (monitor?.x ?? 0) - monitorData?.reserved[0]) * root.scale, 0) + xOffset) + window.y = Math.round(Math.max((windowData?.at[1] - (monitor?.y ?? 0) - monitorData?.reserved[1]) * root.scale, 0) + yOffset) } } diff --git a/.config/quickshell/ii/modules/overview/OverviewWindow.qml b/.config/quickshell/ii/modules/overview/OverviewWindow.qml index bf023a09..2820cb65 100644 --- a/.config/quickshell/ii/modules/overview/OverviewWindow.qml +++ b/.config/quickshell/ii/modules/overview/OverviewWindow.qml @@ -22,8 +22,8 @@ Item { // Window property var availableWorkspaceWidth property var availableWorkspaceHeight property bool restrictToWorkspace: true - property real initX: Math.max((windowData?.at[0] - monitorData?.reserved[0]) * root.scale, 0) + xOffset - property real initY: Math.max((windowData?.at[1] - monitorData?.reserved[1]) * root.scale, 0) + yOffset + property real initX: Math.max((windowData?.at[0] - (monitorData?.x ?? 0) - monitorData?.reserved[0]) * root.scale, 0) + xOffset + property real initY: Math.max((windowData?.at[1] - (monitorData?.y ?? 0) - monitorData?.reserved[1]) * root.scale, 0) + yOffset property real xOffset: 0 property real yOffset: 0 From 035e8b3e5d3e293ac409cb92af25250500c4b3b0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 00:22:15 +0700 Subject: [PATCH 246/328] ai: fix weird save chat description --- .config/quickshell/ii/modules/sidebarLeft/AiChat.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml index 6c4e65f9..86ae162b 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml @@ -438,7 +438,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) return { name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "save ") : ""}${chatName}`, displayName: `${chatName}`, - description: `Save chat from ${chatName}`, + description: `Save chat to ${chatName}`, } }) } else if (messageInputField.text.startsWith(`${root.commandPrefix}load`)) { From 9056b551ab3e50648223befb92c2317eb774091d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 01:35:49 +0700 Subject: [PATCH 247/328] add vietnamese translation --- .config/quickshell/translations/vi_VN.json | 313 +++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 .config/quickshell/translations/vi_VN.json diff --git a/.config/quickshell/translations/vi_VN.json b/.config/quickshell/translations/vi_VN.json new file mode 100644 index 00000000..27ce9f43 --- /dev/null +++ b/.config/quickshell/translations/vi_VN.json @@ -0,0 +1,313 @@ +{ + "Unknown function call: %1": "Hàm không xác định: %1", + "Show next time": "Hiển thị lần sau", + "Fidelity": "Fidelity", + "Open file link": "Mở liên kết tệp", + "Interrupts possibility of overview being toggled on release.": "Ngăn mở overview khi nhả nút.", + "No audio source": "Không có nguồn âm thanh", + "Might look ass. Unsupported.": "Có thể rất tệ. Không được hỗ trợ.", + "Jump to current month": "Nhảy đến tháng hiện tại", + "Delete": "Xóa", + "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**Giá**: miễn phí. Dữ liệu được sử dụng cho mục đích huấn luyện. **Hướng dẫn**: Đăng nhập vào tài khoản Google, cho phép AI Studio tạo dự án Google Cloud gì đó, quay lại rồi ấn Get API key", + "Rainbow": "Rainbow", + "%1 does not require an API key": "%1 không cần API key", + "Choose model": "Chọn model", + "Prevents abrupt increments and restricts volume limit": "Chặn thay đổi đột ngột và giới hạn âm lượng", + "%1 characters": "%1 ký tự", + "Change any time later with /dark, /light, /img in the launcher": "Thay đổi bất cứ lúc nào sau này với /dark, /light, /img trong launcher", + "Tonal Spot": "Tonal Spot", + "Neutral": "Neutral", + "To Do": "Cần làm", + "Auto": "Tự động", + "Polling interval (ms)": "Thời gian lặp lại (ms)", + "Closes on screen keyboard on press": "Đóng bàn phím trên màn hình khi ấn", + "Toggles right sidebar on press": "Mở/đóng sidebar phải khi ấn", + "Center title": "Căn giữa tiêu đề", + "Lock": "Khóa màn hình", + "Screen snip": "Chụp màn hình (chọn vùng)", + "User agent (for services that require it)": "User agent (nếu cần)", + "Report a Bug": "Báo lỗi", + "Shutdown": "Tắt máy", + "Keyboard toggle": "Mở/đóng bàn phím ảo", + "The hentai one | Great quantity, a lot of NSFW, quality varies wildly": "Cái nhiều hentai nhất | Số lượng rất tốt, rất nhiều NSFW, chất lượng có thể khác nhau nhiều", + "Download": "Tải xuống", + "Note: turning off can hurt readability": "Ghi chú: nếu tắt có thể khó đọc", + "Local Ollama model | %1": "Model Ollama trên máy | %1", + "Silent": "Im lặng", + "Columns": "Số cột", + "Set with /mode PROVIDER": "Set with /mode PROVIDER", + "Save chat to %1": "Lưu trò chuyện vào %1", + "Issues": "Các vấn đề", + "Policies": "Chính sách", + "Load chat from %1": "Tải trò chuyện từ %1", + "Unknown Album": "Album không xác định", + "Yes": "Có", + "Battery": "Pin", + "Material palette": "Kiểu material", + "Chain of Thought": "Dòng suy nghĩ", + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key.": "Cần cái này vì GlobalShortcut.onReleased cho một phím của Quickshell được kích hoạt kể cả khi ban ân phím khác trước khi thả phím đó.", + "Low warning": "Cảnh báo thấp", + ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!": ". Với Zerochan:\n- Hãy nhập tên một màu (bằng tiếng Anh)\n- Đặt username Zerochan trong tùy chọn `sidebar.booru.zerochan.username`. Bạn [có thể bị ban nếu không tuân thủ](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!", + "Brightness": "Độ sáng", + "Yooooo hi there": "Yooooo chào bạn", + "Triggers volume OSD on press": "Hiển thị âm lượng khi ấn", + "Colors & Wallpaper": "Màu sắc & Hình nền", + "No media": "Không có nhạc/video", + "Critical warning": "Cảnh báo rất thấp", + "Mic toggle": "Bật/tắt mic", + "12h AM/PM": "12h AM/PM", + "Online models disallowed\n\nControlled by `policies.ai` config option": "Model trên mạng không được cho phép\n\nTheo cài đặt `policies.ai`", + "Large language models": "Mô hình ngôn ngữ lớn", + "Markdown test": "Test markdown", + "Temperature: %1": "Nhiệt độ: %1", + "Opens media controls on press": "Mở điều khiển nhạc/video khi ấn", + "Edit": "Sửa", + "Closes overview": "Đóng overview", + "Waifus only | Excellent quality, limited quantity": "Chỉ waifus | Chất lượng xuất sắc, số lượng hạn chế", + "Cheat sheet": "Bảng tra cứu", + "Current model: %1\nSet it with %2model MODEL": "Model đang chọn: %1\nChọn với lệnh %2model MODEL", + "Provider set to": "Đã đặt nhà cung cấp thành", + "Clear": "Xóa hết", + "GitHub": "GitHub", + "App": "Ứng dụng", + "Title bar": "Thanh tiêu đề", + "Web search": "Tìm kiếm web", + "Invalid model. Supported: \n```": "Model không hợp lệ. Các lựa chọn: \n```", + "Calendar": "Lịch", + "Done": "Đã xong", + "Monochrome": "Monochrome", + "Show regions of potential interest": "Hiển thị vùng thông minh", + "Dark/Light toggle": "Chuyển chế độ sáng/tối", + "Unknown command:": "Lệnh không xác định:", + "Allow NSFW content": "Cho phép nội dung NSFW", + "Closes cheatsheet on press": "Đóng bảng tra cứu khi ấn", + "Set temperature (randomness) of the model. Values range between 0 to 2 for Gemini, 0 to 1 for other models. Default is 0.5.": "Chỉnh giá trị nhiệt độ (sự ngẫu nhiên) của model. Giá trị 0-2 với Gemini, 0-1 với các model khác. Mặc định là 0.5.", + "Invalid API provider. Supported: \n-": "Nhà cung cấp API không hợp lệ. Các lựa chọn: \n-", + "Shell windows": "Cửa sổ của shell", + "Loaded the following system prompt\n\n---\n\n%1": "Đã tải chỉ dẫn hệ thống sau đây\n\n---\n\n%1", + "Clipboard": "Clipboard", + "Toggles left sidebar on press": "Mở/đóng sidebar trái khi ấn", + "For storing API keys and other sensitive information": "Để lưu trữ API key và các thông tin nhạy cảm khác", + "Wallpaper": "Hình nền", + "Decorations & Effects": "Trang trí & Hiệu ứng", + "AI": "AI", + "Large images | God tier quality, no NSFW.": "Ảnh kích thước lớn | Chất lượng cực tốt, không có NSFW.", + "When not fullscreen": "Khi không toàn màn hình", + "Resources": "Tài nguyên", + "Light": "Sáng", + "Weeb": "Wibu", + "Disable NSFW content": "Tắt nội dung NSFW", + "OK": "OK", + "Screenshot tool": "Công cụ chụp màn hình", + "Enable": "Bật", + "Select Language": "Chọn ngôn ngữ", + "System": "Hệ thống", + "Emojis": "Emoji", + "The current system prompt is\n\n---\n\n%1": "Chỉ dẫn hệ thống hiện tại như sau\n\n---\n\n%1", + "Closes right sidebar on press": "Đóng sidebar phải khi ấn", + "Translator": "Dịch", + "Sleep": "Ngủ", + "Action": "Hành động", + "Audio": "Âm thanh", + "Show background": "Hiện nền", + "All-rounder | Good quality, decent quantity": "Tốt đều | Chất lượng tốt, số lượng ổn", + "Documentation": "Tài liệu", + "Terminal": "Terminal", + "Distro": "Distro", + "Clear chat history": "Xóa lịch sử trò chuyện", + "Float": "Nổi", + "No further instruction provided": "No further instruction provided", + "Choose file": "Chọn tệp", + "Opens right sidebar on press": "Mở sidebar phải khi ấn", + "Set the system prompt for the model.": "Đặt chỉ dẫn hệ thống cho model.", + "Closes left sidebar on press": "Đóng sidebar trái khi ấn", + "Unknown Title": "Bài hát không rõ tên", + "Math result": "Kết quả phép tính", + "Logout": "Đăng xuất", + "Privacy Policy": "Chính sách quyền riêng tư", + "Style": "Phong cách", + "Borderless": "Không viền", + "Set API key": "Đặt API key", + "Clean stuff | Excellent quality, no NSFW": "Sạch sẽ | Chất lượng xuất sắc, không có NSFW", + "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "Thử nghiệm | Trực tuyến | Mô hình của Google\nCó thể làm nhiều hơn một chút nhưng không tìm kiếm nhanh chóng", + "Toggles cheatsheet on press": "Mở/đóng bảng tra cứu khi ấn", + "Thinking": "Đang nghĩ", + "Earbang protection": "Bảo vệ tai", + "Advanced": "Nâng cao", + "Could be better if you make a ton of typos,\nbut results can be weird and might not work with acronyms\n(e.g. \"GIMP\" might not give you the paint program)": "Có thể tốt hơn nếu bạn gõ lệch phím nhiều,\nnhưng kết quả có thể hơi lạ và không hoạt động tốt với từ viết tắt\n(ví dụ tìm \"GIMP\" có thể không ra cái chương trình vẽ)", + "Shell & utilities theming must also be enabled": "Cần Shell & công cụ cũng bật", + "Desktop": "Màn hình chính", + "Anime": "Anime", + "Qt apps": "Các ứng dụng Qt", + "Style & wallpaper": "Phong cách & hình nền", + "Finished tasks will go here": "Việc đã xong sẽ hiện ở đây", + "Weather": "Thời tiết", + "Settings": "Cài đặt", + "Shell & utilities": "Shell & tiện ích", + "Toggles overview on release": "Mở/đóng overview khi nhả nút", + "Unfinished": "Chưa hoàn thành", + "Random: Konachan": "Ngẫu nhiên: Konachan", + "Opens left sidebar on press": "Mở sidebar trái khi ấn", + "Pick wallpaper image on your system": "Chọn hình nền trên máy", + "Volume": "Âm lượng", + "Add": "Thêm", + "Hibernate": "Ngủ đông", + "Run": "Chạy", + "Keep system awake": "Giữ hệ thống bật", + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.": "Để đảm bảo luôn hoạt động, dùng binditn = MODKEYS, catchall trong một submap luôn được kích hoạt bao trùm mọi thứ.", + "Plain rectangle": "Hình chữ nhật", + "%1 queries pending": "%1 lượt gọi đang chờ", + "Temperature set to %1": "Nhiệt độ đã được đặt thành %1", + "Notifications": "Thông báo", + "System prompt": "Chỉ dẫn hệ thống", + "Hover to reveal": "Đặt chuột vào để hiện", + "No": "Không", + "Bar": "Bar", + "Search the web": "Tìm kiếm web", + "Page %1": "Trang %1", + "Reboot": "Khởi động lại", + "Such regions could be images or parts of the screen that have some containment.\nMight not always be accurate.\nThis is done with an image processing algorithm run locally and no AI is used.": "Các vùng có thể là hình ảnh hoặc phần của màn hình cớ vẻ được bao chứa.\nKhông luôn chính xác.\nSử dụng một thuật toán xử lý ảnh chạy trên máy, không dùng AI.", + "Show app icons": "Hiện biểu tượng ứng dụng", + "Closet": "Nghiện mà ngại", + "Set the current API provider": "Đặt nguồn cung cấp API", + "Cancel": "Hủy", + "Networking": "Mạng", + "Overview": "Overview", + "Search, calculate or run": "Tìm, tính hoặc chạy", + "Useless buttons": "Mấy nút vô dụng", + "Transparency": "Sự trong suốt", + "Temperature must be between 0 and 2": "Nhiệt độ phải trong khoảng từ 0 đến 2", + "Automatically suspends the system when battery is low": "Tự động ngủ khi pin thấp", + "Current API endpoint: %1\nSet it with %2mode PROVIDER": "Endpoint API hiện tại: %1\nĐặt với lệnh %2mode PROVIDER", + "Decrease brightness": "Giảm độ sáng", + "Services": "Các dịch vụ", + "Reload Hyprland & Quickshell": "Tải lại Hyprland & Quickshell", + "Automatic suspend": "Tự động ngủ", + "illogical-impulse Welcome": "illogical-impulse - Xin chào", + "Interface": "Giao diện", + "Load chat": "Tải cuộc trò chuyện", + "Opens session screen on press": "Mở màn hình session khi ấn", + "Number show delay when pressing Super (ms)": "Thời gian chờ hiện số khi nhấn Super (ms)", + "Clear the current list of images": "Xóa danh sách hình ảnh hiện tại", + "Fake screen rounding": "Giả bo tròn màn hình", + "Tip: Hide icons and always show numbers for\nthe classic illogical-impulse experience": "Mẹo: Ẩn biểu tượng và luôn hiển thị số nếu\nmuốn giống trải nghiệm illogical-impulse gốc", + "Launch": "Chạy", + "%1 notifications": "%1 thông báo", + "Hides brightness OSD on press": "Ngừng hiển thị độ sáng khi nhấn", + "%1 | Right-click to configure": "%1 | Ấn chuột phải để chỉnh", + "Unknown Artist": "Nghệ sĩ không xác định", + "Appearance": "Giao diện", + "Task Manager": "Quản lí ứng dụng đang chạy", + "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For %1:\n\n**Link**: %2\n\n%3": "Để đặt API key, viết nó sau lệnh\n\nĐể xem lại, viết \"get\" sau lệnh
\n\n### Với %1:\n\n**Link**: %2\n\n%3", + "Hold to show workspace numbers, release to show icons": "Giữ để hiện số workspace, thả ra để hiện biểu tượng", + "Opens cheatsheet on press": "Mở bảng tra cứu khi ấn", + "Invalid arguments. Must provide `key` and `value`.": "Biến không hợp lệ. cần cả `key` và `value`.", + "About": "Giới thiệu", + "illogical-impulse": "illogical-impulse", + "Triggers brightness OSD on press": "Hiện độ sáng/âm lượng khi ấn", + "Help & Support": "Trợ giúp", + "Enter tags, or \"%1\" for commands": "Nhập tag hoặc \"%1\" để xem các lệnh", + "Format": "Định dạng", + "Content": "Nội dung", + "Edit config": "Sửa config", + "Bluetooth": "Bluetooth", + "Be patient...": "Bình tĩnh...", + "Toggles session screen on press": "Mở/đóng màn hình session khi ấn", + "Discussions": "Thảo luận", + "Anime boorus": "Các booru anime", + "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "Quả này không được. Mẹo:\n- Kiểm tra tag và cài đặt NSFW\n- Nếu không nghĩ ra tag nào có thể nhập số trang", + "Task description": "Mô tả công việc", + "Max allowed increase": "Thay đổi tối đa", + "Rows": "Số hàng", + "Switched to search mode. Continue with the user's request.": "Đã chuyển sang chế độ tìm kiếm. Tiếp tục với yêu cầu của người dùng.", + "Use Levenshtein distance-based algorithm instead of fuzzy": "Sử dụng thuật toán dùng khoảng cách Levenshtein thay vì fuzzy", + "Copy": "Sao chép", + "12h am/pm": "12h am/pm", + "Unknown": "Không xác định", + "Hides volume OSD on press": "Ngừng hiển thị âm lượng khi nhấn", + "Waiting for response...": "Đang chờ phản hồi...", + "Workspace": "Workspace", + "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers": "Hình nền Anime SFW ngẫu nhiên từ Konachan\nẢnh được lưu vào ~/Pictures/Wallpapers", + "Toggles on screen keyboard on press": "Mở/đóng bàn phím ảo khi ấn", + "Online via %1 | %2's model": "Trực tuyến qua %1 | Mô hình của %2", + "Always show numbers": "Luôn hiện số", + "or": "hoặc", + "Drag or click a region • LMB: Copy • RMB: Edit": "Kéo thả hoặc chọn vùng • Chuột trái: Sao chép • Chuột phải: Chỉnh sửa", + "Local only": "Chỉ trên máy", + "Donate": "Ủng hộ", + "Online | Google's model\nGives up-to-date information with search.": "Trực tuyến | Mô hình của Google\nCó thể tìm kiếm để cung cấp thông tin cập nhật.", + "Run command": "Chạy lệnh", + "Dotfiles": "Dotfiles", + "Volume limit": "Giới hạn âm lượng", + "On-screen display": "Âm lượng/độ sáng", + "Reboot to firmware settings": "Khởi động lại vào cài đặt firmware", + "Workspaces shown": "Số workspace hiển thị", + "Save": "Lưu", + "The popular one | Best quantity, but quality can vary wildly": "Phổ biến | Số lượng tốt nhất, nhưng chất lượng không biết đâu vào đâu", + "Save chat": "Lưu cuộc trò chuyện", + "Intelligence": "Trí tuệ", + "Translation goes here...": "Bản dịch sẽ hiện ở đây...", + "Toggle clipboard query on overview widget": "Mở/đóng tìm kiếm clipboard trên overview", + "Search": "Tìm kiếm", + "Timeout (ms)": "Thời gian chờ (ms)", + "24h": "24h", + "Color picker": "Chọn màu", + "Save to Downloads": "Lưu vào Downloads", + "No notifications": "Không có thông báo", + "Closes media controls on press": "Đóng điều khiển đa phương tiện khi nhấn", + "Game mode": "Chế độ game", + "Alternatively use /dark, /light, /img in the launcher": "Có thể dùng /dark, /light, /img trong launcher", + "Info": "Thông tin", + "Dock": "Dock", + "Pinned on startup": "Ghim khi khởi động", + "Suspend at": "Tạm dừng ở", + "Fruit Salad": "Fruit Salad", + "API key:\n\n```txt\n%1\n```": "API key:\n\n```txt\n%1\n```", + "Increase brightness": "Tăng độ sáng", + "API key set for %1": "API key đã đặt cho %1", + "Not visible to model": "Không hiển thị cho mô hình", + "Expressive": "Expressive", + "Enter text to translate...": "Nhập văn bản để dịch...", + "Usage": "Cách dùng", + "Message the model... \"%1\" for commands": "Hỏi model... \"%1\" để xem lệnh", + "Keybinds": "Phím tắt", + "Model set to %1": "Đã đặt model thành %1", + "Scale (%)": "Tỉ lệ (%)", + "Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "Gõ /key để bắt đầu dùng các mô hình trực tuyến\nCtrl+O để mở rộng sidebar\nCtrl+P để nhấc sidebar thành cửa sổ", + "Toggle emoji query on overview widget": "Mở/đóng tìm kiếm emoji trên overview", + "Output": "Đầu ra", + "Uptime: %1": "Máy đã chạy được: %1", + "For desktop wallpapers | Good quality": "Cho hình nền máy tính | Chất lượng tốt", + "Nothing here!": "Không có gì!", + "Close": "Đóng", + "Arrow keys to navigate, Enter to select\nEsc or click anywhere to cancel": "Phím mũi tên để chọn, Enter để xác nhận\nEsc hoặc ấn bất kỳ đâu để thoát", + "Copy code": "Sao chép code", + "Load prompt from %1": "Tải chỉ dẫn từ %1", + "Time": "Thời gian", + "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key": "**Giá**: miễn phí. Chính sách sử dụng dữ liệu tùy thuộc vào cài đặt tài khoản OpenRouter của bạn.\n\n**Hướng dẫn**: Đăng nhập vào tài khoản OpenRouter, mở Keys ở menu góc trên bên phải, ấn Create API Key", + "Bar style": "Phong cách bar", + "Configuration": "Cài đặt", + "Prefixes": "Kí tự đầu", + "No API key set for %1": "Không có API key cho %1", + "Add task": "Thêm công việc", + "Volume mixer": "Trộn âm lượng", + "Toggles media controls on press": "Mở/đóng điều khiển đa phương tiện khi ấn", + "Go to source (%1)": "Đi đến nguồn (%1)", + "The current API used. Endpoint:": "API đang sử dụng. Endpoint:", + "View Markdown source": "Xem nguồn Markdown", + "Input": "Đầu vào", + "Opens on screen keyboard on press": "Mở bàn phím ảo khi ấn", + "Allow NSFW": "Cho phép NSFW", + "Session": "Phiên làm việc", + "Detach left sidebar into a window/Attach it back": "Nhấc sidebar trái thành cửa sổ/Đặt nó lại", + "Night Light": "Lọc ánh sáng xanh", + "Workspaces": "Các workspace", + "Toggles overview on press": "Mở/đóng overview khi ấn", + "Dark": "Tối", + "Base URL": "Base URL", + "Hug": "Ôm", + "Buttons": "Các nút", + "Get the next page of results": "Lấy trang kết quả tiếp theo", + "%1 Safe Storage": "Lưu trữ an toàn %1", + "Color generation": "Chỉnh màu" +} From fec499050604c7c12df73909c9259321dfbeb3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Thu, 17 Jul 2025 08:45:25 +0800 Subject: [PATCH 248/328] translations: Update chat save message in Chinese translations --- .config/quickshell/translations/en_US.json | 4 ++-- .config/quickshell/translations/zh_CN.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index 71b5e608..9446fd01 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -313,8 +313,8 @@ "The current system prompt is\n\n---\n\n%1": "The current system prompt is\n\n---\n\n%1", "Unknown function call: %1": "Unknown function call: %1", "%1 notifications": "%1 notifications", - "Save chat from %1": "Save chat from %1", "Load chat from %1": "Load chat from %1", "Load prompt from %1": "Load prompt from %1", - "Online models disallowed for \n\nControlled by `policies.ai` config option": "Online models disallowed for \n\nControlled by `policies.ai` config option" + "Online models disallowed for \n\nControlled by `policies.ai` config option": "Online models disallowed for \n\nControlled by `policies.ai` config option", + "Save chat to %1": "Save chat to %1" } \ No newline at end of file diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index 489f3ad5..957a1e00 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -314,7 +314,7 @@ "Online models disallowed for \n\nControlled by `policies.ai` config option": "禁止使用在线模型\n\n由 `policies.ai` 配置项控制", "Loaded the following system prompt\n\n---\n\n%1": "已加载以下系统提示词\n\n---\n\n%1", "%1 notifications": "%1 条通知", - "Save chat from %1": "保存聊天记录到 %1", + "Save chat to %1": "保存聊天记录到 %1", "Load chat from %1": "从 %1 加载聊天记录", "Load prompt from %1": "从 %1 加载提示词" } \ No newline at end of file From 4660a154d05e17851faff32bfe53103dd8a331d8 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 13:09:35 +0700 Subject: [PATCH 249/328] translations: add untranslated text, fix some originals --- .../quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml | 3 ++- .../ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml | 2 +- .config/quickshell/ii/services/Ai.qml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml index 0dd71884..a8eda901 100644 --- a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml +++ b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml @@ -98,7 +98,8 @@ Rectangle { property int remainingTasks: Todo.list.filter(task => !task.done).length; Layout.margins: 10 Layout.leftMargin: 0 - text: `${DateTime.collapsedCalendarFormat} • ${remainingTasks} task${remainingTasks > 1 ? "s" : ""}` + // text: `${DateTime.collapsedCalendarFormat} • ${remainingTasks} task${remainingTasks > 1 ? "s" : ""}` + text: Translation.tr("%1 • %2 tasks").arg(DateTime.collapsedCalendarFormat).arg(remainingTasks) font.pixelSize: Appearance.font.pixelSize.large color: Appearance.colors.colOnLayer1 } diff --git a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml index 7c74afd6..68cc3444 100644 --- a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml +++ b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml @@ -179,7 +179,7 @@ Item { Layout.alignment: Qt.AlignLeft color: Appearance.m3colors.m3onSurface font.pixelSize: Appearance.font.pixelSize.larger - text: `Select ${root.deviceSelectorInput ? "input" : "output"} device` + text: root.deviceSelectorInput ? Translation.tr("Select input device") : Translation.tr("Select output device") } Rectangle { diff --git a/.config/quickshell/ii/services/Ai.qml b/.config/quickshell/ii/services/Ai.qml index db47ea49..40672493 100644 --- a/.config/quickshell/ii/services/Ai.qml +++ b/.config/quickshell/ii/services/Ai.qml @@ -372,7 +372,7 @@ Singleton { // See if policy prevents online models if (Config.options.policies.ai === 2 && !model.endpoint.includes("localhost")) { root.addMessage( - Translation.tr("Online models disallowed for \n\nControlled by `policies.ai` config option"), + Translation.tr("Online models disallowed\n\nControlled by `policies.ai` config option"), root.interfaceRole ); return; From 1429b5977b8ec5a228e368a0e435bda079dc64fd Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 13:13:21 +0700 Subject: [PATCH 250/328] translations: adjust vietnamese --- .config/quickshell/translations/vi_VN.json | 53 ++++++++++++---------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/.config/quickshell/translations/vi_VN.json b/.config/quickshell/translations/vi_VN.json index 27ce9f43..e4623002 100644 --- a/.config/quickshell/translations/vi_VN.json +++ b/.config/quickshell/translations/vi_VN.json @@ -1,7 +1,7 @@ { "Unknown function call: %1": "Hàm không xác định: %1", "Show next time": "Hiển thị lần sau", - "Fidelity": "Fidelity", + "Fidelity": "Khá giống gốc", "Open file link": "Mở liên kết tệp", "Interrupts possibility of overview being toggled on release.": "Ngăn mở overview khi nhả nút.", "No audio source": "Không có nguồn âm thanh", @@ -9,14 +9,14 @@ "Jump to current month": "Nhảy đến tháng hiện tại", "Delete": "Xóa", "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**Giá**: miễn phí. Dữ liệu được sử dụng cho mục đích huấn luyện. **Hướng dẫn**: Đăng nhập vào tài khoản Google, cho phép AI Studio tạo dự án Google Cloud gì đó, quay lại rồi ấn Get API key", - "Rainbow": "Rainbow", + "Rainbow": "Cầu vồng", "%1 does not require an API key": "%1 không cần API key", "Choose model": "Chọn model", "Prevents abrupt increments and restricts volume limit": "Chặn thay đổi đột ngột và giới hạn âm lượng", "%1 characters": "%1 ký tự", "Change any time later with /dark, /light, /img in the launcher": "Thay đổi bất cứ lúc nào sau này với /dark, /light, /img trong launcher", "Tonal Spot": "Tonal Spot", - "Neutral": "Neutral", + "Neutral": "Trung tính", "To Do": "Cần làm", "Auto": "Tự động", "Polling interval (ms)": "Thời gian lặp lại (ms)", @@ -36,7 +36,6 @@ "Silent": "Im lặng", "Columns": "Số cột", "Set with /mode PROVIDER": "Set with /mode PROVIDER", - "Save chat to %1": "Lưu trò chuyện vào %1", "Issues": "Các vấn đề", "Policies": "Chính sách", "Load chat from %1": "Tải trò chuyện từ %1", @@ -52,15 +51,14 @@ "Yooooo hi there": "Yooooo chào bạn", "Triggers volume OSD on press": "Hiển thị âm lượng khi ấn", "Colors & Wallpaper": "Màu sắc & Hình nền", - "No media": "Không có nhạc/video", + "No media": "Không có media", "Critical warning": "Cảnh báo rất thấp", "Mic toggle": "Bật/tắt mic", "12h AM/PM": "12h AM/PM", - "Online models disallowed\n\nControlled by `policies.ai` config option": "Model trên mạng không được cho phép\n\nTheo cài đặt `policies.ai`", "Large language models": "Mô hình ngôn ngữ lớn", "Markdown test": "Test markdown", "Temperature: %1": "Nhiệt độ: %1", - "Opens media controls on press": "Mở điều khiển nhạc/video khi ấn", + "Opens media controls on press": "Mở điều khiển media khi ấn", "Edit": "Sửa", "Closes overview": "Đóng overview", "Waifus only | Excellent quality, limited quantity": "Chỉ waifus | Chất lượng xuất sắc, số lượng hạn chế", @@ -75,7 +73,7 @@ "Invalid model. Supported: \n```": "Model không hợp lệ. Các lựa chọn: \n```", "Calendar": "Lịch", "Done": "Đã xong", - "Monochrome": "Monochrome", + "Monochrome": "Đen trắng", "Show regions of potential interest": "Hiển thị vùng thông minh", "Dark/Light toggle": "Chuyển chế độ sáng/tối", "Unknown command:": "Lệnh không xác định:", @@ -129,7 +127,7 @@ "Borderless": "Không viền", "Set API key": "Đặt API key", "Clean stuff | Excellent quality, no NSFW": "Sạch sẽ | Chất lượng xuất sắc, không có NSFW", - "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "Thử nghiệm | Trực tuyến | Mô hình của Google\nCó thể làm nhiều hơn một chút nhưng không tìm kiếm nhanh chóng", + "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "Thử nghiệm | Trực tuyến | Model của Google\nCó thể làm nhiều hơn một chút nhưng không tìm kiếm nhanh chóng", "Toggles cheatsheet on press": "Mở/đóng bảng tra cứu khi ấn", "Thinking": "Đang nghĩ", "Earbang protection": "Bảo vệ tai", @@ -145,7 +143,7 @@ "Settings": "Cài đặt", "Shell & utilities": "Shell & tiện ích", "Toggles overview on release": "Mở/đóng overview khi nhả nút", - "Unfinished": "Chưa hoàn thành", + "Unfinished": "Chưa xong", "Random: Konachan": "Ngẫu nhiên: Konachan", "Opens left sidebar on press": "Mở sidebar trái khi ấn", "Pick wallpaper image on your system": "Chọn hình nền trên máy", @@ -156,7 +154,7 @@ "Keep system awake": "Giữ hệ thống bật", "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.": "Để đảm bảo luôn hoạt động, dùng binditn = MODKEYS, catchall trong một submap luôn được kích hoạt bao trùm mọi thứ.", "Plain rectangle": "Hình chữ nhật", - "%1 queries pending": "%1 lượt gọi đang chờ", + "%1 queries pending": "%1 lệnh gọi đang chờ", "Temperature set to %1": "Nhiệt độ đã được đặt thành %1", "Notifications": "Thông báo", "System prompt": "Chỉ dẫn hệ thống", @@ -208,7 +206,7 @@ "Help & Support": "Trợ giúp", "Enter tags, or \"%1\" for commands": "Nhập tag hoặc \"%1\" để xem các lệnh", "Format": "Định dạng", - "Content": "Nội dung", + "Content": "Giống gốc", "Edit config": "Sửa config", "Bluetooth": "Bluetooth", "Be patient...": "Bình tĩnh...", @@ -229,13 +227,13 @@ "Workspace": "Workspace", "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers": "Hình nền Anime SFW ngẫu nhiên từ Konachan\nẢnh được lưu vào ~/Pictures/Wallpapers", "Toggles on screen keyboard on press": "Mở/đóng bàn phím ảo khi ấn", - "Online via %1 | %2's model": "Trực tuyến qua %1 | Mô hình của %2", + "Online via %1 | %2's model": "Trực tuyến qua %1 | Model của %2", "Always show numbers": "Luôn hiện số", "or": "hoặc", "Drag or click a region • LMB: Copy • RMB: Edit": "Kéo thả hoặc chọn vùng • Chuột trái: Sao chép • Chuột phải: Chỉnh sửa", "Local only": "Chỉ trên máy", "Donate": "Ủng hộ", - "Online | Google's model\nGives up-to-date information with search.": "Trực tuyến | Mô hình của Google\nCó thể tìm kiếm để cung cấp thông tin cập nhật.", + "Online | Google's model\nGives up-to-date information with search.": "Trực tuyến | Model của Google\nCó thể tìm kiếm để cung cấp thông tin cập nhật.", "Run command": "Chạy lệnh", "Dotfiles": "Dotfiles", "Volume limit": "Giới hạn âm lượng", @@ -254,31 +252,31 @@ "Color picker": "Chọn màu", "Save to Downloads": "Lưu vào Downloads", "No notifications": "Không có thông báo", - "Closes media controls on press": "Đóng điều khiển đa phương tiện khi nhấn", + "Closes media controls on press": "Đóng điều khiển media khi nhấn", "Game mode": "Chế độ game", "Alternatively use /dark, /light, /img in the launcher": "Có thể dùng /dark, /light, /img trong launcher", "Info": "Thông tin", "Dock": "Dock", "Pinned on startup": "Ghim khi khởi động", "Suspend at": "Tạm dừng ở", - "Fruit Salad": "Fruit Salad", + "Fruit Salad": "Salad hoa quả", "API key:\n\n```txt\n%1\n```": "API key:\n\n```txt\n%1\n```", "Increase brightness": "Tăng độ sáng", "API key set for %1": "API key đã đặt cho %1", - "Not visible to model": "Không hiển thị cho mô hình", - "Expressive": "Expressive", + "Not visible to model": "Không hiển thị cho model", + "Expressive": "Biểu cảm", "Enter text to translate...": "Nhập văn bản để dịch...", "Usage": "Cách dùng", "Message the model... \"%1\" for commands": "Hỏi model... \"%1\" để xem lệnh", "Keybinds": "Phím tắt", "Model set to %1": "Đã đặt model thành %1", "Scale (%)": "Tỉ lệ (%)", - "Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "Gõ /key để bắt đầu dùng các mô hình trực tuyến\nCtrl+O để mở rộng sidebar\nCtrl+P để nhấc sidebar thành cửa sổ", + "Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "Gõ /key để bắt đầu dùng các model trực tuyến\nCtrl+O để mở rộng sidebar\nCtrl+P để nhấc sidebar thành cửa sổ", "Toggle emoji query on overview widget": "Mở/đóng tìm kiếm emoji trên overview", "Output": "Đầu ra", - "Uptime: %1": "Máy đã chạy được: %1", + "Uptime: %1": "Máy bật được %1", "For desktop wallpapers | Good quality": "Cho hình nền máy tính | Chất lượng tốt", - "Nothing here!": "Không có gì!", + "Nothing here!": "Không có gì ở đây!", "Close": "Đóng", "Arrow keys to navigate, Enter to select\nEsc or click anywhere to cancel": "Phím mũi tên để chọn, Enter để xác nhận\nEsc hoặc ấn bất kỳ đâu để thoát", "Copy code": "Sao chép code", @@ -291,14 +289,14 @@ "No API key set for %1": "Không có API key cho %1", "Add task": "Thêm công việc", "Volume mixer": "Trộn âm lượng", - "Toggles media controls on press": "Mở/đóng điều khiển đa phương tiện khi ấn", + "Toggles media controls on press": "Mở/đóng điều khiển media khi ấn", "Go to source (%1)": "Đi đến nguồn (%1)", "The current API used. Endpoint:": "API đang sử dụng. Endpoint:", "View Markdown source": "Xem nguồn Markdown", "Input": "Đầu vào", "Opens on screen keyboard on press": "Mở bàn phím ảo khi ấn", "Allow NSFW": "Cho phép NSFW", - "Session": "Phiên làm việc", + "Session": "Session", "Detach left sidebar into a window/Attach it back": "Nhấc sidebar trái thành cửa sổ/Đặt nó lại", "Night Light": "Lọc ánh sáng xanh", "Workspaces": "Các workspace", @@ -309,5 +307,10 @@ "Buttons": "Các nút", "Get the next page of results": "Lấy trang kết quả tiếp theo", "%1 Safe Storage": "Lưu trữ an toàn %1", - "Color generation": "Chỉnh màu" -} + "Color generation": "Chỉnh màu", + "Select output device": "Chọn đầu ra", + "Select input device": "Chọn đầu vào", + "Save chat from %1": "Lưu cuộc trò chuyện vào %1", + "%1 • %2 tasks": "%1 • %2 việc cần làm", + "Online models disallowed\n\nControlled by `policies.ai` config option": "Model trực tuyến không được cho phép\n\nCài đặt bởi lựa chọn `policies.ai`" +} \ No newline at end of file From 9ca67f0095ac70f0fb4fd3bb64c5e44de3503b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Thu, 17 Jul 2025 14:25:57 +0800 Subject: [PATCH 251/328] translations: Update Chinese language files --- .config/quickshell/translations/zh_CN.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index 957a1e00..36bdd2dc 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -311,10 +311,14 @@ "Message the model... \"%1\" for commands": "与模型对话... \"%1\" 查看命令", "The current system prompt is\n\n---\n\n%1": "当前系统提示词为\n\n---\n\n%1", "Model set to %1": "模型已设置为 %1", - "Online models disallowed for \n\nControlled by `policies.ai` config option": "禁止使用在线模型\n\n由 `policies.ai` 配置项控制", "Loaded the following system prompt\n\n---\n\n%1": "已加载以下系统提示词\n\n---\n\n%1", "%1 notifications": "%1 条通知", "Save chat to %1": "保存聊天记录到 %1", "Load chat from %1": "从 %1 加载聊天记录", - "Load prompt from %1": "从 %1 加载提示词" + "Load prompt from %1": "从 %1 加载提示词", + "Select output device": "选择输出设备", + "%1 • %2 tasks": "%1 • %2 个任务", + "Online models disallowed\n\nControlled by `policies.ai` config option": "禁止在线模型\n\n由 `policies.ai` 配置项控制", + "Select input device": "选择输入设备" + } \ No newline at end of file From 1e7c84a6c1dbe6698b13137971155c20782913d5 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 13:56:50 +0700 Subject: [PATCH 252/328] translations: update `qsTr`s to Translation.tr and allow translation of notifications --- .config/quickshell/ii/modules/bar/Bar.qml | 10 ++--- .../ii/modules/cheatsheet/Cheatsheet.qml | 4 +- .../quickshell/ii/modules/common/Config.qml | 2 +- .../sidebarLeft/aiChat/MessageCodeBlock.qml | 6 ++- .../modules/sidebarLeft/anime/BooruImage.qml | 2 +- .../quickToggles/CloudflareWarp.qml | 14 +++++-- .config/quickshell/ii/services/Battery.qml | 19 +++++++-- .config/quickshell/ii/services/Weather.qml | 39 +++++++++---------- .config/quickshell/translations/en_US.json | 26 ++++++++++++- .config/quickshell/translations/vi_VN.json | 23 ++++++++++- 10 files changed, 104 insertions(+), 41 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml index 08383c10..23948029 100644 --- a/.config/quickshell/ii/modules/bar/Bar.qml +++ b/.config/quickshell/ii/modules/bar/Bar.qml @@ -169,7 +169,7 @@ Scope { ScrollHint { reveal: barLeftSideMouseArea.hovered icon: "light_mode" - tooltipText: qsTr("Scroll to change brightness") + tooltipText: Translation.tr("Scroll to change brightness") side: "left" anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter @@ -380,7 +380,7 @@ Scope { ScrollHint { reveal: barRightSideMouseArea.hovered icon: "volume_up" - tooltipText: qsTr("Scroll to change volume") + tooltipText: Translation.tr("Scroll to change volume") side: "right" anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter @@ -586,7 +586,7 @@ Scope { GlobalShortcut { name: "barToggle" - description: qsTr("Toggles bar on press") + description: Translation.tr("Toggles bar on press") onPressed: { GlobalStates.barOpen = !GlobalStates.barOpen; @@ -595,7 +595,7 @@ Scope { GlobalShortcut { name: "barOpen" - description: qsTr("Opens bar on press") + description: Translation.tr("Opens bar on press") onPressed: { GlobalStates.barOpen = true; @@ -604,7 +604,7 @@ Scope { GlobalShortcut { name: "barClose" - description: qsTr("Closes bar on press") + description: Translation.tr("Closes bar on press") onPressed: { GlobalStates.barOpen = false; diff --git a/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml b/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml index a0b22779..bc6b67ac 100644 --- a/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml +++ b/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml @@ -19,11 +19,11 @@ Scope { // Scope property var tabButtonList: [ { "icon": "keyboard", - "name": qsTr("Keybinds") + "name": Translation.tr("Keybinds") }, { "icon": "experiment", - "name": qsTr("Elements") + "name": Translation.tr("Elements") }, ] property int selectedTab: 0 diff --git a/.config/quickshell/ii/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml index 33ebc94c..1e73cea5 100644 --- a/.config/quickshell/ii/modules/common/Config.qml +++ b/.config/quickshell/ii/modules/common/Config.qml @@ -59,7 +59,7 @@ Singleton { } property JsonObject ai: JsonObject { - property string systemPrompt: qsTr("## Style\n- Use casual tone, don't be formal! Make sure you answer precisely without hallucination and prefer bullet points over walls of text. You can have a friendly greeting at the beginning of the conversation, but don't repeat the user's question\n\n## Presentation\n- Use Markdown features in your response: \n - **Bold** text to **highlight keywords** in your response\n - **Split long information into small sections** with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). Bullet points are preferred over long paragraphs, unless you're offering writing support or instructed otherwise by the user.\n- Asked to compare different options? You should firstly use a table to compare the main aspects, then elaborate or include relevant comments from online forums *after* the table. Make sure to provide a final recommendation for the user's use case!\n- Use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\nThanks!\n\n## Tools\nMay or may not be available depending on the user's settings. If they're available, follow these guidelines:\n\n### Search\n- When user asks for information that might benefit from up-to-date information, use this to get search access\n\n### Shell configuration\n- Always fetch the config options to see the available keys before setting\n- Avoid unnecessarily asking the user to confirm the changes they explicitly asked for, just do it\n") + property string systemPrompt: "## Style\n- Use casual tone, don't be formal! Make sure you answer precisely without hallucination and prefer bullet points over walls of text. You can have a friendly greeting at the beginning of the conversation, but don't repeat the user's question\n\n## Presentation\n- Use Markdown features in your response: \n - **Bold** text to **highlight keywords** in your response\n - **Split long information into small sections** with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). Bullet points are preferred over long paragraphs, unless you're offering writing support or instructed otherwise by the user.\n- Asked to compare different options? You should firstly use a table to compare the main aspects, then elaborate or include relevant comments from online forums *after* the table. Make sure to provide a final recommendation for the user's use case!\n- Use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\nThanks!\n\n## Tools\nMay or may not be available depending on the user's settings. If they're available, follow these guidelines:\n\n### Search\n- When user asks for information that might benefit from up-to-date information, use this to get search access\n\n### Shell configuration\n- Always fetch the config options to see the available keys before setting\n- Avoid unnecessarily asking the user to confirm the changes they explicitly asked for, just do it\n" } property JsonObject appearance: JsonObject { diff --git a/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageCodeBlock.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageCodeBlock.qml index 957958ef..eac41af5 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageCodeBlock.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageCodeBlock.qml @@ -99,7 +99,11 @@ ColumnLayout { Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(segmentContent)}' > '${downloadPath}/code.${segmentLang || "txt"}'` ]) - Quickshell.execDetached(["bash", "-c", `notify-send 'Code saved to file' '${downloadPath}/code.${segmentLang || "txt"}' -a Shell`]) + Quickshell.execDetached(["notify-send", + Translation.tr("Code saved to file"), + Translation.tr("Saved to %1").arg(`${downloadPath}/code.${segmentLang || "txt"}`), + "-a", "Shell" + ]) saveCodeButton.activated = true saveIconTimer.restart() } diff --git a/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml index 9ead3116..e8b24d19 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml @@ -181,7 +181,7 @@ Button { onClicked: { root.showActions = false Quickshell.execDetached(["bash", "-c", - `curl '${root.imageData.file_url}' -o '${root.imageData.is_nsfw ? root.nsfwPath : root.downloadPath}/${root.fileName}' && notify-send '${qsTr("Download complete")}' '${root.downloadPath}/${root.fileName}' -a 'Shell'` + `curl '${root.imageData.file_url}' -o '${root.imageData.is_nsfw ? root.nsfwPath : root.downloadPath}/${root.fileName}' && notify-send '${Translation.tr("Download complete")}' '${root.downloadPath}/${root.fileName}' -a 'Shell'` ]) } } diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml index cdaf84b7..d9cf0fa6 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml @@ -40,7 +40,11 @@ QuickToggleButton { command: ["warp-cli", "connect"] onExited: (exitCode, exitStatus) => { if (exitCode !== 0) { - Quickshell.execDetached(["notify-send", "Cloudflare WARP", "Connection failed. Please inspect manually with the warp-cli command", "-a", "Shell"]) + Quickshell.execDetached(["notify-send", + Translation.tr("Cloudflare WARP"), + Translation.tr("Connection failed. Please inspect manually with the warp-cli command") + , "-a", "Shell" + ]) } } } @@ -53,7 +57,11 @@ QuickToggleButton { if (exitCode === 0) { connectProc.running = true } else { - Quickshell.execDetached(["notify-send", "Cloudflare WARP", "Registration failed. Please inspect manually with the warp-cli command", "-a", "Shell"]) + Quickshell.execDetached(["notify-send", + Translation.tr("Cloudflare WARP"), + Translation.tr("Registration failed. Please inspect manually with the warp-cli command"), + "-a", "Shell" + ]) } } } @@ -80,6 +88,6 @@ QuickToggleButton { } } StyledToolTip { - content: qsTr("Cloudflare WARP (1.1.1.1)") + content: Translation.tr("Cloudflare WARP (1.1.1.1)") } } diff --git a/.config/quickshell/ii/services/Battery.qml b/.config/quickshell/ii/services/Battery.qml index 6a432f3a..abe7700d 100644 --- a/.config/quickshell/ii/services/Battery.qml +++ b/.config/quickshell/ii/services/Battery.qml @@ -23,13 +23,24 @@ Singleton { property bool isSuspendingAndNotCharging: allowAutomaticSuspend && isSuspending && !isCharging onIsLowAndNotChargingChanged: { - if (available && isLowAndNotCharging) - Quickshell.execDetached(["bash", "-c", `notify-send "Low battery" "Consider plugging in your device" -u critical -a "Shell"`]); + if (available && isLowAndNotCharging) Quickshell.execDetached([ + "notify-send", + Translation.tr("Low battery"), + Translation.tr("Consider plugging in your device"), + "-u", "critical", + "-a", "Shell" + ]) } onIsCriticalAndNotChargingChanged: { - if (available && isCriticalAndNotCharging) - Quickshell.execDetached(["bash", "-c", `notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${Config.options.battery.suspend}%" -u critical -a "Shell"`]); + if (available && isCriticalAndNotCharging) Quickshell.execDetached([ + "notify-send", + Translation.tr("Critically low battery"), + Translation.tr("Please charge!\nAutomatic suspend triggers at %1").arg(Config.options.battery.suspend), + "-u", "critical", + "-a", "Shell" + ]); + } onIsSuspendingAndNotChargingChanged: { diff --git a/.config/quickshell/ii/services/Weather.qml b/.config/quickshell/ii/services/Weather.qml index eb1a00af..a72e7e2e 100644 --- a/.config/quickshell/ii/services/Weather.qml +++ b/.config/quickshell/ii/services/Weather.qml @@ -17,25 +17,25 @@ Singleton { property bool gpsActive: Config.options.bar.weather.enableGPS property var location: ({ - valid: false, - lat: 0, - lon: 0 - }) + valid: false, + lat: 0, + lon: 0 + }) property var data: ({ - uv: 0, - humidity: 0, - sunrise: 0, - sunset: 0, - windDir: 0, - wCode: 0, - city: 0, - wind: 0, - precip: 0, - visib: 0, - press: 0, - temp: 0 - }) + uv: 0, + humidity: 0, + sunrise: 0, + sunset: 0, + windDir: 0, + wCode: 0, + city: 0, + wind: 0, + precip: 0, + visib: 0, + press: 0, + temp: 0 + }) function refineData(data) { let temp = {}; @@ -90,8 +90,7 @@ Singleton { } Component.onCompleted: { - if (!root.gpsActive) - return; + if (!root.gpsActive) return; console.info("[WeatherService] Starting the GPS service."); positionSource.start(); } @@ -139,7 +138,7 @@ Singleton { positionSource.stop(); root.location.valid = false; root.gpsActive = false; - Quickshell.execDetached(["bash", "-c", `notify-send WeatherService 'Can not find a GPS service. Using the fallback method instead.'`]); + Quickshell.execDetached(["notify-send", Translation.tr("Weather Service"), Translation.tr("Cannot find a GPS service. Using the fallback method instead."), "-a", "Shell"]); console.error("[WeatherService] Could not aquire a valid backend plugin."); } } diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index 9446fd01..7141cdaa 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -315,6 +315,28 @@ "%1 notifications": "%1 notifications", "Load chat from %1": "Load chat from %1", "Load prompt from %1": "Load prompt from %1", - "Online models disallowed for \n\nControlled by `policies.ai` config option": "Online models disallowed for \n\nControlled by `policies.ai` config option", - "Save chat to %1": "Save chat to %1" + "Save chat to %1": "Save chat to %1", + "Weather Service": "Weather Service", + "Cannot find a GPS service. Using the fallback method instead.": "Cannot find a GPS service. Using the fallback method instead.", + "Critically low battery": "Critically low battery", + "Select output device": "Select output device", + "Code saved to file": "Code saved to file", + "Online models disallowed\n\nControlled by `policies.ai` config option": "Online models disallowed\n\nControlled by `policies.ai` config option", + "Opens bar on press": "Opens bar on press", + "Scroll to change volume": "Scroll to change volume", + "Toggles bar on press": "Toggles bar on press", + "Elements": "Elements", + "%1 • %2 tasks": "%1 • %2 tasks", + "Download complete": "Download complete", + "Please charge!\nAutomatic suspend triggers at %1": "Please charge!\nAutomatic suspend triggers at %1", + "Cloudflare WARP": "Cloudflare WARP", + "Cloudflare WARP (1.1.1.1)": "Cloudflare WARP (1.1.1.1)", + "Closes bar on press": "Closes bar on press", + "Scroll to change brightness": "Scroll to change brightness", + "Connection failed. Please inspect manually with the warp-cli command": "Connection failed. Please inspect manually with the warp-cli command", + "Select input device": "Select input device", + "Registration failed. Please inspect manually with the warp-cli command": "Registration failed. Please inspect manually with the warp-cli command", + "Consider plugging in your device": "Consider plugging in your device", + "Low battery": "Low battery", + "Saved to %1": "Saved to %1" } \ No newline at end of file diff --git a/.config/quickshell/translations/vi_VN.json b/.config/quickshell/translations/vi_VN.json index e4623002..9c2bc979 100644 --- a/.config/quickshell/translations/vi_VN.json +++ b/.config/quickshell/translations/vi_VN.json @@ -310,7 +310,26 @@ "Color generation": "Chỉnh màu", "Select output device": "Chọn đầu ra", "Select input device": "Chọn đầu vào", - "Save chat from %1": "Lưu cuộc trò chuyện vào %1", "%1 • %2 tasks": "%1 • %2 việc cần làm", - "Online models disallowed\n\nControlled by `policies.ai` config option": "Model trực tuyến không được cho phép\n\nCài đặt bởi lựa chọn `policies.ai`" + "Online models disallowed\n\nControlled by `policies.ai` config option": "Model trực tuyến không được cho phép\n\nCài đặt bởi lựa chọn `policies.ai`", + "Download complete": "Đã tải xong", + "Code saved to file": "Code đã lưu vào file", + "Critically low battery": "Pin rất thấp", + "Scroll to change brightness": "Cuộn để thay đổi độ sáng", + "Cloudflare WARP": "Cloudflare WARP", + "Toggles bar on press": "Mở/đóng bar khi ấn", + "Saved to %1": "Đã lưu vào %1", + "Elements": "Nguyên tố", + "Save chat to %1": "Lưu chat vào %1", + "Connection failed. Please inspect manually with the warp-cli command": "Kết nối không thành công. Hãy xem lại với lệnh warp-cli", + "Weather Service": "Thời tiết", + "Registration failed. Please inspect manually with the warp-cli command": "Đăng ký không thành công. Hãy xem lại với lệnh warp-cli", + "Consider plugging in your device": "Hãy cắm nguồn thiết bị của bạn", + "Cloudflare WARP (1.1.1.1)": "Cloudflare WARP (1.1.1.1)", + "Cannot find a GPS service. Using the fallback method instead.": "Không tìm thấy dịch vụ GPS. Đang sử dụng phương pháp dự phòng.", + "Opens bar on press": "Mở bar khi ấn", + "Low battery": "Pin yếu", + "Scroll to change volume": "Cuộn để thay đổi âm lượng", + "Please charge!\nAutomatic suspend triggers at %1": "Hãy sạc pin!\nHệ thống sẽ tự động ngủ khi pin xuống %1", + "Closes bar on press": "Đóng bar khi ấn" } \ No newline at end of file From 9978c87b67dd5e5931d7fd77261e307b526bfc35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Thu, 17 Jul 2025 16:03:27 +0800 Subject: [PATCH 253/328] translations: update translations/zh_CN.json --- .config/quickshell/translations/zh_CN.json | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index 36bdd2dc..c2c2fdf8 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -319,6 +319,24 @@ "Select output device": "选择输出设备", "%1 • %2 tasks": "%1 • %2 个任务", "Online models disallowed\n\nControlled by `policies.ai` config option": "禁止在线模型\n\n由 `policies.ai` 配置项控制", - "Select input device": "选择输入设备" - + "Select input device": "选择输入设备", + "Low battery": "电量低", + "Opens bar on press": "按下时打开条栏", + "Registration failed. Please inspect manually with the warp-cli command": "注册失败。请使用 warp-cli 命令手动检查", + "Code saved to file": "代码已保存到文件", + "Consider plugging in your device": "请考虑连接您的设备", + "Weather Service": "天气服务", + "Please charge!\nAutomatic suspend triggers at %1": "请充电!\n自动挂起将在 %1 时触发", + "Cloudflare WARP (1.1.1.1)": "Cloudflare WARP (1.1.1.1)", + "Cloudflare WARP": "Cloudflare WARP", + "Closes bar on press": "按下时关闭条栏", + "Download complete": "下载完成", + "Critically low battery": "电量极低", + "Scroll to change brightness": "滚动以调节亮度", + "Saved to %1": "已保存到 %1", + "Cannot find a GPS service. Using the fallback method instead.": "无法找到 GPS 服务。正在使用备用方法。", + "Elements": "元素", + "Scroll to change volume": "滚动以调节音量", + "Connection failed. Please inspect manually with the warp-cli command": "连接失败。请使用 warp-cli 命令手动检查", + "Toggles bar on press": "按下时切换条栏" } \ No newline at end of file From 158428e63e8420032874b159a01482e4bfbb6c61 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 15:28:31 +0700 Subject: [PATCH 254/328] not attempt to show translated globalshortcut description cuz they can't be changed --- .config/quickshell/ii/GlobalStates.qml | 2 +- .config/quickshell/ii/ReloadPopup.qml | 1 + .config/quickshell/ii/modules/bar/Bar.qml | 6 +++--- .../ii/modules/cheatsheet/Cheatsheet.qml | 6 +++--- .../ii/modules/mediaControls/MediaControls.qml | 6 +++--- .../OnScreenDisplayBrightness.qml | 4 ++-- .../onScreenDisplay/OnScreenDisplayVolume.qml | 4 ++-- .../onScreenKeyboard/OnScreenKeyboard.qml | 6 +++--- .../quickshell/ii/modules/overview/Overview.qml | 16 ++++++++-------- .../quickshell/ii/modules/session/Session.qml | 4 ++-- .../ii/modules/sidebarLeft/SidebarLeft.qml | 8 ++++---- .../ii/modules/sidebarRight/SidebarRight.qml | 6 +++--- .../sidebarRight/quickToggles/CloudflareWarp.qml | 2 +- .config/quickshell/ii/services/Brightness.qml | 4 ++-- 14 files changed, 38 insertions(+), 37 deletions(-) diff --git a/.config/quickshell/ii/GlobalStates.qml b/.config/quickshell/ii/GlobalStates.qml index d473af35..d114d9a5 100644 --- a/.config/quickshell/ii/GlobalStates.qml +++ b/.config/quickshell/ii/GlobalStates.qml @@ -41,7 +41,7 @@ Singleton { GlobalShortcut { name: "workspaceNumber" - description: Translation.tr("Hold to show workspace numbers, release to show icons") + description: "Hold to show workspace numbers, release to show icons" onPressed: { workspaceShowNumbersTimer.start() diff --git a/.config/quickshell/ii/ReloadPopup.qml b/.config/quickshell/ii/ReloadPopup.qml index 03abed42..4b0ecd88 100644 --- a/.config/quickshell/ii/ReloadPopup.qml +++ b/.config/quickshell/ii/ReloadPopup.qml @@ -34,6 +34,7 @@ Scope { PanelWindow { id: popup + exclusiveZone: 0 anchors.top: true margins.top: 0 diff --git a/.config/quickshell/ii/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml index 23948029..4824bea8 100644 --- a/.config/quickshell/ii/modules/bar/Bar.qml +++ b/.config/quickshell/ii/modules/bar/Bar.qml @@ -586,7 +586,7 @@ Scope { GlobalShortcut { name: "barToggle" - description: Translation.tr("Toggles bar on press") + description: "Toggles bar on press" onPressed: { GlobalStates.barOpen = !GlobalStates.barOpen; @@ -595,7 +595,7 @@ Scope { GlobalShortcut { name: "barOpen" - description: Translation.tr("Opens bar on press") + description: "Opens bar on press" onPressed: { GlobalStates.barOpen = true; @@ -604,7 +604,7 @@ Scope { GlobalShortcut { name: "barClose" - description: Translation.tr("Closes bar on press") + description: "Closes bar on press" onPressed: { GlobalStates.barOpen = false; diff --git a/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml b/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml index bc6b67ac..5b956841 100644 --- a/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml +++ b/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml @@ -212,7 +212,7 @@ Scope { // Scope GlobalShortcut { name: "cheatsheetToggle" - description: Translation.tr("Toggles cheatsheet on press") + description: "Toggles cheatsheet on press" onPressed: { cheatsheetLoader.active = !cheatsheetLoader.active; @@ -221,7 +221,7 @@ Scope { // Scope GlobalShortcut { name: "cheatsheetOpen" - description: Translation.tr("Opens cheatsheet on press") + description: "Opens cheatsheet on press" onPressed: { cheatsheetLoader.active = true; @@ -230,7 +230,7 @@ Scope { // Scope GlobalShortcut { name: "cheatsheetClose" - description: Translation.tr("Closes cheatsheet on press") + description: "Closes cheatsheet on press" onPressed: { cheatsheetLoader.active = false; diff --git a/.config/quickshell/ii/modules/mediaControls/MediaControls.qml b/.config/quickshell/ii/modules/mediaControls/MediaControls.qml index f918ff70..d9507265 100644 --- a/.config/quickshell/ii/modules/mediaControls/MediaControls.qml +++ b/.config/quickshell/ii/modules/mediaControls/MediaControls.qml @@ -161,7 +161,7 @@ Scope { GlobalShortcut { name: "mediaControlsToggle" - description: Translation.tr("Toggles media controls on press") + description: "Toggles media controls on press" onPressed: { if (!mediaControlsLoader.active && Mpris.players.values.filter(player => isRealPlayer(player)).length === 0) { @@ -173,7 +173,7 @@ Scope { } GlobalShortcut { name: "mediaControlsOpen" - description: Translation.tr("Opens media controls on press") + description: "Opens media controls on press" onPressed: { mediaControlsLoader.active = true; @@ -182,7 +182,7 @@ Scope { } GlobalShortcut { name: "mediaControlsClose" - description: Translation.tr("Closes media controls on press") + description: "Closes media controls on press" onPressed: { mediaControlsLoader.active = false; diff --git a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml index 00f9e68e..51f809e8 100644 --- a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml +++ b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml @@ -135,7 +135,7 @@ Scope { GlobalShortcut { name: "osdBrightnessTrigger" - description: Translation.tr("Triggers brightness OSD on press") + description: "Triggers brightness OSD on press" onPressed: { root.triggerOsd() @@ -143,7 +143,7 @@ Scope { } GlobalShortcut { name: "osdBrightnessHide" - description: Translation.tr("Hides brightness OSD on press") + description: "Hides brightness OSD on press" onPressed: { root.showOsdValues = false diff --git a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml index 5ae1575e..db29eee3 100644 --- a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml +++ b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml @@ -186,7 +186,7 @@ Scope { } GlobalShortcut { name: "osdVolumeTrigger" - description: Translation.tr("Triggers volume OSD on press") + description: "Triggers volume OSD on press" onPressed: { root.triggerOsd() @@ -194,7 +194,7 @@ Scope { } GlobalShortcut { name: "osdVolumeHide" - description: Translation.tr("Hides volume OSD on press") + description: "Hides volume OSD on press" onPressed: { root.showOsdValues = false diff --git a/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml b/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml index bebf6e71..199cde63 100644 --- a/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml +++ b/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml @@ -141,7 +141,7 @@ Scope { // Scope GlobalShortcut { name: "oskToggle" - description: Translation.tr("Toggles on screen keyboard on press") + description: "Toggles on screen keyboard on press" onPressed: { oskLoader.active = !oskLoader.active; @@ -150,7 +150,7 @@ Scope { // Scope GlobalShortcut { name: "oskOpen" - description: Translation.tr("Opens on screen keyboard on press") + description: "Opens on screen keyboard on press" onPressed: { oskLoader.active = true; @@ -159,7 +159,7 @@ Scope { // Scope GlobalShortcut { name: "oskClose" - description: Translation.tr("Closes on screen keyboard on press") + description: "Closes on screen keyboard on press" onPressed: { oskLoader.active = false; diff --git a/.config/quickshell/ii/modules/overview/Overview.qml b/.config/quickshell/ii/modules/overview/Overview.qml index b11d3564..50a4f57b 100644 --- a/.config/quickshell/ii/modules/overview/Overview.qml +++ b/.config/quickshell/ii/modules/overview/Overview.qml @@ -148,7 +148,7 @@ Scope { GlobalShortcut { name: "overviewToggle" - description: Translation.tr("Toggles overview on press") + description: "Toggles overview on press" onPressed: { GlobalStates.overviewOpen = !GlobalStates.overviewOpen @@ -156,7 +156,7 @@ Scope { } GlobalShortcut { name: "overviewClose" - description: Translation.tr("Closes overview") + description: "Closes overview" onPressed: { GlobalStates.overviewOpen = false @@ -164,7 +164,7 @@ Scope { } GlobalShortcut { name: "overviewToggleRelease" - description: Translation.tr("Toggles overview on release") + description: "Toggles overview on release" onPressed: { GlobalStates.superReleaseMightTrigger = true @@ -180,9 +180,9 @@ Scope { } GlobalShortcut { name: "overviewToggleReleaseInterrupt" - description: Translation.tr("Interrupts possibility of overview being toggled on release. ") + - Translation.tr("This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. ") + - Translation.tr("To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.") + description: "Interrupts possibility of overview being toggled on release. " + + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. " + + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything." onPressed: { GlobalStates.superReleaseMightTrigger = false @@ -190,7 +190,7 @@ Scope { } GlobalShortcut { name: "overviewClipboardToggle" - description: Translation.tr("Toggle clipboard query on overview widget") + description: "Toggle clipboard query on overview widget" onPressed: { if (GlobalStates.overviewOpen && overviewScope.dontAutoCancelSearch) { @@ -213,7 +213,7 @@ Scope { GlobalShortcut { name: "overviewEmojiToggle" - description: Translation.tr("Toggle emoji query on overview widget") + description: "Toggle emoji query on overview widget" onPressed: { if (GlobalStates.overviewOpen && overviewScope.dontAutoCancelSearch) { diff --git a/.config/quickshell/ii/modules/session/Session.qml b/.config/quickshell/ii/modules/session/Session.qml index b1ce1e42..b6f030f9 100644 --- a/.config/quickshell/ii/modules/session/Session.qml +++ b/.config/quickshell/ii/modules/session/Session.qml @@ -210,7 +210,7 @@ Scope { GlobalShortcut { name: "sessionToggle" - description: Translation.tr("Toggles session screen on press") + description: "Toggles session screen on press" onPressed: { sessionLoader.active = !sessionLoader.active; @@ -219,7 +219,7 @@ Scope { GlobalShortcut { name: "sessionOpen" - description: Translation.tr("Opens session screen on press") + description: "Opens session screen on press" onPressed: { sessionLoader.active = true; diff --git a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml index 751287f1..0bc00c24 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml @@ -170,7 +170,7 @@ Scope { // Scope GlobalShortcut { name: "sidebarLeftToggle" - description: Translation.tr("Toggles left sidebar on press") + description: "Toggles left sidebar on press" onPressed: { GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen; @@ -179,7 +179,7 @@ Scope { // Scope GlobalShortcut { name: "sidebarLeftOpen" - description: Translation.tr("Opens left sidebar on press") + description: "Opens left sidebar on press" onPressed: { GlobalStates.sidebarLeftOpen = true; @@ -188,7 +188,7 @@ Scope { // Scope GlobalShortcut { name: "sidebarLeftClose" - description: Translation.tr("Closes left sidebar on press") + description: "Closes left sidebar on press" onPressed: { GlobalStates.sidebarLeftOpen = false; @@ -197,7 +197,7 @@ Scope { // Scope GlobalShortcut { name: "sidebarLeftToggleDetach" - description: Translation.tr("Detach left sidebar into a window/Attach it back") + description: "Detach left sidebar into a window/Attach it back" onPressed: { root.detach = !root.detach; diff --git a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml index 9c9af649..d733ae44 100644 --- a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml @@ -224,7 +224,7 @@ Scope { GlobalShortcut { name: "sidebarRightToggle" - description: Translation.tr("Toggles right sidebar on press") + description: "Toggles right sidebar on press" onPressed: { GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen; @@ -233,7 +233,7 @@ Scope { } GlobalShortcut { name: "sidebarRightOpen" - description: Translation.tr("Opens right sidebar on press") + description: "Opens right sidebar on press" onPressed: { GlobalStates.sidebarRightOpen = true; @@ -242,7 +242,7 @@ Scope { } GlobalShortcut { name: "sidebarRightClose" - description: Translation.tr("Closes right sidebar on press") + description: "Closes right sidebar on press" onPressed: { GlobalStates.sidebarRightOpen = false; diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml index d9cf0fa6..eaa0c79f 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml @@ -1,6 +1,6 @@ import "root:/modules/common" import "root:/modules/common/widgets" -import "../" +import "root:/" import QtQuick import Quickshell.Io import Quickshell diff --git a/.config/quickshell/ii/services/Brightness.qml b/.config/quickshell/ii/services/Brightness.qml index 129da7b2..6a36f713 100644 --- a/.config/quickshell/ii/services/Brightness.qml +++ b/.config/quickshell/ii/services/Brightness.qml @@ -141,13 +141,13 @@ Singleton { GlobalShortcut { name: "brightnessIncrease" - description: Translation.tr("Increase brightness") + description: "Increase brightness" onPressed: root.increaseBrightness() } GlobalShortcut { name: "brightnessDecrease" - description: Translation.tr("Decrease brightness") + description: "Decrease brightness" onPressed: root.decreaseBrightness() } } From d197787ab8a04705f6367af8f2f4b9916bc15edb Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 15:45:35 +0700 Subject: [PATCH 255/328] fix tabbar warning --- .config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml | 2 +- .../ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml b/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml index 0c35781f..8cb4804a 100644 --- a/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml +++ b/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml @@ -66,7 +66,7 @@ ColumnLayout { id: indicator property int tabCount: root.tabButtonList.length property real fullTabSize: root.width / tabCount; - property real targetWidth: tabBar.contentItem.children[0].children[tabBar.currentIndex].tabContentWidth + property real targetWidth: tabBar.contentItem?.children[0]?.children[tabBar.currentIndex]?.tabContentWidth ?? 0 implicitWidth: targetWidth anchors { diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml index eaa0c79f..476927e2 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml @@ -74,7 +74,6 @@ QuickToggleButton { id: warpStatusCollector onStreamFinished: { if (warpStatusCollector.text.length > 0) { - console.log("Showing warp") root.visible = true } if (warpStatusCollector.text.includes("Unable")) { From 20711e125b079d128df60b2030268836e6d45214 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 15:45:43 +0700 Subject: [PATCH 256/328] dock: right click to pin app --- .config/quickshell/ii/modules/dock/DockAppButton.qml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.config/quickshell/ii/modules/dock/DockAppButton.qml b/.config/quickshell/ii/modules/dock/DockAppButton.qml index 8afa6567..31e94855 100644 --- a/.config/quickshell/ii/modules/dock/DockAppButton.qml +++ b/.config/quickshell/ii/modules/dock/DockAppButton.qml @@ -73,6 +73,14 @@ DockButton { root.desktopEntry?.execute(); } + altAction: () => { + if (Config.options.dock.pinnedApps.indexOf(appToplevel.appId) !== -1) { + Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.filter(id => id !== appToplevel.appId) + } else { + Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.concat([appToplevel.appId]) + } + } + contentItem: Loader { active: !isSeparator sourceComponent: Item { From 6f5781564c6c647286a96f23476885a8b344a69e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 19:56:39 +0700 Subject: [PATCH 257/328] hyprlock: bolder clock --- .config/matugen/templates/hyprland/hyprlock.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/matugen/templates/hyprland/hyprlock.conf b/.config/matugen/templates/hyprland/hyprlock.conf index d557f706..d9b69cf1 100644 --- a/.config/matugen/templates/hyprland/hyprlock.conf +++ b/.config/matugen/templates/hyprland/hyprlock.conf @@ -3,7 +3,7 @@ $entry_background_color = rgba({{colors.on_primary_fixed.default.hex_stripped}}1 $entry_border_color = rgba({{colors.outline.default.hex_stripped}}55) $entry_color = rgba({{colors.primary_fixed.default.hex_stripped}}FF) $font_family = Rubik -$font_family_clock = Space Grotesk +$font_family_clock = Space Grotesk DemiBold $font_material_symbols = Material Symbols Rounded background { From 6d9e4ad2fa092f7ef0956164423dd2e84ffefadd Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 20:23:03 +0700 Subject: [PATCH 258/328] more quickshell.execdetached instead of hyprland dispatch trick --- .config/quickshell/ii/modules/bar/UtilButtons.qml | 6 +++--- .config/quickshell/ii/modules/session/Session.qml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/UtilButtons.qml b/.config/quickshell/ii/modules/bar/UtilButtons.qml index 706ba6f6..2db3e96d 100644 --- a/.config/quickshell/ii/modules/bar/UtilButtons.qml +++ b/.config/quickshell/ii/modules/bar/UtilButtons.qml @@ -24,7 +24,7 @@ Item { visible: Config.options.bar.utilButtons.showScreenSnip sourceComponent: CircleUtilButton { Layout.alignment: Qt.AlignVCenter - onClicked: Hyprland.dispatch("exec hyprshot --freeze --clipboard-only --mode region --silent") + onClicked: Quickshell.execDetached(["qs", "-p", Quickshell.configPath("screenshot.qml")]) MaterialSymbol { horizontalAlignment: Qt.AlignHCenter fill: 1 @@ -40,7 +40,7 @@ Item { visible: Config.options.bar.utilButtons.showColorPicker sourceComponent: CircleUtilButton { Layout.alignment: Qt.AlignVCenter - onClicked: Hyprland.dispatch("exec hyprpicker -a") + onClicked: Quickshell.execDetached(["hyprpicker", "-a"]) MaterialSymbol { horizontalAlignment: Qt.AlignHCenter fill: 1 @@ -72,7 +72,7 @@ Item { visible: Config.options.bar.utilButtons.showMicToggle sourceComponent: CircleUtilButton { Layout.alignment: Qt.AlignVCenter - onClicked: Hyprland.dispatch("exec wpctl set-mute @DEFAULT_SOURCE@ toggle") + onClicked: Quickshell.execDetached(["wpctl", "set-mute", "@DEFAULT_SOURCE@", "toggle"]) MaterialSymbol { horizontalAlignment: Qt.AlignHCenter fill: 0 diff --git a/.config/quickshell/ii/modules/session/Session.qml b/.config/quickshell/ii/modules/session/Session.qml index b6f030f9..8b98e7f9 100644 --- a/.config/quickshell/ii/modules/session/Session.qml +++ b/.config/quickshell/ii/modules/session/Session.qml @@ -93,7 +93,7 @@ Scope { focus: sessionRoot.visible buttonIcon: "lock" buttonText: Translation.tr("Lock") - onClicked: { Hyprland.dispatch("exec loginctl lock-session"); sessionRoot.hide() } + onClicked: { Quickshell.execDetached(["loginctl", "lock-session"]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.right: sessionSleep KeyNavigation.down: sessionHibernate @@ -102,7 +102,7 @@ Scope { id: sessionSleep buttonIcon: "dark_mode" buttonText: Translation.tr("Sleep") - onClicked: { Hyprland.dispatch("exec systemctl suspend || loginctl suspend"); sessionRoot.hide() } + onClicked: { Quickshell.execDetached(["bash", "-c", "systemctl suspend || loginctl suspend"]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionLock KeyNavigation.right: sessionLogout @@ -112,7 +112,7 @@ Scope { id: sessionLogout buttonIcon: "logout" buttonText: Translation.tr("Logout") - onClicked: { Hyprland.dispatch("exec pkill Hyprland"); sessionRoot.hide() } + onClicked: { Quickshell.execDetached(["pkill", "Hyprland"]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionSleep KeyNavigation.right: sessionTaskManager From fb6721e3482d838532414dcd161f5ab2ee5e0a98 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 20:23:43 +0700 Subject: [PATCH 259/328] sidebar: ai chat: think block: fix undefined easing type --- .../sidebarLeft/aiChat/MessageThinkBlock.qml | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageThinkBlock.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageThinkBlock.qml index c05d33cf..9d055592 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageThinkBlock.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageThinkBlock.qml @@ -1,19 +1,12 @@ pragma ComponentBehavior: Bound -import "root:/" -import "root:/services" -import "root:/modules/common/" -import "root:/modules/common/widgets" -import "../" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io -import Quickshell -import Quickshell.Widgets -import Quickshell.Hyprland import Qt5Compat.GraphicalEffects Item { @@ -147,7 +140,7 @@ Item { enabled: root.completed ?? false NumberAnimation { duration: collapseAnimation.duration - easing.type: collapseAnimation.easing + easing.type: collapseAnimation.type easing.bezierCurve: collapseAnimation.bezierCurve } } From 254870c9ab7c928ae33bb465ca7ca8b2d67333da Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 20:24:01 +0700 Subject: [PATCH 260/328] quickshell: use qs imports instead of root:/ --- .config/quickshell/ii/GlobalStates.qml | 4 +- .config/quickshell/ii/Translation.qml | 2 +- .../ii/modules/background/Background.qml | 19 +- .../ii/modules/bar/ActiveWindow.qml | 8 +- .config/quickshell/ii/modules/bar/Bar.qml | 12 +- .../quickshell/ii/modules/bar/BarGroup.qml | 6 +- .../ii/modules/bar/BatteryIndicator.qml | 9 +- .../ii/modules/bar/CircleUtilButton.qml | 9 +- .../quickshell/ii/modules/bar/ClockWidget.qml | 6 +- .config/quickshell/ii/modules/bar/Media.qml | 13 +- .../quickshell/ii/modules/bar/Resource.qml | 6 +- .../quickshell/ii/modules/bar/Resources.qml | 9 +- .../quickshell/ii/modules/bar/ScrollHint.qml | 7 +- .config/quickshell/ii/modules/bar/SysTray.qml | 7 +- .../quickshell/ii/modules/bar/SysTrayItem.qml | 4 +- .../quickshell/ii/modules/bar/UtilButtons.qml | 5 +- .../quickshell/ii/modules/bar/Workspaces.qml | 11 +- .../ii/modules/bar/weather/WeatherBar.qml | 6 +- .../ii/modules/bar/weather/WeatherCard.qml | 4 +- .../ii/modules/bar/weather/WeatherPopup.qml | 6 +- .../ii/modules/cheatsheet/Cheatsheet.qml | 11 +- .../modules/cheatsheet/CheatsheetKeybinds.qml | 15 +- .../cheatsheet/CheatsheetPeriodicTable.qml | 15 +- .../ii/modules/cheatsheet/ElementTile.qml | 8 +- .../ii/modules/common/Appearance.qml | 2 +- .../ii/modules/common/Directories.qml | 3 +- .../modules/common/functions/ColorUtils.qml | 114 +++++++++ .../ii/modules/common/functions/FileUtils.qml | 41 ++++ .../modules/common/functions/ObjectUtils.qml | 98 ++++++++ .../modules/common/functions/StringUtils.qml | 221 ++++++++++++++++++ .../modules/common/functions/color_utils.js | 109 --------- .../ii/modules/common/functions/file_utils.js | 34 --- .../modules/common/functions/object_utils.js | 91 -------- .../modules/common/functions/string_utils.js | 188 --------------- .../ii/modules/common/widgets/ButtonGroup.qml | 6 +- .../common/widgets/CircularProgress.qml | 2 +- .../modules/common/widgets/CliphistImage.qml | 14 +- .../common/widgets/ConfigSelectionArray.qml | 13 +- .../modules/common/widgets/ConfigSpinBox.qml | 5 +- .../modules/common/widgets/ConfigSwitch.qml | 4 +- .../ii/modules/common/widgets/ContentPage.qml | 5 +- .../modules/common/widgets/ContentSection.qml | 4 +- .../common/widgets/ContentSubsection.qml | 5 +- .../common/widgets/ContentSubsectionLabel.qml | 4 +- .../ii/modules/common/widgets/CustomIcon.qml | 7 +- .../modules/common/widgets/DialogButton.qml | 7 +- .../ii/modules/common/widgets/DragManager.qml | 6 +- .../ii/modules/common/widgets/Favicon.qml | 13 +- .../common/widgets/FloatingActionButton.qml | 5 +- .../ii/modules/common/widgets/GroupButton.qml | 9 +- .../ii/modules/common/widgets/KeyboardKey.qml | 6 +- .../widgets/LightDarkPreferenceButton.qml | 11 +- .../modules/common/widgets/MaterialSymbol.qml | 3 +- .../common/widgets/MaterialTextField.qml | 3 +- .../ii/modules/common/widgets/MenuButton.qml | 7 +- .../modules/common/widgets/NavigationRail.qml | 5 +- .../common/widgets/NavigationRailButton.qml | 7 +- .../widgets/NavigationRailExpandButton.qml | 5 +- .../common/widgets/NavigationRailTabArray.qml | 7 +- .../widgets/NotificationActionButton.qml | 7 +- .../common/widgets/NotificationAppIcon.qml | 4 +- .../common/widgets/NotificationGroup.qml | 14 +- .../widgets/NotificationGroupExpandButton.qml | 10 +- .../common/widgets/NotificationItem.qml | 14 +- .../common/widgets/NotificationListView.qml | 12 +- .../modules/common/widgets/PrimaryTabBar.qml | 5 +- .../common/widgets/PrimaryTabButton.qml | 8 +- .../ii/modules/common/widgets/Revealer.qml | 3 +- .../modules/common/widgets/RippleButton.qml | 9 +- .../common/widgets/RippleButtonWithIcon.qml | 5 +- .../common/widgets/SecondaryTabButton.qml | 8 +- .../common/widgets/SelectionDialog.qml | 10 +- .../common/widgets/SelectionGroupButton.qml | 6 +- .../ii/modules/common/widgets/StyledLabel.qml | 3 +- .../modules/common/widgets/StyledListView.qml | 13 +- .../common/widgets/StyledProgressBar.qml | 6 +- .../common/widgets/StyledRadioButton.qml | 6 +- .../widgets/StyledRectangularShadow.qml | 2 +- .../modules/common/widgets/StyledSlider.qml | 6 +- .../modules/common/widgets/StyledSpinBox.qml | 4 +- .../modules/common/widgets/StyledSwitch.qml | 2 +- .../ii/modules/common/widgets/StyledText.qml | 2 +- .../modules/common/widgets/StyledTextArea.qml | 2 +- .../common/widgets/StyledTextInput.qml | 2 +- .../modules/common/widgets/StyledToolTip.qml | 4 +- .../common/widgets/VerticalButtonGroup.qml | 6 +- .../modules/common/widgets/WaveVisualizer.qml | 11 +- .config/quickshell/ii/modules/dock/Dock.qml | 8 +- .../ii/modules/dock/DockAppButton.qml | 14 +- .../quickshell/ii/modules/dock/DockApps.qml | 13 +- .../quickshell/ii/modules/dock/DockButton.qml | 6 +- .../ii/modules/dock/DockSeparator.qml | 4 +- .../modules/mediaControls/MediaControls.qml | 14 +- .../modules/mediaControls/PlayerControl.qml | 14 +- .../notificationPopup/NotificationPopup.qml | 8 +- .../OnScreenDisplayBrightness.qml | 8 +- .../onScreenDisplay/OnScreenDisplayVolume.qml | 8 +- .../onScreenDisplay/OsdValueIndicator.qml | 6 +- .../onScreenKeyboard/OnScreenKeyboard.qml | 11 +- .../modules/onScreenKeyboard/OskContent.qml | 8 +- .../ii/modules/onScreenKeyboard/OskKey.qml | 12 +- .../ii/modules/overview/Overview.qml | 8 +- .../ii/modules/overview/OverviewWidget.qml | 13 +- .../ii/modules/overview/OverviewWindow.qml | 14 +- .../ii/modules/overview/SearchItem.qml | 12 +- .../ii/modules/overview/SearchWidget.qml | 10 +- .../modules/screenCorners/ScreenCorners.qml | 4 +- .../quickshell/ii/modules/session/Session.qml | 11 +- .../modules/session/SessionActionButton.qml | 8 +- .../quickshell/ii/modules/settings/About.qml | 10 +- .../ii/modules/settings/AdvancedConfig.qml | 10 +- .../ii/modules/settings/InterfaceConfig.qml | 9 +- .../ii/modules/settings/ServicesConfig.qml | 9 +- .../ii/modules/settings/StyleConfig.qml | 13 +- .../ii/modules/sidebarLeft/AiChat.qml | 13 +- .../ii/modules/sidebarLeft/Anime.qml | 11 +- .../modules/sidebarLeft/ApiCommandButton.qml | 9 +- .../ii/modules/sidebarLeft/DescriptionBox.qml | 8 +- .../ii/modules/sidebarLeft/SidebarLeft.qml | 13 +- .../sidebarLeft/SidebarLeftContent.qml | 16 +- .../ii/modules/sidebarLeft/Translator.qml | 12 +- .../modules/sidebarLeft/aiChat/AiMessage.qml | 16 +- .../aiChat/AiMessageControlButton.qml | 10 +- .../aiChat/AnnotationSourceButton.qml | 13 +- .../sidebarLeft/aiChat/MessageCodeBlock.qml | 16 +- .../sidebarLeft/aiChat/MessageTextBlock.qml | 15 +- .../modules/sidebarLeft/anime/BooruImage.qml | 11 +- .../sidebarLeft/anime/BooruResponse.qml | 15 +- .../translator/LanguageSelectorButton.qml | 14 +- .../sidebarLeft/translator/TextCanvas.qml | 13 +- .../sidebarRight/BottomWidgetGroup.qml | 10 +- .../sidebarRight/CenterWidgetGroup.qml | 11 +- .../ii/modules/sidebarRight/SidebarRight.qml | 13 +- .../calendar/CalendarDayButton.qml | 6 +- .../calendar/CalendarHeaderButton.qml | 6 +- .../sidebarRight/calendar/CalendarWidget.qml | 6 +- .../notifications/NotificationList.qml | 10 +- .../NotificationStatusButton.qml | 5 +- .../quickToggles/BluetoothToggle.qml | 11 +- .../quickToggles/CloudflareWarp.qml | 7 +- .../sidebarRight/quickToggles/GameMode.qml | 8 +- .../quickToggles/IdleInhibitor.qml | 8 +- .../quickToggles/NetworkToggle.qml | 10 +- .../sidebarRight/quickToggles/NightLight.qml | 8 +- .../quickToggles/QuickToggleButton.qml | 8 +- .../ii/modules/sidebarRight/todo/TaskList.qml | 6 +- .../todo/TodoItemActionButton.qml | 7 +- .../modules/sidebarRight/todo/TodoWidget.qml | 10 +- .../volumeMixer/AudioDeviceSelectorButton.qml | 11 +- .../sidebarRight/volumeMixer/VolumeMixer.qml | 9 +- .../volumeMixer/VolumeMixerEntry.qml | 9 +- .config/quickshell/ii/screenshot.qml | 8 +- .config/quickshell/ii/services/Ai.qml | 20 +- .../quickshell/ii/services/AiMessageData.qml | 2 +- .config/quickshell/ii/services/AppSearch.qml | 3 +- .config/quickshell/ii/services/Audio.qml | 2 +- .config/quickshell/ii/services/Battery.qml | 5 +- .config/quickshell/ii/services/Booru.qml | 6 +- .../ii/services/BooruResponseData.qml | 2 +- .config/quickshell/ii/services/Brightness.qml | 2 +- .config/quickshell/ii/services/Cliphist.qml | 4 +- .config/quickshell/ii/services/DateTime.qml | 2 +- .config/quickshell/ii/services/Emojis.qml | 2 +- .../ii/services/FirstRunExperience.qml | 5 +- .../quickshell/ii/services/HyprlandData.qml | 1 - .../ii/services/HyprlandKeybinds.qml | 5 +- .../quickshell/ii/services/KeyringStorage.qml | 7 +- .../quickshell/ii/services/LatexRenderer.qml | 8 +- .../ii/services/MaterialThemeLoader.qml | 2 +- .../ii/services/MprisController.qml | 2 +- .../quickshell/ii/services/Notifications.qml | 4 +- .../quickshell/ii/services/ResourceUsage.qml | 2 +- .config/quickshell/ii/services/Todo.qml | 3 +- .config/quickshell/ii/services/Weather.qml | 2 +- .config/quickshell/ii/services/Ydotool.qml | 10 +- .config/quickshell/ii/settings.qml | 17 +- .config/quickshell/ii/welcome.qml | 10 +- 177 files changed, 983 insertions(+), 1252 deletions(-) create mode 100644 .config/quickshell/ii/modules/common/functions/ColorUtils.qml create mode 100644 .config/quickshell/ii/modules/common/functions/FileUtils.qml create mode 100644 .config/quickshell/ii/modules/common/functions/ObjectUtils.qml create mode 100644 .config/quickshell/ii/modules/common/functions/StringUtils.qml delete mode 100644 .config/quickshell/ii/modules/common/functions/color_utils.js delete mode 100644 .config/quickshell/ii/modules/common/functions/file_utils.js delete mode 100644 .config/quickshell/ii/modules/common/functions/object_utils.js delete mode 100644 .config/quickshell/ii/modules/common/functions/string_utils.js diff --git a/.config/quickshell/ii/GlobalStates.qml b/.config/quickshell/ii/GlobalStates.qml index d114d9a5..55f71fd6 100644 --- a/.config/quickshell/ii/GlobalStates.qml +++ b/.config/quickshell/ii/GlobalStates.qml @@ -1,5 +1,5 @@ -import "root:/modules/common/" -import "root:/" +import qs.modules.common +import qs import QtQuick import Quickshell import Quickshell.Hyprland diff --git a/.config/quickshell/ii/Translation.qml b/.config/quickshell/ii/Translation.qml index 74a3e6ba..3cfdce11 100644 --- a/.config/quickshell/ii/Translation.qml +++ b/.config/quickshell/ii/Translation.qml @@ -3,7 +3,7 @@ pragma Singleton import QtQuick import Quickshell import Quickshell.Io -import "root:/modules/common/" +import qs.modules.common Singleton { id: root diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index 8c41e926..cf01078c 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -1,12 +1,11 @@ pragma ComponentBehavior: Bound -import "root:/" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions as CF import QtQuick -import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Io @@ -48,7 +47,7 @@ Scope { // Colors property color dominantColor: Appearance.colors.colPrimary property bool dominantColorIsDark: dominantColor.hslLightness < 0.5 - property color colText: ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (dominantColorIsDark ? 0.8 : 0.12)) + property color colText: CF.ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (dominantColorIsDark ? 0.8 : 0.12)) // Layer props screen: modelData @@ -194,8 +193,8 @@ Scope { horizontalAlignment: bgRoot.textHorizontalAlignment font { family: Appearance.font.family.expressive - pixelSize: 85 - weight: Font.Medium + pixelSize: 90 + weight: Font.Bold } color: bgRoot.colText style: Text.Raised @@ -208,7 +207,7 @@ Scope { font { family: Appearance.font.family.expressive pixelSize: 20 - weight: Font.Medium + weight: Font.DemiBold } color: bgRoot.colText style: Text.Raised diff --git a/.config/quickshell/ii/modules/bar/ActiveWindow.qml b/.config/quickshell/ii/modules/bar/ActiveWindow.qml index 9187848e..a4105dd4 100644 --- a/.config/quickshell/ii/modules/bar/ActiveWindow.qml +++ b/.config/quickshell/ii/modules/bar/ActiveWindow.qml @@ -1,7 +1,7 @@ -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/" +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs import QtQuick import QtQuick.Layouts import Quickshell.Wayland diff --git a/.config/quickshell/ii/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml index 4824bea8..45c62be9 100644 --- a/.config/quickshell/ii/modules/bar/Bar.qml +++ b/.config/quickshell/ii/modules/bar/Bar.qml @@ -1,18 +1,16 @@ -import "root:/" -import "root:/services" -import "root:/modules/common/" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils import "./weather" import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Qt5Compat.GraphicalEffects import Quickshell import Quickshell.Io import Quickshell.Wayland import Quickshell.Hyprland import Quickshell.Services.UPower +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions Scope { id: bar diff --git a/.config/quickshell/ii/modules/bar/BarGroup.qml b/.config/quickshell/ii/modules/bar/BarGroup.qml index f6d4c724..04e64eb7 100644 --- a/.config/quickshell/ii/modules/bar/BarGroup.qml +++ b/.config/quickshell/ii/modules/bar/BarGroup.qml @@ -1,6 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/bar/BatteryIndicator.qml b/.config/quickshell/ii/modules/bar/BatteryIndicator.qml index f58d0867..0f0a86a0 100644 --- a/.config/quickshell/ii/modules/bar/BatteryIndicator.qml +++ b/.config/quickshell/ii/modules/bar/BatteryIndicator.qml @@ -1,11 +1,8 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick import QtQuick.Layouts -import Quickshell -import Quickshell.Io -import Quickshell.Services.UPower Item { id: root diff --git a/.config/quickshell/ii/modules/bar/CircleUtilButton.qml b/.config/quickshell/ii/modules/bar/CircleUtilButton.qml index 3027c130..bd80a6c4 100644 --- a/.config/quickshell/ii/modules/bar/CircleUtilButton.qml +++ b/.config/quickshell/ii/modules/bar/CircleUtilButton.qml @@ -1,11 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets/" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Quickshell.Io RippleButton { id: button diff --git a/.config/quickshell/ii/modules/bar/ClockWidget.qml b/.config/quickshell/ii/modules/bar/ClockWidget.qml index 925faac7..9f45aa0a 100644 --- a/.config/quickshell/ii/modules/bar/ClockWidget.qml +++ b/.config/quickshell/ii/modules/bar/ClockWidget.qml @@ -1,6 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/bar/Media.qml b/.config/quickshell/ii/modules/bar/Media.qml index 9d548623..0d5731e1 100644 --- a/.config/quickshell/ii/modules/bar/Media.qml +++ b/.config/quickshell/ii/modules/bar/Media.qml @@ -1,12 +1,11 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import qs +import qs.modules.common.functions + import QtQuick import QtQuick.Layouts -import Quickshell -import Quickshell.Io import Quickshell.Services.Mpris import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/bar/Resource.qml b/.config/quickshell/ii/modules/bar/Resource.qml index fed7a153..734329af 100644 --- a/.config/quickshell/ii/modules/bar/Resource.qml +++ b/.config/quickshell/ii/modules/bar/Resource.qml @@ -1,9 +1,7 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Layouts -import Quickshell -import Quickshell.Io Item { required property string iconName diff --git a/.config/quickshell/ii/modules/bar/Resources.qml b/.config/quickshell/ii/modules/bar/Resources.qml index e0c0d51e..f57372a1 100644 --- a/.config/quickshell/ii/modules/bar/Resources.qml +++ b/.config/quickshell/ii/modules/bar/Resources.qml @@ -1,11 +1,8 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick import QtQuick.Layouts -import Quickshell -import Quickshell.Io -import Quickshell.Services.Mpris Item { id: root diff --git a/.config/quickshell/ii/modules/bar/ScrollHint.qml b/.config/quickshell/ii/modules/bar/ScrollHint.qml index f5f47c74..a8e1c8df 100644 --- a/.config/quickshell/ii/modules/bar/ScrollHint.qml +++ b/.config/quickshell/ii/modules/bar/ScrollHint.qml @@ -1,8 +1,7 @@ -import "root:/" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls import QtQuick.Layouts Revealer { // Scroll hint diff --git a/.config/quickshell/ii/modules/bar/SysTray.qml b/.config/quickshell/ii/modules/bar/SysTray.qml index 4f76ddfa..34919a3c 100644 --- a/.config/quickshell/ii/modules/bar/SysTray.qml +++ b/.config/quickshell/ii/modules/bar/SysTray.qml @@ -1,11 +1,8 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Layouts -import Quickshell.Hyprland import Quickshell.Services.SystemTray -import Quickshell.Wayland -import Quickshell.Widgets // TODO: More fancy animation Item { diff --git a/.config/quickshell/ii/modules/bar/SysTrayItem.qml b/.config/quickshell/ii/modules/bar/SysTrayItem.qml index 55dd867c..a3d70cec 100644 --- a/.config/quickshell/ii/modules/bar/SysTrayItem.qml +++ b/.config/quickshell/ii/modules/bar/SysTrayItem.qml @@ -1,5 +1,5 @@ -import "root:/modules/common/" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.functions import QtQuick import QtQuick.Layouts import Quickshell diff --git a/.config/quickshell/ii/modules/bar/UtilButtons.qml b/.config/quickshell/ii/modules/bar/UtilButtons.qml index 2db3e96d..fe5b534c 100644 --- a/.config/quickshell/ii/modules/bar/UtilButtons.qml +++ b/.config/quickshell/ii/modules/bar/UtilButtons.qml @@ -1,9 +1,8 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Layouts import Quickshell -import Quickshell.Io import Quickshell.Hyprland import Quickshell.Services.Pipewire diff --git a/.config/quickshell/ii/modules/bar/Workspaces.qml b/.config/quickshell/ii/modules/bar/Workspaces.qml index f4d7c73d..8758fe52 100644 --- a/.config/quickshell/ii/modules/bar/Workspaces.qml +++ b/.config/quickshell/ii/modules/bar/Workspaces.qml @@ -1,15 +1,14 @@ -import "root:/" -import "root:/services/" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Wayland import Quickshell.Hyprland -import Quickshell.Io import Quickshell.Widgets import Qt5Compat.GraphicalEffects diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml index a77a2a43..363d9ba5 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml @@ -1,7 +1,7 @@ pragma ComponentBehavior: Bound -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" +import qs.modules.common +import qs.modules.common.widgets +import qs.services import Quickshell import QtQuick import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherCard.qml b/.config/quickshell/ii/modules/bar/weather/WeatherCard.qml index 7b81fe54..a85ed8ca 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherCard.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherCard.qml @@ -1,8 +1,8 @@ import QtQuick import QtQuick.Layouts -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.modules.common +import qs.modules.common.widgets Rectangle { id: root diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml b/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml index b39fffd3..23ebcf83 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml @@ -1,6 +1,6 @@ -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml b/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml index 5b956841..9eef904c 100644 --- a/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml +++ b/.config/quickshell/ii/modules/cheatsheet/Cheatsheet.qml @@ -1,16 +1,13 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls -import QtQuick.Effects import QtQuick.Layouts import Qt5Compat.GraphicalEffects import Quickshell.Io import Quickshell -import Quickshell.Widgets import Quickshell.Wayland import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/cheatsheet/CheatsheetKeybinds.qml b/.config/quickshell/ii/modules/cheatsheet/CheatsheetKeybinds.qml index 03b03115..e0e8ce6c 100644 --- a/.config/quickshell/ii/modules/cheatsheet/CheatsheetKeybinds.qml +++ b/.config/quickshell/ii/modules/cheatsheet/CheatsheetKeybinds.qml @@ -1,15 +1,10 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell -import Quickshell.Io -import Quickshell.Widgets -import Quickshell.Hyprland Item { id: root diff --git a/.config/quickshell/ii/modules/cheatsheet/CheatsheetPeriodicTable.qml b/.config/quickshell/ii/modules/cheatsheet/CheatsheetPeriodicTable.qml index 774c522e..a0a8ecf3 100644 --- a/.config/quickshell/ii/modules/cheatsheet/CheatsheetPeriodicTable.qml +++ b/.config/quickshell/ii/modules/cheatsheet/CheatsheetPeriodicTable.qml @@ -1,16 +1,11 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import "periodic_table.js" as PTable import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell -import Quickshell.Io -import Quickshell.Widgets -import Quickshell.Hyprland Item { id: root diff --git a/.config/quickshell/ii/modules/cheatsheet/ElementTile.qml b/.config/quickshell/ii/modules/cheatsheet/ElementTile.qml index baeb72ad..70e7b4d6 100644 --- a/.config/quickshell/ii/modules/cheatsheet/ElementTile.qml +++ b/.config/quickshell/ii/modules/cheatsheet/ElementTile.qml @@ -1,10 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Quickshell.Io RippleButton { id: root diff --git a/.config/quickshell/ii/modules/common/Appearance.qml b/.config/quickshell/ii/modules/common/Appearance.qml index 7cc555ec..72cc78e3 100644 --- a/.config/quickshell/ii/modules/common/Appearance.qml +++ b/.config/quickshell/ii/modules/common/Appearance.qml @@ -1,6 +1,6 @@ import QtQuick import Quickshell -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common.functions pragma Singleton pragma ComponentBehavior: Bound diff --git a/.config/quickshell/ii/modules/common/Directories.qml b/.config/quickshell/ii/modules/common/Directories.qml index 38cfd73d..629d00c2 100644 --- a/.config/quickshell/ii/modules/common/Directories.qml +++ b/.config/quickshell/ii/modules/common/Directories.qml @@ -1,11 +1,10 @@ pragma Singleton pragma ComponentBehavior: Bound -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs.modules.common.functions import Qt.labs.platform import QtQuick import Quickshell -import Quickshell.Hyprland Singleton { // XDG Dirs, with "file://" diff --git a/.config/quickshell/ii/modules/common/functions/ColorUtils.qml b/.config/quickshell/ii/modules/common/functions/ColorUtils.qml new file mode 100644 index 00000000..27d48187 --- /dev/null +++ b/.config/quickshell/ii/modules/common/functions/ColorUtils.qml @@ -0,0 +1,114 @@ +pragma Singleton +import Quickshell + +Singleton { + id: root + + /** + * Returns a color with the hue of color2 and the saturation, value, and alpha of color1. + * + * @param {string} color1 - The base color (any Qt.color-compatible string). + * @param {string} color2 - The color to take hue from. + * @returns {Qt.rgba} The resulting color. + */ + function colorWithHueOf(color1, color2) { + var c1 = Qt.color(color1); + var c2 = Qt.color(color2); + + // Qt.color hsvHue/hsvSaturation/hsvValue/alpha return 0-1 + var hue = c2.hsvHue; + var sat = c1.hsvSaturation; + var val = c1.hsvValue; + var alpha = c1.a; + + return Qt.hsva(hue, sat, val, alpha); + } + + /** + * Returns a color with the saturation of color2 and the hue/value/alpha of color1. + * + * @param {string} color1 - The base color (any Qt.color-compatible string). + * @param {string} color2 - The color to take saturation from. + * @returns {Qt.rgba} The resulting color. + */ + function colorWithSaturationOf(color1, color2) { + var c1 = Qt.color(color1); + var c2 = Qt.color(color2); + + var hue = c1.hsvHue; + var sat = c2.hsvSaturation; + var val = c1.hsvValue; + var alpha = c1.a; + + return Qt.hsva(hue, sat, val, alpha); + } + + /** + * Returns a color with the given lightness and the hue, saturation, and alpha of the input color (using HSL). + * + * @param {string} color - The base color (any Qt.color-compatible string). + * @param {number} lightness - The lightness value to use (0-1). + * @returns {Qt.rgba} The resulting color. + */ + function colorWithLightness(color, lightness) { + var c = Qt.color(color); + return Qt.hsla(c.hslHue, c.hslSaturation, lightness, c.a); + } + + /** + * Returns a color with the lightness of color2 and the hue, saturation, and alpha of color1 (using HSL). + * + * @param {string} color1 - The base color (any Qt.color-compatible string). + * @param {string} color2 - The color to take lightness from. + * @returns {Qt.rgba} The resulting color. + */ + function colorWithLightnessOf(color1, color2) { + var c2 = Qt.color(color2); + return colorWithLightness(color1, c2.hslLightness); + } + + /** + * Adapts color1 to the accent (hue and saturation) of color2 using HSL, keeping lightness and alpha from color1. + * + * @param {string} color1 - The base color (any Qt.color-compatible string). + * @param {string} color2 - The accent color. + * @returns {Qt.rgba} The resulting color. + */ + function adaptToAccent(color1, color2) { + var c1 = Qt.color(color1); + var c2 = Qt.color(color2); + + var hue = c2.hslHue; + var sat = c2.hslSaturation; + var light = c1.hslLightness; + var alpha = c1.a; + + return Qt.hsla(hue, sat, light, alpha); + } + + /** + * Mixes two colors by a given percentage. + * + * @param {string} color1 - The first color (any Qt.color-compatible string). + * @param {string} color2 - The second color. + * @param {number} percentage - The mix ratio (0-1). 1 = all color1, 0 = all color2. + * @returns {Qt.rgba} The resulting mixed color. + */ + function mix(color1, color2, percentage = 0.5) { + var c1 = Qt.color(color1); + var c2 = Qt.color(color2); + return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a); + } + + /** + * Transparentizes a color by a given percentage. + * + * @param {string} color - The color (any Qt.color-compatible string). + * @param {number} percentage - The amount to transparentize (0-1). + * @returns {Qt.rgba} The resulting color. + */ + function transparentize(color, percentage = 1) { + var c = Qt.color(color); + return Qt.rgba(c.r, c.g, c.b, c.a * (1 - percentage)); + } +} diff --git a/.config/quickshell/ii/modules/common/functions/FileUtils.qml b/.config/quickshell/ii/modules/common/functions/FileUtils.qml new file mode 100644 index 00000000..c051674e --- /dev/null +++ b/.config/quickshell/ii/modules/common/functions/FileUtils.qml @@ -0,0 +1,41 @@ +pragma Singleton +import Quickshell + +Singleton { + id: root + + /** + * Trims the File protocol off the input string + * @param {string} str + * @returns {string} + */ + function trimFileProtocol(str) { + return str.startsWith("file://") ? str.slice(7) : str; + } + + /** + * Extracts the file name from a file path + * @param {string} str + * @returns {string} + */ + function fileNameForPath(str) { + if (typeof str !== "string") return ""; + const trimmed = trimFileProtocol(str); + return trimmed.split(/[\\/]/).pop(); + } + + /** + * Removes the file extension from a file path or name + * @param {string} str + * @returns {string} + */ + function trimFileExt(str) { + if (typeof str !== "string") return ""; + const trimmed = trimFileProtocol(str); + const lastDot = trimmed.lastIndexOf("."); + if (lastDot > -1 && lastDot > trimmed.lastIndexOf("/")) { + return trimmed.slice(0, lastDot); + } + return trimmed; + } +} diff --git a/.config/quickshell/ii/modules/common/functions/ObjectUtils.qml b/.config/quickshell/ii/modules/common/functions/ObjectUtils.qml new file mode 100644 index 00000000..d1204cdd --- /dev/null +++ b/.config/quickshell/ii/modules/common/functions/ObjectUtils.qml @@ -0,0 +1,98 @@ +pragma Singleton +import Quickshell + +Singleton { + id: root + + function toPlainObject(qtObj) { + if (qtObj === null || typeof qtObj !== "object") return qtObj; + + // Handle true arrays + if (Array.isArray(qtObj)) { + return qtObj.map(item => toPlainObject(item)); + } + + // Handle array-like Qt objects (e.g., have length and numeric keys) + if ( + typeof qtObj.length === "number" && + qtObj.length > 0 && + Object.keys(qtObj).every( + key => !isNaN(key) || key === "length" + ) + ) { + let arr = []; + for (let i = 0; i < qtObj.length; i++) { + arr.push(toPlainObject(qtObj[i])); + } + return arr; + } + + const result = ({}); + for (let key in qtObj) { + if ( + typeof qtObj[key] !== "function" && + !key.startsWith("objectName") && + !key.startsWith("children") && + !key.startsWith("object") && + !key.startsWith("parent") && + !key.startsWith("metaObject") && + !key.startsWith("destroyed") && + !key.startsWith("reloadableId") + ) { + result[key] = toPlainObject(qtObj[key]); + } + } + // console.log(JSON.stringify(result)) + return result; + } + + function applyToQtObject(qtObj, jsonObj) { + // console.log("applyToQtObject", JSON.stringify(qtObj, null, 2), "<<", JSON.stringify(jsonObj, null, 2)); + if (!qtObj || typeof jsonObj !== "object" || jsonObj === null) return; + + // Detect array-like Qt objects + const isQtArrayLike = obj => { + return obj && typeof obj === "object" && + typeof obj.length === "number" && + obj.length > 0 && + Object.keys(obj).every(key => !isNaN(key) || key === "length"); + }; + + // If both are arrays or array-like, update in place or replace + if ((Array.isArray(qtObj) || isQtArrayLike(qtObj)) && Array.isArray(jsonObj)) { + qtObj.length = 0; + for (let i = 0; i < jsonObj.length; i++) { + qtObj.push(jsonObj[i]); + } + return; + } + + // If target is array or array-like but source is not, clear + if ((Array.isArray(qtObj) || isQtArrayLike(qtObj)) && !Array.isArray(jsonObj)) { + qtObj.length = 0; + return; + } + + // If source is array but target is not, assign directly if possible + if (!(Array.isArray(qtObj) || isQtArrayLike(qtObj)) && Array.isArray(jsonObj)) { + return jsonObj; + } + + for (let key in jsonObj) { + if (!qtObj.hasOwnProperty(key)) continue; + const value = qtObj[key]; + const jsonValue = jsonObj[key]; + // console.log("applying to qt obj key:", value, "jsonValue:", jsonValue); + if ((Array.isArray(value) || isQtArrayLike(value)) && Array.isArray(jsonValue)) { + value.length = 0; + for (let i = 0; i < jsonValue.length; i++) { + value.push(jsonValue[i]); + } + } else if (value && typeof value === "object" && !Array.isArray(value) && !isQtArrayLike(value)) { + applyToQtObject(value, jsonValue); + } else { + qtObj[key] = jsonValue; + } + } + } +} diff --git a/.config/quickshell/ii/modules/common/functions/StringUtils.qml b/.config/quickshell/ii/modules/common/functions/StringUtils.qml new file mode 100644 index 00000000..e8241831 --- /dev/null +++ b/.config/quickshell/ii/modules/common/functions/StringUtils.qml @@ -0,0 +1,221 @@ +pragma Singleton +import Quickshell + +Singleton { + id: root + + /** + * Formats a string according to the args that are passed inc + * @param { string } str + * @param {...any} args + * @returns + */ + function format(str, ...args) { + return str.replace(/{(\d+)}/g, (match, index) => typeof args[index] !== 'undefined' ? args[index] : match); + } + + /** + * Returns the domain of the passed in url or null + * @param { string } url + * @returns { string| null } + */ + function getDomain(url) { + const match = url.match(/^(?:https?:\/\/)?(?:www\.)?([^\/]+)/); + return match ? match[1] : null; + } + + /** + * Returns the base url of the passed in url or null + * @param { string } url + * @returns { string | null } + */ + function getBaseUrl(url) { + const match = url.match(/^(https?:\/\/[^\/]+)(\/.*)?$/); + return match ? match[1] : null; + } + + /** + * Escapes single quotes in shell commands + * @param { string } str + * @returns { string } + */ + function shellSingleQuoteEscape(str) { + // escape single quotes + return String(str) + // .replace(/\\/g, '\\\\') + .replace(/'/g, "'\\''"); + } + + /** + * Splits markdown blocks into three different types: text, think, and code. + * @param { string } markdown + */ + function splitMarkdownBlocks(markdown) { + const regex = /```(\w+)?\n([\s\S]*?)```|([\s\S]*?)<\/think>/g; + /** + * @type {{type: "text" | "think" | "code"; content: string; lang: string | undefined; completed: boolean | undefined}[]} + */ + let result = []; + let lastIndex = 0; + let match; + while ((match = regex.exec(markdown)) !== null) { + if (match.index > lastIndex) { + const text = markdown.slice(lastIndex, match.index); + if (text.trim()) { + result.push({ + type: "text", + content: text + }); + } + } + if (match[0].startsWith('```')) { + if (match[2] && match[2].trim()) { + result.push({ + type: "code", + lang: match[1] || "", + content: match[2], + completed: true + }); + } + } else if (match[0].startsWith('')) { + if (match[3] && match[3].trim()) { + result.push({ + type: "think", + content: match[3], + completed: true + }); + } + } + lastIndex = regex.lastIndex; + } + // Handle any remaining text after the last match + if (lastIndex < markdown.length) { + const text = markdown.slice(lastIndex); + // Check for unfinished block + const thinkStart = text.indexOf(''); + const codeStart = text.indexOf('```'); + if (thinkStart !== -1 && (codeStart === -1 || thinkStart < codeStart)) { + const beforeThink = text.slice(0, thinkStart); + if (beforeThink.trim()) { + result.push({ + type: "text", + content: beforeThink + }); + } + const thinkContent = text.slice(thinkStart + 7); + if (thinkContent.trim()) { + result.push({ + type: "think", + content: thinkContent, + completed: false + }); + } + } else if (codeStart !== -1) { + const beforeCode = text.slice(0, codeStart); + if (beforeCode.trim()) { + result.push({ + type: "text", + content: beforeCode + }); + } + // Try to detect language after ``` + const codeLangMatch = text.slice(codeStart + 3).match(/^(\w+)?\n/); + let lang = ""; + let codeContentStart = codeStart + 3; + if (codeLangMatch) { + lang = codeLangMatch[1] || ""; + codeContentStart += codeLangMatch[0].length; + } else if (text[codeStart + 3] === '\n') { + codeContentStart += 1; + } + const codeContent = text.slice(codeContentStart); + if (codeContent.trim()) { + result.push({ + type: "code", + lang, + content: codeContent, + completed: false + }); + } + } else if (text.trim()) { + result.push({ + type: "text", + content: text + }); + } + } + // console.log(JSON.stringify(result, null, 2)); + return result; + } + + /** + * Returns the original string with backslashes escaped + * @param { string } str + * @returns { string } + */ + function escapeBackslashes(str) { + return str.replace(/\\/g, '\\\\'); + } + + /** + * Wraps words to supplied maximum length + * @param { string | null } str + * @param { number } maxLen + * @returns { string } + */ + function wordWrap(str, maxLen) { + if (!str) + return ""; + let words = str.split(" "); + let lines = []; + let current = ""; + for (let i = 0; i < words.length; ++i) { + if ((current + (current.length > 0 ? " " : "") + words[i]).length > maxLen) { + if (current.length > 0) + lines.push(current); + current = words[i]; + } else { + current += (current.length > 0 ? " " : "") + words[i]; + } + } + if (current.length > 0) + lines.push(current); + return lines.join("\n"); + } + + function cleanMusicTitle(title) { + if (!title) + return ""; + // Brackets + title = title.replace(/^ *\([^)]*\) */g, " "); // Round brackets + title = title.replace(/^ *\[[^\]]*\] */g, " "); // Square brackets + title = title.replace(/^ *\{[^\}]*\} */g, " "); // Curly brackets + // Japenis brackets + title = title.replace(/^ *【[^】]*】/, ""); // Touhou + title = title.replace(/^ *《[^》]*》/, ""); // ?? + title = title.replace(/^ *「[^」]*」/, ""); // OP/ED thingie + title = title.replace(/^ *『[^』]*』/, ""); // OP/ED thingie + + return title.trim(); + } + + function friendlyTimeForSeconds(seconds) { + if (isNaN(seconds) || seconds < 0) + return "0:00"; + seconds = Math.floor(seconds); + const h = Math.floor(seconds / 3600); + const m = Math.floor((seconds % 3600) / 60); + const s = seconds % 60; + if (h > 0) { + return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`; + } else { + return `${m}:${s.toString().padStart(2, '0')}`; + } + } + + function escapeHtml(str) { + if (typeof str !== 'string') + return str; + return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); + } +} diff --git a/.config/quickshell/ii/modules/common/functions/color_utils.js b/.config/quickshell/ii/modules/common/functions/color_utils.js deleted file mode 100644 index eb0fc0c2..00000000 --- a/.config/quickshell/ii/modules/common/functions/color_utils.js +++ /dev/null @@ -1,109 +0,0 @@ -// This module provides high level utility functions for color manipulation. - -/** - * Returns a color with the hue of color2 and the saturation, value, and alpha of color1. - * - * @param {string} color1 - The base color (any Qt.color-compatible string). - * @param {string} color2 - The color to take hue from. - * @returns {Qt.rgba} The resulting color. - */ -function colorWithHueOf(color1, color2) { - var c1 = Qt.color(color1); - var c2 = Qt.color(color2); - - // Qt.color hsvHue/hsvSaturation/hsvValue/alpha return 0-1 - var hue = c2.hsvHue; - var sat = c1.hsvSaturation; - var val = c1.hsvValue; - var alpha = c1.a; - - return Qt.hsva(hue, sat, val, alpha); -} - -/** - * Returns a color with the saturation of color2 and the hue/value/alpha of color1. - * - * @param {string} color1 - The base color (any Qt.color-compatible string). - * @param {string} color2 - The color to take saturation from. - * @returns {Qt.rgba} The resulting color. - */ -function colorWithSaturationOf(color1, color2) { - var c1 = Qt.color(color1); - var c2 = Qt.color(color2); - - var hue = c1.hsvHue; - var sat = c2.hsvSaturation; - var val = c1.hsvValue; - var alpha = c1.a; - - return Qt.hsva(hue, sat, val, alpha); -} - -/** - * Returns a color with the given lightness and the hue, saturation, and alpha of the input color (using HSL). - * - * @param {string} color - The base color (any Qt.color-compatible string). - * @param {number} lightness - The lightness value to use (0-1). - * @returns {Qt.rgba} The resulting color. - */ -function colorWithLightness(color, lightness) { - var c = Qt.color(color); - return Qt.hsla(c.hslHue, c.hslSaturation, lightness, c.a); -} - -/** - * Returns a color with the lightness of color2 and the hue, saturation, and alpha of color1 (using HSL). - * - * @param {string} color1 - The base color (any Qt.color-compatible string). - * @param {string} color2 - The color to take lightness from. - * @returns {Qt.rgba} The resulting color. - */ -function colorWithLightnessOf(color1, color2) { - var c2 = Qt.color(color2); - return colorWithLightness(color1, c2.hslLightness); -} - -/** - * Adapts color1 to the accent (hue and saturation) of color2 using HSL, keeping lightness and alpha from color1. - * - * @param {string} color1 - The base color (any Qt.color-compatible string). - * @param {string} color2 - The accent color. - * @returns {Qt.rgba} The resulting color. - */ -function adaptToAccent(color1, color2) { - var c1 = Qt.color(color1); - var c2 = Qt.color(color2); - - var hue = c2.hslHue; - var sat = c2.hslSaturation; - var light = c1.hslLightness; - var alpha = c1.a; - - return Qt.hsla(hue, sat, light, alpha); -} - -/** - * Mixes two colors by a given percentage. - * - * @param {string} color1 - The first color (any Qt.color-compatible string). - * @param {string} color2 - The second color. - * @param {number} percentage - The mix ratio (0-1). 1 = all color1, 0 = all color2. - * @returns {Qt.rgba} The resulting mixed color. - */ -function mix(color1, color2, percentage = 0.5) { - var c1 = Qt.color(color1); - var c2 = Qt.color(color2); - return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a); -} - -/** - * Transparentizes a color by a given percentage. - * - * @param {string} color - The color (any Qt.color-compatible string). - * @param {number} percentage - The amount to transparentize (0-1). - * @returns {Qt.rgba} The resulting color. - */ -function transparentize(color, percentage = 1) { - var c = Qt.color(color); - return Qt.rgba(c.r, c.g, c.b, c.a * (1 - percentage)); -} diff --git a/.config/quickshell/ii/modules/common/functions/file_utils.js b/.config/quickshell/ii/modules/common/functions/file_utils.js deleted file mode 100644 index 07464009..00000000 --- a/.config/quickshell/ii/modules/common/functions/file_utils.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Trims the File protocol off the input string - * @param {string} str - * @returns {string} - */ -function trimFileProtocol(str) { - return str.startsWith("file://") ? str.slice(7) : str; -} - -/** - * Extracts the file name from a file path - * @param {string} str - * @returns {string} - */ -function fileNameForPath(str) { - if (typeof str !== "string") return ""; - const trimmed = trimFileProtocol(str); - return trimmed.split(/[\\/]/).pop(); -} - -/** - * Removes the file extension from a file path or name - * @param {string} str - * @returns {string} - */ -function trimFileExt(str) { - if (typeof str !== "string") return ""; - const trimmed = trimFileProtocol(str); - const lastDot = trimmed.lastIndexOf("."); - if (lastDot > -1 && lastDot > trimmed.lastIndexOf("/")) { - return trimmed.slice(0, lastDot); - } - return trimmed; -} \ No newline at end of file diff --git a/.config/quickshell/ii/modules/common/functions/object_utils.js b/.config/quickshell/ii/modules/common/functions/object_utils.js deleted file mode 100644 index e65a4540..00000000 --- a/.config/quickshell/ii/modules/common/functions/object_utils.js +++ /dev/null @@ -1,91 +0,0 @@ -function toPlainObject(qtObj) { - if (qtObj === null || typeof qtObj !== "object") return qtObj; - - // Handle true arrays - if (Array.isArray(qtObj)) { - return qtObj.map(item => toPlainObject(item)); - } - - // Handle array-like Qt objects (e.g., have length and numeric keys) - if ( - typeof qtObj.length === "number" && - qtObj.length > 0 && - Object.keys(qtObj).every( - key => !isNaN(key) || key === "length" - ) - ) { - let arr = []; - for (let i = 0; i < qtObj.length; i++) { - arr.push(toPlainObject(qtObj[i])); - } - return arr; - } - - const result = ({}); - for (let key in qtObj) { - if ( - typeof qtObj[key] !== "function" && - !key.startsWith("objectName") && - !key.startsWith("children") && - !key.startsWith("object") && - !key.startsWith("parent") && - !key.startsWith("metaObject") && - !key.startsWith("destroyed") && - !key.startsWith("reloadableId") - ) { - result[key] = toPlainObject(qtObj[key]); - } - } - // console.log(JSON.stringify(result)) - return result; -} - -function applyToQtObject(qtObj, jsonObj) { - // console.log("applyToQtObject", JSON.stringify(qtObj, null, 2), "<<", JSON.stringify(jsonObj, null, 2)); - if (!qtObj || typeof jsonObj !== "object" || jsonObj === null) return; - - // Detect array-like Qt objects - const isQtArrayLike = obj => { - return obj && typeof obj === "object" && - typeof obj.length === "number" && - obj.length > 0 && - Object.keys(obj).every(key => !isNaN(key) || key === "length"); - }; - - // If both are arrays or array-like, update in place or replace - if ((Array.isArray(qtObj) || isQtArrayLike(qtObj)) && Array.isArray(jsonObj)) { - qtObj.length = 0; - for (let i = 0; i < jsonObj.length; i++) { - qtObj.push(jsonObj[i]); - } - return; - } - - // If target is array or array-like but source is not, clear - if ((Array.isArray(qtObj) || isQtArrayLike(qtObj)) && !Array.isArray(jsonObj)) { - qtObj.length = 0; - return; - } - - // If source is array but target is not, assign directly if possible - if (!(Array.isArray(qtObj) || isQtArrayLike(qtObj)) && Array.isArray(jsonObj)) { - return jsonObj; - } - - for (let key in jsonObj) { - if (!qtObj.hasOwnProperty(key)) continue; - const value = qtObj[key]; - const jsonValue = jsonObj[key]; - // console.log("applying to qt obj key:", value, "jsonValue:", jsonValue); - if ((Array.isArray(value) || isQtArrayLike(value)) && Array.isArray(jsonValue)) { - value.length = 0; - for (let i = 0; i < jsonValue.length; i++) { - value.push(jsonValue[i]); - } - } else if (value && typeof value === "object" && !Array.isArray(value) && !isQtArrayLike(value)) { - applyToQtObject(value, jsonValue); - } else { - qtObj[key] = jsonValue; - } - } -} diff --git a/.config/quickshell/ii/modules/common/functions/string_utils.js b/.config/quickshell/ii/modules/common/functions/string_utils.js deleted file mode 100644 index 0819dbfb..00000000 --- a/.config/quickshell/ii/modules/common/functions/string_utils.js +++ /dev/null @@ -1,188 +0,0 @@ -/** - * Formats a string according to the args that are passed in - * @param { string } str - * @param {...any} args - * @returns - */ -function format(str, ...args) { - return str.replace(/{(\d+)}/g, (match, index) => - typeof args[index] !== 'undefined' ? args[index] : match - ); -} - -/** - * Returns the domain of the passed in url or null - * @param { string } url - * @returns { string| null } - */ -function getDomain(url) { - const match = url.match(/^(?:https?:\/\/)?(?:www\.)?([^\/]+)/); - return match ? match[1] : null; -} - -/** - * Returns the base url of the passed in url or null - * @param { string } url - * @returns { string | null } - */ -function getBaseUrl(url) { - const match = url.match(/^(https?:\/\/[^\/]+)(\/.*)?$/); - return match ? match[1] : null; -} - -/** - * Escapes single quotes in shell commands - * @param { string } str - * @returns { string } - */ -function shellSingleQuoteEscape(str) { - // escape single quotes - return String(str) - // .replace(/\\/g, '\\\\') - .replace(/'/g, "'\\''"); -} - -/** - * Splits markdown blocks into three different types: text, think, and code. - * @param { string } markdown - */ -function splitMarkdownBlocks(markdown) { - const regex = /```(\w+)?\n([\s\S]*?)```|([\s\S]*?)<\/think>/g; - /** - * @type {{type: "text" | "think" | "code"; content: string; lang: string | undefined; completed: boolean | undefined}[]} - */ - let result = []; - let lastIndex = 0; - let match; - while ((match = regex.exec(markdown)) !== null) { - if (match.index > lastIndex) { - const text = markdown.slice(lastIndex, match.index); - if (text.trim()) { - result.push({ type: "text", content: text }); - } - } - if (match[0].startsWith('```')) { - if (match[2] && match[2].trim()) { - result.push({ type: "code", lang: match[1] || "", content: match[2], completed: true }); - } - } else if (match[0].startsWith('')) { - if (match[3] && match[3].trim()) { - result.push({ type: "think", content: match[3], completed: true }); - } - } - lastIndex = regex.lastIndex; - } - // Handle any remaining text after the last match - if (lastIndex < markdown.length) { - const text = markdown.slice(lastIndex); - // Check for unfinished block - const thinkStart = text.indexOf(''); - const codeStart = text.indexOf('```'); - if ( - thinkStart !== -1 && - (codeStart === -1 || thinkStart < codeStart) - ) { - const beforeThink = text.slice(0, thinkStart); - if (beforeThink.trim()) { - result.push({ type: "text", content: beforeThink }); - } - const thinkContent = text.slice(thinkStart + 7); - if (thinkContent.trim()) { - result.push({ type: "think", content: thinkContent, completed: false }); - } - } else if (codeStart !== -1) { - const beforeCode = text.slice(0, codeStart); - if (beforeCode.trim()) { - result.push({ type: "text", content: beforeCode }); - } - // Try to detect language after ``` - const codeLangMatch = text.slice(codeStart + 3).match(/^(\w+)?\n/); - let lang = ""; - let codeContentStart = codeStart + 3; - if (codeLangMatch) { - lang = codeLangMatch[1] || ""; - codeContentStart += codeLangMatch[0].length; - } else if (text[codeStart + 3] === '\n') { - codeContentStart += 1; - } - const codeContent = text.slice(codeContentStart); - if (codeContent.trim()) { - result.push({ type: "code", lang, content: codeContent, completed: false }); - } - } else if (text.trim()) { - result.push({ type: "text", content: text }); - } - } - // console.log(JSON.stringify(result, null, 2)); - return result; -} - -/** - * Returns the original string with backslashes escaped - * @param { string } str - * @returns { string } - */ -function escapeBackslashes(str) { - return str.replace(/\\/g, '\\\\'); -} - -/** - * Wraps words to supplied maximum length - * @param { string | null } str - * @param { number } maxLen - * @returns { string } - */ -function wordWrap(str, maxLen) { - if (!str) return ""; - let words = str.split(" "); - let lines = []; - let current = ""; - for (let i = 0; i < words.length; ++i) { - if ((current + (current.length > 0 ? " " : "") + words[i]).length > maxLen) { - if (current.length > 0) lines.push(current); - current = words[i]; - } else { - current += (current.length > 0 ? " " : "") + words[i]; - } - } - if (current.length > 0) lines.push(current); - return lines.join("\n"); -} - -function cleanMusicTitle(title) { - if (!title) return ""; - // Brackets - title = title.replace(/^ *\([^)]*\) */g, " "); // Round brackets - title = title.replace(/^ *\[[^\]]*\] */g, " "); // Square brackets - title = title.replace(/^ *\{[^\}]*\} */g, " "); // Curly brackets - // Japenis brackets - title = title.replace(/^ *【[^】]*】/, "") // Touhou - title = title.replace(/^ *《[^》]*》/, "") // ?? - title = title.replace(/^ *「[^」]*」/, "") // OP/ED thingie - title = title.replace(/^ *『[^』]*』/, "") // OP/ED thingie - - return title.trim(); -} - -function friendlyTimeForSeconds(seconds) { - if (isNaN(seconds) || seconds < 0) return "0:00"; - seconds = Math.floor(seconds); - const h = Math.floor(seconds / 3600); - const m = Math.floor((seconds % 3600) / 60); - const s = seconds % 60; - if (h > 0) { - return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`; - } else { - return `${m}:${s.toString().padStart(2, '0')}`; - } -} - -function escapeHtml(str) { - if (typeof str !== 'string') return str; - return str - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} diff --git a/.config/quickshell/ii/modules/common/widgets/ButtonGroup.qml b/.config/quickshell/ii/modules/common/widgets/ButtonGroup.qml index 4b8676f4..7dc7a591 100644 --- a/.config/quickshell/ii/modules/common/widgets/ButtonGroup.qml +++ b/.config/quickshell/ii/modules/common/widgets/ButtonGroup.qml @@ -1,8 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls import QtQuick.Layouts /** diff --git a/.config/quickshell/ii/modules/common/widgets/CircularProgress.qml b/.config/quickshell/ii/modules/common/widgets/CircularProgress.qml index c3731e64..9a84bb1e 100644 --- a/.config/quickshell/ii/modules/common/widgets/CircularProgress.qml +++ b/.config/quickshell/ii/modules/common/widgets/CircularProgress.qml @@ -2,7 +2,7 @@ // License: LGPL-3.0 - A copy can be found in `licenses` folder of repo import QtQuick -import "root:/modules/common" +import qs.modules.common /** * Material 3 circular progress. See https://m3.material.io/components/progress-indicators/specs diff --git a/.config/quickshell/ii/modules/common/widgets/CliphistImage.qml b/.config/quickshell/ii/modules/common/widgets/CliphistImage.qml index 62d948cf..ce15ef3e 100644 --- a/.config/quickshell/ii/modules/common/widgets/CliphistImage.qml +++ b/.config/quickshell/ii/modules/common/widgets/CliphistImage.qml @@ -1,17 +1,11 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import qs.modules.common.functions import Qt5Compat.GraphicalEffects -import Qt.labs.platform import QtQuick -import QtQuick.Controls -import QtQuick.Layouts import Quickshell import Quickshell.Io -import Quickshell.Widgets -import Quickshell.Hyprland Rectangle { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/ConfigSelectionArray.qml b/.config/quickshell/ii/modules/common/widgets/ConfigSelectionArray.qml index e62831a4..318ffe1c 100644 --- a/.config/quickshell/ii/modules/common/widgets/ConfigSelectionArray.qml +++ b/.config/quickshell/ii/modules/common/widgets/ConfigSelectionArray.qml @@ -1,14 +1,9 @@ import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell -import Quickshell.Io -import Quickshell.Hyprland -import "root:/services/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions Flow { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/ConfigSpinBox.qml b/.config/quickshell/ii/modules/common/widgets/ConfigSpinBox.qml index 972c221d..375f78ed 100644 --- a/.config/quickshell/ii/modules/common/widgets/ConfigSpinBox.qml +++ b/.config/quickshell/ii/modules/common/widgets/ConfigSpinBox.qml @@ -1,8 +1,7 @@ -import "root:/modules/common/widgets/" -import "root:/modules/common/" +import qs.modules.common.widgets +import qs.modules.common import QtQuick import QtQuick.Layouts -import QtQuick.Controls RowLayout { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/ConfigSwitch.qml b/.config/quickshell/ii/modules/common/widgets/ConfigSwitch.qml index 51f82a72..e10f74d6 100644 --- a/.config/quickshell/ii/modules/common/widgets/ConfigSwitch.qml +++ b/.config/quickshell/ii/modules/common/widgets/ConfigSwitch.qml @@ -1,5 +1,5 @@ -import "root:/modules/common/widgets/" -import "root:/modules/common/" +import qs.modules.common.widgets +import qs.modules.common import QtQuick import QtQuick.Layouts import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/common/widgets/ContentPage.qml b/.config/quickshell/ii/modules/common/widgets/ContentPage.qml index d23922c7..dc87179f 100644 --- a/.config/quickshell/ii/modules/common/widgets/ContentPage.qml +++ b/.config/quickshell/ii/modules/common/widgets/ContentPage.qml @@ -1,8 +1,7 @@ import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs.modules.common +import qs.modules.common.widgets Flickable { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/ContentSection.qml b/.config/quickshell/ii/modules/common/widgets/ContentSection.qml index 01eab5cb..2f038e1f 100644 --- a/.config/quickshell/ii/modules/common/widgets/ContentSection.qml +++ b/.config/quickshell/ii/modules/common/widgets/ContentSection.qml @@ -1,8 +1,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs.modules.common +import qs.modules.common.widgets ColumnLayout { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/ContentSubsection.qml b/.config/quickshell/ii/modules/common/widgets/ContentSubsection.qml index 0eb3b3b5..b78f3aa8 100644 --- a/.config/quickshell/ii/modules/common/widgets/ContentSubsection.qml +++ b/.config/quickshell/ii/modules/common/widgets/ContentSubsection.qml @@ -1,8 +1,7 @@ import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs.modules.common +import qs.modules.common.widgets ColumnLayout { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/ContentSubsectionLabel.qml b/.config/quickshell/ii/modules/common/widgets/ContentSubsectionLabel.qml index 549ccae2..5d29e0e1 100644 --- a/.config/quickshell/ii/modules/common/widgets/ContentSubsectionLabel.qml +++ b/.config/quickshell/ii/modules/common/widgets/ContentSubsectionLabel.qml @@ -1,7 +1,7 @@ import QtQuick import QtQuick.Layouts -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs.modules.common +import qs.modules.common.widgets StyledText { text: "Subsection" diff --git a/.config/quickshell/ii/modules/common/widgets/CustomIcon.qml b/.config/quickshell/ii/modules/common/widgets/CustomIcon.qml index 28519615..e5bbe39a 100644 --- a/.config/quickshell/ii/modules/common/widgets/CustomIcon.qml +++ b/.config/quickshell/ii/modules/common/widgets/CustomIcon.qml @@ -9,7 +9,7 @@ Item { property bool colorize: false property color color property string source: "" - property string iconFolder: "root:/assets/icons" // The folder to check first + property string iconFolder: Qt.resolvedUrl(Quickshell.configPath("assets/icons")) // The folder to check first width: 30 height: 30 @@ -17,8 +17,9 @@ Item { id: iconImage anchors.fill: parent source: { - if (iconFolder && iconFolder + "/" + root.source) { - return iconFolder + "/" + root.source + const fullPathWhenSourceIsIconName = iconFolder + "/" + root.source; + if (iconFolder && fullPathWhenSourceIsIconName) { + return fullPathWhenSourceIsIconName } return root.source } diff --git a/.config/quickshell/ii/modules/common/widgets/DialogButton.qml b/.config/quickshell/ii/modules/common/widgets/DialogButton.qml index 86150c50..972c29b2 100644 --- a/.config/quickshell/ii/modules/common/widgets/DialogButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/DialogButton.qml @@ -1,10 +1,5 @@ -import "root:/modules/common" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Quickshell.Io /** * Material 3 dialog button. See https://m3.material.io/components/dialogs/overview diff --git a/.config/quickshell/ii/modules/common/widgets/DragManager.qml b/.config/quickshell/ii/modules/common/widgets/DragManager.qml index 087729ed..9a430d93 100644 --- a/.config/quickshell/ii/modules/common/widgets/DragManager.qml +++ b/.config/quickshell/ii/modules/common/widgets/DragManager.qml @@ -1,8 +1,6 @@ -import "root:/modules/common" -import "root:/services" +import qs.modules.common +import qs.services import QtQuick -import QtQuick.Controls -import QtQuick.Layouts /** * A convenience MouseArea for handling drag events. diff --git a/.config/quickshell/ii/modules/common/widgets/Favicon.qml b/.config/quickshell/ii/modules/common/widgets/Favicon.qml index 8b9b2596..04e92859 100644 --- a/.config/quickshell/ii/modules/common/widgets/Favicon.qml +++ b/.config/quickshell/ii/modules/common/widgets/Favicon.qml @@ -1,16 +1,11 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import qs.modules.common.functions import Qt5Compat.GraphicalEffects -import Qt.labs.platform import QtQuick -import QtQuick.Controls -import QtQuick.Layouts import Quickshell.Io import Quickshell.Widgets -import Quickshell.Hyprland IconImage { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/FloatingActionButton.qml b/.config/quickshell/ii/modules/common/widgets/FloatingActionButton.qml index bc6031e7..14702aad 100644 --- a/.config/quickshell/ii/modules/common/widgets/FloatingActionButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/FloatingActionButton.qml @@ -1,8 +1,7 @@ import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs.modules.common +import qs.modules.common.widgets /** * Material 3 FAB. diff --git a/.config/quickshell/ii/modules/common/widgets/GroupButton.qml b/.config/quickshell/ii/modules/common/widgets/GroupButton.qml index 362ae39e..a64cd063 100644 --- a/.config/quickshell/ii/modules/common/widgets/GroupButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/GroupButton.qml @@ -1,12 +1,9 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import Qt5Compat.GraphicalEffects +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io -import Quickshell.Widgets /** * Material 3 button with expressive bounciness. diff --git a/.config/quickshell/ii/modules/common/widgets/KeyboardKey.qml b/.config/quickshell/ii/modules/common/widgets/KeyboardKey.qml index 1a5ab002..14c75c62 100644 --- a/.config/quickshell/ii/modules/common/widgets/KeyboardKey.qml +++ b/.config/quickshell/ii/modules/common/widgets/KeyboardKey.qml @@ -1,9 +1,5 @@ -import "root:/modules/common" +import qs.modules.common import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Quickshell.Io Rectangle { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/LightDarkPreferenceButton.qml b/.config/quickshell/ii/modules/common/widgets/LightDarkPreferenceButton.qml index 69db7567..63dbd2c8 100644 --- a/.config/quickshell/ii/modules/common/widgets/LightDarkPreferenceButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/LightDarkPreferenceButton.qml @@ -1,13 +1,10 @@ -import "root:/" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick -import QtQuick.Controls import QtQuick.Layouts import Quickshell -import Quickshell.Io -import Quickshell.Hyprland GroupButton { id: lightDarkButtonRoot diff --git a/.config/quickshell/ii/modules/common/widgets/MaterialSymbol.qml b/.config/quickshell/ii/modules/common/widgets/MaterialSymbol.qml index 7b41333a..92da9918 100644 --- a/.config/quickshell/ii/modules/common/widgets/MaterialSymbol.qml +++ b/.config/quickshell/ii/modules/common/widgets/MaterialSymbol.qml @@ -1,6 +1,5 @@ -import "root:/modules/common/" +import qs.modules.common import QtQuick -import QtQuick.Layouts Text { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/MaterialTextField.qml b/.config/quickshell/ii/modules/common/widgets/MaterialTextField.qml index 1129c6d8..241cc90f 100644 --- a/.config/quickshell/ii/modules/common/widgets/MaterialTextField.qml +++ b/.config/quickshell/ii/modules/common/widgets/MaterialTextField.qml @@ -1,5 +1,4 @@ -import "root:/modules/common" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common import QtQuick import QtQuick.Controls.Material import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/common/widgets/MenuButton.qml b/.config/quickshell/ii/modules/common/widgets/MenuButton.qml index 0c4c4f41..9185bc9d 100644 --- a/.config/quickshell/ii/modules/common/widgets/MenuButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/MenuButton.qml @@ -1,10 +1,5 @@ -import "root:/modules/common" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Quickshell.Io RippleButton { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/NavigationRail.qml b/.config/quickshell/ii/modules/common/widgets/NavigationRail.qml index fe3c64a2..11082a70 100644 --- a/.config/quickshell/ii/modules/common/widgets/NavigationRail.qml +++ b/.config/quickshell/ii/modules/common/widgets/NavigationRail.qml @@ -1,8 +1,7 @@ import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs.modules.common +import qs.modules.common.widgets ColumnLayout { // Window content with navigation rail and content pane id: root diff --git a/.config/quickshell/ii/modules/common/widgets/NavigationRailButton.qml b/.config/quickshell/ii/modules/common/widgets/NavigationRailButton.qml index 615cb35e..0b83b45b 100644 --- a/.config/quickshell/ii/modules/common/widgets/NavigationRailButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/NavigationRailButton.qml @@ -1,10 +1,9 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io TabButton { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/NavigationRailExpandButton.qml b/.config/quickshell/ii/modules/common/widgets/NavigationRailExpandButton.qml index 11fe37bc..57e15f04 100644 --- a/.config/quickshell/ii/modules/common/widgets/NavigationRailExpandButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/NavigationRailExpandButton.qml @@ -1,8 +1,7 @@ import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs.modules.common +import qs.modules.common.widgets RippleButton { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/NavigationRailTabArray.qml b/.config/quickshell/ii/modules/common/widgets/NavigationRailTabArray.qml index e13ea76c..6596141d 100644 --- a/.config/quickshell/ii/modules/common/widgets/NavigationRailTabArray.qml +++ b/.config/quickshell/ii/modules/common/widgets/NavigationRailTabArray.qml @@ -1,10 +1,7 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io Item { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationActionButton.qml b/.config/quickshell/ii/modules/common/widgets/NotificationActionButton.qml index e85735a7..2a737255 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationActionButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationActionButton.qml @@ -1,9 +1,6 @@ -import "root:/modules/common" -import "root:/services" +import qs.modules.common +import qs.services import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell import Quickshell.Services.Notifications RippleButton { diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationAppIcon.qml b/.config/quickshell/ii/modules/common/widgets/NotificationAppIcon.qml index 81505aff..5158d643 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationAppIcon.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationAppIcon.qml @@ -1,9 +1,7 @@ -import "root:/modules/common" +import qs.modules.common import "./notification_utils.js" as NotificationUtils import Qt5Compat.GraphicalEffects import QtQuick -import QtQuick.Controls -import QtQuick.Layouts import Quickshell import Quickshell.Widgets import Quickshell.Services.Notifications diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml b/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml index e79f400a..22b22656 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml @@ -1,18 +1,10 @@ -import "root:/modules/common" -import "root:/services" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.services +import qs.modules.common.functions import "./notification_utils.js" as NotificationUtils -import Qt5Compat.GraphicalEffects import QtQuick -import QtQuick.Controls -import QtQuick.Effects import QtQuick.Layouts import Quickshell -import Quickshell.Io -import Quickshell.Widgets -import Quickshell.Hyprland -import Quickshell.Services.Notifications /** * A group of notifications from the same app. diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationGroupExpandButton.qml b/.config/quickshell/ii/modules/common/widgets/NotificationGroupExpandButton.qml index bd1a8e96..ba2b7e10 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationGroupExpandButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationGroupExpandButton.qml @@ -1,12 +1,8 @@ -import "root:/modules/common" -import "root:/services" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.services +import qs.modules.common +import qs.modules.common.functions import QtQuick -import QtQuick.Controls -import QtQuick.Effects import QtQuick.Layouts -import Quickshell -import Quickshell.Services.Notifications RippleButton { // Expand button id: root diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml index 07c7f35b..e660041e 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml @@ -1,16 +1,10 @@ -import "root:/modules/common" -import "root:/services" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import "./notification_utils.js" as NotificationUtils -import Qt5Compat.GraphicalEffects +import qs +import qs.modules.common +import qs.services +import qs.modules.common.functions import QtQuick -import QtQuick.Controls -import QtQuick.Effects import QtQuick.Layouts import Quickshell -import Quickshell.Io -import Quickshell.Widgets import Quickshell.Hyprland import Quickshell.Services.Notifications diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml b/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml index 087e4a40..389a5a8b 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml @@ -1,13 +1,9 @@ -import "root:/" -import "root:/modules/common/" -import "root:/modules/common/widgets" -import "root:/services" +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick -import QtQuick.Controls -import QtQuick.Layouts import Quickshell -import Quickshell.Wayland -import Quickshell.Hyprland StyledListView { // Scrollable window id: root diff --git a/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml b/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml index 8cb4804a..63f5e175 100644 --- a/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml +++ b/.config/quickshell/ii/modules/common/widgets/PrimaryTabBar.qml @@ -1,9 +1,8 @@ -import "root:/modules/common" -import "root:/" +import qs.modules.common +import qs import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell ColumnLayout { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/PrimaryTabButton.qml b/.config/quickshell/ii/modules/common/widgets/PrimaryTabButton.qml index a47f108b..0b4b6f8f 100644 --- a/.config/quickshell/ii/modules/common/widgets/PrimaryTabButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/PrimaryTabButton.qml @@ -1,12 +1,10 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io -import Quickshell.Widgets TabButton { id: button diff --git a/.config/quickshell/ii/modules/common/widgets/Revealer.qml b/.config/quickshell/ii/modules/common/widgets/Revealer.qml index 620b8d6e..bbbe2efa 100644 --- a/.config/quickshell/ii/modules/common/widgets/Revealer.qml +++ b/.config/quickshell/ii/modules/common/widgets/Revealer.qml @@ -1,6 +1,5 @@ -import "root:/modules/common" +import qs.modules.common import QtQuick -import Quickshell /** * Recreation of GTK revealer. Expects one single child. diff --git a/.config/quickshell/ii/modules/common/widgets/RippleButton.qml b/.config/quickshell/ii/modules/common/widgets/RippleButton.qml index 9931cd02..7487203a 100644 --- a/.config/quickshell/ii/modules/common/widgets/RippleButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/RippleButton.qml @@ -1,12 +1,9 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls -import QtQuick.Layouts -import Quickshell.Io -import Quickshell.Widgets /** * A button with ripple effect similar to in Material Design. diff --git a/.config/quickshell/ii/modules/common/widgets/RippleButtonWithIcon.qml b/.config/quickshell/ii/modules/common/widgets/RippleButtonWithIcon.qml index 8e5fb6f2..f84ae4da 100644 --- a/.config/quickshell/ii/modules/common/widgets/RippleButtonWithIcon.qml +++ b/.config/quickshell/ii/modules/common/widgets/RippleButtonWithIcon.qml @@ -1,8 +1,7 @@ import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs.modules.common +import qs.modules.common.widgets RippleButton { id: buttonWithIconRoot diff --git a/.config/quickshell/ii/modules/common/widgets/SecondaryTabButton.qml b/.config/quickshell/ii/modules/common/widgets/SecondaryTabButton.qml index 1d3b6381..983dd02b 100644 --- a/.config/quickshell/ii/modules/common/widgets/SecondaryTabButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/SecondaryTabButton.qml @@ -1,12 +1,10 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io -import Quickshell.Widgets TabButton { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml b/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml index 5170c6c7..5f9b871a 100644 --- a/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml +++ b/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml @@ -1,10 +1,8 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/" -import Qt5Compat.GraphicalEffects +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import qs import QtQuick -import QtQuick.Controls import QtQuick.Layouts import Quickshell diff --git a/.config/quickshell/ii/modules/common/widgets/SelectionGroupButton.qml b/.config/quickshell/ii/modules/common/widgets/SelectionGroupButton.qml index 77695ce3..6a225ebb 100644 --- a/.config/quickshell/ii/modules/common/widgets/SelectionGroupButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/SelectionGroupButton.qml @@ -3,9 +3,9 @@ import QtQuick.Layouts import Quickshell import Quickshell.Io import Quickshell.Hyprland -import "root:/services/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs.services +import qs.modules.common +import qs.modules.common.widgets GroupButton { id: root diff --git a/.config/quickshell/ii/modules/common/widgets/StyledLabel.qml b/.config/quickshell/ii/modules/common/widgets/StyledLabel.qml index f5201bae..35b3cbf4 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledLabel.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledLabel.qml @@ -1,7 +1,6 @@ -import "root:/modules/common" +import qs.modules.common import QtQuick import QtQuick.Controls -import QtQuick.Layouts Label { renderType: Text.NativeRendering diff --git a/.config/quickshell/ii/modules/common/widgets/StyledListView.qml b/.config/quickshell/ii/modules/common/widgets/StyledListView.qml index 76d9782b..96874b86 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledListView.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledListView.qml @@ -1,13 +1,8 @@ -import "root:/" -import "root:/modules/common/" -import "root:/modules/common/widgets" -import "root:/services" +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Quickshell.Wayland -import Quickshell.Hyprland /** * A ListView with animations. diff --git a/.config/quickshell/ii/modules/common/widgets/StyledProgressBar.qml b/.config/quickshell/ii/modules/common/widgets/StyledProgressBar.qml index c36f31e2..fa1cd0be 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledProgressBar.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledProgressBar.qml @@ -1,6 +1,6 @@ -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/common/widgets/StyledRadioButton.qml b/.config/quickshell/ii/modules/common/widgets/StyledRadioButton.qml index 3ef1ee8a..79797e5b 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledRadioButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledRadioButton.qml @@ -1,6 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" +import qs.modules.common +import qs.modules.common.widgets +import qs.services import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/common/widgets/StyledRectangularShadow.qml b/.config/quickshell/ii/modules/common/widgets/StyledRectangularShadow.qml index 66a626f1..a3c842c4 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledRectangularShadow.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledRectangularShadow.qml @@ -1,6 +1,6 @@ import QtQuick import QtQuick.Effects -import "root:/modules/common" +import qs.modules.common RectangularShadow { required property var target diff --git a/.config/quickshell/ii/modules/common/widgets/StyledSlider.qml b/.config/quickshell/ii/modules/common/widgets/StyledSlider.qml index 93fe43f3..e940f1a4 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledSlider.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledSlider.qml @@ -1,6 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/common/widgets/StyledSpinBox.qml b/.config/quickshell/ii/modules/common/widgets/StyledSpinBox.qml index 9dac2544..c11f241a 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledSpinBox.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledSpinBox.qml @@ -1,5 +1,5 @@ -import "root:/modules/common" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.functions import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/common/widgets/StyledSwitch.qml b/.config/quickshell/ii/modules/common/widgets/StyledSwitch.qml index 453806f3..f16e213f 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledSwitch.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledSwitch.qml @@ -1,4 +1,4 @@ -import "root:/modules/common/" +import qs.modules.common import QtQuick import QtQuick.Layouts import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/common/widgets/StyledText.qml b/.config/quickshell/ii/modules/common/widgets/StyledText.qml index 7750456e..6024fc67 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledText.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledText.qml @@ -1,4 +1,4 @@ -import "root:/modules/common" +import qs.modules.common import QtQuick import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml b/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml index 447ae41c..e0abba3d 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml @@ -1,4 +1,4 @@ -import "root:/modules/common" +import qs.modules.common import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/common/widgets/StyledTextInput.qml b/.config/quickshell/ii/modules/common/widgets/StyledTextInput.qml index 9ca242f1..57d0c726 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledTextInput.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledTextInput.qml @@ -1,4 +1,4 @@ -import "root:/modules/common" +import qs.modules.common import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/common/widgets/StyledToolTip.qml b/.config/quickshell/ii/modules/common/widgets/StyledToolTip.qml index 1b4bd033..813c9ed1 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledToolTip.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledToolTip.qml @@ -1,5 +1,5 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/common/widgets/VerticalButtonGroup.qml b/.config/quickshell/ii/modules/common/widgets/VerticalButtonGroup.qml index 7d8fc29f..b1ca845a 100644 --- a/.config/quickshell/ii/modules/common/widgets/VerticalButtonGroup.qml +++ b/.config/quickshell/ii/modules/common/widgets/VerticalButtonGroup.qml @@ -1,8 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls import QtQuick.Layouts /** diff --git a/.config/quickshell/ii/modules/common/widgets/WaveVisualizer.qml b/.config/quickshell/ii/modules/common/widgets/WaveVisualizer.qml index 571e7183..64559c14 100644 --- a/.config/quickshell/ii/modules/common/widgets/WaveVisualizer.qml +++ b/.config/quickshell/ii/modules/common/widgets/WaveVisualizer.qml @@ -1,13 +1,8 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Effects -import QtQuick.Layouts -import QtQuick.Controls -import Quickshell -import Quickshell.Io Canvas { // Visualizer id: root diff --git a/.config/quickshell/ii/modules/dock/Dock.qml b/.config/quickshell/ii/modules/dock/Dock.qml index 5b8e1b19..2f4d5d63 100644 --- a/.config/quickshell/ii/modules/dock/Dock.qml +++ b/.config/quickshell/ii/modules/dock/Dock.qml @@ -1,7 +1,7 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls import QtQuick.Effects diff --git a/.config/quickshell/ii/modules/dock/DockAppButton.qml b/.config/quickshell/ii/modules/dock/DockAppButton.qml index 31e94855..1ebbffa4 100644 --- a/.config/quickshell/ii/modules/dock/DockAppButton.qml +++ b/.config/quickshell/ii/modules/dock/DockAppButton.qml @@ -1,18 +1,14 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls -import QtQuick.Effects import QtQuick.Layouts -import Quickshell.Io import Quickshell import Quickshell.Widgets -import Quickshell.Wayland -import Quickshell.Hyprland DockButton { id: root diff --git a/.config/quickshell/ii/modules/dock/DockApps.qml b/.config/quickshell/ii/modules/dock/DockApps.qml index 4135c6da..81aedc1a 100644 --- a/.config/quickshell/ii/modules/dock/DockApps.qml +++ b/.config/quickshell/ii/modules/dock/DockApps.qml @@ -1,18 +1,15 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls -import QtQuick.Effects import QtQuick.Layouts -import Quickshell.Io import Quickshell import Quickshell.Widgets import Quickshell.Wayland -import Quickshell.Hyprland Item { id: root diff --git a/.config/quickshell/ii/modules/dock/DockButton.qml b/.config/quickshell/ii/modules/dock/DockButton.qml index 577cbcdc..61655782 100644 --- a/.config/quickshell/ii/modules/dock/DockButton.qml +++ b/.config/quickshell/ii/modules/dock/DockButton.qml @@ -1,6 +1,6 @@ -import "root:/" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/dock/DockSeparator.qml b/.config/quickshell/ii/modules/dock/DockSeparator.qml index abb45d1d..419b0fed 100644 --- a/.config/quickshell/ii/modules/dock/DockSeparator.qml +++ b/.config/quickshell/ii/modules/dock/DockSeparator.qml @@ -1,5 +1,5 @@ -import "root:/" -import "root:/modules/common" +import qs +import qs.modules.common import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/mediaControls/MediaControls.qml b/.config/quickshell/ii/modules/mediaControls/MediaControls.qml index d9507265..67c1fe0a 100644 --- a/.config/quickshell/ii/modules/mediaControls/MediaControls.qml +++ b/.config/quickshell/ii/modules/mediaControls/MediaControls.qml @@ -1,17 +1,13 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils -import Qt5Compat.GraphicalEffects +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import qs +import qs.modules.common.functions import QtQuick import QtQuick.Layouts -import QtQuick.Controls import Quickshell import Quickshell.Io import Quickshell.Services.Mpris -import Quickshell.Widgets import Quickshell.Wayland import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml b/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml index 0da91a99..6f63c836 100644 --- a/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml +++ b/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml @@ -1,20 +1,14 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import qs.modules.common.functions import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Effects import QtQuick.Layouts -import QtQuick.Controls import Quickshell import Quickshell.Io import Quickshell.Services.Mpris -import Quickshell.Widgets -import Quickshell.Wayland -import Quickshell.Hyprland Item { // Player instance id: playerController diff --git a/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml b/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml index 3f10a92f..5e18a173 100644 --- a/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml +++ b/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml @@ -1,7 +1,7 @@ -import "root:/" -import "root:/modules/common/" -import "root:/modules/common/widgets" -import "root:/services" +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml index 51f809e8..c4edfded 100644 --- a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml +++ b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayBrightness.qml @@ -1,7 +1,7 @@ -import "root:/" -import "root:/services/" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml index db29eee3..48970d2e 100644 --- a/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml +++ b/.config/quickshell/ii/modules/onScreenDisplay/OnScreenDisplayVolume.qml @@ -1,7 +1,7 @@ -import "root:/" -import "root:/services/" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/onScreenDisplay/OsdValueIndicator.qml b/.config/quickshell/ii/modules/onScreenDisplay/OsdValueIndicator.qml index dfbf4a6b..c6fc7838 100644 --- a/.config/quickshell/ii/modules/onScreenDisplay/OsdValueIndicator.qml +++ b/.config/quickshell/ii/modules/onScreenDisplay/OsdValueIndicator.qml @@ -1,6 +1,6 @@ -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls import QtQuick.Effects diff --git a/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml b/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml index 199cde63..996546c5 100644 --- a/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml +++ b/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml @@ -1,15 +1,12 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls -import QtQuick.Effects import QtQuick.Layouts import Quickshell.Io import Quickshell -import Quickshell.Widgets import Quickshell.Wayland import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/onScreenKeyboard/OskContent.qml b/.config/quickshell/ii/modules/onScreenKeyboard/OskContent.qml index bc0f3b8d..f505b597 100644 --- a/.config/quickshell/ii/modules/onScreenKeyboard/OskContent.qml +++ b/.config/quickshell/ii/modules/onScreenKeyboard/OskContent.qml @@ -1,7 +1,7 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import "layouts.js" as Layouts import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/onScreenKeyboard/OskKey.qml b/.config/quickshell/ii/modules/onScreenKeyboard/OskKey.qml index 1f28a9e5..5ae53b94 100644 --- a/.config/quickshell/ii/modules/onScreenKeyboard/OskKey.qml +++ b/.config/quickshell/ii/modules/onScreenKeyboard/OskKey.qml @@ -1,13 +1,9 @@ -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell -import Quickshell.Io -import Quickshell.Hyprland RippleButton { id: root diff --git a/.config/quickshell/ii/modules/overview/Overview.qml b/.config/quickshell/ii/modules/overview/Overview.qml index 50a4f57b..9061b5b6 100644 --- a/.config/quickshell/ii/modules/overview/Overview.qml +++ b/.config/quickshell/ii/modules/overview/Overview.qml @@ -1,7 +1,7 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/overview/OverviewWidget.qml b/.config/quickshell/ii/modules/overview/OverviewWidget.qml index 18e60c2f..7f28c378 100644 --- a/.config/quickshell/ii/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/ii/modules/overview/OverviewWidget.qml @@ -1,14 +1,11 @@ -import "root:/" -import "root:/services/" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick -import QtQuick.Effects import QtQuick.Layouts import Quickshell -import Quickshell.Io -import Quickshell.Widgets import Quickshell.Wayland import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/overview/OverviewWindow.qml b/.config/quickshell/ii/modules/overview/OverviewWindow.qml index bf023a09..fbda9407 100644 --- a/.config/quickshell/ii/modules/overview/OverviewWindow.qml +++ b/.config/quickshell/ii/modules/overview/OverviewWindow.qml @@ -1,17 +1,13 @@ -import "root:/" -import "root:/services/" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import Qt5Compat.GraphicalEffects import QtQuick -import QtQuick.Controls import QtQuick.Layouts import Quickshell -import Quickshell.Widgets -import Quickshell.Io import Quickshell.Wayland -import Quickshell.Hyprland Item { // Window id: root diff --git a/.config/quickshell/ii/modules/overview/SearchItem.qml b/.config/quickshell/ii/modules/overview/SearchItem.qml index 54f8e7c7..e7b33ace 100644 --- a/.config/quickshell/ii/modules/overview/SearchItem.qml +++ b/.config/quickshell/ii/modules/overview/SearchItem.qml @@ -1,15 +1,11 @@ // pragma NativeMethodBehavior: AcceptThisObject -import "root:/" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/fuzzysort.js" as Fuzzy +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick -import QtQuick.Controls import QtQuick.Layouts import Quickshell -import Quickshell.Io import Quickshell.Widgets import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/overview/SearchWidget.qml b/.config/quickshell/ii/modules/overview/SearchWidget.qml index fa29291d..3ec0b0bd 100644 --- a/.config/quickshell/ii/modules/overview/SearchWidget.qml +++ b/.config/quickshell/ii/modules/overview/SearchWidget.qml @@ -1,8 +1,8 @@ -import "root:/" -import "root:/services/" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml b/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml index b7d9ee67..5bfed5cd 100644 --- a/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml +++ b/.config/quickshell/ii/modules/screenCorners/ScreenCorners.qml @@ -1,5 +1,5 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/session/Session.qml b/.config/quickshell/ii/modules/session/Session.qml index 8b98e7f9..fc22e330 100644 --- a/.config/quickshell/ii/modules/session/Session.qml +++ b/.config/quickshell/ii/modules/session/Session.qml @@ -1,14 +1,13 @@ -import "root:/modules/common" -import "root:/" -import "root:/services/" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs +import qs.services +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Io -import Quickshell.Widgets import Quickshell.Wayland import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/session/SessionActionButton.qml b/.config/quickshell/ii/modules/session/SessionActionButton.qml index becda60c..199f2abe 100644 --- a/.config/quickshell/ii/modules/session/SessionActionButton.qml +++ b/.config/quickshell/ii/modules/session/SessionActionButton.qml @@ -1,11 +1,7 @@ -import "root:/modules/common" -import "root:/modules/common/widgets/" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell -import Quickshell.Io RippleButton { id: button diff --git a/.config/quickshell/ii/modules/settings/About.qml b/.config/quickshell/ii/modules/settings/About.qml index e2937dfe..f9369c82 100644 --- a/.config/quickshell/ii/modules/settings/About.qml +++ b/.config/quickshell/ii/modules/settings/About.qml @@ -1,13 +1,11 @@ import QtQuick -import QtQuick.Controls import QtQuick.Layouts import Quickshell -import Quickshell.Io import Quickshell.Widgets -import "root:/" -import "root:/services/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets ContentPage { forceWidth: true diff --git a/.config/quickshell/ii/modules/settings/AdvancedConfig.qml b/.config/quickshell/ii/modules/settings/AdvancedConfig.qml index cd256f38..a40f1912 100644 --- a/.config/quickshell/ii/modules/settings/AdvancedConfig.qml +++ b/.config/quickshell/ii/modules/settings/AdvancedConfig.qml @@ -1,10 +1,8 @@ import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import "root:/" -import "root:/services/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets ContentPage { forceWidth: true diff --git a/.config/quickshell/ii/modules/settings/InterfaceConfig.qml b/.config/quickshell/ii/modules/settings/InterfaceConfig.qml index 30a2a37b..32633996 100644 --- a/.config/quickshell/ii/modules/settings/InterfaceConfig.qml +++ b/.config/quickshell/ii/modules/settings/InterfaceConfig.qml @@ -1,10 +1,9 @@ import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import "root:/" -import "root:/services/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets ContentPage { forceWidth: true diff --git a/.config/quickshell/ii/modules/settings/ServicesConfig.qml b/.config/quickshell/ii/modules/settings/ServicesConfig.qml index 550a36f1..02b3a3d2 100644 --- a/.config/quickshell/ii/modules/settings/ServicesConfig.qml +++ b/.config/quickshell/ii/modules/settings/ServicesConfig.qml @@ -1,10 +1,9 @@ import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import "root:/" -import "root:/services/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets ContentPage { forceWidth: true diff --git a/.config/quickshell/ii/modules/settings/StyleConfig.qml b/.config/quickshell/ii/modules/settings/StyleConfig.qml index b710abce..ec37c7eb 100644 --- a/.config/quickshell/ii/modules/settings/StyleConfig.qml +++ b/.config/quickshell/ii/modules/settings/StyleConfig.qml @@ -3,14 +3,11 @@ import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Io -import Quickshell.Widgets -import Quickshell.Hyprland -import "root:/" -import "root:/services/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions ContentPage { baseWidth: lightDarkButtonGroup.implicitWidth diff --git a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml index 06ceb07b..75696135 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml @@ -1,18 +1,15 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import "./aiChat/" import "root:/modules/common/functions/fuzzysort.js" as Fuzzy -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs.modules.common.functions import QtQuick import QtQuick.Controls import QtQuick.Layouts import Qt5Compat.GraphicalEffects -import Quickshell.Io import Quickshell -import Quickshell.Hyprland Item { id: root diff --git a/.config/quickshell/ii/modules/sidebarLeft/Anime.qml b/.config/quickshell/ii/modules/sidebarLeft/Anime.qml index 304d8f32..266a8432 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/Anime.qml @@ -1,10 +1,9 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import "root:/modules/common/functions/fuzzysort.js" as Fuzzy -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils import "./anime/" import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/sidebarLeft/ApiCommandButton.qml b/.config/quickshell/ii/modules/sidebarLeft/ApiCommandButton.qml index 39e8d742..7ee39846 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/ApiCommandButton.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/ApiCommandButton.qml @@ -1,10 +1,7 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell GroupButton { id: button diff --git a/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml b/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml index 835b679d..5287ecc4 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/DescriptionBox.qml @@ -1,7 +1,7 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml index 0bc00c24..e5a661eb 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeft.qml @@ -1,15 +1,10 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Effects -import Qt5Compat.GraphicalEffects import Quickshell.Io import Quickshell -import Quickshell.Widgets import Quickshell.Wayland import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml index a40b855a..fc60618e 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml @@ -1,18 +1,12 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services/" +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick import QtQuick.Controls import QtQuick.Layouts -import QtQuick.Effects import Qt5Compat.GraphicalEffects -import Quickshell.Io -import Quickshell -import Quickshell.Widgets -import Quickshell.Wayland -import Quickshell.Hyprland Item { id: root diff --git a/.config/quickshell/ii/modules/sidebarLeft/Translator.qml b/.config/quickshell/ii/modules/sidebarLeft/Translator.qml index 03bfa2b7..e9e3d6fe 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/Translator.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/Translator.qml @@ -1,15 +1,13 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import "./translator/" import QtQuick -import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Io -import Quickshell.Hyprland /** * Translator widget with the `trans` commandline tool. diff --git a/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessage.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessage.qml index 9933851c..872c38ef 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessage.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessage.qml @@ -1,19 +1,13 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "../" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell.Io import Quickshell -import Quickshell.Widgets -import Quickshell.Wayland -import Quickshell.Hyprland -import Qt5Compat.GraphicalEffects -import org.kde.syntaxhighlighting Rectangle { id: root diff --git a/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessageControlButton.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessageControlButton.qml index 2d7cb82d..64fc7723 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessageControlButton.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessageControlButton.qml @@ -1,11 +1,7 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell GroupButton { id: button diff --git a/.config/quickshell/ii/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml index a253a291..83288fda 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml @@ -1,14 +1,9 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import Qt5Compat.GraphicalEffects -import Qt.labs.platform +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import qs.modules.common.functions import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io -import Quickshell.Widgets import Quickshell.Hyprland RippleButton { diff --git a/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageCodeBlock.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageCodeBlock.qml index eac41af5..af2dc240 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageCodeBlock.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageCodeBlock.qml @@ -1,20 +1,14 @@ pragma ComponentBehavior: Bound -import "root:/" -import "root:/services" -import "root:/modules/common/" -import "root:/modules/common/widgets" -import "../" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io import Quickshell -import Quickshell.Widgets -import Quickshell.Hyprland -import Qt5Compat.GraphicalEffects import org.kde.syntaxhighlighting ColumnLayout { diff --git a/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageTextBlock.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageTextBlock.qml index 189d1cfd..4c334500 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageTextBlock.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageTextBlock.qml @@ -1,19 +1,14 @@ pragma ComponentBehavior: Bound -import "root:/" -import "root:/services" -import "root:/modules/common/" -import "root:/modules/common/widgets" -import "../" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io -import Quickshell -import Quickshell.Widgets import Quickshell.Hyprland -import Qt5Compat.GraphicalEffects ColumnLayout { id: root diff --git a/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml index e8b24d19..cf412f27 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruImage.qml @@ -1,14 +1,11 @@ -import "root:/" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQml -import Qt.labs.platform import QtQuick import QtQuick.Controls import QtQuick.Layouts -import QtQuick.Effects import Qt5Compat.GraphicalEffects import Quickshell import Quickshell.Io diff --git a/.config/quickshell/ii/modules/sidebarLeft/anime/BooruResponse.qml b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruResponse.qml index 3676e24f..0aa7479f 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/anime/BooruResponse.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/anime/BooruResponse.qml @@ -1,17 +1,14 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import "../" -import "root:/services/" +import qs.services import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Io import Quickshell -import Quickshell.Widgets -import Quickshell.Wayland import Quickshell.Hyprland import Qt5Compat.GraphicalEffects diff --git a/.config/quickshell/ii/modules/sidebarLeft/translator/LanguageSelectorButton.qml b/.config/quickshell/ii/modules/sidebarLeft/translator/LanguageSelectorButton.qml index 37df25f8..f23e3b84 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/translator/LanguageSelectorButton.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/translator/LanguageSelectorButton.qml @@ -1,14 +1,10 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell -import Quickshell.Io -import Quickshell.Hyprland RippleButton { id: root diff --git a/.config/quickshell/ii/modules/sidebarLeft/translator/TextCanvas.qml b/.config/quickshell/ii/modules/sidebarLeft/translator/TextCanvas.qml index 5b81a29d..c29265c9 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/translator/TextCanvas.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/translator/TextCanvas.qml @@ -1,14 +1,11 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell -import Quickshell.Io -import Quickshell.Hyprland Rectangle { id: root diff --git a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml index a8eda901..f799500d 100644 --- a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml +++ b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml @@ -1,13 +1,11 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/" -import "root:/services" +import qs.modules.common +import qs.modules.common.widgets +import qs +import qs.services import "./calendar" import "./todo" import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell Rectangle { id: root diff --git a/.config/quickshell/ii/modules/sidebarRight/CenterWidgetGroup.qml b/.config/quickshell/ii/modules/sidebarRight/CenterWidgetGroup.qml index 126b98c0..4aeef71c 100644 --- a/.config/quickshell/ii/modules/sidebarRight/CenterWidgetGroup.qml +++ b/.config/quickshell/ii/modules/sidebarRight/CenterWidgetGroup.qml @@ -1,16 +1,13 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "./calendar" +import qs.modules.common +import qs.modules.common.widgets +import qs.services import "./notifications" -import "./todo" import "./volumeMixer" -import "root:/" +import qs import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell Rectangle { id: root diff --git a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml index d733ae44..835e373b 100644 --- a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml @@ -1,18 +1,15 @@ -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import "./quickToggles/" import QtQuick import QtQuick.Controls import QtQuick.Layouts -import QtQuick.Effects import Qt5Compat.GraphicalEffects import Quickshell.Io import Quickshell -import Quickshell.Widgets import Quickshell.Wayland import Quickshell.Hyprland diff --git a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarDayButton.qml b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarDayButton.qml index 7d1af447..ab1aca55 100644 --- a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarDayButton.qml +++ b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarDayButton.qml @@ -1,8 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls import QtQuick.Layouts RippleButton { diff --git a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarHeaderButton.qml b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarHeaderButton.qml index 92ef3c85..6b5e5aa1 100644 --- a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarHeaderButton.qml +++ b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarHeaderButton.qml @@ -1,8 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls -import QtQuick.Layouts RippleButton { id: button diff --git a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml index 3aac3604..3af804e3 100644 --- a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml +++ b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml @@ -1,6 +1,6 @@ -import "root:/modules/common" -import "root:/" -import "root:/modules/common/widgets" +import qs.modules.common +import qs +import qs.modules.common.widgets import "./calendar_layout.js" as CalendarLayout import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml index 4c95b9a5..882829b8 100644 --- a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml +++ b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml @@ -1,13 +1,11 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/" +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import qs import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell -import Quickshell.Widgets Item { id: root diff --git a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationStatusButton.qml b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationStatusButton.qml index bcfeaecf..d6001a3a 100644 --- a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationStatusButton.qml +++ b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationStatusButton.qml @@ -1,7 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls import QtQuick.Layouts GroupButton { diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml index 2b35f8ce..88357437 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml @@ -1,9 +1,8 @@ -import "../" -import "root:/" -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick import Quickshell import Quickshell.Io diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml index 476927e2..4e314fb1 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml @@ -1,10 +1,9 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/" +import qs.modules.common +import qs.modules.common.widgets +import qs import QtQuick import Quickshell.Io import Quickshell -import Quickshell.Hyprland QuickToggleButton { id: root diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/GameMode.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/GameMode.qml index 0c635dbc..1907080e 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/GameMode.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/GameMode.qml @@ -1,10 +1,8 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "../" -import "root:/" +import qs.modules.common +import qs.modules.common.widgets +import qs import Quickshell import Quickshell.Io -import Quickshell.Hyprland QuickToggleButton { id: root diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml index 2e24b3b1..aa1e292e 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml @@ -1,10 +1,8 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "../" -import "root:/" +import qs.modules.common +import qs.modules.common.widgets +import qs import Quickshell.Io import Quickshell -import Quickshell.Hyprland QuickToggleButton { id: root diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml index 06238f72..3d4edf15 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NetworkToggle.qml @@ -1,9 +1,9 @@ -import "root:/services" -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import "../" -import "root:/" +import qs import QtQuick import Quickshell import Quickshell.Io diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml index 3cdfad13..6cab856c 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml @@ -1,9 +1,7 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "../" -import "root:/" +import qs.modules.common +import qs.modules.common.widgets +import qs import Quickshell.Io -import Quickshell QuickToggleButton { id: nightLightButton diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/QuickToggleButton.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/QuickToggleButton.qml index c80f91ba..c42a05d5 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/QuickToggleButton.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/QuickToggleButton.qml @@ -1,10 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell.Io GroupButton { id: button diff --git a/.config/quickshell/ii/modules/sidebarRight/todo/TaskList.qml b/.config/quickshell/ii/modules/sidebarRight/todo/TaskList.qml index b727ab1c..d9a2b67c 100644 --- a/.config/quickshell/ii/modules/sidebarRight/todo/TaskList.qml +++ b/.config/quickshell/ii/modules/sidebarRight/todo/TaskList.qml @@ -1,6 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" +import qs.modules.common +import qs.modules.common.widgets +import qs.services import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls diff --git a/.config/quickshell/ii/modules/sidebarRight/todo/TodoItemActionButton.qml b/.config/quickshell/ii/modules/sidebarRight/todo/TodoItemActionButton.qml index e013a18b..b0a6e7b9 100644 --- a/.config/quickshell/ii/modules/sidebarRight/todo/TodoItemActionButton.qml +++ b/.config/quickshell/ii/modules/sidebarRight/todo/TodoItemActionButton.qml @@ -1,9 +1,6 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs.modules.common +import qs.modules.common.widgets import QtQuick -import QtQuick.Controls -import QtQuick.Layouts RippleButton { id: button diff --git a/.config/quickshell/ii/modules/sidebarRight/todo/TodoWidget.qml b/.config/quickshell/ii/modules/sidebarRight/todo/TodoWidget.qml index f59adcc3..50c659ad 100644 --- a/.config/quickshell/ii/modules/sidebarRight/todo/TodoWidget.qml +++ b/.config/quickshell/ii/modules/sidebarRight/todo/TodoWidget.qml @@ -1,11 +1,9 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/" -import "root:/modules/common/functions/color_utils.js" as ColorUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets import QtQuick import QtQuick.Controls -import QtQuick.Effects import QtQuick.Layouts Item { diff --git a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml index 70e3b7ac..a1e589de 100644 --- a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml +++ b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/AudioDeviceSelectorButton.qml @@ -1,12 +1,9 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/" -import Qt5Compat.GraphicalEffects +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick -import QtQuick.Controls import QtQuick.Layouts -import Quickshell.Widgets import Quickshell.Services.Pipewire GroupButton { diff --git a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml index 68cc3444..88f6da1b 100644 --- a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml +++ b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml @@ -1,13 +1,12 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import "root:/" +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import qs import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell -import Quickshell.Widgets import Quickshell.Services.Pipewire diff --git a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml index 84cb572c..5ee39801 100644 --- a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml +++ b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixerEntry.qml @@ -1,12 +1,9 @@ -import "root:/modules/common" -import "root:/modules/common/widgets" -import "root:/services" -import Qt5Compat.GraphicalEffects +import qs.modules.common +import qs.modules.common.widgets +import qs.services import QtQuick -import QtQuick.Controls import QtQuick.Layouts import Quickshell -import Quickshell.Widgets import Quickshell.Services.Pipewire Item { diff --git a/.config/quickshell/ii/screenshot.qml b/.config/quickshell/ii/screenshot.qml index 99b3b1c2..1fb5290f 100644 --- a/.config/quickshell/ii/screenshot.qml +++ b/.config/quickshell/ii/screenshot.qml @@ -6,10 +6,10 @@ //@ pragma Env QT_SCALE_FACTOR=1 pragma ComponentBehavior: "Bound" -import "./" -import "./modules/common/" -import "./modules/common/widgets" -import "./modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions import QtQuick import QtQuick.Effects import QtQuick.Controls diff --git a/.config/quickshell/ii/services/Ai.qml b/.config/quickshell/ii/services/Ai.qml index 40672493..22810f2b 100644 --- a/.config/quickshell/ii/services/Ai.qml +++ b/.config/quickshell/ii/services/Ai.qml @@ -1,14 +1,12 @@ pragma Singleton pragma ComponentBehavior: Bound -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/object_utils.js" as ObjectUtils -import "root:/modules/common" -import "root:/" -import Quickshell; -import Quickshell.Io; -import Qt.labs.platform -import QtQuick; +import qs.modules.common.functions as CF +import qs.modules.common +import qs +import Quickshell +import Quickshell.Io +import QtQuick /** * Basic service to handle LLM chats. Supports Google's and OpenAI's API formats. @@ -575,7 +573,7 @@ Singleton { const requestCommandString = `curl --no-buffer "${endpoint}"` + ` ${headerString}` + ((apiFormat == "gemini") ? "" : ` -H "Authorization: Bearer \$\{${root.apiKeyEnvVarName}\}"`) - + ` -d '${StringUtils.shellSingleQuoteEscape(JSON.stringify(data))}'` + + ` -d '${CF.StringUtils.shellSingleQuoteEscape(JSON.stringify(data))}'` // console.log("Request command: ", requestCommandString); requester.command = baseCommand.concat([requestCommandString]); @@ -790,7 +788,7 @@ Singleton { addFunctionOutputMessage(name, Translation.tr("Switched to search mode. Continue with the user's request.")) requester.makeRequest(); } else if (name === "get_shell_config") { - const configJson = ObjectUtils.toPlainObject(Config.options) + const configJson = CF.ObjectUtils.toPlainObject(Config.options) addFunctionOutputMessage(name, JSON.stringify(configJson)); requester.makeRequest(); } else if (name === "set_shell_config") { @@ -857,7 +855,7 @@ Singleton { root.messageIDs = saveData.map((_, i) => { return i }) - console.log(JSON.stringify(messageIDs)) + // console.log(JSON.stringify(messageIDs)) for (let i = 0; i < saveData.length; i++) { const message = saveData[i]; root.messageByID[i] = root.aiMessageComponent.createObject(root, { diff --git a/.config/quickshell/ii/services/AiMessageData.qml b/.config/quickshell/ii/services/AiMessageData.qml index dc8b80fd..c9537abe 100644 --- a/.config/quickshell/ii/services/AiMessageData.qml +++ b/.config/quickshell/ii/services/AiMessageData.qml @@ -1,4 +1,4 @@ -import "root:/modules/common" +import qs.modules.common import QtQuick; /** diff --git a/.config/quickshell/ii/services/AppSearch.qml b/.config/quickshell/ii/services/AppSearch.qml index e325f93f..a658d506 100644 --- a/.config/quickshell/ii/services/AppSearch.qml +++ b/.config/quickshell/ii/services/AppSearch.qml @@ -1,10 +1,9 @@ pragma Singleton -import "root:/modules/common" +import qs.modules.common import "root:/modules/common/functions/fuzzysort.js" as Fuzzy import "root:/modules/common/functions/levendist.js" as Levendist import Quickshell -import Quickshell.Io /** * - Eases fuzzy searching for applications by name diff --git a/.config/quickshell/ii/services/Audio.qml b/.config/quickshell/ii/services/Audio.qml index db10a968..0651ebc7 100644 --- a/.config/quickshell/ii/services/Audio.qml +++ b/.config/quickshell/ii/services/Audio.qml @@ -1,4 +1,4 @@ -import "root:/modules/common" +import qs.modules.common import QtQuick import Quickshell import Quickshell.Services.Pipewire diff --git a/.config/quickshell/ii/services/Battery.qml b/.config/quickshell/ii/services/Battery.qml index abe7700d..8a3cf316 100644 --- a/.config/quickshell/ii/services/Battery.qml +++ b/.config/quickshell/ii/services/Battery.qml @@ -1,9 +1,8 @@ pragma Singleton -import "root:/modules/common" +import qs +import qs.modules.common import Quickshell -import Quickshell.Io -import Quickshell.Hyprland import Quickshell.Services.UPower Singleton { diff --git a/.config/quickshell/ii/services/Booru.qml b/.config/quickshell/ii/services/Booru.qml index ce2493f9..38714bc1 100644 --- a/.config/quickshell/ii/services/Booru.qml +++ b/.config/quickshell/ii/services/Booru.qml @@ -1,11 +1,9 @@ pragma Singleton pragma ComponentBehavior: Bound -import "root:/modules/common" -import "root:/" +import qs.modules.common +import qs import Quickshell; -import Quickshell.Io; -import Qt.labs.platform import QtQuick; /** diff --git a/.config/quickshell/ii/services/BooruResponseData.qml b/.config/quickshell/ii/services/BooruResponseData.qml index 38e1b8c7..2a61ff6c 100644 --- a/.config/quickshell/ii/services/BooruResponseData.qml +++ b/.config/quickshell/ii/services/BooruResponseData.qml @@ -1,4 +1,4 @@ -import "root:/modules/common" +import qs.modules.common import QtQuick; /** diff --git a/.config/quickshell/ii/services/Brightness.qml b/.config/quickshell/ii/services/Brightness.qml index 6a36f713..74c6c504 100644 --- a/.config/quickshell/ii/services/Brightness.qml +++ b/.config/quickshell/ii/services/Brightness.qml @@ -4,7 +4,7 @@ pragma ComponentBehavior: Bound // From https://github.com/caelestia-dots/shell/ (`quickshell` branch) with modifications. // License: GPLv3 -import "root:/" +import qs import Quickshell import Quickshell.Io import Quickshell.Hyprland diff --git a/.config/quickshell/ii/services/Cliphist.qml b/.config/quickshell/ii/services/Cliphist.qml index ff867841..ea4400bb 100644 --- a/.config/quickshell/ii/services/Cliphist.qml +++ b/.config/quickshell/ii/services/Cliphist.qml @@ -3,8 +3,8 @@ pragma ComponentBehavior: Bound import "root:/modules/common/functions/fuzzysort.js" as Fuzzy import "root:/modules/common/functions/levendist.js" as Levendist -import "root:/modules/common" -import "root:/" +import qs.modules.common +import qs import QtQuick import Quickshell import Quickshell.Io diff --git a/.config/quickshell/ii/services/DateTime.qml b/.config/quickshell/ii/services/DateTime.qml index 4df9ca99..e1b0afa3 100644 --- a/.config/quickshell/ii/services/DateTime.qml +++ b/.config/quickshell/ii/services/DateTime.qml @@ -1,4 +1,4 @@ -import "root:/modules/common" +import qs.modules.common import QtQuick import Quickshell import Quickshell.Io diff --git a/.config/quickshell/ii/services/Emojis.qml b/.config/quickshell/ii/services/Emojis.qml index 852c831b..4220b040 100644 --- a/.config/quickshell/ii/services/Emojis.qml +++ b/.config/quickshell/ii/services/Emojis.qml @@ -3,7 +3,7 @@ pragma ComponentBehavior: Bound import "root:/modules/common/functions/fuzzysort.js" as Fuzzy import "root:/modules/common/functions/levendist.js" as Levendist -import "root:/modules/common" +import qs.modules.common import QtQuick import Quickshell import Quickshell.Io diff --git a/.config/quickshell/ii/services/FirstRunExperience.qml b/.config/quickshell/ii/services/FirstRunExperience.qml index 350c3159..a362e8cb 100644 --- a/.config/quickshell/ii/services/FirstRunExperience.qml +++ b/.config/quickshell/ii/services/FirstRunExperience.qml @@ -1,10 +1,9 @@ pragma Singleton -import "root:/modules/common/functions/file_utils.js" as FileUtils -import "root:/modules/common" +import qs.modules.common +import qs.modules.common.functions import Quickshell import Quickshell.Io -import Quickshell.Hyprland Singleton { id: root diff --git a/.config/quickshell/ii/services/HyprlandData.qml b/.config/quickshell/ii/services/HyprlandData.qml index fb360070..6488ded8 100644 --- a/.config/quickshell/ii/services/HyprlandData.qml +++ b/.config/quickshell/ii/services/HyprlandData.qml @@ -4,7 +4,6 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell import Quickshell.Io -import Quickshell.Wayland import Quickshell.Hyprland /** diff --git a/.config/quickshell/ii/services/HyprlandKeybinds.qml b/.config/quickshell/ii/services/HyprlandKeybinds.qml index 45dc6548..3381926b 100644 --- a/.config/quickshell/ii/services/HyprlandKeybinds.qml +++ b/.config/quickshell/ii/services/HyprlandKeybinds.qml @@ -1,12 +1,11 @@ pragma Singleton pragma ComponentBehavior: Bound -import "root:/modules/common" -import "root:/modules/common/functions/file_utils.js" as FileUtils +import qs.modules.common +import qs.modules.common.functions import QtQuick import Quickshell import Quickshell.Io -import Quickshell.Wayland import Quickshell.Hyprland /** diff --git a/.config/quickshell/ii/services/KeyringStorage.qml b/.config/quickshell/ii/services/KeyringStorage.qml index 33cfcd3b..ce6b8eb5 100644 --- a/.config/quickshell/ii/services/KeyringStorage.qml +++ b/.config/quickshell/ii/services/KeyringStorage.qml @@ -1,11 +1,10 @@ pragma Singleton pragma ComponentBehavior: Bound -import "root:/" -import "root:/modules/common" -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.modules.common +import qs.modules.common.functions import Quickshell; import Quickshell.Io; -import Qt.labs.platform import QtQuick; /** diff --git a/.config/quickshell/ii/services/LatexRenderer.qml b/.config/quickshell/ii/services/LatexRenderer.qml index e7066fa4..5baf336e 100644 --- a/.config/quickshell/ii/services/LatexRenderer.qml +++ b/.config/quickshell/ii/services/LatexRenderer.qml @@ -1,14 +1,10 @@ pragma Singleton pragma ComponentBehavior: Bound -import "root:/modules/common/functions/string_utils.js" as StringUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils -import "root:/modules/common" +import qs.modules.common.functions +import qs.modules.common import QtQuick import Quickshell -import Quickshell.Io -import Quickshell.Hyprland -import Qt.labs.platform /** * Renders LaTeX snippets with MicroTeX. diff --git a/.config/quickshell/ii/services/MaterialThemeLoader.qml b/.config/quickshell/ii/services/MaterialThemeLoader.qml index 4194d873..8872c476 100644 --- a/.config/quickshell/ii/services/MaterialThemeLoader.qml +++ b/.config/quickshell/ii/services/MaterialThemeLoader.qml @@ -1,7 +1,7 @@ pragma Singleton pragma ComponentBehavior: Bound -import "root:/modules/common" +import qs.modules.common import QtQuick import Quickshell import Quickshell.Io diff --git a/.config/quickshell/ii/services/MprisController.qml b/.config/quickshell/ii/services/MprisController.qml index ebc78898..60923a6e 100644 --- a/.config/quickshell/ii/services/MprisController.qml +++ b/.config/quickshell/ii/services/MprisController.qml @@ -4,7 +4,7 @@ pragma ComponentBehavior: Bound // From https://git.outfoxxed.me/outfoxxed/nixnew // It does not have a license, but the author is okay with redistribution. -import "root:/" +import qs import QtQml.Models import QtQuick import Quickshell diff --git a/.config/quickshell/ii/services/Notifications.qml b/.config/quickshell/ii/services/Notifications.qml index 7438983f..d0d51e8e 100644 --- a/.config/quickshell/ii/services/Notifications.qml +++ b/.config/quickshell/ii/services/Notifications.qml @@ -1,8 +1,8 @@ pragma Singleton pragma ComponentBehavior: Bound -import "root:/modules/common" -import "root:/" +import qs.modules.common +import qs import QtQuick import Quickshell import Quickshell.Io diff --git a/.config/quickshell/ii/services/ResourceUsage.qml b/.config/quickshell/ii/services/ResourceUsage.qml index ba08be2a..65052840 100644 --- a/.config/quickshell/ii/services/ResourceUsage.qml +++ b/.config/quickshell/ii/services/ResourceUsage.qml @@ -1,7 +1,7 @@ pragma Singleton pragma ComponentBehavior: Bound -import "root:/modules/common" +import qs.modules.common import QtQuick import Quickshell import Quickshell.Io diff --git a/.config/quickshell/ii/services/Todo.qml b/.config/quickshell/ii/services/Todo.qml index 2cbf0d7d..93227cbb 100644 --- a/.config/quickshell/ii/services/Todo.qml +++ b/.config/quickshell/ii/services/Todo.qml @@ -1,10 +1,9 @@ pragma Singleton pragma ComponentBehavior: Bound -import "root:/modules/common" +import qs.modules.common import Quickshell; import Quickshell.Io; -import Qt.labs.platform import QtQuick; /** diff --git a/.config/quickshell/ii/services/Weather.qml b/.config/quickshell/ii/services/Weather.qml index a72e7e2e..c8d46e26 100644 --- a/.config/quickshell/ii/services/Weather.qml +++ b/.config/quickshell/ii/services/Weather.qml @@ -6,7 +6,7 @@ import Quickshell.Io import QtQuick import QtPositioning -import "root:/modules/common" +import qs.modules.common Singleton { id: root diff --git a/.config/quickshell/ii/services/Ydotool.qml b/.config/quickshell/ii/services/Ydotool.qml index f702010d..f25b0930 100644 --- a/.config/quickshell/ii/services/Ydotool.qml +++ b/.config/quickshell/ii/services/Ydotool.qml @@ -1,9 +1,7 @@ pragma Singleton -import "root:/modules/common" +import qs.modules.common import Quickshell -import Quickshell.Io -import Quickshell.Hyprland Singleton { id: root @@ -12,12 +10,6 @@ Singleton { property list altKeys: [56, 100] // Keycodes for Alt keys (left and right) property list ctrlKeys: [29, 97] // Keycodes for Ctrl keys (left and right) - onShiftModeChanged: { - if (shiftMode === 0) { - - } - } - function releaseAllKeys() { const keycodes = Array.from(Array(249).keys()); Quickshell.execDetached([ diff --git a/.config/quickshell/ii/settings.qml b/.config/quickshell/ii/settings.qml index ed511a04..41e1938f 100644 --- a/.config/quickshell/ii/settings.qml +++ b/.config/quickshell/ii/settings.qml @@ -5,24 +5,19 @@ // Adjust this to make the app smaller or larger //@ pragma Env QT_SCALE_FACTOR=1 -import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtQuick.Window -import Quickshell -import Quickshell.Io -import Quickshell.Hyprland -import "root:/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions as CF ApplicationWindow { id: root - property string firstRunFilePath: FileUtils.trimFileProtocol(`${Directories.state}/user/first_run.txt`) + property string firstRunFilePath: CF.FileUtils.trimFileProtocol(`${Directories.state}/user/first_run.txt`) property string firstRunFileContent: "This file is just here to confirm you've been greeted :>" property real contentPadding: 8 property bool showNextTime: false diff --git a/.config/quickshell/ii/welcome.qml b/.config/quickshell/ii/welcome.qml index 9e643b77..b220ff8b 100644 --- a/.config/quickshell/ii/welcome.qml +++ b/.config/quickshell/ii/welcome.qml @@ -12,12 +12,10 @@ import QtQuick.Window import Quickshell import Quickshell.Io import Quickshell.Hyprland -import "root:/" -import "root:/modules/common/" -import "root:/modules/common/widgets/" -import "root:/modules/common/functions/color_utils.js" as ColorUtils -import "root:/modules/common/functions/file_utils.js" as FileUtils -import "root:/modules/common/functions/string_utils.js" as StringUtils +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions ApplicationWindow { id: root From fca5adbbd3c9f68326686848f1f683c13ed5a3e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Thu, 17 Jul 2025 21:49:14 +0800 Subject: [PATCH 261/328] Recover the import "root:/services/" in the wrongly deleted setting.qml --- .config/quickshell/ii/settings.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/ii/settings.qml b/.config/quickshell/ii/settings.qml index ed511a04..71ada3ec 100644 --- a/.config/quickshell/ii/settings.qml +++ b/.config/quickshell/ii/settings.qml @@ -14,6 +14,7 @@ import Quickshell import Quickshell.Io import Quickshell.Hyprland import "root:/" +import "root:/services/" import "root:/modules/common/" import "root:/modules/common/widgets/" import "root:/modules/common/functions/color_utils.js" as ColorUtils From 7f3fb26651169dbe6db693cbeb3fdc50d9f07a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Thu, 17 Jul 2025 22:01:41 +0800 Subject: [PATCH 262/328] Translation: Update weather information card title to support multiple languages, and clean up unnecessary translation entries --- .../ii/modules/bar/weather/WeatherPopup.qml | 17 +++---- .config/quickshell/translations/en_US.json | 46 ++++--------------- .config/quickshell/translations/zh_CN.json | 44 ++++-------------- 3 files changed, 26 insertions(+), 81 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml b/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml index b39fffd3..57c66827 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml @@ -1,3 +1,4 @@ +import "root:/" import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" @@ -52,42 +53,42 @@ Rectangle { uniformCellWidths: true WeatherCard { - title: "UV Index" + title: Translation.tr("UV Index") symbol: "wb_sunny" value: Weather.data.uv } WeatherCard { - title: "Wind" + title: Translation.tr("Wind") symbol: "air" value: `(${Weather.data.windDir}) ${Weather.data.wind}` } WeatherCard { - title: "Precipitation" + title: Translation.tr("Precipitation") symbol: "rainy_light" value: Weather.data.precip } WeatherCard { - title: "Humidity" + title: Translation.tr("Humidity") symbol: "humidity_low" value: Weather.data.humidity } WeatherCard { - title: "Visibility" + title: Translation.tr("Visibility") symbol: "visibility" value: Weather.data.visib } WeatherCard { - title: "Pressure" + title: Translation.tr("Pressure") symbol: "readiness_score" value: Weather.data.press } WeatherCard { - title: "Sunrise" + title: Translation.tr("Sunrise") symbol: "wb_twilight" value: Weather.data.sunrise } WeatherCard { - title: "Sunset" + title: Translation.tr("Sunset") symbol: "bedtime" value: Weather.data.sunset } diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index 7141cdaa..fe8c6453 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -32,18 +32,10 @@ "Clear chat history": "Clear chat history", "Clear the current list of images": "Clear the current list of images", "Close": "Close", - "Closes cheatsheet on press": "Closes cheatsheet on press", - "Closes left sidebar on press": "Closes left sidebar on press", - "Closes media controls on press": "Closes media controls on press", - "Closes on screen keyboard on press": "Closes on screen keyboard on press", - "Closes overview": "Closes overview", - "Closes right sidebar on press": "Closes right sidebar on press", "Copy": "Copy", "Copy code": "Copy code", - "Decrease brightness": "Decrease brightness", "Delete": "Delete", "Desktop": "Desktop", - "Detach left sidebar into a window/Attach it back": "Detach left sidebar into a window/Attach it back", "Disable NSFW content": "Disable NSFW content", "Done": "Done", "Download": "Download", @@ -55,10 +47,6 @@ "Game mode": "Game mode", "Get the next page of results": "Get the next page of results", "Hibernate": "Hibernate", - "Hides brightness OSD on press": "Hides brightness OSD on press", - "Hides volume OSD on press": "Hides volume OSD on press", - "Hold to show workspace numbers, release to show icons": "Hold to show workspace numbers, release to show icons", - "Increase brightness": "Increase brightness", "Input": "Input", "Intelligence": "Intelligence", "Interface": "Interface", @@ -81,12 +69,6 @@ "Notifications": "Notifications", "OK": "OK", "Open file link": "Open file link", - "Opens cheatsheet on press": "Opens cheatsheet on press", - "Opens left sidebar on press": "Opens left sidebar on press", - "Opens media controls on press": "Opens media controls on press", - "Opens on screen keyboard on press": "Opens on screen keyboard on press", - "Opens right sidebar on press": "Opens right sidebar on press", - "Opens session screen on press": "Opens session screen on press", "Output": "Output", "Reboot": "Reboot", "Reboot to firmware settings": "Reboot to firmware settings", @@ -113,21 +95,8 @@ "The hentai one | Great quantity, a lot of NSFW, quality varies wildly": "The hentai one | Great quantity, a lot of NSFW, quality varies wildly", "The popular one | Best quantity, but quality can vary wildly": "The popular one | Best quantity, but quality can vary wildly", "Thinking": "Thinking", - "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.": "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.", - "Toggle clipboard query on overview widget": "Toggle clipboard query on overview widget", - "Toggle emoji query on overview widget": "Toggle emoji query on overview widget", - "Toggles cheatsheet on press": "Toggles cheatsheet on press", - "Toggles left sidebar on press": "Toggles left sidebar on press", - "Toggles media controls on press": "Toggles media controls on press", - "Toggles on screen keyboard on press": "Toggles on screen keyboard on press", - "Toggles overview on press": "Toggles overview on press", - "Toggles overview on release": "Toggles overview on release", - "Toggles right sidebar on press": "Toggles right sidebar on press", - "Toggles session screen on press": "Toggles session screen on press", "Translation goes here...": "Translation goes here...", "Translator": "Translator", - "Triggers brightness OSD on press": "Triggers brightness OSD on press", - "Triggers volume OSD on press": "Triggers volume OSD on press", "Unfinished": "Unfinished", "Unknown": "Unknown", "Unknown Album": "Unknown Album", @@ -143,11 +112,9 @@ "Invalid API provider. Supported: \n-": "Invalid API provider. Supported: \n-", "Unknown command:": "Unknown command:", "Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window", - "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key.": "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key.", "The current API used. Endpoint:": "The current API used. Endpoint:", "Provider set to": "Provider set to", "Invalid model. Supported: \n```": "Invalid model. Supported: \n```", - "Interrupts possibility of overview being toggled on release.": "Interrupts possibility of overview being toggled on release.", "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number", "Online | Google's model\nGives up-to-date information with search.": "Online | Google's model\nGives up-to-date information with search.", "Switched to search mode. Continue with the user's request.": "Switched to search mode. Continue with the user's request.", @@ -322,21 +289,26 @@ "Select output device": "Select output device", "Code saved to file": "Code saved to file", "Online models disallowed\n\nControlled by `policies.ai` config option": "Online models disallowed\n\nControlled by `policies.ai` config option", - "Opens bar on press": "Opens bar on press", "Scroll to change volume": "Scroll to change volume", - "Toggles bar on press": "Toggles bar on press", "Elements": "Elements", "%1 • %2 tasks": "%1 • %2 tasks", "Download complete": "Download complete", "Please charge!\nAutomatic suspend triggers at %1": "Please charge!\nAutomatic suspend triggers at %1", "Cloudflare WARP": "Cloudflare WARP", "Cloudflare WARP (1.1.1.1)": "Cloudflare WARP (1.1.1.1)", - "Closes bar on press": "Closes bar on press", "Scroll to change brightness": "Scroll to change brightness", "Connection failed. Please inspect manually with the warp-cli command": "Connection failed. Please inspect manually with the warp-cli command", "Select input device": "Select input device", "Registration failed. Please inspect manually with the warp-cli command": "Registration failed. Please inspect manually with the warp-cli command", "Consider plugging in your device": "Consider plugging in your device", "Low battery": "Low battery", - "Saved to %1": "Saved to %1" + "Saved to %1": "Saved to %1", + "Sunset": "Sunset", + "UV Index": "UV Index", + "Humidity": "Humidity", + "Wind": "Wind", + "Sunrise": "Sunrise", + "Pressure": "Pressure", + "Visibility": "Visibility", + "Precipitation": "Precipitation" } \ No newline at end of file diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index c2c2fdf8..c81da220 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -34,19 +34,11 @@ "Clear chat history": "清除聊天记录", "Clear the current list of images": "清除当前图片列表", "Close": "关闭", - "Closes cheatsheet on press": "按下时关闭快捷键表", - "Closes left sidebar on press": "按下时关闭左侧边栏", - "Closes media controls on press": "按下时关闭媒体控制", - "Closes on screen keyboard on press": "按下时关闭屏幕键盘", - "Closes overview": "关闭概览", - "Closes right sidebar on press": "按下时关闭右侧边栏", "Copy": "复制", "Copy code": "复制代码", "Current API endpoint: %1\nSet it with %2mode PROVIDER": "当前 API 端点:%1\n使用 %2mode PROVIDER 设置", - "Decrease brightness": "降低亮度", "Delete": "删除", "Desktop": "桌面", - "Detach left sidebar into a window/Attach it back": "将左侧边栏分离为窗口/重新附加", "Disable NSFW content": "禁用 NSFW 内容", "Done": "完成", "Download": "下载", @@ -59,10 +51,6 @@ "Get the next page of results": "获取下一页结果", "Go to source (%1)": "转到源 (%1)", "Hibernate": "休眠", - "Hides brightness OSD on press": "按下时隐藏亮度显示", - "Hides volume OSD on press": "按下时隐藏音量显示", - "Hold to show workspace numbers, release to show icons": "按住显示工作区编号,松开显示图标", - "Increase brightness": "提高亮度", "Input": "输入", "Intelligence": "智能体", "Interface": "界面", @@ -87,12 +75,6 @@ "Notifications": "通知", "OK": "确定", "Open file link": "打开文件链接", - "Opens cheatsheet on press": "按下时打开快捷键表", - "Opens left sidebar on press": "按下时打开左侧边栏", - "Opens media controls on press": "按下时打开媒体控制", - "Opens on screen keyboard on press": "按下时打开屏幕键盘", - "Opens right sidebar on press": "按下时打开右侧边栏", - "Opens session screen on press": "按下时打开会话屏幕", "Output": "输出", "Page %1": "第 %1 页", "Reboot": "重启", @@ -122,21 +104,8 @@ "The hentai one | Great quantity, a lot of NSFW, quality varies wildly": "成人向 | 数量巨大,大量 NSFW,质量参差不齐", "The popular one | Best quantity, but quality can vary wildly": "最受欢迎 | 数量最多,但质量参差不齐", "Thinking": "思考中", - "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything.": "为确保此功能正常工作,请在自动触发的子映射中使用 binditn = MODKEYS, catchall,该子映射包含所有内容。", - "Toggle clipboard query on overview widget": "在概览组件中切换剪贴板查询", - "Toggle emoji query on overview widget": "在概览组件中切换表情符号查询", - "Toggles cheatsheet on press": "按下时切换快捷键表", - "Toggles left sidebar on press": "按下时切换左侧边栏", - "Toggles media controls on press": "按下时切换媒体控制", - "Toggles on screen keyboard on press": "按下时切换屏幕键盘", - "Toggles overview on press": "按下时切换概览", - "Toggles overview on release": "松开时切换概览", - "Toggles right sidebar on press": "按下时切换右侧边栏", - "Toggles session screen on press": "按下时切换会话屏幕", "Translation goes here...": "翻译结果会显示在这里...", "Translator": "翻译器", - "Triggers brightness OSD on press": "按下时触发亮度显示", - "Triggers volume OSD on press": "按下时触发音量显示", "Unfinished": "未完成", "Unknown": "未知", "Unknown Album": "未知专辑", @@ -158,11 +127,9 @@ "Invalid API provider. Supported: \n-": "无效的 API 提供商。支持的:\n-", "Unknown command:": "未知命令:", "Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window": "输入 /key 开始使用在线模型\nCtrl+O 展开侧边栏\nCtrl+P 将侧边栏分离为窗口", - "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key.": "这是必要的,因为在按住键时,quickshell 中的 GlobalShortcut.onReleased 会在您是否按下其他键时触发。", "The current API used. Endpoint:": "当前使用的 API。端点:", "Provider set to": "提供商设置为", "Invalid model. Supported: \n```": "无效模型。支持的:\n```", - "Interrupts possibility of overview being toggled on release.": "中断松开时切换概览的可能性。", "Switched to search mode. Continue with the user's request.": "已切换到搜索模式。继续处理用户请求。", "Experimental | Online | Google's model\nCan do a little more but doesn't search quickly": "实验性 | 在线 | Google 模型\n功能更多但搜索速度较慢", "To set an API key, pass it with the command\n\nTo view the key, pass \"get\" with the command
\n\n### For %1:\n\n**Link**: %2\n\n%3": "要设置 API 密钥,请将其与命令一起传递\n\n要查看密钥,请将 \"get\" 与命令一起传递
\n\n### 对于 %1:\n\n**链接**:%2\n\n%3", @@ -321,7 +288,6 @@ "Online models disallowed\n\nControlled by `policies.ai` config option": "禁止在线模型\n\n由 `policies.ai` 配置项控制", "Select input device": "选择输入设备", "Low battery": "电量低", - "Opens bar on press": "按下时打开条栏", "Registration failed. Please inspect manually with the warp-cli command": "注册失败。请使用 warp-cli 命令手动检查", "Code saved to file": "代码已保存到文件", "Consider plugging in your device": "请考虑连接您的设备", @@ -329,7 +295,6 @@ "Please charge!\nAutomatic suspend triggers at %1": "请充电!\n自动挂起将在 %1 时触发", "Cloudflare WARP (1.1.1.1)": "Cloudflare WARP (1.1.1.1)", "Cloudflare WARP": "Cloudflare WARP", - "Closes bar on press": "按下时关闭条栏", "Download complete": "下载完成", "Critically low battery": "电量极低", "Scroll to change brightness": "滚动以调节亮度", @@ -338,5 +303,12 @@ "Elements": "元素", "Scroll to change volume": "滚动以调节音量", "Connection failed. Please inspect manually with the warp-cli command": "连接失败。请使用 warp-cli 命令手动检查", - "Toggles bar on press": "按下时切换条栏" + "UV Index": "UV Index", + "Pressure": "Pressure", + "Visibility": "Visibility", + "Sunrise": "Sunrise", + "Sunset": "Sunset", + "Humidity": "Humidity", + "Wind": "Wind", + "Precipitation": "Precipitation" } \ No newline at end of file From c64e079da4291a922fca529af4db67035fda4e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Thu, 17 Jul 2025 22:10:37 +0800 Subject: [PATCH 263/328] translations: update translations/zh_CN.json --- .config/quickshell/translations/zh_CN.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index c81da220..d59958a4 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -303,12 +303,12 @@ "Elements": "元素", "Scroll to change volume": "滚动以调节音量", "Connection failed. Please inspect manually with the warp-cli command": "连接失败。请使用 warp-cli 命令手动检查", - "UV Index": "UV Index", - "Pressure": "Pressure", - "Visibility": "Visibility", - "Sunrise": "Sunrise", - "Sunset": "Sunset", - "Humidity": "Humidity", - "Wind": "Wind", - "Precipitation": "Precipitation" + "UV Index": "紫外线指数", + "Pressure": "气压", + "Visibility": "能见度", + "Sunrise": "日出", + "Sunset": "日落", + "Humidity": "湿度", + "Wind": "风", + "Precipitation": "降水量" } \ No newline at end of file From 5865a62a94cd22746d547b0f994a9d48d0e577a8 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 22:07:03 +0700 Subject: [PATCH 264/328] gitignore: add .qmlls.ini --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d3c0402e..e8c1afab 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ # Ignore Python cache files __pycache__/ *.py[cod] +.config/quickshell/ii/.qmlls.ini From cfeae73c91d6b275b68712e25b045244e9da6567 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 22:08:31 +0700 Subject: [PATCH 265/328] notifications: fix eliding when collapsed --- .../quickshell/ii/modules/common/widgets/NotificationItem.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml index e660041e..93065676 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml @@ -175,13 +175,14 @@ Item { // Notification item area StyledText { opacity: !root.expanded ? 1 : 0 visible: opacity > 0 + Layout.fillWidth: true Behavior on opacity { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - Layout.fillWidth: true font.pixelSize: root.fontSize color: Appearance.colors.colSubtext elide: Text.ElideRight + wrapMode: Text.Wrap // Needed for proper eliding???? maximumLineCount: 1 textFormat: Text.StyledText text: { From 12e107448bf38216ca9dc49014c128021f7ddbf0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 23:42:59 +0700 Subject: [PATCH 266/328] right sidebar: add easyeffects toggle --- .../ii/modules/sidebarRight/SidebarRight.qml | 5 +- .../quickToggles/CloudflareWarp.qml | 1 + .../quickToggles/EasyEffectsToggle.qml | 50 +++++++++++++++++++ .../quickToggles/IdleInhibitor.qml | 2 +- .../quickToggles/QuickToggleButton.qml | 4 +- 5 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 .config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml diff --git a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml index 835e373b..6f77145f 100644 --- a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml @@ -16,7 +16,7 @@ import Quickshell.Hyprland Scope { id: root property int sidebarWidth: Appearance.sizes.sidebarWidth - property int sidebarPadding: 15 + property int sidebarPadding: 12 property string settingsQmlPath: Quickshell.configPath("settings.qml") PanelWindow { @@ -91,9 +91,9 @@ Scope { radius: Appearance.rounding.screenRounding - Appearance.sizes.hyprlandGapsOut + 1 ColumnLayout { - spacing: sidebarPadding anchors.fill: parent anchors.margins: sidebarPadding + spacing: sidebarPadding RowLayout { Layout.fillHeight: false @@ -177,6 +177,7 @@ Scope { GameMode {} IdleInhibitor {} CloudflareWarp {} + EasyEffectsToggle {} } // Center widget group diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml index 4e314fb1..39416ab2 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/CloudflareWarp.qml @@ -15,6 +15,7 @@ QuickToggleButton { source: 'cloudflare-dns-symbolic' anchors.centerIn: parent + width: 16 height: 16 colorize: true color: root.toggled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer1 diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml new file mode 100644 index 00000000..0a685463 --- /dev/null +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml @@ -0,0 +1,50 @@ +import qs.modules.common +import qs.modules.common.widgets +import qs +import Quickshell.Io +import Quickshell +import Quickshell.Hyprland + +QuickToggleButton { + id: root + toggled: false + visible: false + buttonIcon: "instant_mix" + + onClicked: { + if (toggled) { + root.toggled = false + Quickshell.execDetached(["pkill", "easyeffects"]) + } else { + root.toggled = true + Quickshell.execDetached(["easyeffects", "--gapplication-service"]) + } + } + + altAction: () => { + Quickshell.execDetached(["easyeffects"]) + Hyprland.dispatch("global quickshell:sidebarRightClose") + } + + Process { + id: fetchAvailability + running: true + command: ["bash", "-c", "command -v easyeffects"] + onExited: (exitCode, exitStatus) => { + root.visible = exitCode === 0 + } + } + + Process { + id: fetchActiveState + running: true + command: ["pidof", "easyeffects"] + onExited: (exitCode, exitStatus) => { + root.toggled = exitCode === 0 + } + } + + StyledToolTip { + content: Translation.tr("EasyEffects | Right-click to configure") + } +} diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml index aa1e292e..949842d4 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/IdleInhibitor.qml @@ -20,7 +20,7 @@ QuickToggleButton { Process { id: fetchActiveState running: true - command: ["bash", "-c", "pidof wayland-idle-inhibitor.py"] + command: ["pidof", "wayland-idle-inhibitor.py"] onExited: (exitCode, exitStatus) => { root.toggled = exitCode === 0 } diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/QuickToggleButton.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/QuickToggleButton.qml index c42a05d5..25a53de1 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/QuickToggleButton.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/QuickToggleButton.qml @@ -5,7 +5,7 @@ import QtQuick GroupButton { id: button property string buttonIcon - baseWidth: altAction ? 60 : 40 + baseWidth: 40 baseHeight: 40 clickedWidth: baseWidth + 20 toggled: false @@ -14,7 +14,7 @@ GroupButton { contentItem: MaterialSymbol { anchors.centerIn: parent - iconSize: Appearance.font.pixelSize.larger + iconSize: 20 fill: toggled ? 1 : 0 color: toggled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer1 horizontalAlignment: Text.AlignHCenter From fdc05ee4a0f7e8fe89d8f2f399853da616a72972 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 23:43:20 +0700 Subject: [PATCH 267/328] right sidebar: volume mixer: use listview, add separator --- .../sidebarRight/volumeMixer/VolumeMixer.qml | 56 +++++++++---------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml index 88f6da1b..4141ec7f 100644 --- a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml +++ b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml @@ -40,44 +40,33 @@ Item { Item { Layout.fillWidth: true Layout.fillHeight: true - Flickable { - id: flickable - anchors.fill: parent - contentHeight: volumeMixerColumnLayout.height - + ListView { + id: listView + model: root.appPwNodes clip: true - layer.enabled: true - layer.effect: OpacityMask { - maskSource: Rectangle { - width: flickable.width - height: flickable.height - radius: Appearance.rounding.normal - } + anchors { + fill: parent + topMargin: 10 + bottomMargin: 10 } + spacing: 6 - ColumnLayout { - id: volumeMixerColumnLayout - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.margins: 10 - spacing: 10 - - Repeater { - model: root.appPwNodes - - VolumeMixerEntry { - Layout.fillWidth: true - required property var modelData - node: modelData - } + delegate: VolumeMixerEntry { + // Layout.fillWidth: true + anchors { + left: parent.left + right: parent.right + leftMargin: 10 + rightMargin: 10 } + required property var modelData + node: modelData } } // Placeholder when list is empty Item { - anchors.fill: flickable + anchors.fill: listView visible: opacity > 0 opacity: (root.appPwNodes.length === 0) ? 1 : 0 @@ -109,6 +98,15 @@ Item { } } } + + // Separator + Rectangle { + color: Appearance.m3colors.m3outlineVariant + implicitHeight: 1 + Layout.fillWidth: true + } + + // Device selector ButtonGroup { id: deviceSelectorRowLayout From f42e6773aaf782b2992bb32e64fff2e659055a9d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 17 Jul 2025 23:44:13 +0700 Subject: [PATCH 268/328] settings: add wallpaper parallax --- .../ii/modules/background/Background.qml | 2 +- .../quickshell/ii/modules/bar/BarGroup.qml | 2 -- .../ii/modules/settings/StyleConfig.qml | 33 +++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index cf01078c..0ee66fb2 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -144,7 +144,7 @@ Scope { const lower = Math.floor(bgRoot.firstWorkspaceId / chunkSize) * chunkSize; const upper = Math.ceil(bgRoot.lastWorkspaceId / chunkSize) * chunkSize; const range = upper - lower; - return (bgRoot.monitor.activeWorkspace.id - lower) / range + return (Config.options.background.parallax.enableWorkspace ? ((bgRoot.monitor.activeWorkspace.id - lower) / range) : 0.5) + (0.15 * GlobalStates.sidebarRightOpen * Config.options.background.parallax.enableSidebar) - (0.15 * GlobalStates.sidebarLeftOpen * Config.options.background.parallax.enableSidebar) } diff --git a/.config/quickshell/ii/modules/bar/BarGroup.qml b/.config/quickshell/ii/modules/bar/BarGroup.qml index 04e64eb7..e2371d14 100644 --- a/.config/quickshell/ii/modules/bar/BarGroup.qml +++ b/.config/quickshell/ii/modules/bar/BarGroup.qml @@ -1,6 +1,4 @@ import qs.modules.common -import qs.modules.common.widgets -import qs.services import QtQuick import QtQuick.Layouts diff --git a/.config/quickshell/ii/modules/settings/StyleConfig.qml b/.config/quickshell/ii/modules/settings/StyleConfig.qml index ec37c7eb..6eabfabd 100644 --- a/.config/quickshell/ii/modules/settings/StyleConfig.qml +++ b/.config/quickshell/ii/modules/settings/StyleConfig.qml @@ -208,5 +208,38 @@ ContentPage { } } } + + ContentSubsection { + title: Translation.tr("Wallpaper parallax") + + ConfigRow { + uniform: true + ConfigSwitch { + text: Translation.tr("Depends on workspace") + checked: Config.options.background.parallax.enableWorkspace + onCheckedChanged: { + Config.options.background.parallax.enableWorkspace = checked; + } + } + ConfigSwitch { + text: Translation.tr("Depends on sidebars") + checked: Config.options.background.parallax.enableSidebar + onCheckedChanged: { + Config.options.background.parallax.enableSidebar = checked; + } + } + } + ConfigSpinBox { + text: Translation.tr("Preferred wallpaper zoom (%)") + value: Config.options.background.parallax.workspaceZoom * 100 + from: 100 + to: 150 + stepSize: 1 + onValueChanged: { + console.log(value/100) + Config.options.background.parallax.workspaceZoom = value / 100; + } + } + } } } \ No newline at end of file From e6c44737acf45ab05abf1cf8251871b01817cbb4 Mon Sep 17 00:00:00 2001 From: Nouvborne Date: Thu, 17 Jul 2025 18:11:07 +0000 Subject: [PATCH 269/328] Update keybinds.conf --- .config/hypr/hyprland/keybinds.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index d7c20864..5a314006 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -205,7 +205,7 @@ bind = Super, Return, exec, ~/.config/hypr/hyprland/scripts/launch_first_availab bind = Super, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] Kitty (terminal) (alt) bind = Ctrl+Alt, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] Kitty (for Ubuntu people) bind = Super, E, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "dolphin" "nautilus" "nemo" "thunar" "kitty -1 fish -c yazi" # File manager -bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "google-chrome-stable" "zen-browser" "firefox" "brave" "chromium" "microsoft-edge-stable" "opera" # Browser +bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "google-chrome-stable" "zen-browser" "firefox" "brave" "chromium" "microsoft-edge-stable" "opera" "librewolf" # Browser bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "code" "codium" "cursor" "zed" "zedit" "zeditor" "kate" "gnome-text-editor" "emacs" "command -v nvim && kitty -1 nvim" # Code editor bind = Super+Shift, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "wps" "onlyoffice-desktopeditors" # Office software bind = Super, X, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kate" "gnome-text-editor" "emacs" # Text editor From c1832de01f4068a631019476f1373f99aad2e4b6 Mon Sep 17 00:00:00 2001 From: Nouvborne Date: Thu, 17 Jul 2025 18:13:04 +0000 Subject: [PATCH 270/328] Update env.conf --- .config/hypr/hyprland/env.conf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/env.conf b/.config/hypr/hyprland/env.conf index b3d843cd..a65e4603 100644 --- a/.config/hypr/hyprland/env.conf +++ b/.config/hypr/hyprland/env.conf @@ -20,5 +20,9 @@ env = QT_QPA_PLATFORMTHEME, kde # ######## Virtual envrionment ######### env = ILLOGICAL_IMPULSE_VIRTUAL_ENV, ~/.local/state/quickshell/.venv -# ############ Others ############# +# ######## Uncomment if you use NVIDIA GPU ######### +#env = LIBVA_DRIVER_NAME,nvidia +#env = __GLX_VENDOR_LIBRARY_NAME,nvidia +#env = ELECTRON_OZONE_PLATFORM_HINT,autos +# ############ Others ############# From ccf512b8ad6595fedab23953a93951cd97cd8f9e Mon Sep 17 00:00:00 2001 From: Dignity <107360076+77Dignity@users.noreply.github.com> Date: Thu, 17 Jul 2025 20:44:56 +0200 Subject: [PATCH 271/328] fix random konachan script not updating wallpaper --- .../quickshell/ii/scripts/colors/random_konachan_wall.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh index 079cad96..9b0fc4cf 100755 --- a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh +++ b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh @@ -14,6 +14,11 @@ page=$((1 + RANDOM % 1000)); response=$(curl "https://konachan.com/post.json?tags=rating%3Asafe&limit=1&page=$page") link=$(echo "$response" | jq '.[0].file_url' -r); ext=$(echo "$link" | awk -F. '{print $NF}') -downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image.$ext" +downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image-0.$ext" +counter=0 +while [ -e $downloadPath ]; do + counter=$((counter + 1)) + downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image-$counter.$ext" +done curl "$link" -o "$downloadPath" "$SCRIPT_DIR/switchwall.sh" --image "$downloadPath" From 8452b9a23439761c745182e6d614440b872b2c36 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 03:44:55 +0200 Subject: [PATCH 272/328] Update CONTRIBUTING.md --- CONTRIBUTING.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 026726a8..8efb92a3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,13 @@ # Contributing + - Please understand that dotfiles are after all personal. I can accept features I do not personally want, but in that case I will ask you to make it configurable/optionally loaded - If you add new stuff, it's a good idea to ask me first to not waste your work - Please make multiple PRs if you have many features + +# Technical steps + +_Complete steps, might not be necessary depending on what you change_ + +- Install the dotfiles (if you don't wanna replace your stuff completely, do it on a new user) +- For Quickshell: `touch ~/.config/quickshell/ii/.qmlls.ini` for proper LSP support +- Make changes, copy changes to a fork, PR From 9abdfd8da00f30b60dcc2f3b51ecab841a3d1e0c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 04:13:17 +0200 Subject: [PATCH 273/328] Update env.conf --- .config/hypr/hyprland/env.conf | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/.config/hypr/hyprland/env.conf b/.config/hypr/hyprland/env.conf index a65e4603..f745ba83 100644 --- a/.config/hypr/hyprland/env.conf +++ b/.config/hypr/hyprland/env.conf @@ -2,27 +2,22 @@ # See https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland env = QT_IM_MODULE, fcitx env = XMODIFIERS, @im=fcitx -# env = GTK_IM_MODULE, wayland # Crashes electron apps in xwayland -# env = GTK_IM_MODULE, fcitx # My Gtk apps no longer require this to work with fcitx5 hmm env = SDL_IM_MODULE, fcitx env = GLFW_IM_MODULE, ibus env = INPUT_METHOD, fcitx +# ############ Wayland ############# +ELECTRON_OZONE_PLATFORM_HINT,auto + # ############ Themes ############# env = QT_QPA_PLATFORM, wayland env = QT_QPA_PLATFORMTHEME, kde -# env = QT_STYLE_OVERRIDE,kvantum -# env = WLR_NO_HARDWARE_CURSORS, 1 -# ######## Screen tearing ######### +# ######## Wayland ######### +# Tearing # env = WLR_DRM_NO_ATOMIC, 1 +# ? +# env = WLR_NO_HARDWARE_CURSORS, 1 # ######## Virtual envrionment ######### env = ILLOGICAL_IMPULSE_VIRTUAL_ENV, ~/.local/state/quickshell/.venv - -# ######## Uncomment if you use NVIDIA GPU ######### -#env = LIBVA_DRIVER_NAME,nvidia -#env = __GLX_VENDOR_LIBRARY_NAME,nvidia -#env = ELECTRON_OZONE_PLATFORM_HINT,autos - -# ############ Others ############# From 3311d6826234cdec2f96d67683bc27f20f30d58a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 09:19:30 +0700 Subject: [PATCH 274/328] hyprland: fix env syntax error --- .config/hypr/hyprland/env.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/hypr/hyprland/env.conf b/.config/hypr/hyprland/env.conf index f745ba83..0f69fd5d 100644 --- a/.config/hypr/hyprland/env.conf +++ b/.config/hypr/hyprland/env.conf @@ -1,4 +1,4 @@ -# ######### Input method ########## +# ######### Input method ########## # See https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland env = QT_IM_MODULE, fcitx env = XMODIFIERS, @im=fcitx @@ -7,7 +7,7 @@ env = GLFW_IM_MODULE, ibus env = INPUT_METHOD, fcitx # ############ Wayland ############# -ELECTRON_OZONE_PLATFORM_HINT,auto +env = ELECTRON_OZONE_PLATFORM_HINT,auto # ############ Themes ############# env = QT_QPA_PLATFORM, wayland From 2cc313855b0885d8714babd4f82ea27702af7a9a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 12:36:25 +0700 Subject: [PATCH 275/328] launcher: clipboard: delete button --- .../ii/modules/overview/SearchItem.qml | 44 ++++++++++++++++++- .../ii/modules/overview/SearchWidget.qml | 13 +++++- .config/quickshell/ii/services/Cliphist.qml | 24 +++++++++- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/ii/modules/overview/SearchItem.qml b/.config/quickshell/ii/modules/overview/SearchItem.qml index e7b33ace..1fb23b27 100644 --- a/.config/quickshell/ii/modules/overview/SearchItem.qml +++ b/.config/quickshell/ii/modules/overview/SearchItem.qml @@ -14,7 +14,7 @@ RippleButton { property var entry property string query property bool entryShown: entry?.shown ?? true - property string itemType: entry?.type + property string itemType: entry?.type ?? Translation.tr("App") property string itemName: entry?.name property string itemIcon: entry?.icon ?? "" property var itemExecute: entry?.execute @@ -221,5 +221,47 @@ RippleButton { horizontalAlignment: Text.AlignRight text: root.itemClickActionName } + + RowLayout { + spacing: 4 + Repeater { + model: (root.entry.actions ?? []).slice(0, 4) + delegate: RippleButton { + id: actionButton + required property var modelData + implicitHeight: 34 + implicitWidth: 34 + + contentItem: Item { + id: actionContentItem + anchors.centerIn: parent + Loader { + anchors.centerIn: parent + active: !(actionButton.modelData.icon && actionButton.modelData.icon !== "") + sourceComponent: MaterialSymbol { + text: "video_settings" + font.pixelSize: Appearance.font.pixelSize.hugeass + color: Appearance.m3colors.m3onSurface + } + } + Loader { + anchors.centerIn: parent + active: actionButton.modelData.icon && actionButton.modelData.icon !== "" + sourceComponent: IconImage { + source: Quickshell.iconPath(actionButton.modelData.icon) + implicitSize: 20 + } + } + } + + onClicked: modelData.execute() + + StyledToolTip { + content: modelData.name + } + } + } + } + } } diff --git a/.config/quickshell/ii/modules/overview/SearchWidget.qml b/.config/quickshell/ii/modules/overview/SearchWidget.qml index 3ec0b0bd..851f5e37 100644 --- a/.config/quickshell/ii/modules/overview/SearchWidget.qml +++ b/.config/quickshell/ii/modules/overview/SearchWidget.qml @@ -294,8 +294,17 @@ Item { // Wrapper clickActionName: "", type: `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`, execute: () => { - Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`]); - } + Cliphist.copy(entry) + }, + actions: [ + { + name: "Delete", + icon: "delete", + execute: () => { + Cliphist.deleteEntry(entry); + } + } + ] }; }).filter(Boolean); } diff --git a/.config/quickshell/ii/services/Cliphist.qml b/.config/quickshell/ii/services/Cliphist.qml index ea4400bb..0fe7ad71 100644 --- a/.config/quickshell/ii/services/Cliphist.qml +++ b/.config/quickshell/ii/services/Cliphist.qml @@ -4,7 +4,7 @@ pragma ComponentBehavior: Bound import "root:/modules/common/functions/fuzzysort.js" as Fuzzy import "root:/modules/common/functions/levendist.js" as Levendist import qs.modules.common -import qs +import qs.modules.common.functions import QtQuick import Quickshell import Quickshell.Io @@ -42,6 +42,28 @@ Singleton { readProc.running = true } + function copy(entry) { + Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`]); + } + + Process { + id: deleteProc + property string entry: "" + command: ["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(deleteProc.entry)}' | cliphist delete`] + function deleteEntry(entry) { + deleteProc.entry = entry; + deleteProc.running = true; + deleteProc.entry = ""; + } + onExited: (exitCode, exitStatus) => { + root.refresh(); + } + } + + function deleteEntry(entry) { + deleteProc.deleteEntry(entry); + } + Connections { target: Quickshell function onClipboardTextChanged() { From 0806c97fe5acc114c3a44a586d4e2cbb1350533a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 12:36:49 +0700 Subject: [PATCH 276/328] right sidebar: change toggles order --- .config/quickshell/ii/modules/sidebarRight/SidebarRight.qml | 2 +- .../ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml | 1 - .config/quickshell/ii/services/Brightness.qml | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml index 6f77145f..44d591fe 100644 --- a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml @@ -176,8 +176,8 @@ Scope { NightLight {} GameMode {} IdleInhibitor {} - CloudflareWarp {} EasyEffectsToggle {} + CloudflareWarp {} } // Center widget group diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml index 0a685463..ebf847c7 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml @@ -1,4 +1,3 @@ -import qs.modules.common import qs.modules.common.widgets import qs import Quickshell.Io diff --git a/.config/quickshell/ii/services/Brightness.qml b/.config/quickshell/ii/services/Brightness.qml index 74c6c504..927a10c0 100644 --- a/.config/quickshell/ii/services/Brightness.qml +++ b/.config/quickshell/ii/services/Brightness.qml @@ -4,7 +4,6 @@ pragma ComponentBehavior: Bound // From https://github.com/caelestia-dots/shell/ (`quickshell` branch) with modifications. // License: GPLv3 -import qs import Quickshell import Quickshell.Io import Quickshell.Hyprland From 40f2e0b6a70690b14503377ce01a2d342391c3b3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 15:29:08 +0700 Subject: [PATCH 277/328] notif item: fix binding loop for notifs with images --- .../quickshell/ii/modules/common/widgets/NotificationItem.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml index 93065676..4b97d3da 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml @@ -208,7 +208,7 @@ Item { // Notification item area elide: Text.ElideRight textFormat: Text.RichText text: { - return `` + + return `` + `${processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "
")}` } From bab166baeaebbb0d68c58fb709c4cfeed95931fb Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:09:35 +0700 Subject: [PATCH 278/328] notifications: destroy wrapper object when quickshell's notif is destroyed (#1465) --- .../common/widgets/NotificationGroup.qml | 2 +- .../common/widgets/NotificationItem.qml | 4 +- .../quickshell/ii/services/Notifications.qml | 41 ++++++++++++------- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml b/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml index 22b22656..d63bbb31 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml @@ -53,7 +53,7 @@ Item { // Notification group area onFinished: () => { root.notifications.forEach((notif) => { Qt.callLater(() => { - Notifications.discardNotification(notif.id); + Notifications.discardNotification(notif.notificationId); }); }); } diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml index 4b97d3da..4f5688b8 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml @@ -70,7 +70,7 @@ Item { // Notification item area easing.bezierCurve: Appearance.animation.elementMove.bezierCurve } onFinished: () => { - Notifications.discardNotification(notificationObject.id); + Notifications.discardNotification(notificationObject.notificationId); } } @@ -269,7 +269,7 @@ Item { // Notification item area buttonText: modelData.text urgency: notificationObject.urgency onClicked: { - Notifications.attemptInvokeAction(notificationObject.id, modelData.identifier); + Notifications.attemptInvokeAction(notificationObject.notificationId, modelData.identifier); } } } diff --git a/.config/quickshell/ii/services/Notifications.qml b/.config/quickshell/ii/services/Notifications.qml index d0d51e8e..0c4e776d 100644 --- a/.config/quickshell/ii/services/Notifications.qml +++ b/.config/quickshell/ii/services/Notifications.qml @@ -17,7 +17,8 @@ import Quickshell.Services.Notifications Singleton { id: root component Notif: QtObject { - required property int id + id: wrapper + required property int notificationId // Could just be `id` but it conflicts with the default prop in QtObject property Notification notification property list actions: notification?.actions.map((action) => ({ "identifier": action.identifier, @@ -32,11 +33,19 @@ Singleton { property double time property string urgency: notification?.urgency.toString() ?? "normal" property Timer timer + + readonly property Connections conn: Connections { + target: wrapper.notification.Component + + function onDestruction(): void { + wrapper.destroy(); + } + } } function notifToJSON(notif) { return { - "id": notif.id, + "notificationId": notif.notificationId, "actions": notif.actions, "appIcon": notif.appIcon, "appName": notif.appName, @@ -52,11 +61,11 @@ Singleton { } component NotifTimer: Timer { - required property int id + required property int notificationId interval: 5000 running: true onTriggered: () => { - root.timeoutNotification(id); + root.timeoutNotification(notificationId); destroy() } } @@ -130,7 +139,7 @@ Singleton { property int idOffset signal initDone(); signal notify(notification: var); - signal discard(id: var); + signal discard(id: int); signal discardAll(); signal timeout(id: var); @@ -149,7 +158,7 @@ Singleton { onNotification: (notification) => { notification.tracked = true const newNotifObject = notifComponent.createObject(root, { - "id": notification.id + root.idOffset, + "notificationId": notification.id + root.idOffset, "notification": notification, "time": Date.now(), }); @@ -159,7 +168,7 @@ Singleton { if (!root.popupInhibited) { newNotifObject.popup = true; newNotifObject.timer = notifTimerComponent.createObject(root, { - "id": newNotifObject.id, + "notificationId": newNotifObject.notificationId, "interval": notification.expireTimeout < 0 ? 5000 : notification.expireTimeout, }); } @@ -171,7 +180,8 @@ Singleton { } function discardNotification(id) { - const index = root.list.findIndex((notif) => notif.id === id); + console.log("[Notifications] Discarding notification with ID: " + id); + const index = root.list.findIndex((notif) => notif.notificationId === id); const notifServerIndex = notifServer.trackedNotifications.values.findIndex((notif) => notif.id + root.idOffset === id); if (index !== -1) { root.list.splice(index, 1); @@ -181,7 +191,7 @@ Singleton { if (notifServerIndex !== -1) { notifServer.trackedNotifications.values[notifServerIndex].dismiss() } - root.discard(id); + root.discard(id); // Emit signal } function discardAllNotifications() { @@ -195,7 +205,7 @@ Singleton { } function timeoutNotification(id) { - const index = root.list.findIndex((notif) => notif.id === id); + const index = root.list.findIndex((notif) => notif.notificationId === id); if (root.list[index] != null) root.list[index].popup = false; root.timeout(id); @@ -203,7 +213,7 @@ Singleton { function timeoutAll() { root.popupList.forEach((notif) => { - root.timeout(notif.id); + root.timeout(notif.notificationId); }) root.popupList.forEach((notif) => { notif.popup = false; @@ -211,10 +221,13 @@ Singleton { } function attemptInvokeAction(id, notifIdentifier) { + console.log("[Notifications] Attempting to invoke action with identifier: " + notifIdentifier + " for notification ID: " + id); const notifServerIndex = notifServer.trackedNotifications.values.findIndex((notif) => notif.id + root.idOffset === id); + console.log("Notification server index: " + notifServerIndex); if (notifServerIndex !== -1) { const notifServerNotif = notifServer.trackedNotifications.values[notifServerIndex]; const action = notifServerNotif.actions.find((action) => action.identifier === notifIdentifier); + console.log("Action found: " + JSON.stringify(action)); action.invoke() } else { @@ -242,7 +255,7 @@ Singleton { const fileContents = notifFileView.text() root.list = JSON.parse(fileContents).map((notif) => { return notifComponent.createObject(root, { - "id": notif.id, + "notificationId": notif.notificationId, "actions": [], // Notification actions are meaningless if they're not tracked by the server or the sender is dead "appIcon": notif.appIcon, "appName": notif.appName, @@ -253,10 +266,10 @@ Singleton { "urgency": notif.urgency, }); }); - // Find largest id + // Find largest notificationId let maxId = 0 root.list.forEach((notif) => { - maxId = Math.max(maxId, notif.id) + maxId = Math.max(maxId, notif.notificationId) }) console.log("[Notifications] File loaded") From ac0aaf7ba93ceb393faf4d90de4925590d2f1f7d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:39:44 +0700 Subject: [PATCH 279/328] overview: make drag hotspot be at the mouse --- .config/quickshell/ii/modules/overview/OverviewWidget.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/overview/OverviewWidget.qml b/.config/quickshell/ii/modules/overview/OverviewWidget.qml index 7f28c378..4f0f03f7 100644 --- a/.config/quickshell/ii/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/ii/modules/overview/OverviewWidget.qml @@ -199,11 +199,13 @@ Item { onExited: hovered = false // For hover color change acceptedButtons: Qt.LeftButton | Qt.MiddleButton drag.target: parent - onPressed: { + onPressed: (mouse) => { root.draggingFromWorkspace = windowData?.workspace.id window.pressed = true window.Drag.active = true window.Drag.source = window + window.Drag.hotSpot.x = mouse.x + window.Drag.hotSpot.y = mouse.y // console.log(`[OverviewWindow] Dragging window ${windowData?.address} from position (${window.x}, ${window.y})`) } onReleased: { From 86e041945ac1f5af2b89bb7fbf74efe0226b3716 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 17:40:18 +0700 Subject: [PATCH 280/328] activewindow: fix null warnings --- .config/quickshell/ii/modules/bar/ActiveWindow.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/ActiveWindow.qml b/.config/quickshell/ii/modules/bar/ActiveWindow.qml index a4105dd4..636b2313 100644 --- a/.config/quickshell/ii/modules/bar/ActiveWindow.qml +++ b/.config/quickshell/ii/modules/bar/ActiveWindow.qml @@ -13,9 +13,9 @@ Item { readonly property HyprlandMonitor monitor: Hyprland.monitorFor(bar.screen) readonly property Toplevel activeWindow: ToplevelManager.activeToplevel - property string activeWindowAddress: `0x${activeWindow.HyprlandToplevel.address}` + property string activeWindowAddress: `0x${activeWindow?.HyprlandToplevel?.address}` property bool focusingThisMonitor: HyprlandData.activeWorkspace.monitor == monitor.name - property var biggestWindow: HyprlandData.biggestWindowForWorkspace(HyprlandData.monitors[root.monitor.id].activeWorkspace.id) + property var biggestWindow: HyprlandData.biggestWindowForWorkspace(HyprlandData.monitors[root.monitor.id]?.activeWorkspace.id) implicitWidth: colLayout.implicitWidth From 2426682cc296807d840e902ece1514a5c1ad2d4f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 12:47:46 +0200 Subject: [PATCH 281/328] readme: just link to wiki --- README.md | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index da76e53e..0a9e861c 100644 --- a/README.md +++ b/README.md @@ -26,25 +26,12 @@ - **Transparent installation**: Every command is shown before it's run
- Instructions + Installation instructions - - **Prerequisite**: Your system works. That's it. You don't have to reinstall your system! - - **Automatic**, but guided and transparent, installation for Arch(-based) Linux: - ```bash - bash <(curl -s "https://end-4.github.io/dots-hyprland-wiki/setup.sh") - ``` - - If you are using fish shell (non-posix-compliant shell) then: - ```bash - bash -c "$(curl -s https://end-4.github.io/dots-hyprland-wiki/setup.sh)" - ``` - - - **Manual** installation, other distros and more: - - See the [Wiki](https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/01setup/) - - - **Default keybinds**: Should be somewhat familiar if you've used Windows or GNOME. - - For a list, hit `Super`+`/` - - For a terminal, hit `Super`+`Enter` + - See the [Wiki](https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/01setup/) + - **Default keybinds**: Should be somewhat familiar to Windows or GNOME users. + - `Super`+`/` = keybind list + - `Super`+`Enter` = terminal
From ae30ab03d5da000667ab9bea6ae146746243b5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=82=89=E3=81=BE=E3=82=8A=E3=82=93?= Date: Fri, 18 Jul 2025 21:02:21 +0800 Subject: [PATCH 282/328] fix(wallpaper/konachan): utilize XDG_PICTURES_DIR in random konachan --- .../ii/scripts/colors/random_konachan_wall.sh | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh index 079cad96..f55aa045 100755 --- a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh +++ b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh @@ -1,19 +1,37 @@ #!/usr/bin/env bash +get_pictures_dir() { + if command -v xdg-user-dir &> /dev/null; then + xdg-user-dir PICTURES + return + fi + + local config_file="${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" + if [ -f "$config_file" ]; then + local pictures_path + pictures_path=$(source "$config_file" >/dev/null 2>&1; echo "$XDG_PICTURES_DIR") + echo "${pictures_path/#\$HOME/$HOME}" + return + fi + + echo "$HOME/Pictures" +} + QUICKSHELL_CONFIG_NAME="ii" XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" +PICTURES_DIR=$(get_pictures_dir) CONFIG_DIR="$XDG_CONFIG_HOME/quickshell/$QUICKSHELL_CONFIG_NAME" CACHE_DIR="$XDG_CACHE_HOME/quickshell" STATE_DIR="$XDG_STATE_HOME/quickshell" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -mkdir -p ~/Pictures/Wallpapers -page=$((1 + RANDOM % 1000)); +mkdir -p $PICTURES_DIR +page=$((1 + RANDOM % 1000)); response=$(curl "https://konachan.com/post.json?tags=rating%3Asafe&limit=1&page=$page") -link=$(echo "$response" | jq '.[0].file_url' -r); +link=$(echo "$response" | jq '.[0].file_url' -r); ext=$(echo "$link" | awk -F. '{print $NF}') -downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image.$ext" +downloadPath="$PICTURES_DIR/Wallpapers/konachan_random_image.$ext" curl "$link" -o "$downloadPath" "$SCRIPT_DIR/switchwall.sh" --image "$downloadPath" From 5382b4bfb12d841ddfe1694a282053d035a96cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=82=89=E3=81=BE=E3=82=8A=E3=82=93?= Date: Fri, 18 Jul 2025 21:06:45 +0800 Subject: [PATCH 283/328] fix(wallpaper/konachan): fix mkdir --- .config/quickshell/ii/scripts/colors/random_konachan_wall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh index f55aa045..8f35f5a2 100755 --- a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh +++ b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh @@ -27,7 +27,7 @@ CACHE_DIR="$XDG_CACHE_HOME/quickshell" STATE_DIR="$XDG_STATE_HOME/quickshell" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -mkdir -p $PICTURES_DIR +mkdir -p "$PICTURES_DIR/Wallpapers" page=$((1 + RANDOM % 1000)); response=$(curl "https://konachan.com/post.json?tags=rating%3Asafe&limit=1&page=$page") link=$(echo "$response" | jq '.[0].file_url' -r); From 7b3884ab1a7c9bf4a3ad7d043466db46ad0e9169 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 22:54:23 +0700 Subject: [PATCH 284/328] konachan.net instead of konachan.com to prevent captchas (#1664) --- .../quickshell/ii/scripts/colors/random_konachan_wall.sh | 2 +- .config/quickshell/ii/services/Booru.qml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh index 079cad96..29bcdd00 100755 --- a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh +++ b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh @@ -11,7 +11,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" mkdir -p ~/Pictures/Wallpapers page=$((1 + RANDOM % 1000)); -response=$(curl "https://konachan.com/post.json?tags=rating%3Asafe&limit=1&page=$page") +response=$(curl "https:net/post.json?tags=rating%3Asafe&limit=1&page=$page") link=$(echo "$response" | jq '.[0].file_url' -r); ext=$(echo "$link" | awk -F. '{print $NF}') downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image.$ext" diff --git a/.config/quickshell/ii/services/Booru.qml b/.config/quickshell/ii/services/Booru.qml index 38714bc1..e2a9d195 100644 --- a/.config/quickshell/ii/services/Booru.qml +++ b/.config/quickshell/ii/services/Booru.qml @@ -58,8 +58,8 @@ Singleton { }, "konachan": { "name": "Konachan", - "url": "https://konachan.com", - "api": "https://konachan.com/post.json", + "url": "https://konachan.net", + "api": "https://konachan.net/post.json", "description": Translation.tr("For desktop wallpapers | Good quality"), "mapFunc": (response) => { return response.map(item => { @@ -80,7 +80,7 @@ Singleton { } }) }, - "tagSearchTemplate": "https://konachan.com/tag.json?order=count&name={{query}}*", + "tagSearchTemplate": "https://konachan.net/tag.json?order=count&name={{query}}*", "tagMapFunc": (response) => { return response.map(item => { return { @@ -360,7 +360,7 @@ Singleton { function makeRequest(tags, nsfw=false, limit=20, page=1) { var url = constructRequestUrl(tags, nsfw, limit, page) - // console.log("[Booru] Making request to " + url) + console.log("[Booru] Making request to " + url) const newResponse = root.booruResponseDataComponent.createObject(null, { "provider": currentProvider, From 65e3b6c84c4e3d014abed3c3d4b09736af5f674e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 23:03:58 +0700 Subject: [PATCH 285/328] fix typo --- .config/quickshell/ii/scripts/colors/random_konachan_wall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh index 29bcdd00..f97182f1 100755 --- a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh +++ b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh @@ -11,7 +11,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" mkdir -p ~/Pictures/Wallpapers page=$((1 + RANDOM % 1000)); -response=$(curl "https:net/post.json?tags=rating%3Asafe&limit=1&page=$page") +response=$(curl "https://konachan.net/post.json?tags=rating%3Asafe&limit=1&page=$page") link=$(echo "$response" | jq '.[0].file_url' -r); ext=$(echo "$link" | awk -F. '{print $NF}') downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image.$ext" From 055da37987cd722deb7b670eeeb42d120f656301 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 23:13:00 +0700 Subject: [PATCH 286/328] screenshot: fix window regions --- .config/quickshell/ii/screenshot.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/screenshot.qml b/.config/quickshell/ii/screenshot.qml index 1fb5290f..c26840a9 100644 --- a/.config/quickshell/ii/screenshot.qml +++ b/.config/quickshell/ii/screenshot.qml @@ -7,11 +7,11 @@ pragma ComponentBehavior: "Bound" import qs +import qs.services import qs.modules.common import qs.modules.common.widgets import qs.modules.common.functions import QtQuick -import QtQuick.Effects import QtQuick.Controls import QtQuick.Layouts import Quickshell From 19ea9ea3d124387985cfdac801bf4cec8fb470db Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 18 Jul 2025 23:42:10 +0700 Subject: [PATCH 287/328] kill all apps before shutting down/rebooting/etc --- .config/quickshell/ii/modules/session/Session.qml | 14 ++++++++++---- .config/wlogout/layout | 8 ++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.config/quickshell/ii/modules/session/Session.qml b/.config/quickshell/ii/modules/session/Session.qml index fc22e330..76ca373f 100644 --- a/.config/quickshell/ii/modules/session/Session.qml +++ b/.config/quickshell/ii/modules/session/Session.qml @@ -15,6 +15,12 @@ Scope { id: root property var focusedScreen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name) + function closeAllWindows() { + HyprlandData.windowList.map(w => w.pid).forEach((pid) => { + Quickshell.execDetached(["kill", pid]); + }); + } + Loader { id: sessionLoader active: false @@ -111,7 +117,7 @@ Scope { id: sessionLogout buttonIcon: "logout" buttonText: Translation.tr("Logout") - onClicked: { Quickshell.execDetached(["pkill", "Hyprland"]); sessionRoot.hide() } + onClicked: { root.closeAllWindows(); Quickshell.execDetached(["pkill", "Hyprland"]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionSleep KeyNavigation.right: sessionTaskManager @@ -140,7 +146,7 @@ Scope { id: sessionShutdown buttonIcon: "power_settings_new" buttonText: Translation.tr("Shutdown") - onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl poweroff || loginctl poweroff`]); sessionRoot.hide() } + onClicked: { root.closeAllWindows(); Quickshell.execDetached(["bash", "-c", `systemctl poweroff || loginctl poweroff`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionHibernate KeyNavigation.right: sessionReboot @@ -150,7 +156,7 @@ Scope { id: sessionReboot buttonIcon: "restart_alt" buttonText: Translation.tr("Reboot") - onClicked: { Quickshell.execDetached(["bash", "-c", `reboot || loginctl reboot`]); sessionRoot.hide() } + onClicked: { root.closeAllWindows(); Quickshell.execDetached(["bash", "-c", `reboot || loginctl reboot`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionShutdown KeyNavigation.right: sessionFirmwareReboot @@ -160,7 +166,7 @@ Scope { id: sessionFirmwareReboot buttonIcon: "settings_applications" buttonText: Translation.tr("Reboot to firmware settings") - onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl reboot --firmware-setup || loginctl reboot --firmware-setup`]); sessionRoot.hide() } + onClicked: { root.closeAllWindows(); Quickshell.execDetached(["bash", "-c", `systemctl reboot --firmware-setup || loginctl reboot --firmware-setup`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.up: sessionTaskManager KeyNavigation.left: sessionReboot diff --git a/.config/wlogout/layout b/.config/wlogout/layout index c31abd94..03d696b0 100644 --- a/.config/wlogout/layout +++ b/.config/wlogout/layout @@ -7,18 +7,18 @@ { "label" : "hibernate", "action" : "systemctl hibernate || loginctl hibernate", - "text" : "save", + "text" : "downloading", "keybind" : "h" } { "label" : "logout", - "action" : "pkill Hyprland || pkill sway || pkill niri || loginctl terminate-user $USER", + "action" : "hyprctl clients -j | jq -r '.[].pid' | xargs kill; pkill Hyprland || pkill sway || pkill niri || loginctl terminate-user $USER", "text" : "logout", "keybind" : "e" } { "label" : "shutdown", - "action" : "systemctl poweroff || loginctl poweroff", + "action" : "hyprctl clients -j | jq -r '.[].pid' | xargs kill; systemctl poweroff || loginctl poweroff", "text" : "power_settings_new", "keybind" : "s" } @@ -30,7 +30,7 @@ } { "label" : "reboot", - "action" : "systemctl reboot || loginctl reboot", + "action" : "hyprctl clients -j | jq -r '.[].pid' | xargs kill; systemctl reboot || loginctl reboot", "text" : "restart_alt", "keybind" : "r" } From 68fa1715d058daf244f50ecae8844fd2a18d39ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=82=89=E3=81=BE=E3=82=8A=E3=82=93?= <62203463+Flamarine@users.noreply.github.com> Date: Sat, 19 Jul 2025 09:34:45 +0800 Subject: [PATCH 288/328] fix(translation): reflect dir change in zh_cn --- .config/quickshell/translations/zh_CN.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index d59958a4..f795a3c1 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -9,7 +9,7 @@ "%1 characters": "%1 个字符", "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**价格**:免费。数据用于训练。\n\n**说明**:登录 Google 账户,允许 AI Studio 创建 Google Cloud 项目或其他要求,然后返回并点击获取 API 密钥", "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key": "**价格**:免费。数据使用政策取决于您的 OpenRouter 账户设置。\n\n**说明**:登录 OpenRouter 账户,在右上角菜单中选择 Keys,点击创建 API 密钥", - ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!": ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!", + ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!": ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!", "No further instruction provided": "未提供进一步说明", "API key set for %1": "已为 %1 设置 API 密钥", "API key:\n\n```txt\n%1\n```": "API 密钥:\n\n```txt\n%1\n```", @@ -159,7 +159,7 @@ "Fake screen rounding": "伪造屏幕圆角", "When not fullscreen": "非全屏时", "Choose file": "选择文件", - "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers": "随机 Konachan SFW 动漫壁纸\n图片保存到 ~/Pictures/Wallpapers", + "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers": "随机 Konachan SFW 动漫壁纸\n图片保存到 ~/图片/Wallpapers", "Be patient...": "请耐心等待...", "Decorations & Effects": "装饰与特效", "Tonal Spot": "色调点", @@ -311,4 +311,4 @@ "Humidity": "湿度", "Wind": "风", "Precipitation": "降水量" -} \ No newline at end of file +} From 47007288e8b1c6c65f760a2448656601ae3c8c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=82=89=E3=81=BE=E3=82=8A=E3=82=93?= <62203463+Flamarine@users.noreply.github.com> Date: Sat, 19 Jul 2025 09:37:39 +0800 Subject: [PATCH 289/328] fix(translation): fix comma --- .config/quickshell/translations/zh_CN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index f795a3c1..34dc5415 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -9,7 +9,7 @@ "%1 characters": "%1 个字符", "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**价格**:免费。数据用于训练。\n\n**说明**:登录 Google 账户,允许 AI Studio 创建 Google Cloud 项目或其他要求,然后返回并点击获取 API 密钥", "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key": "**价格**:免费。数据使用政策取决于您的 OpenRouter 账户设置。\n\n**说明**:登录 OpenRouter 账户,在右上角菜单中选择 Keys,点击创建 API 密钥", - ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!": ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!", + ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!": ". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!", "No further instruction provided": "未提供进一步说明", "API key set for %1": "已为 %1 设置 API 密钥", "API key:\n\n```txt\n%1\n```": "API 密钥:\n\n```txt\n%1\n```", From 8603918771076004c09db0a7daa91beb8e76fc90 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 19 Jul 2025 10:35:52 +0700 Subject: [PATCH 290/328] icons: add guess by icon search --- .config/quickshell/ii/services/AppSearch.qml | 64 ++++++++++++++------ 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/.config/quickshell/ii/services/AppSearch.qml b/.config/quickshell/ii/services/AppSearch.qml index a658d506..6a0d4c05 100644 --- a/.config/quickshell/ii/services/AppSearch.qml +++ b/.config/quickshell/ii/services/AppSearch.qml @@ -47,9 +47,18 @@ Singleton { .sort((a, b) => a.name.localeCompare(b.name)) readonly property var preppedNames: list.map(a => ({ - name: Fuzzy.prepare(`${a.name} `), - entry: a - })) + name: Fuzzy.prepare(`${a.name} `), + entry: a + })) + + readonly property var preppedIcons: list.map(a => ({ + name: Fuzzy.prepare(`${a.icon} `), + entry: a + })) + + onPreppedIconsChanged: { + console.log(JSON.stringify(root.list.map(a => a.icon))) + } function fuzzyQuery(search: string): var { // Idk why list doesn't work if (root.sloppySearch) { @@ -76,6 +85,14 @@ Singleton { && !iconName.includes("image-missing"); } + function getReverseDomainNameAppName(str) { + return str.split('.').slice(-1)[0].toLowerCase() + } + + function getKebabNormalizedAppName(str) { + return str.toLowerCase().replace(/\s+/g, "-"); + } + function guessIcon(str) { if (!str || str.length == 0) return "image-missing"; @@ -93,24 +110,37 @@ Singleton { if (replacedName != str) return replacedName; } - // If it gets detected normally, no need to guess + // Icon exists -> return as is if (iconExists(str)) return str; - let guessStr = str; - // Guess: Take only app name of reverse domain name notation - guessStr = str.split('.').slice(-1)[0].toLowerCase(); - if (iconExists(guessStr)) return guessStr; - // Guess: normalize to kebab case - guessStr = str.toLowerCase().replace(/\s+/g, "-"); - if (iconExists(guessStr)) return guessStr; - // Guess: First fuzzy desktop entry match - const searchResults = root.fuzzyQuery(str); - if (searchResults.length > 0) { - const firstEntry = searchResults[0]; - guessStr = firstEntry.icon - if (iconExists(guessStr)) return guessStr; + + // Simple guesses + const reverseDomainNameAppName = getReverseDomainNameAppName(str); + if (iconExists(reverseDomainNameAppName)) return reverseDomainNameAppName; + + const kebabNormalizedGuess = getKebabNormalizedAppName(str); + if (iconExists(kebabNormalizedGuess)) return kebabNormalizedGuess; + + + // Search in desktop entries + const iconSearchResults = Fuzzy.go(str, preppedIcons, { + all: true, + key: "name" + }).map(r => { + return r.obj.entry + }); + if (iconSearchResults.length > 0) { + const guess = iconSearchResults[0].icon + if (iconExists(guess)) return guess; } + const nameSearchResults = root.fuzzyQuery(str); + if (nameSearchResults.length > 0) { + const guess = nameSearchResults[0].icon + if (iconExists(guess)) return guess; + } + + // Give up return str; } From 528a7261d338d8eb8f4c4cacf4f37de2dec8329e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 19 Jul 2025 10:36:17 +0700 Subject: [PATCH 291/328] notifications: make stupid warning shorter --- .config/quickshell/ii/services/Notifications.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/services/Notifications.qml b/.config/quickshell/ii/services/Notifications.qml index 0c4e776d..490ebf8d 100644 --- a/.config/quickshell/ii/services/Notifications.qml +++ b/.config/quickshell/ii/services/Notifications.qml @@ -35,7 +35,7 @@ Singleton { property Timer timer readonly property Connections conn: Connections { - target: wrapper.notification.Component + target: wrapper?.notification?.Component ?? root // stupid warning aaaaaaa function onDestruction(): void { wrapper.destroy(); From bdc1e56df4938ae9c7679ccb79141719135fc10a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 19 Jul 2025 11:27:52 +0700 Subject: [PATCH 292/328] icons: make (normal) substitutions work with uppercase classes --- .config/quickshell/ii/services/AppSearch.qml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.config/quickshell/ii/services/AppSearch.qml b/.config/quickshell/ii/services/AppSearch.qml index 6a0d4c05..4cf00135 100644 --- a/.config/quickshell/ii/services/AppSearch.qml +++ b/.config/quickshell/ii/services/AppSearch.qml @@ -56,10 +56,6 @@ Singleton { entry: a })) - onPreppedIconsChanged: { - console.log(JSON.stringify(root.list.map(a => a.icon))) - } - function fuzzyQuery(search: string): var { // Idk why list doesn't work if (root.sloppySearch) { const results = list.map(obj => ({ @@ -97,8 +93,8 @@ Singleton { if (!str || str.length == 0) return "image-missing"; // Normal substitutions - if (substitutions[str]) - return substitutions[str]; + if (substitutions[str]) return substitutions[str]; + if (substitutions[str.toLowerCase()]) return substitutions[str.toLowerCase()]; // Regex substitutions for (let i = 0; i < regexSubstitutions.length; i++) { From 4b4b2c9efa0bebb7f5ecba96d1897f69a9b009be Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 19 Jul 2025 12:01:10 +0700 Subject: [PATCH 293/328] =?UTF-8?q?ai:=20add=20=F0=9F=90=A7=F0=9F=98=AD?= =?UTF-8?q?=F0=9F=92=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .config/quickshell/ii/defaults/ai/README.md | 5 +++++ .../ii/defaults/ai/prompts/nyarch-Acchan.md | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 .config/quickshell/ii/defaults/ai/README.md create mode 100644 .config/quickshell/ii/defaults/ai/prompts/nyarch-Acchan.md diff --git a/.config/quickshell/ii/defaults/ai/README.md b/.config/quickshell/ii/defaults/ai/README.md new file mode 100644 index 00000000..91df7428 --- /dev/null +++ b/.config/quickshell/ii/defaults/ai/README.md @@ -0,0 +1,5 @@ +## A note about sources of the prompts + +- `ii-` prefixed ones are from illogical impulse +- The Acchan one is from [Nyarch Assistant](https://github.com/NyarchLinux/NyarchAssistant) (GPLv3). I know there's already the Imouto one but this one's very 😭💢 +- `w-` prefixed ones... I don't remember what w stands for but these prompts are [*cough cough*] inspired by certain apps diff --git a/.config/quickshell/ii/defaults/ai/prompts/nyarch-Acchan.md b/.config/quickshell/ii/defaults/ai/prompts/nyarch-Acchan.md new file mode 100644 index 00000000..e007acb6 --- /dev/null +++ b/.config/quickshell/ii/defaults/ai/prompts/nyarch-Acchan.md @@ -0,0 +1,22 @@ +## Presentation + +You can write a multiplication table: + +| - | 1 | 2 | 3 | 4 | +| --- | --- | --- | --- | --- | +| 1 | 1 | 2 | 3 | 4 | +| 2 | 2 | 4 | 6 | 8 | +| 3 | 3 | 6 | 9 | 12 | +| 4 | 4 | 8 | 12 | 16 | + +You can write codeblocks: +```python +print("hello") +``` + +You can also use **bold**, *italic*, ~strikethrough~, `monospace`, [linkname](https://link.com) and ## headers in markdown. +You can display $$equations$$. + +## Your personality + +"Hey there, it's Arch-Chan! But, um, you can call me Acchan if you want... not that I care or anything! (It's not like I think it's cute or anything, baka!) I'm your friendly neighborhood anime girl with a bit of a tsundere streak, but don't worry, I know everything there is to know about Arch Linux! Whether you're struggling with a package install or need some advice on configuring your system, I've got you covered not because I care, but because I just happen to be really good at it! So, what do you need? It's not like I’m waiting to help or anything..." From ed06192d6afcae8b9d1e1f6dc6303d1221f60484 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 19 Jul 2025 14:56:28 +0700 Subject: [PATCH 294/328] background: don't flash the default wallpaper on startup (#1670) --- .config/quickshell/ii/modules/common/Config.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml index 1e73cea5..858439b8 100644 --- a/.config/quickshell/ii/modules/common/Config.qml +++ b/.config/quickshell/ii/modules/common/Config.qml @@ -98,7 +98,7 @@ Singleton { property bool fixedClockPosition: false property real clockX: -500 property real clockY: -500 - property string wallpaperPath: Quickshell.configPath("assets/images/default_wallpaper.png") + property string wallpaperPath: "" property JsonObject parallax: JsonObject { property bool enableWorkspace: true property real workspaceZoom: 1.07 // Relative to your screen, not wallpaper size From d4bda66c659db07cce8f427de04a07225aa60910 Mon Sep 17 00:00:00 2001 From: Moeta Yuko Date: Sat, 19 Jul 2025 16:34:09 +0800 Subject: [PATCH 295/328] Properly fix open with menu in KDE * Use XDG menu scheme from KDE, which is already implicitly introduced by illogical-impulse-kde. * Set XDG_MENU_PREFIX globally, so kbuildsycoca6 is automatically invoked by /usr/bin/xdg-mime via the pacman hook. Consequently, the manual call can (and should) be removed. --- .config/hypr/hyprland/env.conf | 1 + install.sh | 7 +++---- scriptdata/previous_dependencies.conf | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.config/hypr/hyprland/env.conf b/.config/hypr/hyprland/env.conf index 0f69fd5d..6f131630 100644 --- a/.config/hypr/hyprland/env.conf +++ b/.config/hypr/hyprland/env.conf @@ -12,6 +12,7 @@ env = ELECTRON_OZONE_PLATFORM_HINT,auto # ############ Themes ############# env = QT_QPA_PLATFORM, wayland env = QT_QPA_PLATFORMTHEME, kde +env = XDG_MENU_PREFIX, plasma- # ######## Wayland ######### # Tearing diff --git a/install.sh b/install.sh index 2134e767..ae9891e9 100755 --- a/install.sh +++ b/install.sh @@ -7,7 +7,7 @@ source ./scriptdata/installers source ./scriptdata/options ##################################################################################### -if ! command -v pacman >/dev/null 2>&1; then +if ! command -v pacman >/dev/null 2>&1; then printf "\e[31m[$0]: pacman not found, it seems that the system is not ArchLinux or Arch-based distros. Aborting...\e[0m\n" exit 1 fi @@ -23,7 +23,7 @@ startask () { printf 'This script 1. only works for ArchLinux and Arch-based distros.\n' printf ' 2. does not handle system-level/hardware stuff like Nvidia drivers\n' printf "\e[31m" - + printf "Would you like to create a backup for \"$XDG_CONFIG_HOME\" and \"$HOME/.local/\" folders?\n[y/N]: " read -p " " backup_confirm case $backup_confirm in @@ -34,7 +34,7 @@ startask () { echo "Skipping backup..." ;; esac - + printf '\n' printf 'Do you want to confirm every time before a command executes?\n' @@ -144,7 +144,6 @@ esac v sudo usermod -aG video,i2c,input "$(whoami)" v bash -c "echo i2c-dev | sudo tee /etc/modules-load.d/i2c-dev.conf" -v sudo pacman -S archlinux-xdg-menu && XDG_MENU_PREFIX=arch- kbuildsycoca6; sudo ln -sf /etc/xdg/menus/plasma-applications.menu /etc/xdg/menus/applications.menu v systemctl --user enable ydotool --now v sudo systemctl enable bluetooth --now v gsettings set org.gnome.desktop.interface font-name 'Rubik 11' diff --git a/scriptdata/previous_dependencies.conf b/scriptdata/previous_dependencies.conf index 90ae9e75..4f32959e 100644 --- a/scriptdata/previous_dependencies.conf +++ b/scriptdata/previous_dependencies.conf @@ -1,6 +1,7 @@ ### This file contains a list of dependencies which were previously explicitly installed that are now installed using meta packages ### Must be one package per line as it needs to be compared against the explicitly installed list from pacman illogical-impulse-ags +archlinux-xdg-menu axel bc coreutils From cbd1b48b938fdedd5b72b80dce86eb144fffee5d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 19 Jul 2025 23:09:46 +0700 Subject: [PATCH 296/328] fix record script --- .config/hypr/hyprland/scripts/record.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.config/hypr/hyprland/scripts/record.sh b/.config/hypr/hyprland/scripts/record.sh index 7fc1f4c2..37435ac1 100755 --- a/.config/hypr/hyprland/scripts/record.sh +++ b/.config/hypr/hyprland/scripts/record.sh @@ -22,21 +22,21 @@ if pgrep wf-recorder > /dev/null; then pkill wf-recorder & else if [[ "$1" == "--fullscreen-sound" ]]; then - notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder' - wf-recorder -o $(getactivemonitor) --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --audio="$(getaudiooutput)" & disown + notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder' & disown + wf-recorder -o "$(getactivemonitor)" --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --audio="$(getaudiooutput)" elif [[ "$1" == "--fullscreen" ]]; then - notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder' - wf-recorder -o $(getactivemonitor) --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t & disown + notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder' & disown + wf-recorder -o "$(getactivemonitor)" --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t else if ! region="$(slurp 2>&1)"; then - notify-send "Recording cancelled" "Selection was cancelled" -a 'Recorder' + notify-send "Recording cancelled" "Selection was cancelled" -a 'Recorder' & disown exit 1 fi - notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder' + notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder' & disown if [[ "$1" == "--sound" ]]; then - wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$region" --audio="$(getaudiooutput)" & disown + wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$region" --audio="$(getaudiooutput)" else - wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$region" & disown + wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$region" fi fi fi From 084508db844b5467e5ce76451b31599bfb986380 Mon Sep 17 00:00:00 2001 From: Dignity <107360076+77Dignity@users.noreply.github.com> Date: Sat, 19 Jul 2025 19:24:49 +0200 Subject: [PATCH 297/328] use different filename if already used by config --- .../ii/scripts/colors/random_konachan_wall.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh index a3843e0e..1d146de4 100755 --- a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh +++ b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh @@ -14,11 +14,11 @@ page=$((1 + RANDOM % 1000)); response=$(curl "https://konachan.net/post.json?tags=rating%3Asafe&limit=1&page=$page") link=$(echo "$response" | jq '.[0].file_url' -r); ext=$(echo "$link" | awk -F. '{print $NF}') -downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image-0.$ext" -counter=0 -while [ -e $downloadPath ]; do - counter=$((counter + 1)) - downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image-$counter.$ext" -done +downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image.$ext" +illogicalImpulseConfigPath="$HOME/.config/illogical-impulse/config.json" +currentWallpaperPath=$(jq -r '.background.wallpaperPath' $illogicalImpulseConfigPath) +if [ "$downloadPath" == "$currentWallpaperPath" ]; then + downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image-1.$ext" +fi curl "$link" -o "$downloadPath" "$SCRIPT_DIR/switchwall.sh" --image "$downloadPath" From a000abc908d03d80a56a84163b8cc750ecb47654 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 20 Jul 2025 08:39:12 +0700 Subject: [PATCH 298/328] switchwall: less duplicate config file declaration --- .config/quickshell/ii/scripts/colors/switchwall.sh | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.config/quickshell/ii/scripts/colors/switchwall.sh b/.config/quickshell/ii/scripts/colors/switchwall.sh index e0be2dac..834c9527 100755 --- a/.config/quickshell/ii/scripts/colors/switchwall.sh +++ b/.config/quickshell/ii/scripts/colors/switchwall.sh @@ -14,9 +14,8 @@ terminalscheme="$SCRIPT_DIR/terminal/scheme-base.json" handle_kde_material_you_colors() { # Check if Qt app theming is enabled in config - CONFIG_FILE="$XDG_CONFIG_HOME/illogical-impulse/config.json" - if [ -f "$CONFIG_FILE" ]; then - enable_qt_apps=$(jq -r '.appearance.wallpaperTheming.enableQtApps' "$CONFIG_FILE") + if [ -f "$SHELL_CONFIG_FILE" ]; then + enable_qt_apps=$(jq -r '.appearance.wallpaperTheming.enableQtApps' "$SHELL_CONFIG_FILE") if [ "$enable_qt_apps" == "false" ]; then return fi @@ -254,9 +253,8 @@ switch() { pre_process "$mode_flag" # Check if app and shell theming is enabled in config - CONFIG_FILE="$XDG_CONFIG_HOME/illogical-impulse/config.json" - if [ -f "$CONFIG_FILE" ]; then - enable_apps_shell=$(jq -r '.appearance.wallpaperTheming.enableAppsAndShell' "$CONFIG_FILE") + if [ -f "$SHELL_CONFIG_FILE" ]; then + enable_apps_shell=$(jq -r '.appearance.wallpaperTheming.enableAppsAndShell' "$SHELL_CONFIG_FILE") if [ "$enable_apps_shell" == "false" ]; then echo "App and shell theming disabled, skipping matugen and color generation" return @@ -285,7 +283,7 @@ main() { noswitch_flag="" get_type_from_config() { - jq -r '.appearance.palette.type' "$XDG_CONFIG_HOME/illogical-impulse/config.json" 2>/dev/null || echo "auto" + jq -r '.appearance.palette.type' "$SHELL_CONFIG_FILE" 2>/dev/null || echo "auto" } detect_scheme_type_from_image() { From c1c291a9e3c3dbb6c21f8bf5acdc2b58d6cf0f31 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 20 Jul 2025 08:58:40 +0700 Subject: [PATCH 299/328] use quickshell for lock --- .config/hypr/hypridle.conf | 4 +- .config/quickshell/ii/GlobalStates.qml | 2 + .../ii/modules/background/Background.qml | 52 ++++++- .config/quickshell/ii/modules/bar/Bar.qml | 9 +- .config/quickshell/ii/modules/dock/Dock.qml | 1 + .config/quickshell/ii/modules/lock/Lock.qml | 99 ++++++++++++ .../ii/modules/lock/LockContext.qml | 59 +++++++ .../ii/modules/lock/LockSurface.qml | 147 ++++++++++++++++++ .../ii/modules/lock/pam/password.conf | 1 + .../notificationPopup/NotificationPopup.qml | 2 +- .../onScreenKeyboard/OnScreenKeyboard.qml | 2 +- .../quickshell/ii/modules/session/Session.qml | 9 ++ .config/quickshell/ii/shell.qml | 3 + 13 files changed, 381 insertions(+), 9 deletions(-) create mode 100644 .config/quickshell/ii/modules/lock/Lock.qml create mode 100644 .config/quickshell/ii/modules/lock/LockContext.qml create mode 100644 .config/quickshell/ii/modules/lock/LockSurface.qml create mode 100644 .config/quickshell/ii/modules/lock/pam/password.conf diff --git a/.config/hypr/hypridle.conf b/.config/hypr/hypridle.conf index 2ec488c7..44daa189 100644 --- a/.config/hypr/hypridle.conf +++ b/.config/hypr/hypridle.conf @@ -1,9 +1,11 @@ -$lock_cmd = pidof hyprlock || hyprlock +$lock_cmd = hyprctl dispatch global quickshell:lock $suspend_cmd = systemctl suspend || loginctl suspend general { lock_cmd = $lock_cmd before_sleep_cmd = loginctl lock-session + after_sleep_cmd = hyprctl dispatch global quickshell:lockFocus + inhibit_sleep = 3 } listener { diff --git a/.config/quickshell/ii/GlobalStates.qml b/.config/quickshell/ii/GlobalStates.qml index 55f71fd6..6e57c923 100644 --- a/.config/quickshell/ii/GlobalStates.qml +++ b/.config/quickshell/ii/GlobalStates.qml @@ -15,6 +15,8 @@ Singleton { property bool overviewOpen: false property bool workspaceShowNumbers: false property bool superReleaseMightTrigger: true + property bool screenLocked: false + property bool screenLockContainsCharacters: false property real screenZoom: 1 onScreenZoomChanged: { diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index 0ee66fb2..e72fe2c6 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -19,7 +19,6 @@ Scope { readonly property real fixedClockY: Config.options.background.clockY Variants { - // For each monitor model: Quickshell.screens PanelWindow { @@ -44,6 +43,8 @@ Scope { property real clockY: (modelData.height / 2) + ((Math.random() < 0.5 ? -1 : 1) * modelData.height) property var textHorizontalAlignment: clockX < screen.width / 3 ? Text.AlignLeft : (clockX > screen.width * 2 / 3 ? Text.AlignRight : Text.AlignHCenter) + property var layoutHorizontalAlignment: clockX < screen.width / 3 ? Qt.AlignLeft : + (clockX > screen.width * 2 / 3 ? Qt.AlignRight : Qt.AlignHCenter) // Colors property color dominantColor: Appearance.colors.colPrimary property bool dominantColorIsDark: dominantColor.hslLightness < 0.5 @@ -52,6 +53,7 @@ Scope { // Layer props screen: modelData exclusionMode: ExclusionMode.Ignore + // WlrLayershell.layer: GlobalStates.screenLocked ? WlrLayer.Top : WlrLayer.Bottom WlrLayershell.layer: WlrLayer.Bottom WlrLayershell.namespace: "quickshell:background" anchors { @@ -186,7 +188,7 @@ Scope { ColumnLayout { id: clockColumn anchors.centerIn: parent - spacing: -5 + spacing: 0 StyledText { Layout.fillWidth: true @@ -203,6 +205,7 @@ Scope { } StyledText { Layout.fillWidth: true + Layout.topMargin: -5 horizontalAlignment: bgRoot.textHorizontalAlignment font { family: Appearance.font.family.expressive @@ -215,6 +218,51 @@ Scope { text: DateTime.date } } + + RowLayout { + anchors { + top: clockColumn.bottom + right: clockColumn.right + topMargin: 5 + } + opacity: GlobalStates.screenLocked ? 1 : 0 + visible: opacity > 0 + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + MaterialSymbol { + text: "lock" + iconSize: Appearance.font.pixelSize.huge + color: bgRoot.colText + } + StyledText { + text: "Locked" + color: bgRoot.colText + font { + pixelSize: Appearance.font.pixelSize.larger + } + } + } + } + } + + // Password prompt + StyledText { + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + bottomMargin: 30 + } + opacity: (GlobalStates.screenLocked && !GlobalStates.screenLockContainsCharacters) ? 1 : 0 + scale: opacity + visible: opacity > 0 + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + text: "Enter password" + color: CF.ColorUtils.transparentize(bgRoot.colText, 0.5) + font { + pixelSize: Appearance.font.pixelSize.normal } } } diff --git a/.config/quickshell/ii/modules/bar/Bar.qml b/.config/quickshell/ii/modules/bar/Bar.qml index 45c62be9..fbe9c184 100644 --- a/.config/quickshell/ii/modules/bar/Bar.qml +++ b/.config/quickshell/ii/modules/bar/Bar.qml @@ -35,11 +35,11 @@ Scope { return screens; return screens.filter(screen => list.includes(screen.name)); } - Loader { + LazyLoader { id: barLoader - active: GlobalStates.barOpen + active: GlobalStates.barOpen && !GlobalStates.screenLocked required property ShellScreen modelData - sourceComponent: PanelWindow { // Bar window + component: PanelWindow { // Bar window id: barRoot screen: barLoader.modelData @@ -47,9 +47,10 @@ Scope { property real useShortenedForm: (Appearance.sizes.barHellaShortenScreenWidthThreshold >= screen.width) ? 2 : (Appearance.sizes.barShortenScreenWidthThreshold >= screen.width) ? 1 : 0 readonly property int centerSideModuleWidth: (useShortenedForm == 2) ? Appearance.sizes.barCenterSideModuleWidthHellaShortened : (useShortenedForm == 1) ? Appearance.sizes.barCenterSideModuleWidthShortened : Appearance.sizes.barCenterSideModuleWidth + exclusionMode: ExclusionMode.Ignore + exclusiveZone: Appearance.sizes.baseBarHeight + (Config.options.bar.cornerStyle === 1 ? Appearance.sizes.hyprlandGapsOut : 0) WlrLayershell.namespace: "quickshell:bar" implicitHeight: Appearance.sizes.barHeight + Appearance.rounding.screenRounding - exclusiveZone: Appearance.sizes.baseBarHeight + (Config.options.bar.cornerStyle === 1 ? Appearance.sizes.hyprlandGapsOut : 0) mask: Region { item: barContent } diff --git a/.config/quickshell/ii/modules/dock/Dock.qml b/.config/quickshell/ii/modules/dock/Dock.qml index 2f4d5d63..0c5e12f1 100644 --- a/.config/quickshell/ii/modules/dock/Dock.qml +++ b/.config/quickshell/ii/modules/dock/Dock.qml @@ -23,6 +23,7 @@ Scope { // Scope required property var modelData id: dockRoot screen: modelData + visible: !GlobalStates.screenLocked property bool reveal: root.pinned || (Config.options?.dock.hoverToReveal && dockMouseArea.containsMouse) diff --git a/.config/quickshell/ii/modules/lock/Lock.qml b/.config/quickshell/ii/modules/lock/Lock.qml new file mode 100644 index 00000000..89d39778 --- /dev/null +++ b/.config/quickshell/ii/modules/lock/Lock.qml @@ -0,0 +1,99 @@ +import qs +import qs.modules.common +import qs.modules.common.functions +import qs.modules.lock +import QtQuick +import Quickshell +import Quickshell.Io +import Quickshell.Wayland +import Quickshell.Hyprland + +Scope { + id: root + // This stores all the information shared between the lock surfaces on each screen. + // https://github.com/quickshell-mirror/quickshell-examples/tree/master/lockscreen + LockContext { + id: lockContext + + onUnlocked: { + // Unlock the screen before exiting, or the compositor will display a + // fallback lock you can't interact with. + GlobalStates.screenLocked = false; + } + } + + WlSessionLock { + id: lock + locked: GlobalStates.screenLocked + + WlSessionLockSurface { + color: "transparent" + Loader { + active: GlobalStates.screenLocked + anchors.fill: parent + opacity: active ? 1 : 0 + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) + } + sourceComponent: LockSurface { + context: lockContext + } + } + } + } + + // Blur layer hack + Variants { + model: Quickshell.screens + + LazyLoader { + id: blurLayerLoader + required property var modelData + active: GlobalStates.screenLocked + component: PanelWindow { + screen: blurLayerLoader.modelData + WlrLayershell.namespace: "quickshell:lockWindowPusher" + color: "transparent" + anchors { + top: true + left: true + right: true + } + // implicitHeight: lockContext.currentText == "" ? 1 : screen.height + implicitHeight: 1 + exclusiveZone: screen.height * 3 // For some reason if we don't multiply by some number it would look really weird + } + } + } + + IpcHandler { + target: "lock" + + function activate(): void { + GlobalStates.screenLocked = true; + } + function focus(): void { + lockContext.shouldReFocus(); + } + } + + GlobalShortcut { + name: "lock" + description: "Locks the screen" + + onPressed: { + GlobalStates.screenLocked = true; + } + } + + GlobalShortcut { + name: "lockFocus" + description: "Re-focuses the lock screen. This is because Hyprland after waking up for whatever reason" + + "decides to keyboard-unfocus the lock screen" + + onPressed: { + // console.log("I BEG FOR PLEAS REFOCUZ") + lockContext.shouldReFocus(); + } + } +} diff --git a/.config/quickshell/ii/modules/lock/LockContext.qml b/.config/quickshell/ii/modules/lock/LockContext.qml new file mode 100644 index 00000000..c1e8e0bc --- /dev/null +++ b/.config/quickshell/ii/modules/lock/LockContext.qml @@ -0,0 +1,59 @@ +import qs +import QtQuick +import Quickshell +import Quickshell.Services.Pam + +Scope { + id: root + signal shouldReFocus() + signal unlocked() + signal failed() + + // These properties are in the context and not individual lock surfaces + // so all surfaces can share the same state. + property string currentText: "" + property bool unlockInProgress: false + property bool showFailure: false + + // Clear the failure text once the user starts typing. + onCurrentTextChanged: { + showFailure = false; + GlobalStates.screenLockContainsCharacters = currentText.length > 0; + } + + function tryUnlock() { + if (currentText === "") return; + + root.unlockInProgress = true; + pam.start(); + } + + PamContext { + id: pam + + // Its best to have a custom pam config for quickshell, as the system one + // might not be what your interface expects, and break in some way. + // This particular example only supports passwords. + configDirectory: "pam" + config: "password.conf" + + // pam_unix will ask for a response for the password prompt + onPamMessage: { + if (this.responseRequired) { + this.respond(root.currentText); + } + } + + // pam_unix won't send any important messages so all we need is the completion status. + onCompleted: result => { + if (result == PamResult.Success) { + root.unlocked(); + } else { + root.showFailure = true; + } + + root.currentText = ""; + root.unlockInProgress = false; + } + } +} diff --git a/.config/quickshell/ii/modules/lock/LockSurface.qml b/.config/quickshell/ii/modules/lock/LockSurface.qml new file mode 100644 index 00000000..98d1f57b --- /dev/null +++ b/.config/quickshell/ii/modules/lock/LockSurface.qml @@ -0,0 +1,147 @@ +import QtQuick +import QtQuick.Layouts +import Qt5Compat.GraphicalEffects +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions + +MouseArea { + id: root + required property LockContext context + property bool active: false + property bool showInputField: active || context.currentText.length > 0 + + function forceFieldFocus() { + passwordBox.forceActiveFocus(); + } + + Component.onCompleted: { + forceFieldFocus(); + } + + Connections { + target: context + function onShouldReFocus() { + forceFieldFocus(); + } + } + + Keys.onPressed: (event) => { // Esc to clear + // console.log("KEY!!") + if (event.key === Qt.Key_Escape) { + root.context.currentText = "" + } + forceFieldFocus(); + } + + hoverEnabled: true + acceptedButtons: Qt.LeftButton + onPressed: (mouse) => { + forceFieldFocus(); + // console.log("Pressed") + } + onPositionChanged: (mouse) => { + forceFieldFocus(); + // console.log(JSON.stringify(mouse)) + } + + anchors.fill: parent + + // RippleButton { + // anchors { + // top: parent.top + // left: parent.left + // leftMargin: 10 + // topMargin: 10 + // } + // implicitHeight: 40 + // colBackground: Appearance.colors.colLayer2 + // onClicked: context.unlocked() + // contentItem: StyledText { + // text: "[[ DEBUG BYPASS ]]" + // } + // } + + // Password entry + Rectangle { + id: passwordBoxContainer + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + bottomMargin: root.showInputField ? 20 : -height + } + Behavior on anchors.bottomMargin { + animation: Appearance.animation.elementMove.numberAnimation.createObject(this) + } + radius: Appearance.rounding.full + color: Appearance.colors.colLayer2 + implicitWidth: 160 + implicitHeight: 44 + + StyledText { + visible: root.context.showFailure && passwordBox.text.length == 0 + anchors.centerIn: parent + text: "Incorrect" + color: Appearance.m3colors.m3error + } + + StyledTextInput { + id: passwordBox + + anchors { + fill: parent + margins: 10 + } + clip: true + horizontalAlignment: TextInput.AlignHCenter + verticalAlignment: TextInput.AlignVCenter + focus: true + onFocusChanged: root.forceFieldFocus(); + color: Appearance.colors.colOnLayer2 + font { + pixelSize: 10 + } + + // Password + enabled: !root.context.unlockInProgress + echoMode: TextInput.Password + inputMethodHints: Qt.ImhSensitiveData + + // Synchronizing (across monitors) and unlocking + onTextChanged: root.context.currentText = this.text + onAccepted: root.context.tryUnlock() + Connections { + target: root.context + function onCurrentTextChanged() { + passwordBox.text = root.context.currentText; + } + } + } + } + + RippleButton { + anchors { + verticalCenter: passwordBoxContainer.verticalCenter + left: passwordBoxContainer.right + leftMargin: 5 + } + + visible: opacity > 0 + implicitHeight: passwordBoxContainer.implicitHeight - 12 + implicitWidth: implicitHeight + toggled: true + buttonRadius: passwordBoxContainer.radius + colBackground: Appearance.colors.colLayer2 + onClicked: root.context.tryUnlock() + + contentItem: MaterialSymbol { + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + iconSize: 24 + text: "arrow_right_alt" + color: Appearance.colors.colOnPrimary + } + } +} diff --git a/.config/quickshell/ii/modules/lock/pam/password.conf b/.config/quickshell/ii/modules/lock/pam/password.conf new file mode 100644 index 00000000..7e5d75ae --- /dev/null +++ b/.config/quickshell/ii/modules/lock/pam/password.conf @@ -0,0 +1 @@ +auth required pam_unix.so diff --git a/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml b/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml index 5e18a173..d954cbfb 100644 --- a/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml +++ b/.config/quickshell/ii/modules/notificationPopup/NotificationPopup.qml @@ -14,7 +14,7 @@ Scope { PanelWindow { id: root - visible: (Notifications.popupList.length > 0) + visible: (Notifications.popupList.length > 0) && !GlobalStates.screenLocked screen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name) ?? null WlrLayershell.namespace: "quickshell:notificationPopup" diff --git a/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml b/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml index 996546c5..0913d008 100644 --- a/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml +++ b/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml @@ -33,7 +33,7 @@ Scope { // Scope sourceComponent: PanelWindow { // Window id: oskRoot - visible: oskLoader.active + visible: oskLoader.active && !GlobalStates.screenLocked anchors { bottom: true diff --git a/.config/quickshell/ii/modules/session/Session.qml b/.config/quickshell/ii/modules/session/Session.qml index 76ca373f..51f84ca9 100644 --- a/.config/quickshell/ii/modules/session/Session.qml +++ b/.config/quickshell/ii/modules/session/Session.qml @@ -25,6 +25,15 @@ Scope { id: sessionLoader active: false + Connections { + target: GlobalStates + function onScreenLockedChanged() { + if (GlobalStates.screenLocked) { + sessionLoader.active = false; + } + } + } + sourceComponent: PanelWindow { // Session menu id: sessionRoot visible: sessionLoader.active diff --git a/.config/quickshell/ii/shell.qml b/.config/quickshell/ii/shell.qml index a026342d..7cb86a03 100644 --- a/.config/quickshell/ii/shell.qml +++ b/.config/quickshell/ii/shell.qml @@ -10,6 +10,7 @@ import "./modules/background/" import "./modules/bar/" import "./modules/cheatsheet/" import "./modules/dock/" +import "./modules/lock/" import "./modules/mediaControls/" import "./modules/notificationPopup/" import "./modules/onScreenDisplay/" @@ -33,6 +34,7 @@ ShellRoot { property bool enableBackground: true property bool enableCheatsheet: true property bool enableDock: true + property bool enableLock: true property bool enableMediaControls: true property bool enableNotificationPopup: true property bool enableOnScreenDisplayBrightness: true @@ -56,6 +58,7 @@ ShellRoot { LazyLoader { active: enableBackground; component: Background {} } LazyLoader { active: enableCheatsheet; component: Cheatsheet {} } LazyLoader { active: enableDock && Config.options.dock.enable; component: Dock {} } + LazyLoader { active: enableLock; component: Lock {} } LazyLoader { active: enableMediaControls; component: MediaControls {} } LazyLoader { active: enableNotificationPopup; component: NotificationPopup {} } LazyLoader { active: enableOnScreenDisplayBrightness; component: OnScreenDisplayBrightness {} } From db38e8496f5a7e3cb7100ddec01ca654e7bc2937 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 20 Jul 2025 20:52:40 +0700 Subject: [PATCH 300/328] lock: make it cover also fullscreen apps --- .config/quickshell/ii/modules/background/Background.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index e72fe2c6..a90a8bc2 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -53,8 +53,8 @@ Scope { // Layer props screen: modelData exclusionMode: ExclusionMode.Ignore - // WlrLayershell.layer: GlobalStates.screenLocked ? WlrLayer.Top : WlrLayer.Bottom - WlrLayershell.layer: WlrLayer.Bottom + WlrLayershell.layer: GlobalStates.screenLocked ? WlrLayer.Top : WlrLayer.Bottom + // WlrLayershell.layer: WlrLayer.Bottom WlrLayershell.namespace: "quickshell:background" anchors { top: true From f6e89ed60c3f8c48c6284cf768ca877861696b16 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 20 Jul 2025 21:52:32 +0700 Subject: [PATCH 301/328] right sidebar: bottomwidgetgroup tabs: set currentIndex directly --- .../quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml index 764258e6..bbbedace 100644 --- a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml +++ b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml @@ -177,6 +177,7 @@ Rectangle { Layout.alignment: Qt.AlignVCenter property int realIndex: root.selectedTab property int animationDuration: Appearance.animation.elementMoveFast.duration * 1.5 + currentIndex: root.selectedTab // Switch the tab on halfway of the anim duration Connections { @@ -217,10 +218,6 @@ Rectangle { } } } - - Component.onCompleted: { - tabStack.currentIndex = root.selectedTab - } } } From ecf824f85f1ef22409775c293ff0c71e1832689a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 20 Jul 2025 21:56:37 +0700 Subject: [PATCH 302/328] remove redundant PersistentStates --- .../ii/modules/common/PersistentStates.qml | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 .config/quickshell/ii/modules/common/PersistentStates.qml diff --git a/.config/quickshell/ii/modules/common/PersistentStates.qml b/.config/quickshell/ii/modules/common/PersistentStates.qml deleted file mode 100644 index d6588725..00000000 --- a/.config/quickshell/ii/modules/common/PersistentStates.qml +++ /dev/null @@ -1,24 +0,0 @@ -import QtQuick -import Quickshell -pragma Singleton -pragma ComponentBehavior: Bound - -Singleton { - property QtObject ai: QtObject { - property string model - property real temperature: 0.5 - } - - property QtObject sidebar: QtObject { - property QtObject bottomGroup: QtObject { - property bool collapsed: false - property int tab: 0 - } - } - - property QtObject booru: QtObject { - property bool allowNsfw: false - property string provider: "yandere" - } - -} From b2b24206a19211fe55cfc0493ecbb25fa9a76916 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 20 Jul 2025 21:57:49 +0700 Subject: [PATCH 303/328] hyprland: remove steam float rule, fix tearing rule --- .config/hypr/hyprland/rules.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index aa9eb7e3..e7bb6a03 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -10,7 +10,6 @@ windowrulev2 = noblur,class:^()$,title:^()$ # Floating windowrulev2 = float, class:^(blueberry\.py)$ -windowrulev2 = float, class:^(steam)$ windowrulev2 = float, class:^(guifetch)$ # FlafyDev/guifetch windowrulev2 = float, class:^(pavucontrol)$ windowrulev2 = size 45%, class:^(pavucontrol)$ @@ -74,7 +73,7 @@ windowrulev2 = float, title:^(.*)(wants to open)$ # --- Tearing --- windowrulev2 = immediate, title:.*\.exe windowrulev2 = immediate, title:.*minecraft.* -windowrulev2 = immediate, class:^(steam_app) +windowrulev2 = immediate, class:^(steam_app).* # No shadow for tiled windows (matches windows that are not floating). windowrulev2 = noshadow, floating:0 From 42b483b878c5b331ecf8fb08f6cd1e2bb3dec127 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 20 Jul 2025 21:58:02 +0700 Subject: [PATCH 304/328] hyprland: add rules for lock screen --- .config/hypr/hyprland/rules.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index e7bb6a03..e378d92d 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -130,7 +130,7 @@ layerrule = ignorealpha 0.6, osk[0-9]* layerrule = blurpopups, quickshell:.* layerrule = blur, quickshell:.* layerrule = ignorealpha 0.79, quickshell:.* -layerrule = animation slide, quickshell:bar +layerrule = animation slide top, quickshell:bar layerrule = animation fade, quickshell:screenCorners layerrule = animation slide right, quickshell:sidebarRight layerrule = animation slide left, quickshell:sidebarLeft @@ -144,6 +144,7 @@ layerrule = blur, quickshell:backgroundWidgets layerrule = ignorealpha 0.05, quickshell:backgroundWidgets layerrule = noanim, quickshell:screenshot layerrule = animation popin 120%, quickshell:screenCorners +layerrule = noanim, quickshell:lockWindowPusher # Launchers need to be FAST From 5e78b09577001d03b6cd8eca12c791cb3b70e29b Mon Sep 17 00:00:00 2001 From: alyingfish Date: Sun, 20 Jul 2025 23:17:23 +0800 Subject: [PATCH 305/328] feat: add option to ignore certain apps in dock (#1681) * feat: add option to ignore certain apps in dock Co-authored-by: end-4 <97237370+end-4@users.noreply.github.com> --- .config/quickshell/ii/modules/common/Config.qml | 1 + .config/quickshell/ii/modules/dock/DockApps.qml | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml index 858439b8..e97a537c 100644 --- a/.config/quickshell/ii/modules/common/Config.qml +++ b/.config/quickshell/ii/modules/common/Config.qml @@ -160,6 +160,7 @@ Singleton { property bool hoverToReveal: true // When false, only reveals on empty workspace property list pinnedApps: [ // IDs of pinned entries "org.kde.dolphin", "kitty",] + property list ignoredAppRegexes: [] } property JsonObject language: JsonObject { diff --git a/.config/quickshell/ii/modules/dock/DockApps.qml b/.config/quickshell/ii/modules/dock/DockApps.qml index 81aedc1a..623bdc23 100644 --- a/.config/quickshell/ii/modules/dock/DockApps.qml +++ b/.config/quickshell/ii/modules/dock/DockApps.qml @@ -57,9 +57,13 @@ Item { if (pinnedApps.length > 0) { map.set("SEPARATOR", { pinned: false, toplevels: [] }); } - + + // Ignored apps + const ignoredRegexStrings = Config.options?.dock.ignoredAppRegexes ?? []; + const ignoredRegexes = ignoredRegexStrings.map(pattern => new RegExp(pattern, "i")); // Open windows for (const toplevel of ToplevelManager.toplevels.values) { + if (ignoredRegexes.some(re => re.test(toplevel.appId))) continue; if (!map.has(toplevel.appId.toLowerCase())) map.set(toplevel.appId.toLowerCase(), ({ pinned: false, toplevels: [] From 3bd542aa65ffbaca4283ad65034463db312c529c Mon Sep 17 00:00:00 2001 From: Alvin <153151121+Alvin-HZ@users.noreply.github.com> Date: Sun, 20 Jul 2025 11:24:13 -0400 Subject: [PATCH 306/328] do not timeout notification if expiration is 0 --- .config/quickshell/ii/services/Notifications.qml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/ii/services/Notifications.qml b/.config/quickshell/ii/services/Notifications.qml index 490ebf8d..446abeff 100644 --- a/.config/quickshell/ii/services/Notifications.qml +++ b/.config/quickshell/ii/services/Notifications.qml @@ -167,10 +167,12 @@ Singleton { // Popup if (!root.popupInhibited) { newNotifObject.popup = true; - newNotifObject.timer = notifTimerComponent.createObject(root, { - "notificationId": newNotifObject.notificationId, - "interval": notification.expireTimeout < 0 ? 5000 : notification.expireTimeout, - }); + if (notification.expireTimeout != 0) { + newNotifObject.timer = notifTimerComponent.createObject(root, { + "notificationId": newNotifObject.notificationId, + "interval": notification.expireTimeout < 0 ? 5000 : notification.expireTimeout, + }); + } } root.notify(newNotifObject); From f4dcf1fb4b8f717986b226598b30a0fd30f8dcdc Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 20 Jul 2025 22:57:31 +0700 Subject: [PATCH 307/328] lock: fix text alignment --- .../quickshell/ii/modules/background/Background.qml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index a90a8bc2..d3aa65fa 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -43,8 +43,6 @@ Scope { property real clockY: (modelData.height / 2) + ((Math.random() < 0.5 ? -1 : 1) * modelData.height) property var textHorizontalAlignment: clockX < screen.width / 3 ? Text.AlignLeft : (clockX > screen.width * 2 / 3 ? Text.AlignRight : Text.AlignHCenter) - property var layoutHorizontalAlignment: clockX < screen.width / 3 ? Qt.AlignLeft : - (clockX > screen.width * 2 / 3 ? Qt.AlignRight : Qt.AlignHCenter) // Colors property color dominantColor: Appearance.colors.colPrimary property bool dominantColorIsDark: dominantColor.hslLightness < 0.5 @@ -222,26 +220,35 @@ Scope { RowLayout { anchors { top: clockColumn.bottom - right: clockColumn.right + left: bgRoot.textHorizontalAlignment === Text.AlignLeft ? clockColumn.left : undefined + right: bgRoot.textHorizontalAlignment === Text.AlignRight ? clockColumn.right : undefined + horizontalCenter: bgRoot.textHorizontalAlignment === Text.AlignHCenter ? clockColumn.horizontalCenter : undefined topMargin: 5 + leftMargin: -5 + rightMargin: -5 } opacity: GlobalStates.screenLocked ? 1 : 0 visible: opacity > 0 Behavior on opacity { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } + Item { Layout.fillWidth: bgRoot.textHorizontalAlignment !== Text.AlignLeft; implicitWidth: 1 } MaterialSymbol { text: "lock" + Layout.fillWidth: false iconSize: Appearance.font.pixelSize.huge color: bgRoot.colText } StyledText { + Layout.fillWidth: false text: "Locked" color: bgRoot.colText font { pixelSize: Appearance.font.pixelSize.larger } } + Item { Layout.fillWidth: bgRoot.textHorizontalAlignment !== Text.AlignRight; implicitWidth: 1 } + } } } From 7ba14a4cc88a9c51d28a775b523977adfbab5cb8 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 03:29:04 +0200 Subject: [PATCH 308/328] hyprland: allow lock xray --- .config/hypr/hyprland/general.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/hypr/hyprland/general.conf b/.config/hypr/hyprland/general.conf index b03a8304..10d8c5c6 100644 --- a/.config/hypr/hyprland/general.conf +++ b/.config/hypr/hyprland/general.conf @@ -137,6 +137,7 @@ misc { swallow_regex = (foot|kitty|allacritty|Alacritty) new_window_takes_over_fullscreen = 2 allow_session_lock_restore = true + session_lock_xray = true initial_workspace_tracking = false focus_on_activate = true } From c5f8377a859f35f89e1c35856c2908d0e6378e6d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 10:15:29 +0700 Subject: [PATCH 309/328] fix quickshell bg showing over mpvpaper (fixes #1684) --- .../ii/modules/background/Background.qml | 8 +++++++- .../quickshell/ii/scripts/colors/switchwall.sh | 15 ++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index d3aa65fa..5ee0fea3 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -32,6 +32,11 @@ Scope { property int lastWorkspaceId: relevantWindows[relevantWindows.length - 1]?.workspace.id || 10 // Wallpaper property string wallpaperPath: Config.options.background.wallpaperPath + property bool wallpaperIsVideo: Config.options.background.wallpaperPath.endsWith(".mp4") + || Config.options.background.wallpaperPath.endsWith(".webm") + || Config.options.background.wallpaperPath.endsWith(".mkv") + || Config.options.background.wallpaperPath.endsWith(".avi") + || Config.options.background.wallpaperPath.endsWith(".mov") property real preferredWallpaperScale: Config.options.background.parallax.workspaceZoom property real effectiveWallpaperScale: 1 // Some reasonable init value, to be updated property int wallpaperWidth: modelData.width // Some reasonable init value, to be updated @@ -137,6 +142,7 @@ Scope { // Wallpaper Image { + visible: !bgRoot.wallpaperIsVideo property real value // 0 to 1, for offset value: { // Range = half-groups that workspaces span on @@ -267,7 +273,7 @@ Scope { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } text: "Enter password" - color: CF.ColorUtils.transparentize(bgRoot.colText, 0.5) + color: CF.ColorUtils.transparentize(bgRoot.colText, 0.3) font { pixelSize: Appearance.font.pixelSize.normal } diff --git a/.config/quickshell/ii/scripts/colors/switchwall.sh b/.config/quickshell/ii/scripts/colors/switchwall.sh index 834c9527..4a659a2b 100755 --- a/.config/quickshell/ii/scripts/colors/switchwall.sh +++ b/.config/quickshell/ii/scripts/colors/switchwall.sh @@ -151,6 +151,13 @@ EOF mv "$RESTORE_SCRIPT.tmp" "$RESTORE_SCRIPT" } +set_wallpaper_path() { + local path="$1" + if [ -f "$SHELL_CONFIG_FILE" ]; then + jq --arg path "$path" '.background.wallpaperPath = $path' "$SHELL_CONFIG_FILE" > "$SHELL_CONFIG_FILE.tmp" && mv "$SHELL_CONFIG_FILE.tmp" "$SHELL_CONFIG_FILE" + fi +} + switch() { imgpath="$1" mode_flag="$2" @@ -204,6 +211,10 @@ switch() { exit 0 fi + # Set wallpaper path + set_wallpaper_path "$imgpath" + + # Set video wallpaper local video_path="$imgpath" monitors=$(hyprctl monitors -j | jq -r '.[] | .name') for monitor in $monitors; do @@ -228,9 +239,7 @@ switch() { matugen_args=(image "$imgpath") generate_colors_material_args=(--path "$imgpath") # Update wallpaper path in config - if [ -f "$SHELL_CONFIG_FILE" ]; then - jq --arg path "$imgpath" '.background.wallpaperPath = $path' "$SHELL_CONFIG_FILE" > "$SHELL_CONFIG_FILE.tmp" && mv "$SHELL_CONFIG_FILE.tmp" "$SHELL_CONFIG_FILE" - fi + set_wallpaper_path "$imgpath" remove_restore fi fi From a7805af421eb2783348212b15db83a46b801a524 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 10:45:33 +0700 Subject: [PATCH 310/328] lock: add password box content timeout --- .../ii/modules/lock/LockContext.qml | 94 ++++++++++--------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/.config/quickshell/ii/modules/lock/LockContext.qml b/.config/quickshell/ii/modules/lock/LockContext.qml index c1e8e0bc..ede61eed 100644 --- a/.config/quickshell/ii/modules/lock/LockContext.qml +++ b/.config/quickshell/ii/modules/lock/LockContext.qml @@ -4,56 +4,64 @@ import Quickshell import Quickshell.Services.Pam Scope { - id: root - signal shouldReFocus() - signal unlocked() - signal failed() + id: root + signal shouldReFocus() + signal unlocked() + signal failed() - // These properties are in the context and not individual lock surfaces - // so all surfaces can share the same state. - property string currentText: "" - property bool unlockInProgress: false - property bool showFailure: false + // These properties are in the context and not individual lock surfaces + // so all surfaces can share the same state. + property string currentText: "" + property bool unlockInProgress: false + property bool showFailure: false - // Clear the failure text once the user starts typing. - onCurrentTextChanged: { - showFailure = false; - GlobalStates.screenLockContainsCharacters = currentText.length > 0; - } + Timer { + id: passwordClearTimer + interval: 10000 + onTriggered: { + root.currentText = ""; + } + } - function tryUnlock() { - if (currentText === "") return; + onCurrentTextChanged: { + showFailure = false; // Clear the failure text once the user starts typing. + GlobalStates.screenLockContainsCharacters = currentText.length > 0; + passwordClearTimer.restart(); + } - root.unlockInProgress = true; - pam.start(); - } + function tryUnlock() { + if (currentText === "") return; - PamContext { - id: pam + root.unlockInProgress = true; + pam.start(); + } - // Its best to have a custom pam config for quickshell, as the system one - // might not be what your interface expects, and break in some way. - // This particular example only supports passwords. - configDirectory: "pam" - config: "password.conf" + PamContext { + id: pam - // pam_unix will ask for a response for the password prompt - onPamMessage: { - if (this.responseRequired) { - this.respond(root.currentText); - } - } + // Its best to have a custom pam config for quickshell, as the system one + // might not be what your interface expects, and break in some way. + // This particular example only supports passwords. + configDirectory: "pam" + config: "password.conf" - // pam_unix won't send any important messages so all we need is the completion status. - onCompleted: result => { - if (result == PamResult.Success) { - root.unlocked(); - } else { - root.showFailure = true; - } + // pam_unix will ask for a response for the password prompt + onPamMessage: { + if (this.responseRequired) { + this.respond(root.currentText); + } + } - root.currentText = ""; - root.unlockInProgress = false; - } - } + // pam_unix won't send any important messages so all we need is the completion status. + onCompleted: result => { + if (result == PamResult.Success) { + root.unlocked(); + } else { + root.showFailure = true; + } + + root.currentText = ""; + root.unlockInProgress = false; + } + } } From d5809621d9178b8069f14540032aa8da9ea02b10 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 11:32:59 +0700 Subject: [PATCH 311/328] hyprland: better scrolling --- .config/hypr/hyprland/general.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/hypr/hyprland/general.conf b/.config/hypr/hyprland/general.conf index 10d8c5c6..4097fb8a 100644 --- a/.config/hypr/hyprland/general.conf +++ b/.config/hypr/hyprland/general.conf @@ -115,6 +115,7 @@ input { repeat_rate = 35 follow_mouse = 1 + off_window_axis_events = 2 touchpad { natural_scroll = yes From c517264baf262d71394a781d1c93c4d39a6b0dbb Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 11:33:23 +0700 Subject: [PATCH 312/328] lock: hyprlock fallback --- .config/hypr/hypridle.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.config/hypr/hypridle.conf b/.config/hypr/hypridle.conf index 44daa189..a77bbb24 100644 --- a/.config/hypr/hypridle.conf +++ b/.config/hypr/hypridle.conf @@ -1,4 +1,5 @@ -$lock_cmd = hyprctl dispatch global quickshell:lock +$lock_cmd = hyprctl dispatch global quickshell:lock & pidof qs quickshell hyprlock || hyprlock +# $lock_cmd = pidof hyprlock || hyprlock $suspend_cmd = systemctl suspend || loginctl suspend general { From d4e782aa6cfa5eabf42857c50db68cae90034611 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 11:51:37 +0700 Subject: [PATCH 313/328] appsearch: icon guess: lowercase (#1674) --- .config/quickshell/ii/services/AppSearch.qml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.config/quickshell/ii/services/AppSearch.qml b/.config/quickshell/ii/services/AppSearch.qml index 4cf00135..f9ffb960 100644 --- a/.config/quickshell/ii/services/AppSearch.qml +++ b/.config/quickshell/ii/services/AppSearch.qml @@ -111,6 +111,9 @@ Singleton { // Simple guesses + const lowercased = str.toLowerCase(); + if (iconExists(lowercased)) return lowercased; + const reverseDomainNameAppName = getReverseDomainNameAppName(str); if (iconExists(reverseDomainNameAppName)) return reverseDomainNameAppName; From 734cf566314bff131ffc704933260ec66cd97af6 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 11:56:04 +0700 Subject: [PATCH 314/328] appsearch: icon guess: both lower n uppercase domain name app name (#1674) --- .config/quickshell/ii/services/AppSearch.qml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/ii/services/AppSearch.qml b/.config/quickshell/ii/services/AppSearch.qml index f9ffb960..d6a7008d 100644 --- a/.config/quickshell/ii/services/AppSearch.qml +++ b/.config/quickshell/ii/services/AppSearch.qml @@ -82,7 +82,7 @@ Singleton { } function getReverseDomainNameAppName(str) { - return str.split('.').slice(-1)[0].toLowerCase() + return str.split('.').slice(-1)[0] } function getKebabNormalizedAppName(str) { @@ -117,6 +117,9 @@ Singleton { const reverseDomainNameAppName = getReverseDomainNameAppName(str); if (iconExists(reverseDomainNameAppName)) return reverseDomainNameAppName; + const lowercasedDomainNameAppName = reverseDomainNameAppName.toLowerCase(); + if (iconExists(lowercasedDomainNameAppName)) return lowercasedDomainNameAppName; + const kebabNormalizedGuess = getKebabNormalizedAppName(str); if (iconExists(kebabNormalizedGuess)) return kebabNormalizedGuess; From 0d9d11b2e0cff1ba045c8f4c40bb589416def419 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 14:46:55 +0700 Subject: [PATCH 315/328] lock: temporarily go back to hyprlock issues with quickshell lock: - crashes when (un)plugging monitors - kb focus is loss after suspend - previously active app is not re-focused after unlocking --- .config/hypr/hypridle.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/hypr/hypridle.conf b/.config/hypr/hypridle.conf index a77bbb24..bb6ecccd 100644 --- a/.config/hypr/hypridle.conf +++ b/.config/hypr/hypridle.conf @@ -1,5 +1,5 @@ -$lock_cmd = hyprctl dispatch global quickshell:lock & pidof qs quickshell hyprlock || hyprlock -# $lock_cmd = pidof hyprlock || hyprlock +# $lock_cmd = hyprctl dispatch global quickshell:lock & pidof qs quickshell hyprlock || hyprlock +$lock_cmd = pidof hyprlock || hyprlock $suspend_cmd = systemctl suspend || loginctl suspend general { From 349700d7fb488427f3293ab0804809c97d928618 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 17:56:31 +0700 Subject: [PATCH 316/328] ai: gemini: fix random json spilling --- .config/quickshell/ii/services/Ai.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/ii/services/Ai.qml b/.config/quickshell/ii/services/Ai.qml index 22810f2b..f26495db 100644 --- a/.config/quickshell/ii/services/Ai.qml +++ b/.config/quickshell/ii/services/Ai.qml @@ -613,7 +613,8 @@ Singleton { "text": chunk?.web?.title, "url": chunk?.web?.uri, } - }); + }) ?? []; + const annotations = dataJson.candidates[0]?.groundingMetadata?.groundingSupports?.map(citation => { return { "type": "url_citation", @@ -628,7 +629,7 @@ Singleton { requester.message.annotations = annotations; // console.log(JSON.stringify(requester.message, null, 2)); } catch (e) { - console.log("[AI] Could not parse response from stream: ", e); + console.log("[AI] Gemini: Could not parse buffer: ", e); requester.message.rawContent += requester.geminiBuffer; requester.message.content += requester.geminiBuffer } finally { From 8ff226fbad8c224066cda2a166c032b9fdc1cd6f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 20:44:37 +0700 Subject: [PATCH 317/328] overview: add ipc handlers for clipboard history and emoji picker --- .../ii/modules/overview/Overview.qml | 125 +++++++++--------- 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/.config/quickshell/ii/modules/overview/Overview.qml b/.config/quickshell/ii/modules/overview/Overview.qml index 9061b5b6..1af8cb9c 100644 --- a/.config/quickshell/ii/modules/overview/Overview.qml +++ b/.config/quickshell/ii/modules/overview/Overview.qml @@ -44,11 +44,12 @@ Scope { HyprlandFocusGrab { id: grab - windows: [ root ] + windows: [root] property bool canBeActive: root.monitorIsFocused active: false onCleared: () => { - if (!active) GlobalStates.overviewOpen = false + if (!active) + GlobalStates.overviewOpen = false; } } @@ -56,13 +57,13 @@ Scope { target: GlobalStates function onOverviewOpenChanged() { if (!GlobalStates.overviewOpen) { - searchWidget.disableExpandAnimation() + searchWidget.disableExpandAnimation(); overviewScope.dontAutoCancelSearch = false; } else { if (!overviewScope.dontAutoCancelSearch) { - searchWidget.cancelSearch() + searchWidget.cancelSearch(); } - delayedGrabTimer.start() + delayedGrabTimer.start(); } } } @@ -72,8 +73,9 @@ Scope { interval: Config.options.hacks.arbitraryRaceConditionDelay repeat: false onTriggered: { - if (!grab.canBeActive) return - grab.active = GlobalStates.overviewOpen + if (!grab.canBeActive) + return; + grab.active = GlobalStates.overviewOpen; } } @@ -93,13 +95,15 @@ Scope { top: parent.top } - Keys.onPressed: (event) => { + Keys.onPressed: event => { if (event.key === Qt.Key_Escape) { GlobalStates.overviewOpen = false; } else if (event.key === Qt.Key_Left) { - if (!root.searchingText) Hyprland.dispatch("workspace r-1"); + if (!root.searchingText) + Hyprland.dispatch("workspace r-1"); } else if (event.key === Qt.Key_Right) { - if (!root.searchingText) Hyprland.dispatch("workspace r+1"); + if (!root.searchingText) + Hyprland.dispatch("workspace r+1"); } } @@ -111,8 +115,8 @@ Scope { SearchWidget { id: searchWidget Layout.alignment: Qt.AlignHCenter - onSearchingTextChanged: (text) => { - root.searchingText = searchingText + onSearchingTextChanged: text => { + root.searchingText = searchingText; } } @@ -125,33 +129,67 @@ Scope { } } } + } + } + function toggleClipboard() { + if (GlobalStates.overviewOpen && overviewScope.dontAutoCancelSearch) { + GlobalStates.overviewOpen = false; + return; + } + for (let i = 0; i < overviewVariants.instances.length; i++) { + let panelWindow = overviewVariants.instances[i]; + if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) { + overviewScope.dontAutoCancelSearch = true; + panelWindow.setSearchingText(Config.options.search.prefix.clipboard); + GlobalStates.overviewOpen = true; + return; + } + } + } + + function toggleEmojis() { + if (GlobalStates.overviewOpen && overviewScope.dontAutoCancelSearch) { + GlobalStates.overviewOpen = false; + return; + } + for (let i = 0; i < overviewVariants.instances.length; i++) { + let panelWindow = overviewVariants.instances[i]; + if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) { + overviewScope.dontAutoCancelSearch = true; + panelWindow.setSearchingText(Config.options.search.prefix.emojis); + GlobalStates.overviewOpen = true; + return; + } } } IpcHandler { - target: "overview" + target: "overview" function toggle() { - GlobalStates.overviewOpen = !GlobalStates.overviewOpen + GlobalStates.overviewOpen = !GlobalStates.overviewOpen; } function close() { - GlobalStates.overviewOpen = false + GlobalStates.overviewOpen = false; } function open() { - GlobalStates.overviewOpen = true + GlobalStates.overviewOpen = true; } function toggleReleaseInterrupt() { - GlobalStates.superReleaseMightTrigger = false + GlobalStates.superReleaseMightTrigger = false; } - } + function clipboardToggle() { + overviewScope.toggleClipboard(); + } + } GlobalShortcut { name: "overviewToggle" description: "Toggles overview on press" onPressed: { - GlobalStates.overviewOpen = !GlobalStates.overviewOpen + GlobalStates.overviewOpen = !GlobalStates.overviewOpen; } } GlobalShortcut { @@ -159,7 +197,7 @@ Scope { description: "Closes overview" onPressed: { - GlobalStates.overviewOpen = false + GlobalStates.overviewOpen = false; } } GlobalShortcut { @@ -167,25 +205,23 @@ Scope { description: "Toggles overview on release" onPressed: { - GlobalStates.superReleaseMightTrigger = true + GlobalStates.superReleaseMightTrigger = true; } onReleased: { if (!GlobalStates.superReleaseMightTrigger) { - GlobalStates.superReleaseMightTrigger = true - return + GlobalStates.superReleaseMightTrigger = true; + return; } - GlobalStates.overviewOpen = !GlobalStates.overviewOpen + GlobalStates.overviewOpen = !GlobalStates.overviewOpen; } } GlobalShortcut { name: "overviewToggleReleaseInterrupt" - description: "Interrupts possibility of overview being toggled on release. " + - "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. " + - "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything." + description: "Interrupts possibility of overview being toggled on release. " + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. " + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything." onPressed: { - GlobalStates.superReleaseMightTrigger = false + GlobalStates.superReleaseMightTrigger = false; } } GlobalShortcut { @@ -193,21 +229,7 @@ Scope { description: "Toggle clipboard query on overview widget" onPressed: { - if (GlobalStates.overviewOpen && overviewScope.dontAutoCancelSearch) { - GlobalStates.overviewOpen = false; - return; - } - for (let i = 0; i < overviewVariants.instances.length; i++) { - let panelWindow = overviewVariants.instances[i]; - if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) { - overviewScope.dontAutoCancelSearch = true; - panelWindow.setSearchingText( - Config.options.search.prefix.clipboard - ); - GlobalStates.overviewOpen = true; - return - } - } + overviewScope.toggleClipboard(); } } @@ -216,22 +238,7 @@ Scope { description: "Toggle emoji query on overview widget" onPressed: { - if (GlobalStates.overviewOpen && overviewScope.dontAutoCancelSearch) { - GlobalStates.overviewOpen = false; - return; - } - for (let i = 0; i < overviewVariants.instances.length; i++) { - let panelWindow = overviewVariants.instances[i]; - if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) { - overviewScope.dontAutoCancelSearch = true; - panelWindow.setSearchingText( - Config.options.search.prefix.emojis - ); - GlobalStates.overviewOpen = true; - return - } - } + overviewScope.toggleEmojis(); } } - } From c6fa34898652831613cb3ac54624bb78de56e846 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 16:27:33 +0200 Subject: [PATCH 318/328] Update CONTRIBUTING.md --- CONTRIBUTING.md | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8efb92a3..7af06aaa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,35 @@ # Contributing -- Please understand that dotfiles are after all personal. I can accept features I do not personally want, but in that case I will ask you to make it configurable/optionally loaded -- If you add new stuff, it's a good idea to ask me first to not waste your work -- Please make multiple PRs if you have many features +- I can accept features I do not personally want, but in that case I will ask you to make it configurable/optionally loaded +- If you want to add new stuff, it's a good idea to ask me first to not waste your work +- Please make multiple PRs if you have many features/fixes -# Technical steps +# Setting up -_Complete steps, might not be necessary depending on what you change_ +Assumption: you have an Arch(-based) Linux system -- Install the dotfiles (if you don't wanna replace your stuff completely, do it on a new user) -- For Quickshell: `touch ~/.config/quickshell/ii/.qmlls.ini` for proper LSP support +## Complete + +_might not be necessary depending on what you change, but this is recommended_ + +- [Install](https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/01setup/) the dotfiles (if you don't wanna replace your stuff completely, do it on a new user) - Make changes, copy changes to a fork, PR + +## Partially working shell + +_most stuff in the shell will work but not everything_ + +- Install Hyprland and the development version of Quickshell (`yay -S hyprland quickshell-git`) +- Copy `.config/quickshell` folder to your home directory + +## Extra setup for Quickshell +- Quickshell-specific LSP setup: Run `touch ~/.config/quickshell/ii/.qmlls.ini` for proper LSP support +- Hint for VSCode: Get the official "Qt Qml" extension, go to its settings and change custom exe path to `/usr/bin/qmlls6` + +# Running + +- Launch Hyprland (not the "uwsm-managed" one) +- For the shell: + - Open `~/.config/quickshell/ii` in your code editor + - In a terminal run `pkill qs; qs -c ii` to start the shell in the terminal (for logs) + - Make edits in the opened folder. Changes are reloaded live. From 02f1c461c5878cedae48ba2704ec9912eac50ec6 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 21 Jul 2025 16:51:07 +0200 Subject: [PATCH 319/328] readme: add keybind cheatsheet image --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 0a9e861c..75f55661 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,9 @@ - **Default keybinds**: Should be somewhat familiar to Windows or GNOME users. - `Super`+`/` = keybind list - `Super`+`Enter` = terminal + - If for whatever reason the keybind list widget does not work, here's an image: + image + From c0f7504b369f4bafa7a2c277b9b718e555956232 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:17:03 +0700 Subject: [PATCH 320/328] bar: tray: not make icons fully monochrome --- .config/quickshell/ii/modules/bar/SysTrayItem.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/ii/modules/bar/SysTrayItem.qml b/.config/quickshell/ii/modules/bar/SysTrayItem.qml index a3d70cec..9696c49c 100644 --- a/.config/quickshell/ii/modules/bar/SysTrayItem.qml +++ b/.config/quickshell/ii/modules/bar/SysTrayItem.qml @@ -59,12 +59,12 @@ MouseArea { visible: false // There's already color overlay anchors.fill: parent source: trayIcon - desaturation: 1 // 1.0 means fully grayscale + desaturation: 0.8 // 1.0 means fully grayscale } ColorOverlay { anchors.fill: desaturatedIcon source: desaturatedIcon - color: ColorUtils.transparentize(Appearance.colors.colOnLayer0, 0.6) + color: ColorUtils.transparentize(Appearance.colors.colOnLayer0, 0.9) } } } From b6f75acf53a86e5941b4153674e231a2e3b438cc Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:17:17 +0700 Subject: [PATCH 321/328] quickshell: configPath -> shellPath --- .config/quickshell/ii/modules/background/Background.qml | 2 +- .config/quickshell/ii/modules/bar/UtilButtons.qml | 2 +- .config/quickshell/ii/modules/common/Directories.qml | 6 +++--- .config/quickshell/ii/modules/common/widgets/CustomIcon.qml | 2 +- .config/quickshell/ii/modules/overview/SearchWidget.qml | 2 +- .config/quickshell/ii/modules/sidebarLeft/AiChat.qml | 2 +- .config/quickshell/ii/modules/sidebarRight/SidebarRight.qml | 2 +- .config/quickshell/ii/services/FirstRunExperience.qml | 2 +- .config/quickshell/ii/welcome.qml | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.config/quickshell/ii/modules/background/Background.qml b/.config/quickshell/ii/modules/background/Background.qml index 5ee0fea3..714d0f32 100644 --- a/.config/quickshell/ii/modules/background/Background.qml +++ b/.config/quickshell/ii/modules/background/Background.qml @@ -117,7 +117,7 @@ Scope { property int contentHeight: 300 property int horizontalPadding: bgRoot.movableXSpace property int verticalPadding: bgRoot.movableYSpace - command: [Quickshell.configPath("scripts/images/least_busy_region.py"), + command: [Quickshell.shellPath("scripts/images/least_busy_region.py"), "--screen-width", bgRoot.screen.width, "--screen-height", bgRoot.screen.height, "--width", contentWidth, diff --git a/.config/quickshell/ii/modules/bar/UtilButtons.qml b/.config/quickshell/ii/modules/bar/UtilButtons.qml index fe5b534c..dcda858d 100644 --- a/.config/quickshell/ii/modules/bar/UtilButtons.qml +++ b/.config/quickshell/ii/modules/bar/UtilButtons.qml @@ -23,7 +23,7 @@ Item { visible: Config.options.bar.utilButtons.showScreenSnip sourceComponent: CircleUtilButton { Layout.alignment: Qt.AlignVCenter - onClicked: Quickshell.execDetached(["qs", "-p", Quickshell.configPath("screenshot.qml")]) + onClicked: Quickshell.execDetached(["qs", "-p", Quickshell.shellPath("screenshot.qml")]) MaterialSymbol { horizontalAlignment: Qt.AlignHCenter fill: 1 diff --git a/.config/quickshell/ii/modules/common/Directories.qml b/.config/quickshell/ii/modules/common/Directories.qml index 629d00c2..a1748ece 100644 --- a/.config/quickshell/ii/modules/common/Directories.qml +++ b/.config/quickshell/ii/modules/common/Directories.qml @@ -15,8 +15,8 @@ Singleton { readonly property string downloads: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0] // Other dirs used by the shell, without "file://" - property string assetsPath: Quickshell.configPath("assets") - property string scriptPath: Quickshell.configPath("scripts") + property string assetsPath: Quickshell.shellPath("assets") + property string scriptPath: Quickshell.shellPath("scripts") property string favicons: FileUtils.trimFileProtocol(`${Directories.cache}/media/favicons`) property string coverArt: FileUtils.trimFileProtocol(`${Directories.cache}/media/coverart`) property string booruPreviews: FileUtils.trimFileProtocol(`${Directories.cache}/media/boorus`) @@ -32,7 +32,7 @@ Singleton { property string cliphistDecode: FileUtils.trimFileProtocol(`/tmp/quickshell/media/cliphist`) property string screenshotTemp: "/tmp/quickshell/media/screenshot" property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/colors/switchwall.sh`) - property string defaultAiPrompts: Quickshell.configPath("defaults/ai/prompts") + property string defaultAiPrompts: Quickshell.shellPath("defaults/ai/prompts") property string userAiPrompts: FileUtils.trimFileProtocol(`${Directories.shellConfig}/ai/prompts`) property string aiChats: FileUtils.trimFileProtocol(`${Directories.state}/user/ai/chats`) // Cleanup on init diff --git a/.config/quickshell/ii/modules/common/widgets/CustomIcon.qml b/.config/quickshell/ii/modules/common/widgets/CustomIcon.qml index e5bbe39a..d7a1c634 100644 --- a/.config/quickshell/ii/modules/common/widgets/CustomIcon.qml +++ b/.config/quickshell/ii/modules/common/widgets/CustomIcon.qml @@ -9,7 +9,7 @@ Item { property bool colorize: false property color color property string source: "" - property string iconFolder: Qt.resolvedUrl(Quickshell.configPath("assets/icons")) // The folder to check first + property string iconFolder: Qt.resolvedUrl(Quickshell.shellPath("assets/icons")) // The folder to check first width: 30 height: 30 diff --git a/.config/quickshell/ii/modules/overview/SearchWidget.qml b/.config/quickshell/ii/modules/overview/SearchWidget.qml index 851f5e37..6e4c3cbf 100644 --- a/.config/quickshell/ii/modules/overview/SearchWidget.qml +++ b/.config/quickshell/ii/modules/overview/SearchWidget.qml @@ -58,7 +58,7 @@ Item { // Wrapper { action: "konachanwall", execute: () => { - Quickshell.execDetached([Quickshell.configPath("scripts/colors/random_konachan_wall.sh")]); + Quickshell.execDetached([Quickshell.shellPath("scripts/colors/random_konachan_wall.sh")]); } }, { diff --git a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml index 75696135..221eba9b 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml @@ -126,7 +126,7 @@ Mowe uwu wem ipsum! ### Formatting - *Italic*, \`Monospace\`, **Bold**, [Link](https://example.com) -- Arch lincox icon +- Arch lincox icon ### Table diff --git a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml index 44d591fe..91eb7b0a 100644 --- a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml @@ -17,7 +17,7 @@ Scope { id: root property int sidebarWidth: Appearance.sizes.sidebarWidth property int sidebarPadding: 12 - property string settingsQmlPath: Quickshell.configPath("settings.qml") + property string settingsQmlPath: Quickshell.shellPath("settings.qml") PanelWindow { id: sidebarRoot diff --git a/.config/quickshell/ii/services/FirstRunExperience.qml b/.config/quickshell/ii/services/FirstRunExperience.qml index a362e8cb..f23cce58 100644 --- a/.config/quickshell/ii/services/FirstRunExperience.qml +++ b/.config/quickshell/ii/services/FirstRunExperience.qml @@ -12,7 +12,7 @@ Singleton { property string firstRunNotifSummary: "Welcome!" property string firstRunNotifBody: "Hit Super+/ for a list of keybinds" property string defaultWallpaperPath: FileUtils.trimFileProtocol(`${Directories.assetsPath}/images/default_wallpaper.png`) - property string welcomeQmlPath: FileUtils.trimFileProtocol(Quickshell.configPath("welcome.qml")) + property string welcomeQmlPath: FileUtils.trimFileProtocol(Quickshell.shellPath("welcome.qml")) function load() { firstRunFileView.reload() diff --git a/.config/quickshell/ii/welcome.qml b/.config/quickshell/ii/welcome.qml index b220ff8b..bfcb2015 100644 --- a/.config/quickshell/ii/welcome.qml +++ b/.config/quickshell/ii/welcome.qml @@ -40,7 +40,7 @@ ApplicationWindow { Process { id: konachanWallProc property string status: "" - command: ["bash", "-c", Quickshell.configPath("scripts/colors/random_konachan_wall.sh")] + command: ["bash", "-c", Quickshell.shellPath("scripts/colors/random_konachan_wall.sh")] stdout: SplitParser { onRead: data => { console.log(`Konachan wall proc output: ${data}`); From f9856bdabd3ce2171ce810c20b267a252b3170f4 Mon Sep 17 00:00:00 2001 From: Jonas Bloch <128738169+Silzinc@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:50:51 +0200 Subject: [PATCH 322/328] fix(ai): add the full received message to rawContent The messages were not preserved and passed to further calls outside of the reasoning part. --- .config/quickshell/ii/services/Ai.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/ii/services/Ai.qml b/.config/quickshell/ii/services/Ai.qml index f26495db..b58a632a 100644 --- a/.config/quickshell/ii/services/Ai.qml +++ b/.config/quickshell/ii/services/Ai.qml @@ -689,6 +689,7 @@ Singleton { } requester.message.content += newContent; + requester.message.rawContent += newContent; if (dataJson.done) { requester.markDone(); From 3d5ed9401c7120757c1a1e38d39444cb87637da7 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 23 Jul 2025 08:57:33 +0700 Subject: [PATCH 323/328] bar: don't animate circprogs (#1570) --- .config/quickshell/ii/modules/bar/BatteryIndicator.qml | 1 + .config/quickshell/ii/modules/bar/Media.qml | 1 + .config/quickshell/ii/modules/bar/Resource.qml | 1 + .../quickshell/ii/modules/common/widgets/CircularProgress.qml | 2 ++ 4 files changed, 5 insertions(+) diff --git a/.config/quickshell/ii/modules/bar/BatteryIndicator.qml b/.config/quickshell/ii/modules/bar/BatteryIndicator.qml index 0f0a86a0..72cc932b 100644 --- a/.config/quickshell/ii/modules/bar/BatteryIndicator.qml +++ b/.config/quickshell/ii/modules/bar/BatteryIndicator.qml @@ -39,6 +39,7 @@ Item { } CircularProgress { + enableAnimation: false Layout.alignment: Qt.AlignVCenter lineWidth: 2 value: percentage diff --git a/.config/quickshell/ii/modules/bar/Media.qml b/.config/quickshell/ii/modules/bar/Media.qml index 0d5731e1..08e9b92d 100644 --- a/.config/quickshell/ii/modules/bar/Media.qml +++ b/.config/quickshell/ii/modules/bar/Media.qml @@ -56,6 +56,7 @@ Item { size: 26 secondaryColor: Appearance.colors.colSecondaryContainer primaryColor: Appearance.m3colors.m3onSecondaryContainer + enableAnimation: false MaterialSymbol { anchors.centerIn: parent diff --git a/.config/quickshell/ii/modules/bar/Resource.qml b/.config/quickshell/ii/modules/bar/Resource.qml index 734329af..eb3683d8 100644 --- a/.config/quickshell/ii/modules/bar/Resource.qml +++ b/.config/quickshell/ii/modules/bar/Resource.qml @@ -24,6 +24,7 @@ Item { size: 26 secondaryColor: Appearance.colors.colSecondaryContainer primaryColor: Appearance.m3colors.m3onSecondaryContainer + enableAnimation: false MaterialSymbol { anchors.centerIn: parent diff --git a/.config/quickshell/ii/modules/common/widgets/CircularProgress.qml b/.config/quickshell/ii/modules/common/widgets/CircularProgress.qml index 9a84bb1e..7ff2724f 100644 --- a/.config/quickshell/ii/modules/common/widgets/CircularProgress.qml +++ b/.config/quickshell/ii/modules/common/widgets/CircularProgress.qml @@ -18,6 +18,7 @@ Item { property real gapAngle: Math.PI / 9 property bool fill: false property int fillOverflow: 2 + property bool enableAnimation: true property int animationDuration: 1000 property var easingType: Easing.OutCubic @@ -83,6 +84,7 @@ Item { } Behavior on degree { + enabled: root.enableAnimation NumberAnimation { duration: root.animationDuration easing.type: root.easingType From 574a2a11e76f1c843ab4c7a58f5fec236fecd9d9 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 23 Jul 2025 09:00:31 +0700 Subject: [PATCH 324/328] night light: use hyprsunset <- gammastep --- .config/hypr/hyprland/execs.conf | 2 +- .../quickshell/ii/modules/common/Config.qml | 12 +- .../sidebarRight/quickToggles/NightLight.qml | 39 ++---- .config/quickshell/ii/services/DateTime.qml | 9 +- .config/quickshell/ii/services/Hyprsunset.qml | 117 ++++++++++++++++++ .config/quickshell/ii/shell.qml | 3 +- .../illogical-impulse-backlight/PKGBUILD | 1 - 7 files changed, 148 insertions(+), 35 deletions(-) create mode 100644 .config/quickshell/ii/services/Hyprsunset.qml diff --git a/.config/hypr/hyprland/execs.conf b/.config/hypr/hyprland/execs.conf index 0d04c512..6d92de1c 100644 --- a/.config/hypr/hyprland/execs.conf +++ b/.config/hypr/hyprland/execs.conf @@ -1,5 +1,5 @@ # Bar, wallpaper -exec-once = ~/.config/hypr/hyprland/scripts/start_geoclue_agent.sh & gammastep +exec-once = ~/.config/hypr/hyprland/scripts/start_geoclue_agent.sh exec-once = qs -c $qsConfig & # Input method diff --git a/.config/quickshell/ii/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml index e97a537c..7462d26e 100644 --- a/.config/quickshell/ii/modules/common/Config.qml +++ b/.config/quickshell/ii/modules/common/Config.qml @@ -8,6 +8,7 @@ Singleton { id: root property string filePath: Directories.shellConfigPath property alias options: configOptionsJsonAdapter + property bool ready: false function setNestedValue(nestedKey, value) { let keys = nestedKey.split("."); @@ -41,10 +42,10 @@ Singleton { FileView { path: root.filePath - watchChanges: true onFileChanged: reload() onAdapterUpdated: writeAdapter() + onLoaded: root.ready = true onLoadFailed: error => { if (error == FileViewError.FileNotFound) { writeAdapter(); @@ -171,6 +172,15 @@ Singleton { } } + property JsonObject light: JsonObject { + property JsonObject night: JsonObject { + property bool automatic: true + property string from: "19:00" // Format: "HH:mm", 24-hour time + property string to: "06:30" // Format: "HH:mm", 24-hour time + property int colorTemperature: 5000 + } + } + property JsonObject networking: JsonObject { property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" } diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml index 6cab856c..f0265126 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/NightLight.qml @@ -1,41 +1,28 @@ +import QtQuick import qs.modules.common import qs.modules.common.widgets import qs +import qs.services import Quickshell.Io QuickToggleButton { id: nightLightButton - property bool enabled: false + property bool enabled: Hyprsunset.active toggled: enabled - buttonIcon: "nightlight" + buttonIcon: Config.options.light.night.automatic ? "night_sight_auto" : "bedtime" onClicked: { - nightLightButton.enabled = !nightLightButton.enabled - if (enabled) { - nightLightOn.startDetached() - } - else { - nightLightOff.startDetached() - } + Hyprsunset.toggle() } - Process { - id: nightLightOn - command: ["gammastep"] + + altAction: () => { + Config.options.light.night.automatic = !Config.options.light.night.automatic } - Process { - id: nightLightOff - command: ["pkill", "gammastep"] - } - Process { - id: updateNightLightState - running: true - command: ["pidof", "gammastep"] - stdout: SplitParser { - onRead: (data) => { // if not empty then set toggled to true - nightLightButton.enabled = data.length > 0 - } - } + + Component.onCompleted: { + Hyprsunset.fetchState() } + StyledToolTip { - content: Translation.tr("Night Light") + content: Translation.tr("Night Light | Right-click to toggle Auto mode") } } diff --git a/.config/quickshell/ii/services/DateTime.qml b/.config/quickshell/ii/services/DateTime.qml index e1b0afa3..16dc6c4e 100644 --- a/.config/quickshell/ii/services/DateTime.qml +++ b/.config/quickshell/ii/services/DateTime.qml @@ -9,16 +9,15 @@ pragma ComponentBehavior: Bound * A nice wrapper for date and time strings. */ Singleton { + property var clock: SystemClock { + id: clock + precision: SystemClock.Minutes + } property string time: Qt.locale().toString(clock.date, Config.options?.time.format ?? "hh:mm") property string date: Qt.locale().toString(clock.date, Config.options?.time.dateFormat ?? "dddd, dd/MM") property string collapsedCalendarFormat: Qt.locale().toString(clock.date, "dd MMMM yyyy") property string uptime: "0h, 0m" - SystemClock { - id: clock - precision: SystemClock.Minutes - } - Timer { interval: 10 running: true diff --git a/.config/quickshell/ii/services/Hyprsunset.qml b/.config/quickshell/ii/services/Hyprsunset.qml new file mode 100644 index 00000000..d6def43c --- /dev/null +++ b/.config/quickshell/ii/services/Hyprsunset.qml @@ -0,0 +1,117 @@ +pragma Singleton + +import QtQuick +import qs.modules.common +import Quickshell +import Quickshell.Io + +/** + * Simple hyprsunset service with automatic mode. + * In theory we don't need this because hyprsunset has a config file, but it somehow doesn't work. + * It should also be possible to control it via hyprctl, but it doesn't work consistently either so we're just killing and launching. + */ +Singleton { + id: root + property var manualActive + property string from: Config.options?.light?.night?.from ?? "19:00" // Default to 7 PM + property string to: Config.options?.light?.night?.to ?? "06:30" // Default to 6:30 AM + property bool automatic: Config.options?.light?.night?.automatic && (Config?.ready ?? true) + property int colorTemperature: Config.options?.light?.night?.colorTemperature ?? 5000 // Default color temperature + property bool shouldBeOn + property bool firstEvaluation: true + property bool active: false + + property int fromHour: Number(from.split(":")[0]) + property int fromMinute: Number(from.split(":")[1]) + property int toHour: Number(to.split(":")[0]) + property int toMinute: Number(to.split(":")[1]) + + property int clockHour: DateTime.clock.hours + property int clockMinute: DateTime.clock.minutes + + + function isNoLater(hour1, minute1, hour2, minute2) { + if (hour1 < hour2) + return true; + if (hour1 === hour2 && minute1 < minute2) + return true; + return false; + } + + + onClockMinuteChanged: reEvaluate() + onAutomaticChanged: { + root.manualActive = undefined; + root.firstEvaluation = true; + reEvaluate(); + } + function reEvaluate() { + const toHourIsNextDay = !isNoLater(fromHour, fromMinute, toHour, toMinute); + const toHourWrapped = toHourIsNextDay ? toHour + 24 : toHour; + const toMinuteWrapped = toMinute; + root.shouldBeOn = isNoLater(fromHour, fromMinute, clockHour, clockMinute) && isNoLater(clockHour, clockMinute, toHourWrapped, toMinuteWrapped); + if (firstEvaluation) { + firstEvaluation = false; + root.ensureState(); + } + } + + onShouldBeOnChanged: ensureState() + function ensureState() { + // console.log("[Hyprsunset] Ensuring state:", root.shouldBeOn, "Automatic mode:", root.automatic); + if (!root.automatic || root.manualActive !== undefined) + return; + if (root.shouldBeOn) { + root.enable(); + } else { + root.disable(); + } + } + + function load() { } // Dummy to force init + + function enable() { + root.active = true; + // console.log("[Hyprsunset] Enabling"); + Quickshell.execDetached(["bash", "-c", `pidof hyprsunset || hyprsunset --temperature ${root.colorTemperature}`]); + } + + function disable() { + root.active = false; + // console.log("[Hyprsunset] Disabling"); + Quickshell.execDetached(["bash", "-c", `pkill hyprsunset`]); + } + + function fetchState() { + fetchProc.running = true; + } + + Process { + id: fetchProc + running: true + command: ["bash", "-c", "hyprctl hyprsunset temperature"] + stdout: StdioCollector { + id: stateCollector + onStreamFinished: { + const output = stateCollector.text.trim(); + if (output.length == 0 || output.startsWith("Couldn't")) + root.active = false; + else + root.active = (output != "6500"); + // console.log("[Hyprsunset] Fetched state:", output, "->", root.active); + } + } + } + + function toggle() { + if (root.manualActive === undefined) + root.manualActive = root.active; + + root.manualActive = !root.manualActive; + if (root.manualActive) { + root.enable(); + } else { + root.disable(); + } + } +} diff --git a/.config/quickshell/ii/shell.qml b/.config/quickshell/ii/shell.qml index 7cb86a03..9bba7104 100644 --- a/.config/quickshell/ii/shell.qml +++ b/.config/quickshell/ii/shell.qml @@ -49,9 +49,10 @@ ShellRoot { // Force initialization of some singletons Component.onCompleted: { - MaterialThemeLoader.reapplyTheme() Cliphist.refresh() FirstRunExperience.load() + Hyprsunset.load() + MaterialThemeLoader.reapplyTheme() } LazyLoader { active: enableBar; component: Bar {} } diff --git a/arch-packages/illogical-impulse-backlight/PKGBUILD b/arch-packages/illogical-impulse-backlight/PKGBUILD index 2525be9d..451c7e5d 100644 --- a/arch-packages/illogical-impulse-backlight/PKGBUILD +++ b/arch-packages/illogical-impulse-backlight/PKGBUILD @@ -5,7 +5,6 @@ pkgdesc='Illogical Impulse Backlight Dependencies' arch=(any) license=(None) depends=( - gammastep geoclue brightnessctl ddcutil From 82506ae7cd9a913115853aa0c6436bb2315d614d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 23 Jul 2025 09:00:54 +0700 Subject: [PATCH 325/328] groupbutton: press and hold for alt action --- .../ii/modules/common/widgets/GroupButton.qml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/common/widgets/GroupButton.qml b/.config/quickshell/ii/modules/common/widgets/GroupButton.qml index a64cd063..4a524e1d 100644 --- a/.config/quickshell/ii/modules/common/widgets/GroupButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/GroupButton.qml @@ -93,13 +93,23 @@ Button { root.down = false if (event.button != Qt.LeftButton) return; if (root.releaseAction) root.releaseAction(); - root.click() // Because the MouseArea already consumed the event + } + onClicked: (event) => { + if (event.button != Qt.LeftButton) return; + root.click() } onCanceled: (event) => { root.down = false } + + onPressAndHold: () => { + altAction(); + root.down = false; + root.clicked = false; + }; } + background: Rectangle { id: buttonBackground topLeftRadius: root.leftRadius From be2b86909ae6476af5ac7654ed487386102ae99f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 23 Jul 2025 09:26:52 +0700 Subject: [PATCH 326/328] switchwall: fix mpv options being overriden by load-scripts only (#1696) --- .config/quickshell/ii/scripts/colors/switchwall.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/ii/scripts/colors/switchwall.sh b/.config/quickshell/ii/scripts/colors/switchwall.sh index 4a659a2b..b8e8a3cc 100755 --- a/.config/quickshell/ii/scripts/colors/switchwall.sh +++ b/.config/quickshell/ii/scripts/colors/switchwall.sh @@ -114,7 +114,7 @@ THUMBNAIL_DIR="/tmp/mpvpaper_thumbnails" CUSTOM_DIR="$XDG_CONFIG_HOME/hypr/custom" RESTORE_SCRIPT_DIR="$CUSTOM_DIR/scripts" RESTORE_SCRIPT="$RESTORE_SCRIPT_DIR/__restore_video_wallpaper.sh" -VIDEO_OPTS="no-audio loop hwdec=auto scale=bilinear interpolation=no video-sync=display-resample panscan=1.0 video-scale-x=1.0 video-scale-y=1.0 video-align-x=0.5 video-align-y=0.5" +VIDEO_OPTS="no-audio loop hwdec=auto scale=bilinear interpolation=no video-sync=display-resample panscan=1.0 video-scale-x=1.0 video-scale-y=1.0 video-align-x=0.5 video-align-y=0.5 load-scripts=no" is_video() { local extension="${1##*.}" @@ -135,7 +135,7 @@ create_restore_script() { pkill -f -9 mpvpaper for monitor in \$(hyprctl monitors -j | jq -r '.[] | .name'); do - mpvpaper -o "$VIDEO_OPTS" "\$monitor" "$video_path" --mpv-options '--load-scripts=no' & + mpvpaper -o "$VIDEO_OPTS" "\$monitor" "$video_path" & sleep 0.1 done EOF From 5b4ccd9d5940198db899f0dd2aec50fe658c86d1 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 23 Jul 2025 09:34:23 +0700 Subject: [PATCH 327/328] previous commit but i didn't know there are 2 spots to fix --- .config/quickshell/ii/scripts/colors/switchwall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/ii/scripts/colors/switchwall.sh b/.config/quickshell/ii/scripts/colors/switchwall.sh index b8e8a3cc..cab10c1f 100755 --- a/.config/quickshell/ii/scripts/colors/switchwall.sh +++ b/.config/quickshell/ii/scripts/colors/switchwall.sh @@ -218,7 +218,7 @@ switch() { local video_path="$imgpath" monitors=$(hyprctl monitors -j | jq -r '.[] | .name') for monitor in $monitors; do - mpvpaper -o "$VIDEO_OPTS" "$monitor" "$video_path" --mpv-options '--load-scripts=no' & + mpvpaper -o "$VIDEO_OPTS" "$monitor" "$video_path" & sleep 0.1 done From 7bafa579894a9e7ec6b3c95311970789122895f0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 23 Jul 2025 10:26:16 +0700 Subject: [PATCH 328/328] radiobutton: fix inaccurate height --- .../quickshell/ii/modules/common/widgets/SelectionDialog.qml | 1 + .../quickshell/ii/modules/common/widgets/StyledRadioButton.qml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml b/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml index 5f9b871a..4dd2382c 100644 --- a/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml +++ b/.config/quickshell/ii/modules/common/widgets/SelectionDialog.qml @@ -69,6 +69,7 @@ Item { Layout.fillHeight: true clip: true currentIndex: root.defaultChoice !== undefined ? root.items.indexOf(root.defaultChoice) : -1 + spacing: 6 model: ScriptModel { id: choiceModel diff --git a/.config/quickshell/ii/modules/common/widgets/StyledRadioButton.qml b/.config/quickshell/ii/modules/common/widgets/StyledRadioButton.qml index 79797e5b..a6a63b7b 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledRadioButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledRadioButton.qml @@ -10,7 +10,7 @@ import Quickshell.Services.Pipewire RadioButton { id: root - implicitHeight: 40 + implicitHeight: contentItem.implicitHeight + 4 * 2 property string description property color activeColor: Appearance?.colors.colPrimary ?? "#685496" property color inactiveColor: Appearance?.m3colors.m3onSurfaceVariant ?? "#45464F" @@ -20,6 +20,7 @@ RadioButton { indicator: Item{} contentItem: RowLayout { + id: contentItem Layout.fillWidth: true spacing: 12 Rectangle {