wallpaper selector: directory validation, common file browser keybinds

This commit is contained in:
end-4
2025-08-23 22:11:41 +07:00
parent 8e6582b801
commit 80af866650
4 changed files with 106 additions and 77 deletions
@@ -17,6 +17,11 @@ Rectangle {
implicitHeight: mainLayout.implicitHeight + padding * 2 implicitHeight: mainLayout.implicitHeight + padding * 2
color: Appearance.colors.colLayer2 color: Appearance.colors.colLayer2
function focusBreadcrumb() {
root.showBreadcrumb = false;
addressInput.forceActiveFocus();
}
RowLayout { RowLayout {
id: mainLayout id: mainLayout
anchors { anchors {
@@ -38,43 +43,54 @@ Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Loader { Rectangle {
active: !root.showBreadcrumb id: directoryEntry
visible: !root.showBreadcrumb visible: !root.showBreadcrumb
anchors.fill: parent anchors.fill: parent
sourceComponent: Rectangle { color: Appearance.colors.colLayer1
color: Appearance.colors.colLayer1 radius: Appearance.rounding.full
radius: Appearance.rounding.full implicitWidth: addressInput.implicitWidth
implicitWidth: addressInput.implicitWidth implicitHeight: addressInput.implicitHeight
implicitHeight: addressInput.implicitHeight
StyledTextInput { Keys.onPressed: event => {
id: addressInput 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 anchors.fill: parent
padding: 10 acceptedButtons: Qt.NoButton
text: root.directory hoverEnabled: true
cursorShape: Qt.IBeamCursor
onAccepted: root.navigateToDirectory(text)
MouseArea {
// I-beam cursor
anchors.fill: parent
acceptedButtons: Qt.NoButton
hoverEnabled: true
cursorShape: Qt.IBeamCursor
}
} }
} }
} }
Loader { Loader {
id: breadcrumbLoader
active: root.showBreadcrumb active: root.showBreadcrumb
visible: root.showBreadcrumb visible: root.showBreadcrumb
anchors.fill: parent anchors.fill: parent
sourceComponent: AddressBreadcrumb { sourceComponent: AddressBreadcrumb {
directory: root.directory directory: root.directory
onNavigateToDirectory: (dir) => { onNavigateToDirectory: dir => {
root.navigateToDirectory(dir) root.navigateToDirectory(dir);
} }
} }
} }
@@ -6,6 +6,7 @@ import QtQuick.Controls
* Does not include visual layout, but includes the easily neglected colors. * Does not include visual layout, but includes the easily neglected colors.
*/ */
TextInput { TextInput {
color: Appearance.colors.colOnLayer1
renderType: Text.NativeRendering renderType: Text.NativeRendering
selectedTextColor: Appearance.m3colors.m3onSecondaryContainer selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
selectionColor: Appearance.colors.colSecondaryContainer selectionColor: Appearance.colors.colSecondaryContainer
@@ -20,11 +20,15 @@ Item {
implicitWidth: columnLayout.implicitWidth implicitWidth: columnLayout.implicitWidth
property var wallpapers: Wallpapers.wallpapers property var wallpapers: Wallpapers.wallpapers
property string filterQuery: "" property string filterQuery: ""
property bool useDarkMode: Appearance.m3colors.darkmode
Keys.onPressed: event => { Keys.onPressed: event => {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
GlobalStates.wallpaperSelectorOpen = false; GlobalStates.wallpaperSelectorOpen = false;
event.accepted = true; 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) { } else if (event.key === Qt.Key_Left) {
grid.moveSelection(-1); grid.moveSelection(-1);
event.accepted = true; event.accepted = true;
@@ -32,11 +36,7 @@ Item {
grid.moveSelection(1); grid.moveSelection(1);
event.accepted = true; event.accepted = true;
} else if (event.key === Qt.Key_Up) { } else if (event.key === Qt.Key_Up) {
if (grid.currentIndex < grid.columns) { grid.moveSelection(-grid.columns);
filterField.forceActiveFocus();
} else {
grid.moveSelection(-grid.columns);
}
event.accepted = true; event.accepted = true;
} else if (event.key === Qt.Key_Down) { } else if (event.key === Qt.Key_Down) {
grid.moveSelection(grid.columns); grid.moveSelection(grid.columns);
@@ -50,6 +50,9 @@ Item {
} }
filterField.forceActiveFocus(); filterField.forceActiveFocus();
event.accepted = true; event.accepted = true;
} else if (event.modifiers & Qt.ControlModifier && event.key === Qt.Key_L) {
addressBar.focusBreadcrumb();
event.accepted = true;
} else { } else {
filterField.forceActiveFocus(); filterField.forceActiveFocus();
if (event.text.length > 0) { if (event.text.length > 0) {
@@ -103,7 +106,7 @@ Item {
Layout.fillHeight: false Layout.fillHeight: false
directory: Wallpapers.directory directory: Wallpapers.directory
onNavigateToDirectory: path => { onNavigateToDirectory: path => {
Wallpapers.directory = path; Wallpapers.setDirectory(path);
} }
radius: wallpaperGridBackground.radius - Layout.margins radius: wallpaperGridBackground.radius - Layout.margins
} }
@@ -154,12 +157,13 @@ Item {
} }
function activateCurrent() { function activateCurrent() {
const path = model[currentIndex]; print("ACTIVATE");
const path = grid.model.values[currentIndex];
if (!path) if (!path)
return; return;
GlobalStates.wallpaperSelectorOpen = false; GlobalStates.wallpaperSelectorOpen = false;
filterField.text = ""; filterField.text = "";
Wallpapers.apply(path); Wallpapers.apply(path, root.useDarkMode);
} }
model: ScriptModel { model: ScriptModel {
@@ -284,7 +288,7 @@ Item {
onClicked: { onClicked: {
GlobalStates.wallpaperSelectorOpen = false; GlobalStates.wallpaperSelectorOpen = false;
filterField.text = ""; filterField.text = "";
Wallpapers.apply(wallpaperItem.modelData); Wallpapers.apply(wallpaperItem.modelData, root.useDarkMode);
} }
} }
} }
@@ -326,22 +330,34 @@ Item {
Layout.fillHeight: true Layout.fillHeight: true
Layout.topMargin: 2 Layout.topMargin: 2
Layout.bottomMargin: 2 Layout.bottomMargin: 2
implicitWidth: height
buttonRadius: Appearance.rounding.full buttonRadius: Appearance.rounding.full
onClicked: { onClicked: {
Wallpapers.openFallbackPicker(); Wallpapers.openFallbackPicker();
GlobalStates.wallpaperSelectorOpen = false; GlobalStates.wallpaperSelectorOpen = false;
} }
contentItem: RowLayout { contentItem: MaterialSymbol {
MaterialSymbol { text: "files"
text: "files" iconSize: Appearance.font.pixelSize.larger
iconSize: Appearance.font.pixelSize.larger
}
StyledText {
text: Translation.tr("System")
}
} }
StyledToolTip { 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 => { Keys.onPressed: event => {
if (text.length === 0) { if (text.length !== 0) {
if (event.key === Qt.Key_Down || event.key === Qt.Key_Left || event.key === Qt.Key_Right) { // No filtering, just navigate grid
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 (event.key === Qt.Key_Down) { if (event.key === Qt.Key_Down) {
grid.moveSelection(grid.columns); grid.moveSelection(grid.columns);
event.accepted = true;
wallpaperGrid.forceActiveFocus(); 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) { event.accepted = false;
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;
}
} }
} }
@@ -409,15 +410,9 @@ Item {
onClicked: { onClicked: {
GlobalStates.wallpaperSelectorOpen = false; GlobalStates.wallpaperSelectorOpen = false;
} }
implicitWidth: height
contentItem: MaterialSymbol { contentItem: StyledText {
text: "close" text: "Cancel"
iconSize: Appearance.font.pixelSize.larger
}
StyledToolTip {
content: "Cancel"
} }
} }
} }
+21 -4
View File
@@ -30,15 +30,32 @@ Singleton {
applyProc.exec([Directories.wallpaperSwitchScriptPath]) applyProc.exec([Directories.wallpaperSwitchScriptPath])
} }
function apply(path) { function apply(path, darkMode = Appearance.m3colors.darkmode) {
if (!path || path.length === 0) return if (!path || path.length === 0) return
applyProc.exec([ applyProc.exec([
"bash", "-c", Directories.wallpaperSwitchScriptPath,
`${StringUtils.shellSingleQuoteEscape(Directories.wallpaperSwitchScriptPath)} ` + "--image", path,
`--image ${StringUtils.shellSingleQuoteEscape(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 // Folder model
FolderListModel { FolderListModel {
id: files id: files