search: use qs' execdetached instead of executor proc

This commit is contained in:
end-4
2025-07-12 19:25:08 +07:00
parent c0a3a0d7d2
commit f6bb5385cf
@@ -4,14 +4,11 @@ import "root:/modules/common"
import "root:/modules/common/widgets" import "root:/modules/common/widgets"
import "root:/modules/common/functions/string_utils.js" as StringUtils import "root:/modules/common/functions/string_utils.js" as StringUtils
import Qt5Compat.GraphicalEffects import Qt5Compat.GraphicalEffects
import Qt.labs.platform
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import Quickshell.Hyprland
Item { // Wrapper Item { // Wrapper
id: root id: root
@@ -29,9 +26,9 @@ Item { // Wrapper
} }
function cancelSearch() { function cancelSearch() {
searchInput.selectAll() searchInput.selectAll();
root.searchingText = "" root.searchingText = "";
searchWidthBehavior.enabled = true; searchWidthBehavior.enabled = true;
} }
function setSearchingText(text) { function setSearchingText(text) {
@@ -43,45 +40,44 @@ Item { // Wrapper
{ {
action: "dark", action: "dark",
execute: () => { execute: () => {
executor.executeCommand(`${Directories.wallpaperSwitchScriptPath} --mode dark --noswitch`) Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--mode", "dark", "--noswitch"]);
} }
}, },
{ {
action: "light", action: "light",
execute: () => { execute: () => {
executor.executeCommand(`${Directories.wallpaperSwitchScriptPath} --mode light --noswitch`) Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--mode", "light", "--noswitch"]);
} }
}, },
{ {
action: "wall", action: "wall",
execute: () => { execute: () => {
executor.executeCommand(Directories.wallpaperSwitchScriptPath) Quickshell.execDetached([Directories.wallpaperSwitchScriptPath]);
} }
}, },
{ {
action: "konachanwall", action: "konachanwall",
execute: () => { execute: () => {
Quickshell.execDetached([Quickshell.configPath("scripts/colors/random_konachan_wall.sh")]) Quickshell.execDetached([Quickshell.configPath("scripts/colors/random_konachan_wall.sh")]);
} }
}, },
{ {
action: "accentcolor", action: "accentcolor",
execute: (args) => { execute: args => {
executor.executeCommand( Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--noswitch", "--color", ...(args != '' ? [`${args}`] : [])]);
`${Directories.wallpaperSwitchScriptPath} --noswitch --color ${args != '' ? ("'"+args+"'") : ""}`
)
} }
}, },
{ {
action: "todo", action: "todo",
execute: (args) => { execute: args => {
Todo.addTask(args) Todo.addTask(args);
} }
}, },
] ]
function focusFirstItemIfNeeded() { function focusFirstItemIfNeeded() {
if (searchInput.focus) appResults.currentIndex = 0; // Focus the first item if (searchInput.focus)
appResults.currentIndex = 0; // Focus the first item
} }
Timer { Timer {
@@ -96,32 +92,22 @@ Item { // Wrapper
id: mathProcess id: mathProcess
property list<string> baseCommand: ["qalc", "-t"] property list<string> baseCommand: ["qalc", "-t"]
function calculateExpression(expression) { function calculateExpression(expression) {
mathProcess.running = false mathProcess.running = false;
mathProcess.command = baseCommand.concat(expression) mathProcess.command = baseCommand.concat(expression);
mathProcess.running = true mathProcess.running = true;
} }
stdout: SplitParser { stdout: SplitParser {
onRead: data => { onRead: data => {
root.mathResult = data root.mathResult = data;
root.focusFirstItemIfNeeded() root.focusFirstItemIfNeeded();
} }
} }
} }
Process { Keys.onPressed: event => {
id: executor
property list<string> baseCommand: ["bash", "-c"]
function executeCommand(command) {
executor.command = baseCommand.concat(
`${command}`
)
executor.startDetached()
}
}
Keys.onPressed: (event) => {
// Prevent Esc and Backspace from registering // Prevent Esc and Backspace from registering
if (event.key === Qt.Key_Escape) return; if (event.key === Qt.Key_Escape)
return;
// Handle Backspace: focus and delete character if not focused // Handle Backspace: focus and delete character if not focused
if (event.key === Qt.Key_Backspace) { if (event.key === Qt.Key_Backspace) {
@@ -142,8 +128,7 @@ Item { // Wrapper
} else { } else {
// Delete character before cursor if any // Delete character before cursor if any
if (searchInput.cursorPosition > 0) { if (searchInput.cursorPosition > 0) {
searchInput.text = searchInput.text.slice(0, searchInput.cursorPosition - 1) + searchInput.text = searchInput.text.slice(0, searchInput.cursorPosition - 1) + searchInput.text.slice(searchInput.cursorPosition);
searchInput.text.slice(searchInput.cursorPosition);
searchInput.cursorPosition -= 1; searchInput.cursorPosition -= 1;
} }
} }
@@ -156,19 +141,12 @@ Item { // Wrapper
} }
// Only handle visible printable characters (ignore control chars, arrows, etc.) // Only handle visible printable characters (ignore control chars, arrows, etc.)
if ( if (event.text && event.text.length === 1 && event.key !== Qt.Key_Enter && event.key !== Qt.Key_Return && event.text.charCodeAt(0) >= 0x20) // ignore control chars like Backspace, Tab, etc.
event.text && {
event.text.length === 1 &&
event.key !== Qt.Key_Enter &&
event.key !== Qt.Key_Return &&
event.text.charCodeAt(0) >= 0x20 // ignore control chars like Backspace, Tab, etc.
) {
if (!searchInput.activeFocus) { if (!searchInput.activeFocus) {
searchInput.forceActiveFocus(); searchInput.forceActiveFocus();
// Insert the character at the cursor position // Insert the character at the cursor position
searchInput.text = searchInput.text.slice(0, searchInput.cursorPosition) + searchInput.text = searchInput.text.slice(0, searchInput.cursorPosition) + event.text + searchInput.text.slice(searchInput.cursorPosition);
event.text +
searchInput.text.slice(searchInput.cursorPosition);
searchInput.cursorPosition += 1; searchInput.cursorPosition += 1;
event.accepted = true; event.accepted = true;
} }
@@ -264,7 +242,8 @@ Item { // Wrapper
} }
} }
Rectangle { // Separator Rectangle {
// Separator
visible: root.showResults visible: root.showResults
Layout.fillWidth: true Layout.fillWidth: true
height: 1 height: 1
@@ -281,10 +260,11 @@ Item { // Wrapper
bottomMargin: 10 bottomMargin: 10
spacing: 2 spacing: 2
KeyNavigation.up: searchBar KeyNavigation.up: searchBar
highlightMoveDuration : 100 highlightMoveDuration: 100
onFocusChanged: { onFocusChanged: {
if(focus) appResults.currentIndex = 1; if (focus)
appResults.currentIndex = 1;
} }
Connections { Connections {
@@ -297,12 +277,15 @@ Item { // Wrapper
model: ScriptModel { model: ScriptModel {
id: model id: model
values: { // Search results are handled here values: {
// Search results are handled here
////////////////// Skip? ////////////////// ////////////////// Skip? //////////////////
if(root.searchingText == "") return []; if (root.searchingText == "")
return [];
///////////// Special cases /////////////// ///////////// Special cases ///////////////
if (root.searchingText.startsWith(Config.options.search.prefix.clipboard)) { // Clipboard if (root.searchingText.startsWith(Config.options.search.prefix.clipboard)) {
// Clipboard
const searchString = root.searchingText.slice(Config.options.search.prefix.clipboard.length); const searchString = root.searchingText.slice(Config.options.search.prefix.clipboard.length);
return Cliphist.fuzzyQuery(searchString).map(entry => { return Cliphist.fuzzyQuery(searchString).map(entry => {
return { return {
@@ -311,14 +294,13 @@ Item { // Wrapper
clickActionName: "", clickActionName: "",
type: `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`, type: `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`,
execute: () => { execute: () => {
Quickshell.execDetached( Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`]);
["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`]
);
} }
}; };
}).filter(Boolean); }).filter(Boolean);
} }
if (root.searchingText.startsWith(Config.options.search.prefix.emojis)) { // Clipboard if (root.searchingText.startsWith(Config.options.search.prefix.emojis)) {
// Clipboard
const searchString = root.searchingText.slice(Config.options.search.prefix.emojis.length); const searchString = root.searchingText.slice(Config.options.search.prefix.emojis.length);
return Emojis.fuzzyQuery(searchString).map(entry => { return Emojis.fuzzyQuery(searchString).map(entry => {
return { return {
@@ -328,12 +310,11 @@ Item { // Wrapper
clickActionName: "", clickActionName: "",
type: "Emoji", type: "Emoji",
execute: () => { execute: () => {
Quickshell.clipboardText = entry.match(/^\s*(\S+)/)?.[1] Quickshell.clipboardText = entry.match(/^\s*(\S+)/)?.[1];
} }
}; };
}).filter(Boolean); }).filter(Boolean);
} }
////////////////// Init /////////////////// ////////////////// Init ///////////////////
nonAppResultsTimer.restart(); nonAppResultsTimer.restart();
@@ -346,7 +327,7 @@ Item { // Wrapper
execute: () => { execute: () => {
Quickshell.clipboardText = root.mathResult; Quickshell.clipboardText = root.mathResult;
} }
} };
const commandResultObject = { const commandResultObject = {
name: searchingText.replace("file://", ""), name: searchingText.replace("file://", ""),
clickActionName: qsTr("Run"), clickActionName: qsTr("Run"),
@@ -354,38 +335,34 @@ Item { // Wrapper
fontType: "monospace", fontType: "monospace",
materialSymbol: 'terminal', materialSymbol: 'terminal',
execute: () => { execute: () => {
executor.executeCommand(searchingText.startsWith('sudo') ? `${Config.options.apps.terminal} fish -C '${root.searchingText.replace("file://", "")}'` : root.searchingText.replace("file://", "")); const cleanedCommand = root.searchingText.replace("file://", "");
Quickshell.execDetached(["bash", "-c", searchingText.startsWith('sudo') ? `${Config.options.apps.terminal} fish -C '${cleanedCommand}'` : cleanedCommand]);
} }
} };
const launcherActionObjects = root.searchActions const launcherActionObjects = root.searchActions.map(action => {
.map(action => { const actionString = `${Config.options.search.prefix.action}${action.action}`;
const actionString = `${Config.options.search.prefix.action}${action.action}`; if (actionString.startsWith(root.searchingText) || root.searchingText.startsWith(actionString)) {
if (actionString.startsWith(root.searchingText) || root.searchingText.startsWith(actionString)) { return {
return { name: root.searchingText.startsWith(actionString) ? root.searchingText : actionString,
name: root.searchingText.startsWith(actionString) ? root.searchingText : actionString, clickActionName: qsTr("Run"),
clickActionName: qsTr("Run"), type: qsTr("Action"),
type: qsTr("Action"), materialSymbol: 'settings_suggest',
materialSymbol: 'settings_suggest', execute: () => {
execute: () => { action.execute(root.searchingText.split(" ").slice(1).join(" "));
action.execute(root.searchingText.split(" ").slice(1).join(" ")) }
}, };
}; }
} return null;
return null; }).filter(Boolean);
})
.filter(Boolean);
let result = []; let result = [];
//////////////// Apps ////////////////// //////////////// Apps //////////////////
result = result.concat( result = result.concat(AppSearch.fuzzyQuery(root.searchingText).map(entry => {
AppSearch.fuzzyQuery(root.searchingText) entry.clickActionName = qsTr("Launch");
.map((entry) => { entry.type = qsTr("App");
entry.clickActionName = qsTr("Launch"); return entry;
entry.type = qsTr("App"); }));
return entry;
})
);
////////// Launcher actions //////////// ////////// Launcher actions ////////////
result = result.concat(launcherActionObjects); result = result.concat(launcherActionObjects);
@@ -407,7 +384,7 @@ Item { // Wrapper
type: qsTr("Search the web"), type: qsTr("Search the web"),
materialSymbol: 'travel_explore', materialSymbol: 'travel_explore',
execute: () => { execute: () => {
let url = Config.options.search.engineBaseUrl + root.searchingText let url = Config.options.search.engineBaseUrl + root.searchingText;
for (let site of Config.options.search.excludedSites) { for (let site of Config.options.search.excludedSites) {
url += ` -site:${site}`; url += ` -site:${site}`;
} }
@@ -419,17 +396,15 @@ Item { // Wrapper
} }
} }
delegate: SearchItem { // The selectable item for each search result delegate: SearchItem {
// The selectable item for each search result
required property var modelData required property var modelData
anchors.left: parent?.left anchors.left: parent?.left
anchors.right: parent?.right anchors.right: parent?.right
entry: modelData entry: modelData
query: root.searchingText.startsWith(Config.options.search.prefix.clipboard) ? query: root.searchingText.startsWith(Config.options.search.prefix.clipboard) ? root.searchingText.slice(Config.options.search.prefix.clipboard.length) : root.searchingText
root.searchingText.slice(Config.options.search.prefix.clipboard.length) :
root.searchingText;
} }
} }
} }
} }
} }