From 80af8666503aa16bccf836c956c9cfb92bfc10c5 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 23 Aug 2025 22:11:41 +0700 Subject: [PATCH] wallpaper selector: directory validation, common file browser keybinds --- .../ii/modules/common/AddressBar.qml | 62 +++++++----- .../common/widgets/StyledTextInput.qml | 1 + .../WallpaperSelectorContent.qml | 95 +++++++++---------- .config/quickshell/ii/services/Wallpapers.qml | 25 ++++- 4 files changed, 106 insertions(+), 77 deletions(-) diff --git a/.config/quickshell/ii/modules/common/AddressBar.qml b/.config/quickshell/ii/modules/common/AddressBar.qml index b2c1f2bed..bc9b7080f 100644 --- a/.config/quickshell/ii/modules/common/AddressBar.qml +++ b/.config/quickshell/ii/modules/common/AddressBar.qml @@ -17,6 +17,11 @@ Rectangle { implicitHeight: mainLayout.implicitHeight + padding * 2 color: Appearance.colors.colLayer2 + function focusBreadcrumb() { + root.showBreadcrumb = false; + addressInput.forceActiveFocus(); + } + RowLayout { id: mainLayout anchors { @@ -38,43 +43,54 @@ Rectangle { Layout.fillWidth: true Layout.fillHeight: true - Loader { - active: !root.showBreadcrumb + Rectangle { + id: directoryEntry visible: !root.showBreadcrumb anchors.fill: parent - sourceComponent: Rectangle { - color: Appearance.colors.colLayer1 - radius: Appearance.rounding.full - implicitWidth: addressInput.implicitWidth - implicitHeight: addressInput.implicitHeight + color: Appearance.colors.colLayer1 + radius: Appearance.rounding.full + implicitWidth: addressInput.implicitWidth + implicitHeight: addressInput.implicitHeight - StyledTextInput { - id: addressInput + Keys.onPressed: event => { + if (directoryEntry.visible && event.key === Qt.Key_Escape) { + root.showBreadcrumb = true; + event.accepted = true; + return; + } + event.accepted = false; + } + + StyledTextInput { + id: addressInput + anchors.fill: parent + padding: 10 + text: root.directory + + onAccepted: { + root.navigateToDirectory(text); + root.showBreadcrumb = true; + } + + MouseArea { + // I-beam cursor anchors.fill: parent - padding: 10 - text: root.directory - - onAccepted: root.navigateToDirectory(text) - - MouseArea { - // I-beam cursor - anchors.fill: parent - acceptedButtons: Qt.NoButton - hoverEnabled: true - cursorShape: Qt.IBeamCursor - } + acceptedButtons: Qt.NoButton + hoverEnabled: true + cursorShape: Qt.IBeamCursor } } } Loader { + id: breadcrumbLoader active: root.showBreadcrumb visible: root.showBreadcrumb anchors.fill: parent sourceComponent: AddressBreadcrumb { directory: root.directory - onNavigateToDirectory: (dir) => { - root.navigateToDirectory(dir) + onNavigateToDirectory: dir => { + root.navigateToDirectory(dir); } } } diff --git a/.config/quickshell/ii/modules/common/widgets/StyledTextInput.qml b/.config/quickshell/ii/modules/common/widgets/StyledTextInput.qml index 57d0c7262..ff98af721 100644 --- a/.config/quickshell/ii/modules/common/widgets/StyledTextInput.qml +++ b/.config/quickshell/ii/modules/common/widgets/StyledTextInput.qml @@ -6,6 +6,7 @@ import QtQuick.Controls * Does not include visual layout, but includes the easily neglected colors. */ TextInput { + color: Appearance.colors.colOnLayer1 renderType: Text.NativeRendering selectedTextColor: Appearance.m3colors.m3onSecondaryContainer selectionColor: Appearance.colors.colSecondaryContainer diff --git a/.config/quickshell/ii/modules/wallpaperSelector/WallpaperSelectorContent.qml b/.config/quickshell/ii/modules/wallpaperSelector/WallpaperSelectorContent.qml index 7ddf4033c..8f49f349d 100644 --- a/.config/quickshell/ii/modules/wallpaperSelector/WallpaperSelectorContent.qml +++ b/.config/quickshell/ii/modules/wallpaperSelector/WallpaperSelectorContent.qml @@ -20,11 +20,15 @@ Item { implicitWidth: columnLayout.implicitWidth property var wallpapers: Wallpapers.wallpapers property string filterQuery: "" + property bool useDarkMode: Appearance.m3colors.darkmode Keys.onPressed: event => { if (event.key === Qt.Key_Escape) { GlobalStates.wallpaperSelectorOpen = false; event.accepted = true; + } else if (event.modifiers & Qt.AltModifier && event.key === Qt.Key_Up) { + Wallpapers.setDirectory(FileUtils.parentDirectory(Wallpapers.directory)); + event.accepted = true; } else if (event.key === Qt.Key_Left) { grid.moveSelection(-1); event.accepted = true; @@ -32,11 +36,7 @@ Item { grid.moveSelection(1); event.accepted = true; } else if (event.key === Qt.Key_Up) { - if (grid.currentIndex < grid.columns) { - filterField.forceActiveFocus(); - } else { - grid.moveSelection(-grid.columns); - } + grid.moveSelection(-grid.columns); event.accepted = true; } else if (event.key === Qt.Key_Down) { grid.moveSelection(grid.columns); @@ -50,6 +50,9 @@ Item { } filterField.forceActiveFocus(); event.accepted = true; + } else if (event.modifiers & Qt.ControlModifier && event.key === Qt.Key_L) { + addressBar.focusBreadcrumb(); + event.accepted = true; } else { filterField.forceActiveFocus(); if (event.text.length > 0) { @@ -103,7 +106,7 @@ Item { Layout.fillHeight: false directory: Wallpapers.directory onNavigateToDirectory: path => { - Wallpapers.directory = path; + Wallpapers.setDirectory(path); } radius: wallpaperGridBackground.radius - Layout.margins } @@ -154,12 +157,13 @@ Item { } function activateCurrent() { - const path = model[currentIndex]; + print("ACTIVATE"); + const path = grid.model.values[currentIndex]; if (!path) return; GlobalStates.wallpaperSelectorOpen = false; filterField.text = ""; - Wallpapers.apply(path); + Wallpapers.apply(path, root.useDarkMode); } model: ScriptModel { @@ -284,7 +288,7 @@ Item { onClicked: { GlobalStates.wallpaperSelectorOpen = false; filterField.text = ""; - Wallpapers.apply(wallpaperItem.modelData); + Wallpapers.apply(wallpaperItem.modelData, root.useDarkMode); } } } @@ -326,22 +330,34 @@ Item { Layout.fillHeight: true Layout.topMargin: 2 Layout.bottomMargin: 2 + implicitWidth: height buttonRadius: Appearance.rounding.full onClicked: { Wallpapers.openFallbackPicker(); GlobalStates.wallpaperSelectorOpen = false; } - contentItem: RowLayout { - MaterialSymbol { - text: "files" - iconSize: Appearance.font.pixelSize.larger - } - StyledText { - text: Translation.tr("System") - } + contentItem: MaterialSymbol { + text: "files" + iconSize: Appearance.font.pixelSize.larger } StyledToolTip { - content: "Use the system file picker instead" + content: Translation.tr("Use the system file picker instead") + } + } + + RippleButton { + Layout.fillHeight: true + Layout.topMargin: 2 + Layout.bottomMargin: 2 + implicitWidth: height + buttonRadius: Appearance.rounding.full + onClicked: root.useDarkMode = !root.useDarkMode + contentItem: MaterialSymbol { + text: root.useDarkMode ? "dark_mode" : "light_mode" + iconSize: Appearance.font.pixelSize.larger + } + StyledToolTip { + content: Translation.tr("Click to toggle light/dark mode (applied when wallpaper is chosen)") } } @@ -369,35 +385,20 @@ Item { } Keys.onPressed: event => { - if (text.length === 0) { - if (event.key === Qt.Key_Down || event.key === Qt.Key_Left || event.key === Qt.Key_Right) { - wallpaperGrid.forceActiveFocus(); - if (event.key === Qt.Key_Down) - grid.moveSelection(grid.columns); - else if (event.key === Qt.Key_Left) - grid.moveSelection(-1); - else if (event.key === Qt.Key_Right) - grid.moveSelection(1); - event.accepted = true; - } - } else { + if (text.length !== 0) { + // No filtering, just navigate grid if (event.key === Qt.Key_Down) { grid.moveSelection(grid.columns); - event.accepted = true; wallpaperGrid.forceActiveFocus(); + event.accepted = true; + } + if (event.key === Qt.Key_Up) { + grid.moveSelection(-grid.columns); + wallpaperGrid.forceActiveFocus(); + event.accepted = true; } } - if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { - grid.activateCurrent(); - event.accepted = true; - } else if (event.key === Qt.Key_Escape) { - if (filterField.text.length > 0) { - filterField.text = ""; - } else { - GlobalStates.wallpaperSelectorOpen = false; - } - event.accepted = true; - } + event.accepted = false; } } @@ -409,15 +410,9 @@ Item { onClicked: { GlobalStates.wallpaperSelectorOpen = false; } - implicitWidth: height - contentItem: MaterialSymbol { - text: "close" - iconSize: Appearance.font.pixelSize.larger - } - - StyledToolTip { - content: "Cancel" + contentItem: StyledText { + text: "Cancel" } } } diff --git a/.config/quickshell/ii/services/Wallpapers.qml b/.config/quickshell/ii/services/Wallpapers.qml index 91c3c4b70..60c4e041b 100644 --- a/.config/quickshell/ii/services/Wallpapers.qml +++ b/.config/quickshell/ii/services/Wallpapers.qml @@ -30,15 +30,32 @@ Singleton { applyProc.exec([Directories.wallpaperSwitchScriptPath]) } - function apply(path) { + function apply(path, darkMode = Appearance.m3colors.darkmode) { if (!path || path.length === 0) return applyProc.exec([ - "bash", "-c", - `${StringUtils.shellSingleQuoteEscape(Directories.wallpaperSwitchScriptPath)} ` + - `--image ${StringUtils.shellSingleQuoteEscape(path)}` + Directories.wallpaperSwitchScriptPath, + "--image", path, + "--mode", (darkMode ? "dark" : "light") ]) } + Process { + id: validateDirProc + property string nicePath: "" + function setDirectoryIfValid(path) { + validateDirProc.nicePath = FileUtils.trimFileProtocol(path).replace(/\/+$/, "") + validateDirProc.exec(["test", "-d", nicePath]) + } + onExited: (exitCode, exitStatus) => { + if (exitCode === 0) { + root.directory = validateDirProc.nicePath + } + } + } + function setDirectory(path) { + validateDirProc.setDirectoryIfValid(path) + } + // Folder model FolderListModel { id: files