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 1/8] 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 58331e368..d928aa3f3 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 c86bce534..b168ba536 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 f5a4b5838..eac2e65b9 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 4b7286be6..ee5a28eb5 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 2/8] 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 2d317a6be..01dda8a2a 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 3/8] 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 e965e12f7..07d889492 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 4/8] 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 000000000..3cdc3f80f --- /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 000000000..e62831a48 --- /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 dd3323ac4..9cec75c3d 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 b168ba536..3e8e7ae35 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 ee5a28eb5..f9245cbc0 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 5/8] 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 32c905621..05741f204 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 9de344507..62d948cf3 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 e1900c9fe..1733bca37 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 e078d503d..fd11e5828 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 e0999d6e3..5faa8699d 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 614efa91e..7d7cc9525 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 94e6123ff..20628edbe 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 3e8e7ae35..87775072a 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 8d7952110..e242030f7 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 ea7bb0ee3..881942b73 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 4e115bc76..51b22d620 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 52ddae7d9..ebdd9e4ee 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 083ecc036..d8c55b58d 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 1cd56acc7..2f7693735 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 5271e3769..010b6ae55 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 08bdee7cd..b19910d85 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 347e8f400..f7dadcee9 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 86ccb98b8..4b1f034cd 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 7cafcbbe2..f702010d1 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 f9245cbc0..9adaef8c1 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 868bea9e6..ae26fc90e 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 6/8] 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 2f7693735..79c1eba7b 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 7/8] 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 01dda8a2a..51f82a727 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 a7817e6e9..8e33db617 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 9cec75c3d..7fc902122 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 87775072a..50803e168 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 8/8] 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 202230a3c..0036eb617 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 8c423e37e..ee2410c40 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 000000000..6df0c8fa9 --- /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 000000000..549ccae27 --- /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 000000000..1129c6d8d --- /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 2c138b879..11fe37bc3 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 7fc902122..000000000 --- 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 000000000..ae051836e --- /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 50803e168..000000000 --- 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 000000000..a02c4f91d --- /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 eac2e65b9..00f07e2ff 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 9adaef8c1..f0895993c 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