mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-03 20:32:07 -04:00
launcher/dsearch: support for folder search and extra filters
This commit is contained in:
@@ -162,6 +162,11 @@ Item {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
property string fileSearchType: "all"
|
||||||
|
property string fileSearchExt: ""
|
||||||
|
property string fileSearchFolder: ""
|
||||||
|
property string fileSearchSort: "score"
|
||||||
|
|
||||||
property string pluginFilter: ""
|
property string pluginFilter: ""
|
||||||
property string activePluginName: ""
|
property string activePluginName: ""
|
||||||
property var activePluginCategories: []
|
property var activePluginCategories: []
|
||||||
@@ -346,6 +351,10 @@ Item {
|
|||||||
previousSearchMode = "all";
|
previousSearchMode = "all";
|
||||||
autoSwitchedToFiles = false;
|
autoSwitchedToFiles = false;
|
||||||
isFileSearching = false;
|
isFileSearching = false;
|
||||||
|
fileSearchType = "all";
|
||||||
|
fileSearchExt = "";
|
||||||
|
fileSearchFolder = "";
|
||||||
|
fileSearchSort = "score";
|
||||||
sections = [];
|
sections = [];
|
||||||
flatModel = [];
|
flatModel = [];
|
||||||
selectedFlatIndex = 0;
|
selectedFlatIndex = 0;
|
||||||
@@ -399,6 +408,34 @@ Item {
|
|||||||
performSearch();
|
performSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setFileSearchType(type) {
|
||||||
|
if (fileSearchType === type)
|
||||||
|
return;
|
||||||
|
fileSearchType = type;
|
||||||
|
performFileSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setFileSearchExt(ext) {
|
||||||
|
if (fileSearchExt === ext)
|
||||||
|
return;
|
||||||
|
fileSearchExt = ext;
|
||||||
|
performFileSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setFileSearchFolder(folder) {
|
||||||
|
if (fileSearchFolder === folder)
|
||||||
|
return;
|
||||||
|
fileSearchFolder = folder;
|
||||||
|
performFileSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setFileSearchSort(sort) {
|
||||||
|
if (fileSearchSort === sort)
|
||||||
|
return;
|
||||||
|
fileSearchSort = sort;
|
||||||
|
performFileSearch();
|
||||||
|
}
|
||||||
|
|
||||||
function clearPluginFilter() {
|
function clearPluginFilter() {
|
||||||
if (pluginFilter) {
|
if (pluginFilter) {
|
||||||
pluginFilter = "";
|
pluginFilter = "";
|
||||||
@@ -832,10 +869,20 @@ Item {
|
|||||||
var params = {
|
var params = {
|
||||||
limit: 20,
|
limit: 20,
|
||||||
fuzzy: true,
|
fuzzy: true,
|
||||||
sort: "score",
|
sort: fileSearchSort || "score",
|
||||||
desc: true
|
desc: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (DSearchService.supportsTypeFilter) {
|
||||||
|
params.type = (fileSearchType && fileSearchType !== "all") ? fileSearchType : "all";
|
||||||
|
}
|
||||||
|
if (fileSearchExt) {
|
||||||
|
params.ext = fileSearchExt;
|
||||||
|
}
|
||||||
|
if (fileSearchFolder) {
|
||||||
|
params.folder = fileSearchFolder;
|
||||||
|
}
|
||||||
|
|
||||||
DSearchService.search(fileQuery, params, function (response) {
|
DSearchService.search(fileQuery, params, function (response) {
|
||||||
isFileSearching = false;
|
isFileSearching = false;
|
||||||
if (response.error)
|
if (response.error)
|
||||||
@@ -845,34 +892,73 @@ Item {
|
|||||||
|
|
||||||
for (var i = 0; i < hits.length; i++) {
|
for (var i = 0; i < hits.length; i++) {
|
||||||
var hit = hits[i];
|
var hit = hits[i];
|
||||||
|
var docTypes = hit.locations?.doc_type;
|
||||||
|
var isDir = docTypes ? !!docTypes["dir"] : false;
|
||||||
fileItems.push(transformFileResult({
|
fileItems.push(transformFileResult({
|
||||||
path: hit.id || "",
|
path: hit.id || "",
|
||||||
score: hit.score || 0
|
score: hit.score || 0,
|
||||||
|
is_dir: isDir
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileSection = {
|
var fileSections = [];
|
||||||
id: "files",
|
var showType = fileSearchType || "all";
|
||||||
title: I18n.tr("Files"),
|
|
||||||
icon: "folder",
|
if (showType === "all" && DSearchService.supportsTypeFilter) {
|
||||||
priority: 4,
|
var onlyFiles = [];
|
||||||
items: fileItems,
|
var onlyDirs = [];
|
||||||
collapsed: collapsedSections["files"] || false,
|
for (var j = 0; j < fileItems.length; j++) {
|
||||||
flatStartIndex: 0
|
if (fileItems[j].data?.is_dir)
|
||||||
};
|
onlyDirs.push(fileItems[j]);
|
||||||
|
else
|
||||||
|
onlyFiles.push(fileItems[j]);
|
||||||
|
}
|
||||||
|
if (onlyFiles.length > 0) {
|
||||||
|
fileSections.push({
|
||||||
|
id: "files",
|
||||||
|
title: I18n.tr("Files"),
|
||||||
|
icon: "insert_drive_file",
|
||||||
|
priority: 4,
|
||||||
|
items: onlyFiles,
|
||||||
|
collapsed: collapsedSections["files"] || false,
|
||||||
|
flatStartIndex: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (onlyDirs.length > 0) {
|
||||||
|
fileSections.push({
|
||||||
|
id: "folders",
|
||||||
|
title: I18n.tr("Folders"),
|
||||||
|
icon: "folder",
|
||||||
|
priority: 4.1,
|
||||||
|
items: onlyDirs,
|
||||||
|
collapsed: collapsedSections["folders"] || false,
|
||||||
|
flatStartIndex: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var filesIcon = showType === "dir" ? "folder" : showType === "file" ? "insert_drive_file" : "folder";
|
||||||
|
var filesTitle = showType === "dir" ? I18n.tr("Folders") : I18n.tr("Files");
|
||||||
|
if (fileItems.length > 0) {
|
||||||
|
fileSections.push({
|
||||||
|
id: "files",
|
||||||
|
title: filesTitle,
|
||||||
|
icon: filesIcon,
|
||||||
|
priority: 4,
|
||||||
|
items: fileItems,
|
||||||
|
collapsed: collapsedSections["files"] || false,
|
||||||
|
flatStartIndex: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var newSections;
|
var newSections;
|
||||||
if (searchMode === "files") {
|
if (searchMode === "files") {
|
||||||
newSections = fileItems.length > 0 ? [fileSection] : [];
|
newSections = fileSections;
|
||||||
} else {
|
} else {
|
||||||
var existingNonFile = sections.filter(function (s) {
|
var existingNonFile = sections.filter(function (s) {
|
||||||
return s.id !== "files";
|
return s.id !== "files" && s.id !== "folders";
|
||||||
});
|
});
|
||||||
if (fileItems.length > 0) {
|
newSections = existingNonFile.concat(fileSections);
|
||||||
newSections = existingNonFile.concat([fileSection]);
|
|
||||||
} else {
|
|
||||||
newSections = existingNonFile;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
newSections.sort(function (a, b) {
|
newSections.sort(function (a, b) {
|
||||||
return a.priority - b.priority;
|
return a.priority - b.priority;
|
||||||
@@ -918,7 +1004,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function transformFileResult(file) {
|
function transformFileResult(file) {
|
||||||
return Transform.transformFileResult(file, I18n.tr("Open"), I18n.tr("Open folder"), I18n.tr("Copy path"));
|
return Transform.transformFileResult(file, I18n.tr("Open"), I18n.tr("Open folder"), I18n.tr("Copy path"), I18n.tr("Open in terminal"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function detectTrigger(query) {
|
function detectTrigger(query) {
|
||||||
@@ -1586,6 +1672,9 @@ Item {
|
|||||||
case "copy_path":
|
case "copy_path":
|
||||||
copyToClipboard(item.data.path);
|
copyToClipboard(item.data.path);
|
||||||
break;
|
break;
|
||||||
|
case "open_terminal":
|
||||||
|
openTerminal(item.data.path);
|
||||||
|
break;
|
||||||
case "copy":
|
case "copy":
|
||||||
copyToClipboard(item.name);
|
copyToClipboard(item.name);
|
||||||
break;
|
break;
|
||||||
@@ -1667,6 +1756,16 @@ Item {
|
|||||||
Qt.openUrlExternally("file://" + folder);
|
Qt.openUrlExternally("file://" + folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openTerminal(path) {
|
||||||
|
if (!path)
|
||||||
|
return;
|
||||||
|
var terminal = Quickshell.env("TERMINAL") || "xterm";
|
||||||
|
Quickshell.execDetached({
|
||||||
|
command: [terminal],
|
||||||
|
workingDirectory: path
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function copyToClipboard(text) {
|
function copyToClipboard(text) {
|
||||||
if (!text)
|
if (!text)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -107,6 +107,10 @@ Item {
|
|||||||
spotlightContent.controller.activePluginId = "";
|
spotlightContent.controller.activePluginId = "";
|
||||||
spotlightContent.controller.activePluginName = "";
|
spotlightContent.controller.activePluginName = "";
|
||||||
spotlightContent.controller.pluginFilter = "";
|
spotlightContent.controller.pluginFilter = "";
|
||||||
|
spotlightContent.controller.fileSearchType = "all";
|
||||||
|
spotlightContent.controller.fileSearchExt = "";
|
||||||
|
spotlightContent.controller.fileSearchFolder = "";
|
||||||
|
spotlightContent.controller.fileSearchSort = "score";
|
||||||
spotlightContent.controller.collapsedSections = {};
|
spotlightContent.controller.collapsedSections = {};
|
||||||
spotlightContent.controller.selectedFlatIndex = 0;
|
spotlightContent.controller.selectedFlatIndex = 0;
|
||||||
spotlightContent.controller.selectedItem = null;
|
spotlightContent.controller.selectedItem = null;
|
||||||
|
|||||||
@@ -116,31 +116,43 @@ function transformBuiltInLauncherItem(item, pluginId, openLabel) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformFileResult(file, openLabel, openFolderLabel, copyPathLabel) {
|
function transformFileResult(file, openLabel, openFolderLabel, copyPathLabel, openTerminalLabel) {
|
||||||
var filename = file.path ? file.path.split("/").pop() : "";
|
var filename = file.path ? file.path.split("/").pop() : "";
|
||||||
var dirname = file.path ? file.path.substring(0, file.path.lastIndexOf("/")) : "";
|
var dirname = file.path ? file.path.substring(0, file.path.lastIndexOf("/")) : "";
|
||||||
|
var isDir = file.is_dir || false;
|
||||||
|
|
||||||
|
var actions = [];
|
||||||
|
if (isDir) {
|
||||||
|
if (openTerminalLabel) {
|
||||||
|
actions.push({
|
||||||
|
name: openTerminalLabel,
|
||||||
|
icon: "terminal",
|
||||||
|
action: "open_terminal"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
actions.push({
|
||||||
|
name: openFolderLabel,
|
||||||
|
icon: "folder_open",
|
||||||
|
action: "open_folder"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
actions.push({
|
||||||
|
name: copyPathLabel,
|
||||||
|
icon: "content_copy",
|
||||||
|
action: "copy_path"
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: file.path || "",
|
id: file.path || "",
|
||||||
type: "file",
|
type: "file",
|
||||||
name: filename,
|
name: filename,
|
||||||
subtitle: dirname,
|
subtitle: dirname,
|
||||||
icon: Utils.getFileIcon(filename),
|
icon: isDir ? "folder" : Utils.getFileIcon(filename),
|
||||||
iconType: "material",
|
iconType: "material",
|
||||||
section: "files",
|
section: "files",
|
||||||
data: file,
|
data: file,
|
||||||
actions: [
|
actions: actions,
|
||||||
{
|
|
||||||
name: openFolderLabel,
|
|
||||||
icon: "folder_open",
|
|
||||||
action: "open_folder"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: copyPathLabel,
|
|
||||||
icon: "content_copy",
|
|
||||||
action: "copy_path"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
primaryAction: {
|
primaryAction: {
|
||||||
name: openLabel,
|
name: openLabel,
|
||||||
icon: "open_in_new",
|
icon: "open_in_new",
|
||||||
|
|||||||
@@ -549,8 +549,151 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
id: fileFilterRow
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height - searchField.height - categoryRow.height - actionPanel.height - Theme.spacingXS * (categoryRow.visible ? 3 : 2)
|
height: showFileFilters ? fileFilterContent.height : 0
|
||||||
|
visible: showFileFilters
|
||||||
|
|
||||||
|
readonly property bool showFileFilters: controller.searchMode === "files"
|
||||||
|
|
||||||
|
Behavior on height {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: fileFilterContent
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: typeChips
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: 2
|
||||||
|
visible: DSearchService.supportsTypeFilter
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: [
|
||||||
|
{
|
||||||
|
id: "all",
|
||||||
|
label: I18n.tr("All"),
|
||||||
|
icon: "search"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "file",
|
||||||
|
label: I18n.tr("Files"),
|
||||||
|
icon: "insert_drive_file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "dir",
|
||||||
|
label: I18n.tr("Folders"),
|
||||||
|
icon: "folder"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
required property var modelData
|
||||||
|
required property int index
|
||||||
|
|
||||||
|
width: chipContent.width + Theme.spacingM * 2
|
||||||
|
height: sortDropdown.height
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: controller.fileSearchType === modelData.id || chipArea.containsMouse ? Theme.primaryContainer : "transparent"
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: chipContent
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
name: modelData.icon
|
||||||
|
size: 14
|
||||||
|
color: controller.fileSearchType === modelData.id ? Theme.primary : Theme.surfaceVariantText
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: modelData.label
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: controller.fileSearchType === modelData.id ? Theme.primary : Theme.surfaceText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: chipArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: controller.setFileSearchType(modelData.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 1
|
||||||
|
height: 20
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: Theme.outlineMedium
|
||||||
|
visible: typeChips.visible
|
||||||
|
}
|
||||||
|
|
||||||
|
DankDropdown {
|
||||||
|
id: sortDropdown
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: Math.min(130, parent.width / 3)
|
||||||
|
compactMode: true
|
||||||
|
dropdownWidth: 130
|
||||||
|
popupWidth: 150
|
||||||
|
maxPopupHeight: 200
|
||||||
|
currentValue: {
|
||||||
|
switch (controller.fileSearchSort) {
|
||||||
|
case "score":
|
||||||
|
return I18n.tr("Score");
|
||||||
|
case "name":
|
||||||
|
return I18n.tr("Name");
|
||||||
|
case "modified":
|
||||||
|
return I18n.tr("Modified");
|
||||||
|
case "size":
|
||||||
|
return I18n.tr("Size");
|
||||||
|
default:
|
||||||
|
return I18n.tr("Score");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options: [I18n.tr("Score"), I18n.tr("Name"), I18n.tr("Modified"), I18n.tr("Size")]
|
||||||
|
|
||||||
|
onValueChanged: value => {
|
||||||
|
var sortMap = {};
|
||||||
|
sortMap[I18n.tr("Score")] = "score";
|
||||||
|
sortMap[I18n.tr("Name")] = "name";
|
||||||
|
sortMap[I18n.tr("Modified")] = "modified";
|
||||||
|
sortMap[I18n.tr("Size")] = "size";
|
||||||
|
controller.setFileSearchSort(sortMap[value] || "score");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankTextField {
|
||||||
|
id: extFilterField
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: Math.min(100, parent.width / 4)
|
||||||
|
height: sortDropdown.height
|
||||||
|
placeholderText: I18n.tr("ext")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
showClearButton: text.length > 0
|
||||||
|
|
||||||
|
onTextChanged: {
|
||||||
|
controller.setFileSearchExt(text.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height - searchField.height - categoryRow.height - fileFilterRow.height - actionPanel.height - Theme.spacingXS * ((categoryRow.visible ? 1 : 0) + (fileFilterRow.visible ? 1 : 0) + 2)
|
||||||
opacity: root.parentModal?.isClosing ? 0 : 1
|
opacity: root.parentModal?.isClosing ? 0 : 1
|
||||||
|
|
||||||
ResultsList {
|
ResultsList {
|
||||||
@@ -586,6 +729,9 @@ FocusScope {
|
|||||||
function onSearchQueryRequested(query) {
|
function onSearchQueryRequested(query) {
|
||||||
searchField.text = query;
|
searchField.text = query;
|
||||||
}
|
}
|
||||||
|
function onModeChanged() {
|
||||||
|
extFilterField.text = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FocusScope {
|
FocusScope {
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ Rectangle {
|
|||||||
font.family: Theme.fontFamily
|
font.family: Theme.fontFamily
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
clip: true
|
||||||
visible: (root.item?.subtitle ?? "").length > 0
|
visible: (root.item?.subtitle ?? "").length > 0
|
||||||
horizontalAlignment: Text.AlignLeft
|
horizontalAlignment: Text.AlignLeft
|
||||||
}
|
}
|
||||||
@@ -181,7 +182,7 @@ Rectangle {
|
|||||||
case "plugin":
|
case "plugin":
|
||||||
return I18n.tr("Plugin");
|
return I18n.tr("Plugin");
|
||||||
case "file":
|
case "file":
|
||||||
return I18n.tr("File");
|
return root.item.data?.is_dir ? I18n.tr("Folder") : I18n.tr("File");
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -435,7 +435,15 @@ Item {
|
|||||||
var mode = root.controller?.searchMode ?? "all";
|
var mode = root.controller?.searchMode ?? "all";
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case "files":
|
case "files":
|
||||||
return "folder_open";
|
var fileType = root.controller?.fileSearchType ?? "all";
|
||||||
|
switch (fileType) {
|
||||||
|
case "dir":
|
||||||
|
return "folder_open";
|
||||||
|
case "file":
|
||||||
|
return "insert_drive_file";
|
||||||
|
default:
|
||||||
|
return "folder_open";
|
||||||
|
}
|
||||||
case "plugins":
|
case "plugins":
|
||||||
return "extension";
|
return "extension";
|
||||||
case "apps":
|
case "apps":
|
||||||
@@ -465,7 +473,15 @@ Item {
|
|||||||
return I18n.tr("Type to search files");
|
return I18n.tr("Type to search files");
|
||||||
if (root.controller.searchQuery.length < 2)
|
if (root.controller.searchQuery.length < 2)
|
||||||
return I18n.tr("Type at least 2 characters");
|
return I18n.tr("Type at least 2 characters");
|
||||||
return I18n.tr("No files found");
|
var fileType = root.controller?.fileSearchType ?? "all";
|
||||||
|
switch (fileType) {
|
||||||
|
case "dir":
|
||||||
|
return I18n.tr("No folders found");
|
||||||
|
case "file":
|
||||||
|
return I18n.tr("No files found");
|
||||||
|
default:
|
||||||
|
return I18n.tr("No results found");
|
||||||
|
}
|
||||||
case "plugins":
|
case "plugins":
|
||||||
return hasQuery ? I18n.tr("No plugin results") : I18n.tr("Browse or search plugins");
|
return hasQuery ? I18n.tr("No plugin results") : I18n.tr("Browse or search plugins");
|
||||||
case "apps":
|
case "apps":
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtCore
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
@@ -13,6 +11,9 @@ Singleton {
|
|||||||
|
|
||||||
property bool dsearchAvailable: false
|
property bool dsearchAvailable: false
|
||||||
property int searchIdCounter: 0
|
property int searchIdCounter: 0
|
||||||
|
property int indexVersion: 0
|
||||||
|
property bool supportsTypeFilter: false
|
||||||
|
property bool versionChecked: false
|
||||||
|
|
||||||
signal searchResultsReceived(var results)
|
signal searchResultsReceived(var results)
|
||||||
signal statsReceived(var stats)
|
signal statsReceived(var stats)
|
||||||
@@ -26,118 +27,157 @@ Singleton {
|
|||||||
stdout: SplitParser {
|
stdout: SplitParser {
|
||||||
onRead: line => {
|
onRead: line => {
|
||||||
if (line && line.trim().length > 0) {
|
if (line && line.trim().length > 0) {
|
||||||
root.dsearchAvailable = true
|
root.dsearchAvailable = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onExited: exitCode => {
|
onExited: exitCode => {
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
root.dsearchAvailable = false
|
root.dsearchAvailable = false;
|
||||||
|
} else {
|
||||||
|
root._checkVersion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _checkVersion() {
|
||||||
|
Proc.runCommand("dsearch-version", ["dsearch", "version", "--json"], (stdout, exitCode) => {
|
||||||
|
root.versionChecked = true;
|
||||||
|
if (exitCode !== 0)
|
||||||
|
return;
|
||||||
|
const response = JSON.parse(stdout);
|
||||||
|
root.indexVersion = response.index_schema || 0;
|
||||||
|
root.supportsTypeFilter = root.indexVersion >= 2;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function ping(callback) {
|
function ping(callback) {
|
||||||
if (!dsearchAvailable) {
|
if (!dsearchAvailable) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({ "error": "dsearch not available" })
|
callback({
|
||||||
|
"error": "dsearch not available"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Proc.runCommand("dsearch-ping", ["dsearch", "ping", "--json"], (stdout, exitCode) => {
|
Proc.runCommand("dsearch-ping", ["dsearch", "ping", "--json"], (stdout, exitCode) => {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
try {
|
try {
|
||||||
const response = JSON.parse(stdout)
|
const response = JSON.parse(stdout);
|
||||||
callback({ "result": response })
|
callback({
|
||||||
|
"result": response
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
callback({ "error": "failed to parse ping response" })
|
callback({
|
||||||
|
"error": "failed to parse ping response"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
callback({ "error": "ping failed" })
|
callback({
|
||||||
|
"error": "ping failed"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function search(query, params, callback) {
|
function search(query, params, callback) {
|
||||||
if (!query || query.length === 0) {
|
if (!query || query.length === 0) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({ "error": "query is required" })
|
callback({
|
||||||
|
"error": "query is required"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dsearchAvailable) {
|
if (!dsearchAvailable) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({ "error": "dsearch not available" })
|
callback({
|
||||||
|
"error": "dsearch not available"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = ["dsearch", "search", query, "--json"]
|
const args = ["dsearch", "search", query, "--json"];
|
||||||
|
|
||||||
if (params) {
|
if (params) {
|
||||||
if (params.limit !== undefined) {
|
if (params.limit !== undefined) {
|
||||||
args.push("-n", String(params.limit))
|
args.push("-n", String(params.limit));
|
||||||
|
}
|
||||||
|
if (params.type) {
|
||||||
|
args.push("-t", params.type);
|
||||||
}
|
}
|
||||||
if (params.ext) {
|
if (params.ext) {
|
||||||
args.push("-e", params.ext)
|
args.push("-e", params.ext);
|
||||||
|
}
|
||||||
|
if (params.folder) {
|
||||||
|
args.push("--folder", params.folder);
|
||||||
}
|
}
|
||||||
if (params.field) {
|
if (params.field) {
|
||||||
args.push("-f", params.field)
|
args.push("-f", params.field);
|
||||||
}
|
}
|
||||||
if (params.fuzzy) {
|
if (params.fuzzy) {
|
||||||
args.push("--fuzzy")
|
args.push("--fuzzy");
|
||||||
}
|
}
|
||||||
if (params.sort) {
|
if (params.sort) {
|
||||||
args.push("--sort", params.sort)
|
args.push("--sort", params.sort);
|
||||||
}
|
}
|
||||||
if (params.desc !== undefined) {
|
if (params.desc !== undefined) {
|
||||||
args.push("--desc=" + (params.desc ? "true" : "false"))
|
args.push("--desc=" + (params.desc ? "true" : "false"));
|
||||||
}
|
}
|
||||||
if (params.minSize !== undefined) {
|
if (params.minSize !== undefined) {
|
||||||
args.push("--min-size", String(params.minSize))
|
args.push("--min-size", String(params.minSize));
|
||||||
}
|
}
|
||||||
if (params.maxSize !== undefined) {
|
if (params.maxSize !== undefined) {
|
||||||
args.push("--max-size", String(params.maxSize))
|
args.push("--max-size", String(params.maxSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Proc.runCommand("dsearch-search", args, (stdout, exitCode) => {
|
Proc.runCommand("dsearch-search", args, (stdout, exitCode) => {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
try {
|
try {
|
||||||
const response = JSON.parse(stdout)
|
const response = JSON.parse(stdout);
|
||||||
searchResultsReceived(response)
|
searchResultsReceived(response);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({ "result": response })
|
callback({
|
||||||
|
"result": response
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const error = "failed to parse search response"
|
const error = "failed to parse search response";
|
||||||
errorOccurred(error)
|
errorOccurred(error);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({ "error": error })
|
callback({
|
||||||
|
"error": error
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (exitCode === 124) {
|
} else if (exitCode === 124) {
|
||||||
const error = "search timed out"
|
const error = "search timed out";
|
||||||
errorOccurred(error)
|
errorOccurred(error);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({ "error": error })
|
callback({
|
||||||
|
"error": error
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const error = "search failed"
|
const error = "search failed";
|
||||||
errorOccurred(error)
|
errorOccurred(error);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({ "error": error })
|
callback({
|
||||||
|
"error": error
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 100, 5000)
|
}, 100, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function rediscover() {
|
function rediscover() {
|
||||||
checkProcess.running = true
|
checkProcess.running = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user